Skip to content

feat(kit-builder): liga undo/redo + limpeza de gravação morta + correções de gate#403

Merged
adm01-debug merged 2 commits into
mainfrom
claude/qa-followups
May 26, 2026
Merged

feat(kit-builder): liga undo/redo + limpeza de gravação morta + correções de gate#403
adm01-debug merged 2 commits into
mainfrom
claude/qa-followups

Conversation

@adm01-debug
Copy link
Copy Markdown
Owner

@adm01-debug adm01-debug commented May 26, 2026

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:

  • pushSnapshot nunca era chamado → history vazio → canUndo sempre false; e undo()/redo() devolviam snapshots que ninguém reaplicava.
  • O snapshot era lossy (boxId/keys) — não permitia restaurar fielmente.

Fix: KitSnapshot agora guarda estado completo restaurável; novo useKitBuilder.restoreKitSnapshot aplica o snapshot sem forçar o passo "summary" (diferente do loadKit); useKitBuilderPageState faz push-on-change (com guard isRestoring) 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 PriceResultV51 e QuantityAndResult eram os únicos lugares que exibiam o margin=markup e o preco_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, tipo CustomizationPriceV2, useGravacaoPriceV2) NÃO é morto — é alcançável via /simulador-precos → ProductPriceSimulator → MultiEngravingResult e/ou coberto por testes. Mantido intacto. (A análise de alcance anterior havia confundido o nome do arquivo useGravacaoV2.ts com um símbolo.)

3. 🔢 Conflação margem×markup no adapter alcançável

price-response.adapter.ts aliasava margin_percent = markup (markup 115% ≠ margem 53%). Agora margin_percent é margem real derivada (markupToMargin: markup/(100+markup)*100). Não é exibido hoje, mas deixa o marginPercent do wizard /simulador correto caso seja exibido.

