mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-15 10:43:07 +00:00
Ações de ajuste (votos, tendência, atualização, liderança) agora retornam à origem ao salvar (toast + from allowlist B110 / Início), sem avançar sozinhas para outro wizard. Removidos fila de encadeamento (wizardActionChain.ts), param entry, skip/Pular (chrome mobile sempre X) e prefill de nota sem produtor. Liderança: botão pós-save 'Continuar' → 'Concluir' (origem). Sem migration.
8.5 KiB
8.5 KiB
Impl: Desfazer o encadeamento automático das ações rápidas do wizard
Status: aprovado Atualizado em: 2026-08-08 Issue: #422 Intenção: docs/plans/desfazer-encadeamento-acoes-wizard.md Appetite restante: herdado (~0,5–1 dia eng); sem migration
Leitura da intenção
- Outcome: ao concluir qualquer ação rápida de ajuste (votos, tendência, atualização, liderança), o usuário volta à origem — nunca avança sozinho para outro wizard. Chrome sem “Pular” em etapa nenhuma; “X” (sair da ação) em todas as etapas e retorna à origem. Fila encadeada,
entryActionde cadeia e “próxima etapa sugerida” pós-save não existem mais. - O que NÃO negociar: retorno à origem via
fromallowlist (B110 — manter); wizards standalone intactos; liderança continua fora (já gateada); sem migration; sem redesenhos de chassis/header; sem mexer no catálogo/FAB/strip das ações. - O que reavaliar: a “Direção no codebase” da intenção mira
wizardActionChain.ts(matriz + continue/end), os skip resolvers e as pontas de sucesso. Confirmei e ampliei: a cadeia está ativa em toda entrada, não só via deep-link —resolveWizardChainEntry(undefined, X) → Xfaz TODO wizard salvo avançar para o próximo elo (o bug reportado acontece até partindo do card do Início, sementry=). A cadeia é o único produtor deentry=. Conclusão: o caminho é remoção total, não “desativar pontas”.
Abordagem recomendada
flowchart LR
A["wizardActionChain.ts<br/>(matriz + continue + entry)"] --> D["DELETAR"]
B["skip resolvers + WIZARD_CHAIN_SKIP_LABEL<br/>(4 libs)"] --> D
C["skip UI: Chrome state, MobileTopBar,<br/>Shell trailingAction, Wizard*SkipTrailing"] --> D
E["Fusão em campaignActionRoutes.ts:<br/>wizardReturnHref (ex chainEnd) +<br/>wizardPreviousHref (só passos internos)"] --> F["5 componentes + page.tsx:<br/>sucesso → router.push(wizardReturnHref)<br/>sem skips, sem entryAction"] --> G["Tests: unit + e2e"]
Opções consideradas: A (neutralizar sem limpar) | B (remoção total) | C (B + manter prefill notePrefill)
Recomendação: B — porque:
- A aceita de produto diz “limpeza total do plumbing/código morto é decisão de implementação” e “o resultado não pode ter 'Pular'/fila morta aparente”.
- A cadeia é o único produtor de
entry=,notePrefill,voteFrom/voteTo(verifiquei: nenhuma registry passa esses params hoje). Manter o plumbing = código morto que oknip/tscvão apontar + “dois sistemas de navegação” que a intenção proíbe. - B é mecanicamente pequeno (módulos pequenos, call sites enumerados).
Rejeitadas: A porque deixa o módulo cadeia órfão e o smash do
skipno chrome vivo (fila morta visível); C porque manternotePrefillsem produtor é especulação (adapter com 1 call site).
Componentes / mudanças
src/lib/wizardActionChain.ts→ deletar arquivo inteiro.wizardReturnHref(exwizardChainEndHref; allowlist B110 → senãoCAMPAIGN_HOME) ewizardPreviousHref(só passos internos; cair a ramificação de elo da cadeia) migram para o módulo profundo que já constrói URIs de wizard —src/lib/campaignActionRoutes.ts(evita umwizardNavigation.tsraso; sem ciclo).src/lib/campaignActionRoutes.ts: removerWIZARD_ENTRY_ACTION_QUERY_KEY,parseWizardEntryActionParam,WizardActionHrefOptions.entryAction, paramentryActiondewizardTrendHref,WIZARD_NOTE_PREFILL_QUERY_KEY,WIZARD_VOTE_FROM_QUERY_KEY,WIZARD_VOTE_TO_QUERY_KEY.wizardTrendHreffinal:(actionSlug, municipalitySlug?, trendStatus?, returnPath?). Manter:isWizardReturnPath/parseWizardReturnPath/appendWizardReturnPath(B110),campaignActionEntryHref,isCampaignWizardActionId,wizardActionHref(leadershipId/returnPath),parseWizardLeadershipIdParam.wizardUpdateUi.ts/politicalTrendWizardUi.ts/wizardLeadershipContract.ts/campaignWizardCopy.ts: remover*SkipAction,resolve*Skip,shouldShow*/show*,WIZARD_CHAIN_SKIP_LABEL. EmpoliticalTrendWizardUiremover tambémPoliticalTrendNotePrefillSource/buildPoliticalTrendNotePrefill/resolvePoliticalTrendNotePrefillSource(sem produtor). Manter labels/títulos eresolveWizardTrendNoteDestination(redirect pós-save RSC).- Page
acoes/[slug]/page.tsx: remover parsing deentry/prefill; ramonoteDestination === 'home'simplifica pararedirect(wizardReturnHref(returnPath)); drop de propsentryAction/prefillExtraParams/initialNote. - Componentes:
WizardExpectedVotesStep,WizardTrendNoteStep,WizardTrendChoiceStep,WizardUpdateBodyStep,WizardLeadershipStep— dropentryAction+skip; sucesso →router.push(wizardReturnHref(returnPath)).CampaignWizardShelldropskip/trailingAction;CampaignWizardChromeContextdropCampaignWizardChromeSkip/camposkip;CampaignMobileTopBarsempre X (chrome.skipsome). DeletarWizardSkipTrailing.tsx+WizardTrendSkipTrailing.tsx. - Liderança — botão flutuante pós-save: destino →
wizardReturnHref(returnPath); rótulo “Continuar” → “Concluir” (opção A recomendada; ver Rabbit holes).handleSaved(grid + dirty) inalterado. - Migration: sem migration (nenhuma mudança de schema).
- Access / Consent: nenhuma mudança.
- UI: Impeccable A/B — mudanças pontuais no chrome (remover skip) e copy; sem redesign.
Fases verificáveis
- Libs + tests de domínio — remoção em
campaignActionRoutes+ libs de wizard;wizardActionChain.ts→ deletado (helpers fundidos); reescreverwizardActionChain.unit.spec.ts→wizardNavigation-equivalent emcampaignActionRoutes.unit.spec.ts; atendertests/unititerativamente. - UI — page + 5 steps + chrome (shell/context/mobile top bar); deletar skip components; testes de componente (
wizardExpectedVotesStep.unit.spec.tsx) + e2e afetadas (campaignHomeActions.e2e.spec.ts,campaignWizardChrome.e2e.spec.ts). - Gates —
pnpm gate:fastna iteração;pnpm test:e2e:affected; entrega compnpm push(gate:ci).
Rabbit holes / Não escopo (engenharia)
- Não redesenhos de chassis/header (nenhum “X” de desktop novo — hoje o desktop só usa o shell; mobile já tem X e passa a tê-lo sempre).
- Não mexer no catálogo/FAB/strip do Início nem nas registries de quick actions (nenhuma passa
entryhoje). - Não adicionar “continuar para a próxima” pós-save (rabbit hole de produto da intenção).
- Não reter
notePrefill/voteFrom/voteTocomo “feature futura” (nenhum produtor). - Decisão em aberto para o gate humano: rótulo do botão flutuante de liderança — A) “Concluir” (recomendado: a ação terminou e sai) vs B) manter “Continuar” (menor churn, mas remete a encadeamento). Aplica-se também se o botão deve sumir (ver Riscos).
Riscos e mitigação
- Deep-link externo com
entry=antigo passa a se comportar como standalone (param ignorado) — sem guarda de URL pública; aceitável (params internos, sem contrato). E2E cobre com asserção “sem Pular mesmo comentry=stale”. - Prefill de nota de tendência some — reduz superfície; hoje sem produtor. Se o produto quiser reabrir, vira issue nova.
- E2E de tendência inexistente — preciso adicionar “mudar tendência → salvar → volta à origem” (o próprio bug reportado). Custo de login; mantenho mínimo.
- knip/tsc — enumerei todas as referências de símbolos removidos (8 arquivos de teste + 7 src); verifico
git grepantes de deletar. - Dupla navegação pós-save da tendência (redirect servidor
noteDestination==='home'+ push client) converge para a MESMA origem — comportamento já existente hoje no standalone; manter.
Aceite de engenharia
- Aceite de produto da intenção ainda coberto (sem encadeamento, sem Pular, X em toda etapa, retorno à origem, B110 mantido)
- Invariantes AGENTS/engineering-standards (sem migration; module-owner editado; copy pt-BR)
- Testes de domínio previstos (unit
wizardReturnHref/wizardPreviousHref/routes; componente votes; e2e retorno à origem para as 4 ações + tendência)
Self-score decision-quality
- Decisões caras têm rejeitadas? Sim (A/B/C explícitas, rótulo liderança aberto)
- Cabe no appetite? Sim (remoção pequena, todo call site enumerado)
- Rabbit holes nomeados? Sim
- Depth check reusa shells/helpers? Sim (funde no módulo profundo de routes; zero módulos novos rasos)
- Intenção satisfeita? Sim — engenharia remove o mecanismo, não reescreve o outcome.
Score: 5/5