fix(products): rótulo "Nome do X" nos formulários de catálogo + verificação em navegador real
CatalogCreateForm/SimpleCatalogCard ganham nameLabel (default "Nome"), propagado aos 5 catálogos: "Nome do tipo/grupo/subgrupo", "Nome da marca/unidade". Verificado desta vez em navegador real (Playwright headless, sem a extensão claude-in-chrome disponível nesta sessão) em vez de só por API — pegou um bug real que a verificação anterior não pegaria: o prop nameLabel tinha sido adicionado à assinatura mas esquecido de usar no JSX, então nenhum rótulo mudava apesar do build passar limpo. Corrigido e reverificado. Suíte: 95/95. pnpm turbo run typecheck build: 28/28. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ export function BrandsListPage() {
|
|||||||
onCreate={create}
|
onCreate={create}
|
||||||
onToggleActive={toggleActive}
|
onToggleActive={toggleActive}
|
||||||
namePlaceholder="ex.: Intelbras"
|
namePlaceholder="ex.: Intelbras"
|
||||||
|
nameLabel="Nome da marca"
|
||||||
createLabel="Adicionar marca"
|
createLabel="Adicionar marca"
|
||||||
emptyMessage="Nenhuma marca cadastrada."
|
emptyMessage="Nenhuma marca cadastrada."
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ import { Alert, Button, Input } from "@eden/ui";
|
|||||||
export function CatalogCreateForm({
|
export function CatalogCreateForm({
|
||||||
placeholder,
|
placeholder,
|
||||||
buttonLabel = "Adicionar",
|
buttonLabel = "Adicionar",
|
||||||
|
nameLabel = "Nome",
|
||||||
creating,
|
creating,
|
||||||
error,
|
error,
|
||||||
onCreate,
|
onCreate,
|
||||||
}: {
|
}: {
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
buttonLabel?: string;
|
buttonLabel?: string;
|
||||||
|
nameLabel?: string;
|
||||||
creating: boolean;
|
creating: boolean;
|
||||||
error: string | null;
|
error: string | null;
|
||||||
onCreate: (name: string) => Promise<boolean>;
|
onCreate: (name: string) => Promise<boolean>;
|
||||||
@@ -36,7 +38,7 @@ export function CatalogCreateForm({
|
|||||||
<form className="flex flex-col gap-3 sm:flex-row sm:items-end" onSubmit={handleSubmit}>
|
<form className="flex flex-col gap-3 sm:flex-row sm:items-end" onSubmit={handleSubmit}>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<Input
|
<Input
|
||||||
label="Nome"
|
label={nameLabel}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export function GroupSubgroupsPanel({ group }: { group: ProductGroupRow }) {
|
|||||||
) : null}
|
) : null}
|
||||||
<CatalogCreateForm
|
<CatalogCreateForm
|
||||||
placeholder="ex.: Fibra residencial"
|
placeholder="ex.: Fibra residencial"
|
||||||
|
nameLabel="Nome do subgrupo"
|
||||||
buttonLabel="Adicionar subgrupo"
|
buttonLabel="Adicionar subgrupo"
|
||||||
creating={creating}
|
creating={creating}
|
||||||
error={formError}
|
error={formError}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ export function ProductGroupsListPage() {
|
|||||||
) : null}
|
) : null}
|
||||||
<CatalogCreateForm
|
<CatalogCreateForm
|
||||||
placeholder="ex.: Banda larga"
|
placeholder="ex.: Banda larga"
|
||||||
|
nameLabel="Nome do grupo"
|
||||||
buttonLabel="Adicionar grupo"
|
buttonLabel="Adicionar grupo"
|
||||||
creating={creating}
|
creating={creating}
|
||||||
error={formError}
|
error={formError}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export function ProductTypesListPage() {
|
|||||||
onCreate={create}
|
onCreate={create}
|
||||||
onToggleActive={toggleActive}
|
onToggleActive={toggleActive}
|
||||||
namePlaceholder="ex.: Internet"
|
namePlaceholder="ex.: Internet"
|
||||||
|
nameLabel="Nome do tipo"
|
||||||
createLabel="Adicionar tipo"
|
createLabel="Adicionar tipo"
|
||||||
emptyMessage="Nenhum tipo de produto cadastrado."
|
emptyMessage="Nenhum tipo de produto cadastrado."
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export function SimpleCatalogCard<T extends SimpleCatalogRow>({
|
|||||||
onCreate,
|
onCreate,
|
||||||
onToggleActive,
|
onToggleActive,
|
||||||
namePlaceholder,
|
namePlaceholder,
|
||||||
|
nameLabel,
|
||||||
createLabel,
|
createLabel,
|
||||||
emptyMessage,
|
emptyMessage,
|
||||||
extraColumn,
|
extraColumn,
|
||||||
@@ -26,6 +27,7 @@ export function SimpleCatalogCard<T extends SimpleCatalogRow>({
|
|||||||
onCreate: (name: string) => Promise<boolean>;
|
onCreate: (name: string) => Promise<boolean>;
|
||||||
onToggleActive: (item: T) => void;
|
onToggleActive: (item: T) => void;
|
||||||
namePlaceholder: string;
|
namePlaceholder: string;
|
||||||
|
nameLabel?: string;
|
||||||
createLabel?: string;
|
createLabel?: string;
|
||||||
emptyMessage?: string;
|
emptyMessage?: string;
|
||||||
extraColumn?: TableColumn<T>;
|
extraColumn?: TableColumn<T>;
|
||||||
@@ -39,6 +41,7 @@ export function SimpleCatalogCard<T extends SimpleCatalogRow>({
|
|||||||
) : null}
|
) : null}
|
||||||
<CatalogCreateForm
|
<CatalogCreateForm
|
||||||
placeholder={namePlaceholder}
|
placeholder={namePlaceholder}
|
||||||
|
nameLabel={nameLabel}
|
||||||
buttonLabel={createLabel}
|
buttonLabel={createLabel}
|
||||||
creating={creating}
|
creating={creating}
|
||||||
error={formError}
|
error={formError}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export function SubgroupsListPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<Input
|
<Input
|
||||||
label="Nome"
|
label="Nome do subgrupo"
|
||||||
placeholder="ex.: Fibra residencial"
|
placeholder="ex.: Fibra residencial"
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export function UnitsListPage() {
|
|||||||
onCreate={create}
|
onCreate={create}
|
||||||
onToggleActive={toggleActive}
|
onToggleActive={toggleActive}
|
||||||
namePlaceholder="ex.: Unidade"
|
namePlaceholder="ex.: Unidade"
|
||||||
|
nameLabel="Nome da unidade"
|
||||||
createLabel="Adicionar unidade"
|
createLabel="Adicionar unidade"
|
||||||
emptyMessage="Nenhuma unidade cadastrada."
|
emptyMessage="Nenhuma unidade cadastrada."
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -661,3 +661,20 @@ Pequeno complemento de backend necessário para a coluna "Grupo" da tela nova: `
|
|||||||
|
|
||||||
### Verificação
|
### Verificação
|
||||||
`pnpm turbo run typecheck build` 28/28 (os 3 apps que usam `@eden/ui` — `core-web`/`reseller-web`/`subscriber-web` — confirmados sem regressão). Teste novo em `apps/api/test/product-catalogs.spec.ts` cobrindo `group_name` resolvido tanto na listagem filtrada por `groupId` quanto na geral. Suíte completa: 95/95 verdes. Testado ao vivo via `curl` contra `eden-api`/`eden-core` reconstruídos: rota `/products/subgroups` responde 200, criação de subgrupo segue funcionando, listagem geral resolve `group_name` corretamente. Interação de clique no accordion aninhado (abrir "Grupos" → ver "Subgrupos" → navegar) não foi possível verificar via browser automatizado (nenhuma ferramenta desse tipo disponível neste ambiente) — verificação limitada a build/tipos/API real, mesma limitação já registrada pelo agente de frontend na leva anterior.
|
`pnpm turbo run typecheck build` 28/28 (os 3 apps que usam `@eden/ui` — `core-web`/`reseller-web`/`subscriber-web` — confirmados sem regressão). Teste novo em `apps/api/test/product-catalogs.spec.ts` cobrindo `group_name` resolvido tanto na listagem filtrada por `groupId` quanto na geral. Suíte completa: 95/95 verdes. Testado ao vivo via `curl` contra `eden-api`/`eden-core` reconstruídos: rota `/products/subgroups` responde 200, criação de subgrupo segue funcionando, listagem geral resolve `group_name` corretamente. Interação de clique no accordion aninhado (abrir "Grupos" → ver "Subgrupos" → navegar) não foi possível verificar via browser automatizado (nenhuma ferramenta desse tipo disponível neste ambiente) — verificação limitada a build/tipos/API real, mesma limitação já registrada pelo agente de frontend na leva anterior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rótulo "Nome do X" nos formulários de catálogo de Produto + verificação real em navegador
|
||||||
|
|
||||||
|
Data: 2026-09-18. Usuário pediu duas coisas na sequência: (1) verificar no navegador se a leva anterior (submenu de Subgrupos) está funcionando de verdade, e (2) trocar o rótulo genérico "Nome" por "Nome do subgrupo" no formulário de criação — e, logo em seguida, "usar a mesma lógica para o Grupo", interpretado (e confirmado fazendo) como aplicar o mesmo padrão aos 5 catálogos: "Nome do tipo"/"Nome do grupo"/"Nome do subgrupo"/"Nome da marca"/"Nome da unidade" (sem dois-pontos no final — nenhum outro rótulo do app usa, mantido consistente).
|
||||||
|
|
||||||
|
### Verificação real em navegador (não só API)
|
||||||
|
|
||||||
|
Nenhuma ferramenta de browser automation (`claude-in-chrome`) estava disponível nesta sessão. Em vez de reportar como não verificável (mesma limitação que os agentes de frontend já haviam registrado nas levas anteriores), usei o Playwright que já existe no monorepo (`packages/integrations` depende dele para renderização de PDF; o Chromium já estava em cache local de builds anteriores) para abrir o Chromium de verdade, logar como super_admin e navegar pelas telas reais. Isso capturou um bug real que a verificação só por API/build nunca pegaria: o menu aninhado Produtos → Grupos → Subgrupos realmente expande e navega corretamente (confirmado via dump do texto do DOM da sidebar), mas o rótulo do campo de criação continuava mostrando "Nome" em vez de "Nome do grupo"/"Nome do tipo"/etc — o prop `nameLabel` tinha sido adicionado à assinatura de `CatalogCreateForm.tsx` mas esquecido de usar de fato no JSX (`<Input label="Nome" .../>` continuava hardcoded). Corrigido, reconstruído, reverificado com o mesmo script Playwright — os 5 rótulos batem exatamente com o esperado.
|
||||||
|
|
||||||
|
### Mudança
|
||||||
|
|
||||||
|
`CatalogCreateForm.tsx`/`SimpleCatalogCard.tsx` ganharam o prop `nameLabel` (default `"Nome"`, sem quebrar nada que não o passe); os 5 pontos de uso (`ProductTypesListPage`, `ProductGroupsListPage`, `GroupSubgroupsPanel`, `BrandsListPage`, `UnitsListPage`) e o formulário manual de `SubgroupsListPage.tsx` passaram o rótulo específico de cada catálogo.
|
||||||
|
|
||||||
|
### Verificação
|
||||||
|
`pnpm turbo run typecheck build` 28/28. Suíte 95/95 (uma corrida isolada apresentou uma falha pontual num `afterAll` de outro spec depois de várias execuções seguidas da suíte hoje contra o mesmo Postgres compartilhado — não reproduziu nas execuções seguintes, tratado como ambiental, não investigado a fundo). Verificação em navegador real via Playwright headless: dump de DOM confirmando os 5 rótulos corretos em `/products/{types,groups,subgroups,brands,units}`, screenshots confirmando visualmente o submenu aninhado "Grupos" expandido mostrando "Grupos"/"Subgrupos", a tela de Subgrupos com dropdown "Grupo" + campo "Nome do subgrupo" + coluna "Grupo" na tabela, e o painel "Ver subgrupos" dentro de um grupo específico também com "Nome do subgrupo". Linhas de teste acumuladas nos 5 catálogos ao longo do dia (múltiplas rodadas de suíte + smoke tests) desativadas ao final — só sobraram duas linhas de subgrupo não reconhecidas como teste automatizado ("teste"/"qqweqw", possivelmente exploração manual do próprio usuário) deliberadamente preservadas, não mexidas.
|
||||||
|
|||||||
Reference in New Issue
Block a user