4. 🔧 Destrava de gates (drift pré-existente, não causado por este PR)

  • useUserManagement.ts TS2589+TS2352: o embed user_roles(role) depende da relação profiles↔user_roles ausente no types.ts gerado (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 com untypedFrom('profiles') (idiomático; query idêntica em runtime) — elimina os erros de forma determinística em vez de baselinar um TS2589 frágil.
  • .eslint-baseline.json recapturado (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

    • Undo/redo do kit‑builder agora funciona com canUndo/canRedo.
    • Snapshots completos (nome, tipo, caixa, itens, personalização, quantidade, identidade).
    • restoreKitSnapshot aplica o snapshot sem trocar o passo atual; push‑on‑change com dedupe e guard isRestoring; testes cobrem push/dedup/undo/redo.
  • Bug Fixes

    • Removidos componentes mortos PriceResultV51 e QuantityAndResult e seus exports.
    • margin_percent corrigido no adapter: agora derivado de markup via markupToMargin.
    • Corrigidos TS2589/TS2352 em useUserManagement usando untypedFrom('profiles').
    • .eslint-baseline.json recapturado (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

    • Suporte melhorado para desfazer/refazer (undo/redo) no construtor de kits.
  • Bug Fixes

    • Correção no cálculo de margem de preço para maior precisão.
  • Refactor

    • Remoção de componentes legados e consolidação de funcionalidades.
    • Melhoria na estrutura interna de gerenciamento de estado.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
we-dream-big Ready Ready Preview, Comment May 26, 2026 2:05am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

Walkthrough

Migração do undo/redo do kit builder para snapshots completos e restauráveis, com auto-registro de mudanças via useEffect. Remoção de componentes obsoletos do pricing simulator. Ajustes em type queries de admin users, fórmula de margin calculation e baseline de lint.

Changes

Kit Builder Snapshot-Based Undo/Redo

Layer / File(s) Summary
KitSnapshot Contract and Foundation
src/hooks/kit-builder/useKitUndoRedo.ts
KitSnapshot interface substitui snapshot lossy anterior com campos completos. pushSnapshot, undo e redo retornam/aceitam KitSnapshot em vez de UndoRedoSnapshot.
useKitBuilder Snapshot Restore Action
src/hooks/kit-builder/useKitBuilder.ts
Nova ação restoreKitSnapshot(snap: KitSnapshot) aplica todos os campos do snapshot (name, type, box, items, personalization, quantity, identity) sem forçar step de wizard.
useKitBuilderPageState Auto-Snapshot Integration
src/hooks/kit-builder/useKitBuilderPageState.ts
Auto-registro de snapshots via useEffect após mudanças do kit, com flag isRestoring para evitar duplicatas. Implementa undo e redo localmente reaplicando snapshots via restoreKitSnapshot.
Snapshot and Undo/Redo Test Coverage
tests/hooks/useKitBuilder-extended.test.ts
Testes para estado inicial, habilitação de undo após segundo snapshot distinto, deduplicação de snapshots idênticos, e ciclo completo de undo/redo.

Pricing Simulator UI Cleanup

Layer / File(s) Summary
Remove Old Pricing Components and Update Barrel
src/components/pricing/simulator/PriceResultV51.tsx, src/components/pricing/simulator/QuantityAndResult.tsx, src/components/pricing/simulator/index.ts
Remoção de PriceResultV51 e QuantityAndResult (total 570 linhas). Barrel atualiza exportações: remove PriceResultV51, QuoteCodeBadge, adiciona EngravingList, MultiEngravingResult.

Supporting Changes

Layer / File(s) Summary
Admin User Management Type Workaround
src/components/admin/users/useUserManagement.ts
Hook useUserManagement usa untypedFrom('profiles') com cast para ProfileWithRoles local para evitar erros de tipo na query com user_roles embutido.
Price Response Adapter Margin Calculation
src/lib/personalization/adapters/price-response.adapter.ts
Helper markupToMargin converte markup_percent em margin_percent via fórmula markup / (100 + markup) * 100 com arredondamento, aplicado em ambos os parsers nested e flat.
ESLint Baseline Updates
.eslint-baseline.json
totalErrors reduzido de 127 para 124. Remoção de baselines para useGlobalSearch, useSellerCarts, logger; adição de baseline para CoverageInsightsDashboardPage.

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 useEffect, não envolvendo novo controle de fluxo entre múltiplos componentes.

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)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed O título descreve com precisão os três eixos principais da PR: ativação do undo/redo, remoção de código morto, e correções de gates/typagem.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/qa-followups

Comment @coderabbitai help to get the list of available commands and usage tips.

@supabase
Copy link
Copy Markdown

supabase Bot commented May 26, 2026

This pull request has been ignored for the connected project doufsxqlfjyuvxuezpln because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@adm01-debug adm01-debug marked this pull request as ready for review May 26, 2026 01:46
Copilot AI review requested due to automatic review settings May 26, 2026 01:46
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_percent passa a ser derivado corretamente a partir de markup_percent no price-response.adapter.
  • Higiene/gates: remoção de componentes mortos do simulador + ajuste de types em useUserManagement com untypedFrom, 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 em history sem respeitar MAX_HISTORY. Após muitos redo’s (ou undo/redo alternado), history pode crescer indefinidamente e canUndo/dedupe passam a operar sobre um array maior do que o limite pretendido. Aplique o mesmo truncamento (shift) usado em pushSnapshot ao fazer setHistory no redo().
  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.

Comment on lines 56 to 60
setFuture((f) => [current, ...f]);
setTimeout(() => {
isRestoringRef.current = false;
}, 100);
return prev;
Comment on lines +63 to 66
const redo = useCallback((): KitSnapshot | null => {
if (future.length === 0) return null;
isRestoringRef.current = true;
const [next, ...rest] = future;
claude added 2 commits May 25, 2026 23:01
…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.
@adm01-debug adm01-debug force-pushed the claude/qa-followups branch from 7ac1353 to 60a786b Compare May 26, 2026 02:01
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Faça narrowing de primaryRole antes de atribuir role (evite cast direto)

Em src/components/admin/users/useUserManagement.ts (linhas 44-52), primaryRole vem como string do untypedFrom; o (primaryRole as AppRole) ignora valores fora do union. AppRole hoje é "dev" | "supervisor" | "vendedor" | "agente" | "coordenador" | "admin" | "manager" (src/lib/roles.ts). Valide contra o conjunto permitido (ex: chaves de ROLE_VISUAL/array de AppRole) 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

pushSnapshot está limpando redo mesmo quando o snapshot é deduplicado

Em 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

📥 Commits

Reviewing files that changed from the base of the PR and between 085b8a3 and 60a786b.

📒 Files selected for processing (10)
  • .eslint-baseline.json
  • src/components/admin/users/useUserManagement.ts
  • src/components/pricing/simulator/PriceResultV51.tsx
  • src/components/pricing/simulator/QuantityAndResult.tsx
  • src/components/pricing/simulator/index.ts
  • src/hooks/kit-builder/useKitBuilder.ts
  • src/hooks/kit-builder/useKitBuilderPageState.ts
  • src/hooks/kit-builder/useKitUndoRedo.ts
  • src/lib/personalization/adapters/price-response.adapter.ts
  • tests/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

@adm01-debug adm01-debug merged commit a50919e into main May 26, 2026
42 of 47 checks passed
@adm01-debug adm01-debug deleted the claude/qa-followups branch May 29, 2026 14:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants