Organization stays by product decision (political branching, e.g. SindMed); the leadership gains `exclusive` (default true) with list badge and form checkbox, and sector/sectorNotes/consentNote leave the collection, zod, forms, list filters/sort, invite autofill and redemption.
9.3 KiB
Simplificar modelo de liderança (exclusivo + limpeza)
Status: entregue 2026-07-30 (org permanece — ver revisão)
Atualizado em: 2026-07-30
Item do roadmap: docs/roadmap.md (Trilha B, item B69 — UX-1 / A4)
Impeccable: B — schema + forms/lista/convite existentes; UI de grid do wizard = B70
Appetite: ~1–1,25 dia eng; uma migration (drop + exclusive); zod/collection/UI lista/forms/invite
Responsável: —
Revisão 2026-07-30 (decisão de produto, pré-implementação): organization permanece — o conceito mapeia como as relações políticas se ramificam na região (várias lideranças na mesma org, ex. SindMed). O escopo final dropou apenas sector/sectorNotes/consentNote; a vertical /campanha/organizacoes, o join leadership.organizations, badges/colunas/contadores e activity.organizations ficam intactos. Confirmado na mesma sessão: exclusive aparece na lista (badge "Não exclusivo") + toggle nos forms; coluna Organizações continua texto simples (melhoria vira fill-in).
Design (Impeccable)
Âncoras: PRODUCT.md / DESIGN.md · tema campaign. Superfícies tocadas = ficha/lista/convite já no Field Desk — craft compacto, não shape de rota nova.
Na implementação: craft compacto → critique → polish.
Brief compacto (B, direção clara):
- Persona: CG/assessor atualizando rede no ritual A4; formulário longo = abandono.
- Job principal: gravar só o que a mesa usa no dia a dia — contato, status, observação, exclusividade — sem setor/org/consentimento externo.
- Estratégia de cor: Restrained.
- Edit where you see: sim nas superfícies existentes (B32 status; forms
/liderancas); exclusividade entra nos forms internos + no form do B70. - Anti-goals: segundo cadastro de pessoa; dropar Consent do convite LGPD; inventar join exclusividade×município nesta fatia.
Dados → decisão → apresentação
Dados: N/A como métrica nova — boolean categórico + remoção de campos. Decisão = “esta liderança ainda articula só conosco?” (sim/não) e menos atrito de cadastro.
Contexto
leadership (src/collections/Leadership.ts) carrega hoje: organizations, sector/sectorNotes, consentNote (“Registro de consentimento externo”), além de supportStatus, notes, stateDeputies, municípios e o trio de Consent do convite (consent / consentContentHash / consentedAt).
Pedido de produto (2026-07-29), no pacote A4 / Cairu (fluxos-acao-primeiro-inicio.md), ajustado em 2026-07-30:
- Conceito de parceria exclusiva (default = exclusivo): liderança que era a articuladora principal e passa a dividir votos com outro candidato deixa de ser exclusiva — e pode voltar. Não é “principal vs secundária” na v1 (ranking implícito); é exclusividade do apoio.
- Remover da mesa os conceitos pouco usados: setor (e notas de setor), registro de consentimento externo (
consentNote). Organização fica (revisão 2026-07-30): ramificação das relações políticas — várias lideranças na mesma org (SindMed). - “A própria liderança é a dobradinha” —
stateDeputyhoje é entidade por nome (semContact);leadershiptemContactúnico. Não unificar collections neste item.
Lista /campanha/liderancas já filtra/ordena por sector (B29 ✓). Invite autofill ainda pede sector/sectorNotes.
Objetivos
- Migration
20260730_043306_simplify_leadership_fields:- DROP
sector,sector_notes,consent_note(+enum_leadership_sector). - ADD
exclusiveboolean NOT NULL DEFAULT true (backfill implícito = todos nascem exclusivos — honesto com o default de produto). Gerada em duas passadas não-interativas (drop, depois add) e fundida à mão — o prompt interativo de rename trava sem TTY; oNOT NULLfoi emendado sobre o SQL gerado.
- DROP
- Collection + zod (
src/lib/schemas/leadership.ts): espelhado;exclusivestaff-managed comosupportStatus/notes. - Removido de create/internal forms, list columns/filters/sort de setor, badges de setor no dossiê;
sector/sectorNotesfora dos view models. - Invite:
sector/sectorNotesfora do schema +CampaignInviteForm+ redemption profile write (o trioconsent*do LGPD do convite intacto). - Lista: coluna setor → coluna "Apoio exclusivo" com badge outline "Não exclusivo" só quando
false(Restrained; badge não compete com os vermelhos da linha). - Checkbox padrão-marcado + input hidden "false" no form de criação (último valor vence), para que desmarcar grave
falsee ausência total da chave caia no default do zod — pin de int cobre os três caminhos. - Sem Consent novo. Sem UI de grid do wizard (B70).
- Unit/int: create default
exclusive: true; update parafalse;?sector=legado canonicaliza fora; invite sem setor.
Decisões travadas
- Campo
exclusive: boolean, defaulttrue, no documentoleadership. Rejeitado:principal/prioritaria(sugerem ranking 1º/2º, não o relato “dividiu apoio”); exclusividade por par liderança×município nesta fatia (caro — join/metadata; o relato do CG é sobre a parceria com a campanha, não nuance A vs B). Gatilho abaixo se a mesma pessoa precisar ser exclusiva em um município e não em outro. - Dropar
sector,sectorNotes,consentNote. Rejeitado: deixar opcionais “por se acaso” (campos mortos travam atualização); dropar o trioconsent*do convite (é LGPDlideranca-autopreenchimento, Onda 0 — distinto doconsentNoteexterno). organizationPERMANECE (revisão 2026-07-30, produto). O rascunho dropava o join; revertido — a org mapeia ramificações políticas (SindMed com várias lideranças). Rejeitado na revisão: remover a vertical/campanha/organizacoesinteira (avaliada e descartada pelo produto na conversa); droparactivity.organizationsjunto.- “Liderança é a dobradinha” = reusar
stateDeputy+leadership.stateDeputies. Criar/vincular a ficha de dobradinha com o nome da pessoa; chips B31 ✓ já expressam a rede. Rejeitado: collection unificada;Contactobrigatório emstateDeputyagora; flagactsAsStateDeputysem entity (segunda verdade). Atalho “criar dobradinha a partir desta liderança” → Adiado. - i18n: identifier
exclusive; copy “Apoio exclusivo” / “Não exclusivo”.
Questões em aberto
Badge “Não exclusivo” na listaFechado 2026-07-30 (produto): na lista — coluna própria com badge outline só quando/liderancasneste item ou só no B70?false.- Exclusividade por município? Opções: A documento (v1) | B join. Recomendação: A; revisitação no Adiado. (assumido — validar com produto se Cairu tiver o mesmo nome em dois municípios com papéis diferentes)
Abordagem proposta
flowchart LR
Mig["migration DROP + exclusive"] --> Zod["zod + Leadership.ts"]
Zod --> UI["forms + lista + invite"]
Componentes (como entregue):
- Migration +
Leadership.ts+src/lib/schemas/leadership.ts+ invite schema. LeadershipForm/LeadershipInternalForm— remover setor/consentNote; checkboxexclusive(default on; hidden "false" na criação).liderancas/page.tsx+leadershipListUrl/ filters — droparsector; coluna "Apoio exclusivo".leadershipData.ts— view models sem setor/sectorNotes/consentNote; incluirexclusive(orgs mantidas).CampaignInviteForm+ redemption + page data — sem setor.- Migration: sim (
20260730_043306_simplify_leadership_fields, drop + add boolean default true NOT NULL).
Dependências
- Nenhuma de outro plano aberto. Soft: B29 ✓ / B31 ✓ / B32 ✓ (superfícies a limpar). Desbloqueia B70.
Não escopo
- Grid de tiles + form do wizard A4 → B70.
- Wiring “quer também liderança?” no A1 → fatia A1.
- Unificar
stateDeputycomContact/ atalho criar-dobradinha → Adiado. - Collection
organizatione a vertical/campanha/organizacoes— intactas por decisão 2026-07-30 (incluileadership.organizations, badges no painel/dossiê e contadores doorganizationData).
Rabbit holes
- Exclusividade por município + histórico de mudanças. Mitigação: boolean no doc; nota em
notesse precisar matizar. - Backfill
exclusive: falsea partir de texto emnotes. Mitigação: não — default true; mesa corrige no wizard.
Adiado com gatilho
- Exclusividade por município. Revisitar quando a mesma liderança tiver papéis opostos em ≥2 municípios no mesmo ritual.
- Atalho “Criar / vincular dobradinha” a partir da ficha/wizard. Revisitar quando B70 shippar e a mesa pedir o gesto ≥2× na mesma semana.
stateDeputy.contactopcional. Revisitar se dedupe nome↔pessoa virar dor (E4R / onboarding).
Referências
- fluxos-acao-primeiro-inicio.md (A4) · simplificar-modelo-sinal.md (precedente B62) · autosave-status-lista-liderancas.md · ordenacao-filtros-lista-liderancas.md
src/collections/Leadership.ts·src/lib/schemas/leadership.ts·src/utilities/leadership/*·src/utilities/access/municipalities.ts·CampaignInviteForm.tsx- AGENTS.md — migrations; Contact único; Consent por chave (convite intacto)
PRODUCT.md/DESIGN.md