feat(kit-builder): liga undo/redo + limpeza de gravação morta + correções de gate#403
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughMigração do undo/redo do kit builder para snapshots completos e restauráveis, com auto-registro de mudanças via ChangesKit Builder Snapshot-Based Undo/Redo
Pricing Simulator UI Cleanup
Supporting Changes
Sequence Diagram(s)Não aplicável: as mudanças não introduzem novo fluxo de componentes. O refactor de undo/redo é principalmente uma mudança de shape de dados e wiring interno com auto-registro via Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Reasoning: Mudanças heterogêneas em três áreas (kit builder undo/redo refactor com lógica de snapshot, remoção de componentes UI pricing de 570 linhas, type workarounds e adapter tweaks). O refactor de undo/redo é o mais denso, envolvendo contrato novo de dados, wiring em múltiplos hooks e testes. Remoções UI são diretas mas requerem validação de impacto em dependências. Type workarounds e adapter são simples logicamente mas demandam compreensão de context. Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
There was a problem hiding this comment.
Pull request overview
Este PR dá continuidade aos follow-ups da auditoria de QA, reativando o undo/redo do kit-builder com snapshots restauráveis, removendo componentes de pricing simulador que estavam mortos/não alcançáveis, corrigindo a derivação de margem no adapter de preço e destravando gates de TypeScript/ESLint via ajustes pontuais.
Changes:
- Kit-builder: snapshots completos + integração do push-on-change e aplicação de snapshots no undo/redo; testes estendidos para dedupe/undo/redo.
- Pricing:
margin_percentpassa a ser derivado corretamente a partir demarkup_percentnoprice-response.adapter. - Higiene/gates: remoção de componentes mortos do simulador + ajuste de types em
useUserManagementcomuntypedFrom, e recaptura do.eslint-baseline.json.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/hooks/useKitBuilder-extended.test.ts | Amplia cobertura do undo/redo (push inicial, dedupe, undo/redo). |
| src/hooks/kit-builder/useKitUndoRedo.ts | Troca snapshot lossy por snapshot completo e expõe isRestoring. |
| src/hooks/kit-builder/useKitBuilderPageState.ts | Passa a capturar snapshots on-change e reaplica snapshot no undo/redo. |
| src/hooks/kit-builder/useKitBuilder.ts | Adiciona restoreKitSnapshot para restaurar estado sem forçar step “summary”. |
| src/lib/personalization/adapters/price-response.adapter.ts | Corrige margin_percent derivando margem real a partir de markup. |
| src/components/pricing/simulator/QuantityAndResult.tsx | Remove componente morto. |
| src/components/pricing/simulator/PriceResultV51.tsx | Remove componente morto. |
| src/components/pricing/simulator/index.ts | Remove exports dos componentes deletados. |
| src/components/admin/users/useUserManagement.ts | Evita drift de tipos com untypedFrom('profiles') para embed user_roles(role). |
| .eslint-baseline.json | Recaptura baseline e remove entradas de arquivos deletados/absorve drift pré-existente. |
Comments suppressed due to low confidence (1)
src/hooks/kit-builder/useKitUndoRedo.ts:72
redo()adiciona snapshots emhistorysem respeitarMAX_HISTORY. Após muitos redo’s (ou undo/redo alternado),historypode crescer indefinidamente ecanUndo/dedupe passam a operar sobre um array maior do que o limite pretendido. Aplique o mesmo truncamento (shift) usado empushSnapshotao fazersetHistorynoredo().
const redo = useCallback((): KitSnapshot | null => {
if (future.length === 0) return null;
isRestoringRef.current = true;
const [next, ...rest] = future;
setFuture(rest);
setHistory((prev) => [...prev, next]);
setTimeout(() => {
isRestoringRef.current = false;
}, 100);
return next;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| setFuture((f) => [current, ...f]); | ||
| setTimeout(() => { | ||
| isRestoringRef.current = false; | ||
| }, 100); | ||
| return prev; |
| const redo = useCallback((): KitSnapshot | null => { | ||
| if (future.length === 0) return null; | ||
| isRestoringRef.current = true; | ||
| const [next, ...rest] = future; |
…argem latente Itens de follow-up da auditoria de QA (PR #332). 1. Undo/redo do kit-builder agora FUNCIONA (antes: botões sempre desabilitados) - pushSnapshot nunca era chamado → history vazio → canUndo sempre false; e undo()/redo() devolviam snapshots que ninguém aplicava de volta. - Snapshot passa a guardar estado COMPLETO restaurável (KitSnapshot) em vez da versão lossy (boxId/keys). - Novo useKitBuilder.restoreKitSnapshot aplica o snapshot SEM forçar o passo "summary" (diferente do loadKit). useKitBuilderPageState faz push-on-change (com guard isRestoring) e aplica o snapshot no undo/redo. - Testes unitários cobrindo push/dedup/undo/redo (15/15 verdes). 2. Remove componentes mortos PriceResultV51 + QuantityAndResult (+ exports do barrel). Eram os ÚNICOS lugares que exibiam o margin=markup e o preco_minimo_unitario=0; sem renderizadores (confirmado: nenhum importador). NOTA: o resto da "cadeia" (useGravacaoV2.ts, tipo CustomizationPriceV2, useGravacaoPriceV2) é ALCANÇÁVEL (via /simulador-precos → MultiEngravingResult) e/ou testado — mantido. 3. Corrige conflação margem×markup no adapter ALCANÇÁVEL (price-response.adapter): margin_percent agora é margem real derivada (markupToMargin), não mais um alias do markup. Não é exibido hoje, mas deixa o marginPercent do wizard correto caso seja exibido.
…nt + recaptura eslint baseline A branch (rebased em main) tropeçava em drift pré-existente de baseline ao rodar os gates, nenhum funcionalmente causado por este PR: 1. useUserManagement.ts (TS2589 + TS2352): o embed `user_roles(role)` depende da relação profiles↔user_roles, AUSENTE no types.ts gerado → SelectQueryError + instanciação profunda. Mesma família de drift do types.ts do #332. Corrigido na raiz com untypedFrom('profiles') (idiomático do projeto; query idêntica em runtime) — elimina os 2 erros de forma determinística, sem baselinar TS2589. 2. .eslint-baseline.json recapturado (127→124): absorve drift pré-existente (CoverageInsightsDashboardPage no-non-null-assertion) e remove entradas dos 2 componentes mortos deletados neste PR. CoverageInsights é de um arquivo NÃO tocado aqui — drift de merges anteriores sem regen do baseline.
7ac1353 to
60a786b
Compare
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/admin/users/useUserManagement.ts (1)
44-52:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFaça narrowing de
primaryRoleantes de atribuirrole(evite cast direto)Em
src/components/admin/users/useUserManagement.ts(linhas 44-52),primaryRolevem comostringdountypedFrom; o(primaryRole as AppRole)ignora valores fora do union.AppRolehoje é"dev" | "supervisor" | "vendedor" | "agente" | "coordenador" | "admin" | "manager"(src/lib/roles.ts). Valide contra o conjunto permitido (ex: chaves deROLE_VISUAL/array deAppRole) e aplique fallback seguro (ex:'vendedor').🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/admin/users/useUserManagement.ts` around lines 44 - 52, O campo role está a receber (primaryRole as AppRole) diretamente; faça narrowing validando primaryRole contra o conjunto permitido antes da atribuição — por exemplo verificar se primaryRole é uma das strings de AppRole (usar o array/const exportado que contém os valores válidos, ex. ROLE_VISUAL ou um array de AppRole) e só então atribuir role = primaryRole, caso contrário usar o fallback 'vendedor'; ajuste a lógica dentro de useUserManagement.ts onde primaryRole e role são calculados para remover o cast direto e aplicar essa validação segura.src/hooks/kit-builder/useKitUndoRedo.ts (1)
34-40:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
pushSnapshotestá limpandoredomesmo quando o snapshot é deduplicadoEm Line 34 você retorna o histórico sem alteração para snapshots idênticos, mas em Line 39
setFuture([])roda sempre. Isso apaga o stack de redo sem haver novo estado real.Diff sugerido
const pushSnapshot = useCallback((snapshot: KitSnapshot) => { if (isRestoringRef.current) return; - setHistory((prev) => { + let didPush = false; + setHistory((prev) => { const last = prev[prev.length - 1]; if (last && JSON.stringify(last) === JSON.stringify(snapshot)) return prev; + didPush = true; const next = [...prev, snapshot]; if (next.length > MAX_HISTORY) next.shift(); return next; }); - setFuture([]); + if (didPush) setFuture([]); }, []);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/hooks/kit-builder/useKitUndoRedo.ts` around lines 34 - 40, A função pushSnapshot atualmente retorna sem alterar o histórico quando o último snapshot é idêntico (comparação JSON), mas sempre chama setFuture([]), o que limpa o stack de redo mesmo sem mudança real; altere pushSnapshot (useKitUndoRedo.ts) para primeiro determinar se o snapshot será adicionado (por ex. dentro do setHistory callback checar `last` vs `snapshot`), e só chamar setFuture([]) quando realmente adicionou o snapshot (ou seja, quando a array `history` foi alterada e potencialmente truncada por MAX_HISTORY); referências-chave: pushSnapshot, setHistory, setFuture, MAX_HISTORY, last, snapshot.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/components/admin/users/useUserManagement.ts`:
- Around line 44-52: O campo role está a receber (primaryRole as AppRole)
diretamente; faça narrowing validando primaryRole contra o conjunto permitido
antes da atribuição — por exemplo verificar se primaryRole é uma das strings de
AppRole (usar o array/const exportado que contém os valores válidos, ex.
ROLE_VISUAL ou um array de AppRole) e só então atribuir role = primaryRole, caso
contrário usar o fallback 'vendedor'; ajuste a lógica dentro de
useUserManagement.ts onde primaryRole e role são calculados para remover o cast
direto e aplicar essa validação segura.
In `@src/hooks/kit-builder/useKitUndoRedo.ts`:
- Around line 34-40: A função pushSnapshot atualmente retorna sem alterar o
histórico quando o último snapshot é idêntico (comparação JSON), mas sempre
chama setFuture([]), o que limpa o stack de redo mesmo sem mudança real; altere
pushSnapshot (useKitUndoRedo.ts) para primeiro determinar se o snapshot será
adicionado (por ex. dentro do setHistory callback checar `last` vs `snapshot`),
e só chamar setFuture([]) quando realmente adicionou o snapshot (ou seja, quando
a array `history` foi alterada e potencialmente truncada por MAX_HISTORY);
referências-chave: pushSnapshot, setHistory, setFuture, MAX_HISTORY, last,
snapshot.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 52d28d4e-0eef-4cf8-83d8-aee8d2d401c9
📒 Files selected for processing (10)
.eslint-baseline.jsonsrc/components/admin/users/useUserManagement.tssrc/components/pricing/simulator/PriceResultV51.tsxsrc/components/pricing/simulator/QuantityAndResult.tsxsrc/components/pricing/simulator/index.tssrc/hooks/kit-builder/useKitBuilder.tssrc/hooks/kit-builder/useKitBuilderPageState.tssrc/hooks/kit-builder/useKitUndoRedo.tssrc/lib/personalization/adapters/price-response.adapter.tstests/hooks/useKitBuilder-extended.test.ts
💤 Files with no reviewable changes (3)
- src/components/pricing/simulator/index.ts
- src/components/pricing/simulator/PriceResultV51.tsx
- src/components/pricing/simulator/QuantityAndResult.tsx
Follow-ups da auditoria de QA (continuação do #332)
Ataca os 3 itens reportados-mas-não-corrigidos no #332. Descoberta importante durante a investigação: 2 dos 3 itens estavam em código não-alcançável, então a abordagem foi ajustada (e aprovada) para entregar valor real em vez de polir tela morta.
Validação: tsc baseline
486→484(drift positivo, zero regressão) · ESLint gate verde · testes das áreas tocadas verdes (kit-builder 15/15 + gravação/simulação 35/35).1. 🟢 Undo/Redo do kit-builder agora FUNCIONA (era feature morta)
Rota
/montador-kits— os botões Desfazer/Refazer estavam permanentemente desabilitados:pushSnapshotnunca era chamado →historyvazio →canUndosemprefalse; eundo()/redo()devolviam snapshots que ninguém reaplicava.boxId/keys) — não permitia restaurar fielmente.Fix:
KitSnapshotagora guarda estado completo restaurável; novouseKitBuilder.restoreKitSnapshotaplica o snapshot sem forçar o passo "summary" (diferente doloadKit);useKitBuilderPageStatefaz push-on-change (com guardisRestoring) e reaplica no undo/redo. Testes unitários cobrindo push/dedup/undo/redo.2. 🧹 Remoção de 2 componentes mortos + correção de premissa
Os componentes
PriceResultV51eQuantityAndResulteram os únicos lugares que exibiam omargin=markupe opreco_minimo_unitario=0— e não têm renderizadores (confirmado: zero importadores). Removidos + exports do barrel.Correção da premissa do #332: o restante da "cadeia de gravação" (
useGravacaoV2.ts, tipoCustomizationPriceV2,useGravacaoPriceV2) NÃO é morto — é alcançável via/simulador-precos → ProductPriceSimulator → MultiEngravingResulte/ou coberto por testes. Mantido intacto. (A análise de alcance anterior havia confundido o nome do arquivouseGravacaoV2.tscom um símbolo.)3. 🔢 Conflação margem×markup no adapter alcançável
price-response.adapter.tsaliasavamargin_percent = markup(markup 115% ≠ margem 53%). Agoramargin_percenté margem real derivada (markupToMargin:markup/(100+markup)*100). Não é exibido hoje, mas deixa omarginPercentdo wizard/simuladorcorreto caso seja exibido.4. 🔧 Destrava de gates (drift pré-existente, não causado por este PR)
useUserManagement.tsTS2589+TS2352: o embeduser_roles(role)depende da relaçãoprofiles↔user_rolesausente notypes.tsgerado (mesma família de drift do fix(qa): correção de 11 bugs reais — MFA bypass, fail-open RBAC, carrinho, autosave + 7 #332). Corrigido na raiz comuntypedFrom('profiles')(idiomático; query idêntica em runtime) — elimina os erros de forma determinística em vez de baselinar umTS2589frágil..eslint-baseline.jsonrecapturado (127→124): absorve drift pré-existente (CoverageInsightsDashboardPage, arquivo não tocado, de merges anteriores sem regen) + remove entradas dos 2 componentes deletados.🤖 Auditoria assistida por Claude Code. Cada mudança tem teste/gate verde; a premissa de código-morto foi verificada e corrigida no meio do caminho, não assumida.
Generated by Claude Code
Summary by cubic
Ativa undo/redo no kit‑builder com snapshots completos e restauração integrada ao estado da página. Remove componentes de simulação mortos e corrige o cálculo de margem; também elimina erros de tipos em gerenciamento de usuários.
New Features
canUndo/canRedo.restoreKitSnapshotaplica o snapshot sem trocar o passo atual; push‑on‑change com dedupe e guardisRestoring; testes cobrem push/dedup/undo/redo.Bug Fixes
PriceResultV51eQuantityAndResulte seus exports.margin_percentcorrigido no adapter: agora derivado demarkupviamarkupToMargin.TS2589/TS2352emuseUserManagementusandountypedFrom('profiles')..eslint-baseline.jsonrecapturado (limpeza de entradas removidas e drift pré-existente).Written for commit 60a786b. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
Notas de Lançamento
New Features
Bug Fixes
Refactor