mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-14 08:53:11 +00:00
6.8 KiB
6.8 KiB
Impl: Assessores — menu do picker de colunas derivado da mesma fonte do AdvisorsTable
Status: concluído (executado 2026-08-11) Atualizado em: 2026-08-11 Issue: #642 Intenção: docs/plans/escala-dry-pos-b197.md Appetite restante: ~0,5 dia (herdado)
Leitura da intenção
- Outcome: o menu do picker de colunas de assessores nasce da mesma fonte
que os
<th>da tabela — adicionar coluna num lugar atualiza o outro de graça. Zero mudança de comportamento. - O que NÃO negociar: mesmos ids (
namemandatory,email,phone,municipalities,actions— contrato do cookiecampaign_columns), mesmos labels pt-BR, mesma ordem, exceção do draft intacta (input de e-mail na linha-draft mesmo com a coluna oculta), e o não-escopo travado de não portar oAdvisorsTableparaCampaignTable. - O que reavaliar: o plano de intenção já recomenda a Opção A (fonte única
no módulo da tabela); a reavaliação aqui é de engenharia fina — onde a
constante vive, como o
<th>consome, como oemailHiddenderiva.
Abordagem recomendada
flowchart LR
S[advisorTableColumns<br/>AdvisorsTable.tsx] --> H[<th> via resolveVisibleColumns]
S --> P[advisorPickerColumns =<br/>toCampaignColumnPickerColumns]
P --> T[CampaignColumnPickerTrailing<br/>assessores/page.tsx]
Opções consideradas: A | B | C | D
Recomendação: A — porque segue o precedente em produção
(supporterColumns/supporterPickerColumns em SupporterList.tsx — o RSC de
apoiadores importa a constante serializável do módulo do componente),
reusa os helpers B17 (toCampaignColumnPickerColumns, resolveVisibleColumns)
e mantém o diff em 2 arquivos.
Rejeitadas:
- B — lib nova (
src/lib/advisorTableColumns.ts): só há dois consumidores e um é o mesmo módulo que renderiza; módulo lib com 1 call site real é camada sem volatilidade (depth check — pass-through). - C — status quo (comentário): o achado que originou a Issue é exatamente que o comentário é insuficiente; rejeitada pela intenção.
- D — extrair só id/label/mandatory e manter widths/sr-only no JSX: deixa
dois lugares para tocar ao adicionar coluna (layout do header) e obrigaria
exceção manual no map para o caso
Ações; a classe de header é propriedade da coluna, declarada junto.
Decisões de engenharia
- Fonte única em
AdvisorsTable.tsx(client). Novo tipo localAdvisorTableColumn { id, label, mandatory?, headerClassName?, visuallyHiddenLabel? }e constanteadvisorTableColumnscom as 5 colunas atuais (incluindow-[20%]/w-[24%]/w-[14%]/w-28 text-rightevisuallyHiddenLabel: trueemAções, que preserva o<span class="sr-only">). <th>consomemresolveVisibleColumns(advisorTableColumns, columnVisibility.hiddenColumnIds)— o mesmo helper B17 das outras listas: filtra por cookie respeitandomandatory, eemailHiddenpassa a derivar devisibleColumns.some(id === 'email'). Descoberta do /simplify (fix incorporado): o corpo renderiza as células incondicionalmente (sóemailtem<td>condicional + exceção do draft), entãophone/municipalities/actionssãomandatory: true— um id escondido por cookie velho derruba o<th>sobre um corpo de 5 células (table-fixed) se não for; o checkbox do picker vira "sempre visível" (honesto em vez do toggle inerte do B197). O corpo (células + exceção do draft) fica intocado.- **
export const advisorPickerColumns = toCampaignColumnPickerColumns(advisorTableColumns)no módulo da tabela — mesma forma desupporterPickerColumns. assessores/page.tsximportaadvisorPickerColumnse passa direto aoCampaignColumnPickerTrailing; removidos o array local, o comentário do espelho e os imports órfãos (toCampaignColumnPickerColumns,CampaignColumnPickerColumn).- e2e
campaignColumnPicker(assessores): asserts novos pinando o contrato mandatory —Nome/Celular"sempre visível" (checked + disabled).
Componentes / mudanças
AdvisorsTable.tsx(src/components/campaign/advisor/): declara a fonte única, exportaadvisorPickerColumns, header por map; corpo intacto.assessores/page.tsx(src/app/(campaign)/campanha/(app)/assessores/): consome a fonte exportada.- Migration: sem migration.
- Access / Consent: sem mudança (acesso já gateado no page).
- UI: Impeccable A — sem superfície nova; refactor estrutura que preserva
DOM/aria (sr-only de
Açõesmantido).
Dados → forma
- Forma escolhida: colunas como dados serializáveis no módulo do componente, convertidas na fonte via helper B17. Alternativas rejeitadas: lib separada (sem call site extra) e manutenção do espelho (o próprio defeito).
Fases verificáveis
- Fonte única + header —
AdvisorsTable.tsx: tipo + constante + export + map do header comresolveVisibleColumns;emailHiddenderivado. - Consumo no page —
assessores/page.tsx: import + remoção do array local e imports órfãos. - Gates —
pnpm exec tsc --noEmit,pnpm lint,pnpm format:check,pnpm test(unit:campaignColumnVisibility— lib intacta), e2ecampaignColumnPicker(spec de assessores cobre exatamente os comportamentos preservados: default oculto, draft com input, religar, persistência);pnpm exec knip(removidos imports órfãos),pnpm check:cycles. - Fechamento — status do plano de intenção → concluído; entrada curta em
docs/CHANGELOG-AGENTS.md.
Rabbit holes / Não escopo (engenharia)
- Não portar
AdvisorsTableparaCampaignTable(decisão travada do B197). - Não mexer em labels/ordem/ids — contrato do cookie
campaign_columns. - Não criar coluna nova, não tocar células do corpo além de
emailHiddenderivado. - Sem novo unit test: o comportamento é idêntico e coberto pelo e2e existente; testar a constante exigiria importar o módulo client inteiro (lucide/next/ sonner) — custo sem retorno para um espelho que deixou de existir.
Riscos e mitigação
- Import de client module em RSC: precedente em produção
(
supporterPickerColumnsemapoiadores/page.tsx); valor serializável (array de{id,label,mandatory}). - Layout
table-fixed: classes de largura movem para o mesmo<th>, na mesma ordem — DOM e classes idênticos, só que gerados por map comkey. emailHiddendivergente do header: eliminado por construção — deriva do mesmovisibleColumnsque renderiza o header.
Aceite de engenharia
- Aceite de produto da intenção ainda coberto (mesma fonte, zero mudança)
- Invariantes AGENTS/engineering-standards (edit the owner: a tabela já possui o concern do menu; reusa lib B17)
- Testes de domínio: sem mudança de access/write path; e2e existente é o guard do comportamento