docs(plan): clarify B159 UI alignment intent
The plan previously suggested the UI wouldn't change — only the code would be refactored. Updated to make explicit that: - Dobradinhas editor changes from RelationChipCell to the same CampaignCellEditOverlay + Command + chips as Assessores/Liderancas. - Liderancas display gains an avatar stack matching Assessores/Dobradinhas. - Inline create is always name-only across all three columns (leadership phone is added later on the detail page). - Assessores is the reference — its UI doesn't change. Related #374
This commit is contained in:
parent
896d957497
commit
84abfa1a7e
1 changed files with 36 additions and 23 deletions
|
|
@ -1,49 +1,62 @@
|
|||
# Generalizar editor e display das colunas de relação na lista de municípios
|
||||
|
||||
Status: ready
|
||||
Atualizado em: 2026-08-04
|
||||
Atualizado em: 2026-08-05
|
||||
Issue: #374
|
||||
Priority: P2
|
||||
Model: composer-2.5
|
||||
Impeccable: B — encaixe em `MunicipalityList` (`/campanha/municipios`); colunas já existentes (Assessores, Lideranças, Dobradinhas); sem rota nova
|
||||
Canvas UI: N/A — consistência visual sobre padrões já em produção; o "antes" e "depois" são variações mínimas do mesmo elemento
|
||||
Impeccable: B — encaixe em `MunicipalityList` (`/campanha/municipios`); colunas já existentes (Assessores, Lideranças, Dobradinhas); sem rota nova; a UI de Dobradinhas e Lideranças muda para igualar a de Assessores, mas os padrões visuais já estão em produção
|
||||
Canvas UI: N/A — os padrões visuais de referência já existem em produção na coluna de Assessores (popover `CampaignCellEditOverlay` + Command + chips + criar inline; avatar stack `-space-x-2` com iniciais + tooltip); esta entrega replica esses mesmos padrões nas colunas de Dobradinhas e Lideranças, sem criar design novo
|
||||
Appetite: ~0,75 dia eng; extração de 2 componentes compartilhados + swap nos 3 call sites; sem migration, sem endpoint novo, sem collection
|
||||
Responsável: —
|
||||
|
||||
## Intenção
|
||||
|
||||
Hoje, na lista de municípios (`/campanha/municipios`), três colunas fazem a mesma coisa — editar relações N:N inline — mas cada uma implementa do seu jeito:
|
||||
Hoje, na lista de municípios (`/campanha/municipios`), três colunas fazem a mesma coisa — editar relações N:N inline — mas cada uma tem UI diferente. O usuário vê inconsistência:
|
||||
|
||||
| Coluna | Editor (popover) | Display (view-only) |
|
||||
| --------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| **Assessores** | `MunicipalityListAdvisorsControl` — `CampaignCellEditOverlay` + Command + chips + criar inline | `MunicipalityAdvisorAvatarStack` — círculos com iniciais + tooltip |
|
||||
| **Lideranças** | `MunicipalityListLeadershipsControl` — `CampaignCellEditOverlay` + Command + chips + criar inline (name+phone) | ❌ _não tem_ — os chips de texto servem de trigger e display ao mesmo tempo |
|
||||
| **Dobradinhas** | `MunicipalityStateDeputyRelationCell` sobre `RelationChipCell` — máquina de interação diferente dos outros dois | `StateDeputyAvatarStack` — círculos com iniciais (filtradas de partido) + tooltip |
|
||||
| Coluna | Editor (popover) | Display (view-only) |
|
||||
| --------------- | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
|
||||
| **Assessores** | `CampaignCellEditOverlay` + Command + chips + criar inline | Avatar stack (círculos com iniciais, `-space-x-2`, tooltip com nomes) — **referência** |
|
||||
| **Lideranças** | `CampaignCellEditOverlay` + Command + chips + criar inline | ❌ _não tem_ — os chips de texto de edição fazem as vezes de display; visual diferente |
|
||||
| **Dobradinhas** | `RelationChipCell` — máquina de interação visualmente diferente (outro container, outra affordance de busca) | Avatar stack (igual ao de assessores, mas implementação separada) |
|
||||
|
||||
O código duplicado já está doendo: `MunicipalityListAdvisorsControl` (431 linhas) e `MunicipalityListLeadershipsControl` (530 linhas) são irmãs estruturais — mesma máquina de estado (otimista, sequência de request, pendingCountRef, toggle, criar inline), mesmo Command+combobox, mesmo `CampaignCellEditOverlay`. A dobradinha usa um container diferente (`RelationChipCell` em trigger mode) que replica a mesma experiência com outra API.
|
||||
O código duplicado é sintoma do desalinhamento: `MunicipalityListAdvisorsControl` (431 linhas) e `MunicipalityListLeadershipsControl` (530 linhas) são irmãs estruturais — mesma máquina de estado, mesmo Command, mesmo overlay. A dobradinha usa um container completamente diferente (`RelationChipCell`) que entrega uma experiência de edição distinta da que o usuário encontra nas outras duas colunas. E no display, o avatar stack de assessores e o de dobradinhas são o mesmo componente escrito duas vezes, enquanto lideranças sequer tem display próprio.
|
||||
|
||||
E no display, o avatar stack de assessores e o de dobradinhas são o mesmo componente escrito duas vezes, enquanto lideranças nem display tem — o trigger com Badges de texto serve de readout e de affordance de edição ao mesmo tempo.
|
||||
**O pedido é alinhar a UI**: as três colunas devem parecer e funcionar iguais para o usuário. A coluna de **Assessores** é a referência — as outras duas mudam para igualá-la.
|
||||
|
||||
**O pedido é alinhar**: um editor compartilhado para as três colunas, e um display (avatar stack) compartilhado para as três.
|
||||
- **Dobradinhas muda de editor:** larga `RelationChipCell` e adota o mesmo `CampaignCellEditOverlay` + Command + chips + criar inline de Assessores/Lideranças.
|
||||
- **Lideranças muda de display:** ganha o avatar stack (círculos com iniciais + tooltip) que Assessores e Dobradinhas já usam, em vez de usar os chips de edição como único readout.
|
||||
|
||||
## Persona e fluxo
|
||||
|
||||
- **Persona / contexto:** Staff da campanha (coordenação, assessores) percorrendo a lista de municípios no desktop, editando vínculos inline. O fluxo já existe e funciona — a entrega não muda comportamento, só alinha implementação.
|
||||
- **Job principal:** Editar (ou só ver) assessores, lideranças e dobradinhas de um município com a mesma affordance, sem surpresa de coluna para coluna.
|
||||
- **Fluxo desejado:** Igual ao atual. A diferença é interna: o coordenador não percebe que a coluna de Dobradinhas usa um container diferente da de Assessores — porque depois desta entrega, não usa mais.
|
||||
- **Persona / contexto:** Staff da campanha (coordenação, assessores) percorrendo a lista de municípios no desktop, editando vínculos inline.
|
||||
- **Job principal:** Editar (ou só ver) assessores, lideranças e dobradinhas de um município com a **mesma UI** nas três colunas. Hoje cada coluna tem uma aparência e interação diferente — o usuário reaprende a cada coluna.
|
||||
- **Fluxo desejado:** O usuário clica no gatilho de qualquer uma das três colunas e encontra o mesmo popover (`CampaignCellEditOverlay` com Command de busca + chips removíveis + criar inline). Fechado, vê o mesmo display de avatar stack com tooltip. A experiência é idêntica de coluna para coluna — a única diferença é o domínio (assessor, liderança, dobradinha) e o texto dos labels.
|
||||
- **Mudanças visíveis para o usuário:**
|
||||
- **Dobradinhas:** o editor popover muda — deixa de ser o container `RelationChipCell` e passa a ser o mesmo `CampaignCellEditOverlay` + Command + chips que Assessores e Lideranças usam. O display (avatar stack) já está alinhado e não muda.
|
||||
- **Lideranças:** o display fechado muda — deixa de ser só os chips de texto do editor e ganha o avatar stack com círculos de iniciais + tooltip, igual a Assessores e Dobradinhas. O editor popover já está alinhado e não muda.
|
||||
- **Assessores:** não muda — é a referência que as outras duas colunas passam a seguir.
|
||||
- **Anti-goals de produto:**
|
||||
- Não é uma quarta coluna nem um editor genérico de "qualquer relação" exposto ao usuário.
|
||||
- Não é redesign do popover — o visual e a interação (Command, chips, criar inline) ficam iguais.
|
||||
- Não é redesign do popover — o visual de referência (Assessores) é mantido; as outras duas colunas são trazidas até ele.
|
||||
- Não mexe em endpoint, schema, migration, Consent, nem access control.
|
||||
|
||||
## Objetivo e aceite
|
||||
|
||||
- As três colunas (Assessores, Lideranças, Dobradinhas) usam **o mesmo componente de popover de edição**, extraído das implementações atuais de assessores e lideranças.
|
||||
- As três colunas usam **o mesmo componente de display** (avatar stack) para o estado fechado/view-only, extraído das implementações atuais de assessores e dobradinhas.
|
||||
- Nenhuma regressão de comportamento: criar inline, remover chip, busca com acento, estado otimista, tratamento de erro e mensagens de toast continuam iguais por coluna.
|
||||
- O contrato de props de `MunicipalityList` não muda (as colunas continuam recebendo `advisorOptions`, `leadershipOptions`, `stateDeputyOptions`, etc.).
|
||||
- A coluna de dobradinhas deixa de usar `RelationChipCell` e passa a usar o popover compartilhado — a migração é interna, sem quebra de API pública.
|
||||
- `MunicipalityListLeadershipsControl` ganha um display view-only (avatar stack), mesmo que hoje a coluna só seja visível para staff que edita — a peça existe e o contrato fica completo.
|
||||
**Alinhamento de UI (visível para o usuário):**
|
||||
|
||||
- A coluna de **Dobradinhas** tem o mesmo popover de edição que Assessores e Lideranças: `CampaignCellEditOverlay` + Command de busca + chips removíveis + criar inline. O usuário vê a mesma UI ao editar qualquer uma das três.
|
||||
- A coluna de **Lideranças** tem o mesmo display fechado que Assessores e Dobradinhas: avatar stack com círculos de iniciais (`-space-x-2`, máx. 3) + tooltip com nomes. O usuário vê a mesma UI nas três colunas fechadas.
|
||||
- A coluna de **Assessores** é a referência — sua UI não muda; as outras duas são trazidas até ela.
|
||||
|
||||
**Alinhamento de código (interno):**
|
||||
|
||||
- As três colunas usam **o mesmo componente de popover de edição**, extraído das implementações atuais de assessores e lideranças.
|
||||
- As três colunas usam **o mesmo componente de display** (avatar stack), extraído das implementações atuais de assessores e dobradinhas.
|
||||
- Nenhuma regressão funcional por coluna: criar inline (só nome; o telefone da liderança pode ser adicionado depois na ficha), remover chip, busca com acento, estado otimista, tratamento de erro e mensagens de toast continuam funcionando.
|
||||
- O contrato de props de `MunicipalityList` não muda.
|
||||
- A coluna de dobradinhas deixa de usar `RelationChipCell` e passa a usar o popover compartilhado.
|
||||
- `MunicipalityListLeadershipsControl` ganha display view-only (avatar stack), mesmo que hoje a coluna só seja visível para staff que edita — a peça existe e o contrato fica completo.
|
||||
|
||||
## Dados (intenção)
|
||||
|
||||
|
|
@ -52,7 +65,7 @@ Dados: N/A — refactor de UI sem métrica, série, ranking ou consulta nova.
|
|||
## Direção no codebase (hipótese)
|
||||
|
||||
- **Áreas prováveis:**
|
||||
- Novo componente shared: `src/components/campaign/shared/MunicipalityRelationEditor.tsx` — extrai a máquina de estado (otimista, sequência, pendingCountRef, toggle, inline create) de `MunicipalityListAdvisorsControl` + `MunicipalityListLeadershipsControl`, parametrizada por: endpoint, opções, labels/copy, build da trigger, e forma de criar inline (só nome vs. nome+telefone vs. nome+partido).
|
||||
- Novo componente shared: `src/components/campaign/shared/MunicipalityRelationEditor.tsx` — extrai a máquina de estado (otimista, sequência, pendingCountRef, toggle, inline create) de `MunicipalityListAdvisorsControl` + `MunicipalityListLeadershipsControl`, parametrizada por: endpoint, opções, labels/copy, build da trigger. O criar inline é sempre só nome (o telefone da liderança, se necessário, é adicionado depois na ficha).
|
||||
- Novo componente shared: `src/components/campaign/shared/MunicipalityRelationAvatarStack.tsx` — unifica `MunicipalityAdvisorAvatarStack` (73 linhas) e `StateDeputyAvatarStack` (~15 linhas dentro de `MunicipalityStateDeputyRelationCell`), parametrizada por: função de iniciais, tooltip, empty state.
|
||||
- `MunicipalityListAdvisorsControl.tsx` → wrapper fino sobre `MunicipalityRelationEditor`.
|
||||
- `MunicipalityListLeadershipsControl.tsx` → wrapper fino sobre `MunicipalityRelationEditor` + ganha display view-only com `MunicipalityRelationAvatarStack`.
|
||||
|
|
|
|||
Loading…
Reference in a new issue