diff --git a/apps/core-web/src/routes/client-registrations/ClientRegistrationDetailPage.tsx b/apps/core-web/src/routes/client-registrations/ClientRegistrationDetailPage.tsx index 93f0c33..409bf04 100644 --- a/apps/core-web/src/routes/client-registrations/ClientRegistrationDetailPage.tsx +++ b/apps/core-web/src/routes/client-registrations/ClientRegistrationDetailPage.tsx @@ -21,10 +21,14 @@ import { PartnersSection } from "./PartnersSection.js"; * (breadcrumb + title/status header, grouped info blocks) and `customers.tsx` * (status badge) — rebuilt with `@eden/ui` Card sections, one per group of * fields, same pattern as QuoteDetailPage/CompanyFormPage. Unlike those two - * (pure display or pure form), this screen mixes both: everything below the - * header is one editable form (single PATCH on submit, matching how the - * API accepts a fully partial `UpdateClientRegistrationDto`), plus a - * separate Sócios sub-section with its own independent list/add/edit calls. + * (pure display or pure form), this screen mixes both: one editable form + * (single PATCH on submit, matching how the API accepts a fully partial + * `UpdateClientRegistrationDto`) split across two `
` elements — + * Status/Dados PF-PJ, then (after the non-form Sócios sub-section) Endereço/ + * Contatos/Portabilidade — both calling the same `handleSubmit`, which + * always reads the complete React `form` state regardless of which one + * triggered it, so the split is purely visual (see the JSX comment above + * the first ``). Sócios has its own independent list/add/edit calls. */ const STATUS_LABEL: Record = { rascunho: "Rascunho", @@ -350,6 +354,15 @@ export function ClientRegistrationDetailPage() { ) : null} + {/* + Ordem pedida pelo usuário: Dados PJ/PF -> Sócios -> Endereço -> + Contatos. `Status` fica primeiro (não mencionado, posição natural) e + `Portabilidade`/botão de salvar ficam no final (idem). `PartnersSection` + renderiza seu próprio interno (form aninhado é inválido em + HTML), então o form único original virou dois — ambos chamam o mesmo + `handleSubmit`, que sempre lê o estado React completo (`form`), não o + DOM, então dividir em dois não muda o que é salvo. + */}
@@ -381,113 +394,6 @@ export function ClientRegistrationDetailPage() {
- -
- updateField("addressZip", e.target.value)} /> -
- updateField("addressStreet", e.target.value)} - /> -
- updateField("addressNumber", e.target.value)} - /> - updateField("addressComplement", e.target.value)} - /> - updateField("addressNeighborhood", e.target.value)} - /> - updateField("addressCity", e.target.value)} - /> - updateField("addressState", e.target.value.toUpperCase())} - /> - updateField("addressCountry", e.target.value)} - placeholder="Brasil" - /> -
-
- - -
-
-

Principal

- updateField("contactPrincipalName", e.target.value)} - /> - updateField("contactPrincipalEmail", e.target.value)} - /> - updateField("contactPrincipalPhone", e.target.value)} - /> -
-
-

Financeiro

- updateField("contactFinancialName", e.target.value)} - /> - updateField("contactFinancialEmail", e.target.value)} - /> - updateField("contactFinancialPhone", e.target.value)} - /> -
-
-

Técnico

- updateField("contactTechnicalName", e.target.value)} - /> - updateField("contactTechnicalEmail", e.target.value)} - /> - updateField("contactTechnicalPhone", e.target.value)} - /> -
-
-
- {registration.person_type === "pf" ? (
@@ -666,6 +572,125 @@ export function ClientRegistrationDetailPage() {
)} + + + {registration.person_type === "pj" ? ( +
+ +
+ ) : null} + +
+ +
+ updateField("addressZip", e.target.value)} /> +
+ updateField("addressStreet", e.target.value)} + /> +
+ updateField("addressNumber", e.target.value)} + /> + updateField("addressComplement", e.target.value)} + /> + updateField("addressNeighborhood", e.target.value)} + /> + updateField("addressCity", e.target.value)} + /> + updateField("addressState", e.target.value.toUpperCase())} + /> + updateField("addressCountry", e.target.value)} + placeholder="Brasil" + /> +
+
+ + +
+
+

Principal

+ updateField("contactPrincipalName", e.target.value)} + /> + updateField("contactPrincipalEmail", e.target.value)} + /> + updateField("contactPrincipalPhone", e.target.value)} + /> +
+
+

Financeiro

+ updateField("contactFinancialName", e.target.value)} + /> + updateField("contactFinancialEmail", e.target.value)} + /> + updateField("contactFinancialPhone", e.target.value)} + /> +
+
+

Técnico

+ updateField("contactTechnicalName", e.target.value)} + /> + updateField("contactTechnicalEmail", e.target.value)} + /> + updateField("contactTechnicalPhone", e.target.value)} + /> +
+
+
{registration.is_portability ? ( @@ -686,16 +711,6 @@ export function ClientRegistrationDetailPage() { - - {registration.person_type === "pj" ? ( -
- -
- ) : null} ); } diff --git a/docs/progress.md b/docs/progress.md index a9c9054..264144d 100644 --- a/docs/progress.md +++ b/docs/progress.md @@ -720,3 +720,14 @@ Verificado: `pnpm turbo run typecheck build` 28/28, suíte 100/100 (95→100, 5 ### Pendências Lookup de CPF pra pessoa física — fora de escopo, não foi pedido. Refresh automático da situação cadastral/endereço (ex. um job periódico) não existe — "Buscar novamente" é manual, sob demanda. + +--- + +## Reordenação do formulário de Cadastro de Cliente + +Data: 2026-09-18. Usuário pediu: "primeiro vem os dados PJ depois vem os sócios depois endereço e depois contatos". Implementado diretamente (mudança de layout, sem lógica nova). Ordem final: Status (não mencionado, mantido primeiro) → Dados PF/PJ → Sócios (só PJ) → Endereço → Contatos → Portabilidade/botão de salvar (não mencionados, mantidos no final). + +`ClientRegistrationDetailPage.tsx`: o `
` único virou dois — `PartnersSection` (Sócios) já renderiza seu próprio `` interno (form aninhado é HTML inválido), então não dá pra intercalar sem quebrar essa regra. Os dois `` chamam o mesmo `handleSubmit`, que sempre lê o estado React completo (`form`), nunca o DOM — testado ao vivo que salvar a partir do botão (agora depois de Contatos, no segundo ``) grava corretamente campos da seção Status (primeiro ``, antes de Sócios) junto com campos de Endereço (segundo ``), confirmando que a divisão é só visual. + +### Verificação +`pnpm turbo run typecheck build` 28/28. Suíte 100/100 (inalterada — mudança é só de frontend). Testado ao vivo em navegador real via Playwright: ordem das seções confirmada por leitura do DOM (`Status, Dados PJ, Sócios, Endereço, Contatos`) e por screenshot; ciclo completo com CNPJ real (Petrobras) mostrando os 10 sócios na nova posição; salvamento testado preenchendo um campo de cada `` e confirmando após reload que os dois persistiram. Cadastro de teste desativado ao final.