Skip to content

Commit

Permalink
oob new client procedure
Browse files Browse the repository at this point in the history
  • Loading branch information
henriquepw committed Nov 19, 2024
1 parent 1e4d448 commit 9a3b09e
Show file tree
Hide file tree
Showing 5 changed files with 281 additions and 265 deletions.
3 changes: 2 additions & 1 deletion static/css/input.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
}

::-webkit-scrollbar {
width: 8px;
width: 6px;
height: 4px;
}

::-webkit-scrollbar-track {
Expand Down
77 changes: 42 additions & 35 deletions web/handlers/client_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,37 +73,6 @@ func (h *ClientHandler) CreateClientAction(w http.ResponseWriter, r *http.Reques
)
}

func (h *ClientHandler) EditClientProcedureAction(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
doneAt, err := time.Parse(time.DateOnly, r.Form.Get("doneAt"))
if err != nil {
fmt.Print(err)
httputil.Render(w, r, http.StatusBadRequest, clientview.ClientProcessEditForm(map[string]string{"doneAt": "Data inválida"}))
return
}

payload := types.ClientProcedureUpdateDTO{
ID: r.PathValue("procedureId"),
Description: r.Form.Get("description"),
ProcedureID: r.Form.Get("procedureId"),
DoneAt: doneAt,
}

p, err := h.clientProcedureSVC.EditClientProcedure(r.Context(), payload)
if err != nil {
httputil.RenderError(w, r, err, func(e errors.ServerError) templ.Component {
return clientview.ClientProcessEditForm(e.Errors)
})
return
}

httputil.Render(
w, r, http.StatusOK,
clientview.ClientProcessEditForm(nil),
clientview.OobUpdateClientProcedure(*p),
)
}

func (h *ClientHandler) ClientDetailPage(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")

Expand Down Expand Up @@ -181,9 +150,7 @@ func (h *ClientHandler) CreateClientProcedureAction(w http.ResponseWriter, r *ht
Description: r.Form.Get("description"),
}

log.Println(payload)
p, err := h.clientProcedureSVC.CreateClientProcedure(r.Context(), payload)
log.Println(p)
_, err := h.clientProcedureSVC.CreateClientProcedure(r.Context(), payload)
if err != nil {
httputil.RenderError(w, r, err, func(e errors.ServerError) templ.Component {
log.Println(payload)
Expand All @@ -192,10 +159,50 @@ func (h *ClientHandler) CreateClientProcedureAction(w http.ResponseWriter, r *ht
return
}

clientProcedures, err := h.clientProcedureSVC.ListClientProcedures(r.Context(), clientID)
if err != nil {
httputil.Render(
w, r, http.StatusCreated,
clientview.ClientProcessCreateForm(clientID, payload, nil),
)
return
}

httputil.Render(
w, r, http.StatusCreated,
clientview.ClientProcessCreateForm(clientID, payload, nil),
// pages.OobNewClient(*client),
clientview.OobNewClientProcedure(clientProcedures),
)
}

func (h *ClientHandler) EditClientProcedureAction(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
doneAt, err := time.Parse(time.DateOnly, r.Form.Get("doneAt"))
if err != nil {
fmt.Print(err)
httputil.Render(w, r, http.StatusBadRequest, clientview.ClientProcessEditForm(map[string]string{"doneAt": "Data inválida"}))
return
}

payload := types.ClientProcedureUpdateDTO{
ID: r.PathValue("procedureId"),
Description: r.Form.Get("description"),
ProcedureID: r.Form.Get("procedureId"),
DoneAt: doneAt,
}

p, err := h.clientProcedureSVC.EditClientProcedure(r.Context(), payload)
if err != nil {
httputil.RenderError(w, r, err, func(e errors.ServerError) templ.Component {
return clientview.ClientProcessEditForm(e.Errors)
})
return
}

httputil.Render(
w, r, http.StatusOK,
clientview.ClientProcessEditForm(nil),
clientview.OobUpdateClientProcedure(*p),
)
}

Expand Down
227 changes: 2 additions & 225 deletions web/view/client_view/client_detail_page.templ
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ templ ClientDetailPage(
@ui.Icon("edit")
</button>
}
<section id="client-section" class="column">
@ClientDetailSection(client)
</section>
@ClientDetailSection(client)
@ClientProcessSection(client.ID, procedures, clientProcedures)
@ui.Modal("editOpen", "editOpen=false", "Editar Cliente") {
@ClientEditForm(client.ID, types.ClientUpdateDTO{
Expand Down Expand Up @@ -173,226 +171,5 @@ templ ClientEditForm(id string, values types.ClientUpdateDTO, errors map[string]
}

templ OobClientUpdated(c types.Client) {
<section id="client-section" class="space-y-4" hx-swap-oob="outerHTML">
@ClientDetailSection(c)
</section>
}

func parseProcedures(items []types.Procedure) string {
result := "["
for _, p := range items {
result = result + fmt.Sprintf("{id:'%s',name:'%s'},", p.ID, p.Name)
}
result = result + "]"

return result
}

templ ClientProcessSection(id string, procedures []types.Procedure, clientProcedures []types.ClientProcedure) {
<section
class="mt-6 mb-10"
x-data={ "{ procedure: undefined, newProcedureOpen: false, procedureTypes:" +
parseProcedures(procedures) + " }" }
>
<div class="row mb-4">
<h2 class="text-2xl flex-1 font-bold">Procedimentos</h2>
</div>
@ClientProcedureList(clientProcedures)
@ui.Modal("!!procedure", "procedure=undefined", "Editar Procedimento") {
@ClientProcessEditForm(nil)
}
@ui.Modal("newProcedureOpen", "newProcedureOpen=false", "Registrar Procedimento") {
@ClientProcessCreateForm(id, types.ClientProcedureCreateDTO{}, nil)
}
<button
type="button"
class="btn-primary fixed bottom-4 right-4 rounded-full p-0 w-12 h-12 shadow-sm shadow-gray-6"
@click="newProcedureOpen = true"
>
@ui.Icon("plus")
</button>
</section>
}

templ OobDeleteClientProcedure(id string) {
<template hx-swap-oob="outerHTML" id={ "client-procedure-" + id }></template>
}

templ OobUpdateClientProcedure(p types.ClientProcedure) {
<li
hx-swap-oob="outerHTML"
id={ "client-procedure-" + p.ID }
class="flex flex-col items-start gap-1 p-2 -ml-2 rounded transition-colors hover:bg-gray-2 cursor-pointer"
@click={ fmt.Sprintf("procedure={id:'%s',procedureId:'%s',doneAt:'%s',description:`%s`}", p.ID, p.ProcedureID,
date.FormatToFormInput(p.DoneAt), p.Description) }
>
<span
class="
text-sm text-gray-11 relative
before:absolute before:size-3 before:bg-gray-1
before:border-2 before:border-accent-8
before:rounded-full before:left-0 before:top-1/2 before:-translate-x-[1.45rem] before:-translate-y-1/2
"
x-text={ ui.FormatDate(p.DoneAt) }
></span>
<span class="text-sm text-accent-12 bg-accent-3 border border-accent-6 px-1 rounded">
{ p.Procedure }
</span>
<span class="font-medium">{ p.Description }</span>
</li>
}

templ clientProcedureItem(p types.ClientProcedure) {
<li
id={ "client-procedure-" + p.ID }
class="flex flex-col items-start gap-1 p-2 -ml-2 rounded transition-colors hover:bg-gray-2 cursor-pointer"
@click={ fmt.Sprintf("procedure={id:'%s',procedureId:'%s',doneAt:'%s',description:`%s`}", p.ID, p.ProcedureID,
date.FormatToFormInput(p.DoneAt), p.Description) }
>
<span
class="
text-sm text-gray-11 relative
before:absolute before:size-3 before:bg-gray-1
before:border-2 before:border-accent-8
before:rounded-full before:left-0 before:top-1/2 before:-translate-x-[1.45rem] before:-translate-y-1/2
"
x-text={ ui.FormatDate(p.DoneAt) }
></span>
<span class="text-sm text-accent-12 bg-accent-3 border border-accent-6 px-1 rounded">
{ p.Procedure }
</span>
<span class="font-medium">{ p.Description }</span>
</li>
}

templ ClientProcessEditForm(errors map[string]string) {
<form
x-init="$watch('procedure', () => htmx.process($el))"
:hx-put="`/clients/${clientId}/procedures/${procedure?.id}`"
hx-target="this"
hx-swap="outerHTML"
hx-indicator="this"
class="flex flex-col gap-4 group [&.htmx-request]:pointer-events-none"
@htmx:before-swap="(e) => {
if (e.detail.xhr.status === 200) {
procedure = undefined;
}
}"
>
<div
class="row"
x-data={ fmt.Sprintf("{selectedProcedure:'%s'}", "") }
x-effect="selectedProcedure=procedure?.procedureId"
>
@ui.FormField("procedureID", "Procedimento", errors["procedureId"], true) {
<select class="input h-9" name="procedureId">
<option value="">Selecione um procedimento</option>
<template x-for="p in procedureTypes">
<option :value="p.id" x-text="p.name" :selected="p.id == selectedProcedure"></option>
</template>
</select>
}
@ui.TextInput(ui.TextInputOps{
Required: true,
Label: "Data de Realização",
Name: "doneAt",
Type: "date",
XValue: "procedure?.doneAt",
Error: errors["doneAt"],
})
</div>
@ui.TextArea(ui.TextAreaOps{
Required: true,
Label: "Descrição",
Name: "description",
Placeholder: "Descreva como foi o procedimento, quais matérias foram usados, etc",
XValue: "procedure?.description",
Error: errors["description"],
})
<div class="flex justify-between">
<button
x-init="$watch('procedure', () => htmx.process($el))"
:hx-delete="`/clients/${clientId}/procedures/${procedure?.id}`"
hx-indicator="this"
class="btn-alert group"
type="button"
>
<div class="items-center gap-1.5 hidden group-[.htmx-request]:flex">
@ui.Icon("loader", "h-5 w-5 animate-spin")
Deletando...
</div>
<div class="flex gap-1.5 group-[.htmx-request]:hidden">
@ui.Icon("trash")
Deletar
</div>
</button>
@ui.SubmitBtn("save", "Salvando...", "ml-auto") {
Salvar
}
</div>
</form>
}

templ ClientProcedureList(procedures []types.ClientProcedure) {
if len(procedures) == 0 {
<div class="card bg-warning-2 border-warning-7">
<p class="text-center text-warning-12">
Nenhum procedimento cadastrado
</p>
</div>
} else {
<div class="flex w-full items-stratch">
<div class="w-0.5 bg-accent-8 mr-4 rounded"></div>
<ul class="space-y-6 flex-1">
for _, i := range procedures {
@clientProcedureItem(i)
}
</ul>
</div>
}
}

templ ClientProcessCreateForm(id string, values types.ClientProcedureCreateDTO, errors map[string]string) {
<form
hx-post={ "/clients/" + id + "/procedures" }
hx-target="this"
hx-swap="outerHTML"
hx-indicator="this"
class="flex flex-col gap-4 group [&.htmx-request]:pointer-events-none"
@htmx:before-swap="(e) => {
if (e.detail.xhr.status === 201) {
newProcedureOpen = false;
}
}"
>
<div class="row" x-data={ fmt.Sprintf("{selectedProcedure:'%s'}", values.ProcedureID) }>
@ui.FormField("procedureID", "Procedimento", errors["procedureId"], true) {
<select class="input h-9" name="procedureId">
<option value="">Selecione um procedimento</option>
<template x-for="p in procedureTypes">
<option :value="p.id" x-text="p.name" :selected="p.id == selectedProcedure"></option>
</template>
</select>
}
@ui.TextInput(ui.TextInputOps{
Required: true,
Label: "Data de Realização",
Name: "doneAt",
Type: "date",
Value: values.DoneAt,
Error: errors["doneAt"],
})
</div>
@ui.TextArea(ui.TextAreaOps{
Required: true,
Name: "description",
Label: "Descrição",
Placeholder: "Descreva como foi o procedimento, quais matérias foram usados, etc",
Value: values.Description,
Error: errors["description"],
})
@ui.SubmitBtn("save", "Salvando...", "ml-auto") {
Salvar
}
</form>
@ClientDetailSection(c, templ.Attributes{"hx-swap-oob": "outerHTML"})
}
4 changes: 2 additions & 2 deletions web/view/client_view/client_detail_section.templ
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"github.com/henriquepw/imperium-tattoo/web/view/ui"
)

templ ClientDetailSection(client types.Client) {
<section x-data="{expanded: false}" class="column">
templ ClientDetailSection(client types.Client, attrs ...templ.Attributes) {
<section x-data="{expanded: false}" id="client-section" class="column" { ui.GetAttrs(attrs...)... }>
<div x-show="expanded" x-transition class="row">
@ui.Tile("Adicionado em") {
<span x-text={ ui.FormatDate(client.CreatedAt) }></span>
Expand Down
Loading

0 comments on commit 9a3b09e

Please sign in to comment.