Skip to content

fix: Sprint 3 — BUG-03/05/26/27/28/29 módulo Cadastro (26/05/2026)#489

Merged
adm01-debug merged 6 commits into
mainfrom
fix/cadastro-sprint3-bugs-20260526
May 27, 2026
Merged

fix: Sprint 3 — BUG-03/05/26/27/28/29 módulo Cadastro (26/05/2026)#489
adm01-debug merged 6 commits into
mainfrom
fix/cadastro-sprint3-bugs-20260526

Conversation

@adm01-debug
Copy link
Copy Markdown
Owner

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

Resumo

Sprint 3 do módulo Cadastro. Completa a auditoria iniciada na PR #488, resolvendo os 5 bugs marcados como pendentes.


Commits (5)

Arquivo Bug(s) Descrição
useEngravingWizard.ts BUG-03/28 flushLocalAreas + warn técnica ausente + sync ref via useEffect
ProductEngravingSection.tsx BUG-03/05 Prop engravingFlushRef + AlertDialog para excluir área
ProductFormStepContent.tsx BUG-03 Passa engravingFlushRef para ProductEngravingSection
ProductFormFullscreen.tsx BUG-03 Prop engravingFlushRef threaded até ProductFormStepContent
AdminProductFormPage.tsx BUG-03 Cria ref + chama flushLocalAreas(newProduct.id) antes do navigate()
useProductsManager.ts BUG-26/27/29 selectedOnPageLabel, handlePageChange com filtros, comentário useEffect

🔴 BUG-03 — Gravações perdidas ao criar novo produto (CRÍTICO)

Causa: Áreas de gravação configuradas no wizard antes de salvar ficavam em localAreas com product_id='pending'. Quando o produto era criado e a página navegava para edit mode, o componente desmontava e as áreas eram perdidas.

Fix (chain completa):

AdminProductFormPage
  engravingFlushRef = useRef(null)  ← cria o ref
  ↓ prop engravingFlushRef
  ProductFormFullscreen
    ↓ prop engravingFlushRef
    ProductFormStepContent (case 'engraving')
      ↓ prop engravingFlushRef
      ProductEngravingSection
        useEffect → engravingFlushRef.current = w.flushLocalAreas  ← popula

Após newProduct = await invokeExternalDbSingle(...):

if (engravingFlushRef.current) {
  await engravingFlushRef.current(newProduct.id); // persiste áreas no DB
}
navigate(`/admin/cadastros/produto/${newProduct.id}`, { replace: true });

flushLocalAreas usa localAreasRef.current (sempre atualizado via useEffect) e chama external-db-bridge com Promise.allSettled para cada área pendente.


🟠 BUG-05 (UI completion) — AlertDialog para excluir área de gravação

Causa: useEngravingWizard já expunha deleteAreaConfirm/confirmDeleteArea/cancelDeleteArea desde a Sprint 2, mas ProductEngravingSection.tsx não renderizava o dialog.

Fix: AlertDialog adicionado ao final do JSX, abrindo quando w.deleteAreaConfirm !== null.


🟡 BUG-26 — Label UX para seleção por página

Fix: selectedOnPageLabel adicionado ao return de useProductsManager:

selectedOnPageLabel: selectedIds.size > 0
  ? `${selectedIds.size} de ${displayedProducts.length} selecionado(s) nesta página`
  : null,

UI pode exibir este label no header de seleção bulk para evitar confusão com "selecionar todos do catálogo".

🟢 BUG-27 — handlePageChange não passava advancedFilters

Fix:

// Antes:
fetchProducts(page, pageSize, searchTerm);
// Depois:
fetchProducts(page, pageSize, searchTerm, advancedFilters); // BUG-27

Filtros ativos agora persistem ao navegar entre páginas.

🟢 BUG-28 — Sem aviso quando técnica de gravação foi deletada do banco

Fix: console.warn em enrichArea quando techById.get(tabela_preco_id) retorna undefined para área salva (não local).

🟢 BUG-29 — useEffect inicial comentado

Fix: Comentário explica por que [] é intencional (fetch único no mount; valores iniciais são seguros para stale-closure).


Testes recomendados

  1. Criar novo produto → configurar 1+ áreas de gravação no wizard → salvar → entrar em edit mode → aba Gravação mostra as áreas
  2. Excluir área de gravação → AlertDialog aparece (não confirm() nativo)
  3. Filtrar produtos por categoria/fornecedor → mudar página → filtro persiste
  4. Selecionar produtos → verificar label "N de M selecionado(s) nesta página"

Summary by cubic

Corrige bugs da Sprint 3 no módulo Cadastro. Áreas de gravação não se perdem ao criar produto, exclusão tem confirmação, e paginação/filtros funcionam como esperado.

  • Bug Fixes
    • BUG-03: Persiste áreas de gravação criadas antes de salvar usando engravingFlushRef (exposto por ProductEngravingSection) e flushLocalAreas(newProduct.id) chamado em AdminProductFormPage antes do navigate(). Sincroniza localAreasRef via useEffect para evitar perda de dados.
    • BUG-05: Adiciona AlertDialog para confirmar exclusão de área (consome estado já exposto por useEngravingWizard).
    • BUG-26: Expõe selectedOnPageLabel para indicar claramente que a seleção é por página.
    • BUG-27: handlePageChange passa advancedFilters para fetchProducts, mantendo filtros ativos ao mudar de página.
    • BUG-28: enrichArea emite console.warn quando a técnica salva não existe mais no cache (provável remoção no banco).
    • BUG-29: Comentário no useEffect inicial documenta a dependência vazia intencional (fetch único no mount).

Written for commit cf9893c. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Corrigida persistência de áreas de gravação personalizadas antes de navegação
    • Melhorado comportamento de confirmação para exclusão de áreas de personalização
    • Filtros avançados agora mantidos ao navegar entre páginas de produtos
  • Refactor

    • Interface de navegação do formulário de produtos reorganizada (desktop e mobile)
    • Botões e rótulos de ação reformatados para melhor clareza
    • Barra inferior móvel agora exibe progresso de etapas

Review Change Stack

Copilot AI review requested due to automatic review settings May 26, 2026 23:07
@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.

@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 11:08pm

@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 ↗︎.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

Walkthrough

PR implementa persistência de áreas de gravação locais (BUG-03) usando ref-based callback, integra AlertDialog para confirmação de delete, e ajusta filtros de página em lista de produtos. Inclui refatorações cosméticas em ProductFormFullscreen.

Changes

Persistência de gravações locais (BUG-03)

Layer / File(s) Summary
Ref threading até ProductEngravingSection
src/pages/admin/AdminProductFormPage.tsx, src/components/admin/products/ProductFormFullscreen.tsx, src/components/admin/products/ProductFormStepContent.tsx, src/components/admin/products/sections/ProductEngravingSection.tsx
engravingFlushRef é criada em AdminProductFormPage com useRef, passada como prop através do form até ProductEngravingSection, onde useEffect vincula w.flushLocalAreas à ref para exposição ao componente pai.
Implementação de flushLocalAreas em useEngravingWizard
src/components/admin/products/sections/engraving/useEngravingWizard.ts
Nova ação flushLocalAreas(newProductId) insere todas as áreas local-* pendentes no banco via external-db-bridge usando Promise.allSettled, exibe toast de sucesso/aviso, e limpa localAreas. Estado deleteAreaConfirm (state-based) substitui antigo confirm(). Hooks de mutação (create/update/delete) condensados, enrichArea adiciona console.warn quando técnica não encontrada.
AlertDialog para confirmação de delete
src/components/admin/products/sections/ProductEngravingSection.tsx
Renderização adiciona AlertDialog controlado por w.deleteAreaConfirm, com handlers cancelDeleteArea (ao fechar/cancelar) e confirmDeleteArea (ao remover). Imports incluem useEffect e componentes de AlertDialog.
Chamada de flush após INSERT
src/pages/admin/AdminProductFormPage.tsx
Após criar produto, chama engravingFlushRef.current(newProduct.id) se disponível; falhas tratadas como não-fatais (log + toast.warning), seguido de toast.success. Refactora productToFormData e productData com padronização de nulos/booleans e parse de meta_keywords.

Filtros e seleção em produtos

Layer / File(s) Summary
Persistência de advancedFilters ao trocar página
src/components/admin/products/useProductsManager.ts
handlePageChange passa advancedFilters explicitamente a fetchProducts, mantendo filtros ativos. Adiciona selectedOnPageLabel ao retorno do hook (string quando há seleção, null caso contrário).

Refatoração cosmética de ProductFormFullscreen

Layer / File(s) Summary
Condensação de hooks e setup
src/components/admin/products/ProductFormFullscreen.tsx
useForm, useProductFormDraft, useProductSeoAI e flags object reformatados para layout compacto. Imports de icons reorganizados. Sem mudanças lógicas.
Validação, navegação e UI
src/components/admin/products/ProductFormFullscreen.tsx
stepErrors mapping, submit-with-validation early-return, e keyboard shortcuts (Ctrl+S, setas) comprimidos. Card stepper/header reescrita, botões desktop relabelados (Salvar/Criar), mobile bar atualizada com progress text e cancel icon.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Razão: Mudanças heterogêneas em 6 arquivos com lógica de persistência async, state-based confirmations, refactores de UI, e ajustes de filtro. Requer validação de Promise.allSettled em flush, não-regressão de navegação em delete, integridade de ref lifecycle, e padronização de campos em INSERT. Refactores cosméticos reduzem densidade efetiva.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 reflete com precisão as mudanças: corrige 5 bugs no módulo Cadastro, com referências explícitas aos BUGs tratados e contexto de sprint/data.
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 fix/cadastro-sprint3-bugs-20260526

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

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

Completes Sprint 3 fixes for the Cadastro products module, mainly around preserving engraving areas during new-product creation and improving product-list pagination/selection UX.

Changes:

  • Threads engravingFlushRef from the product page down to the engraving section and calls it after product creation.
  • Adds AlertDialog confirmation for engraving-area deletion.
  • Updates products manager selection label exposure and page-change filtering behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/pages/admin/AdminProductFormPage.tsx Creates and invokes the engraving flush ref before navigating after product creation.
src/components/admin/products/ProductFormFullscreen.tsx Passes the engraving flush ref through the stepper form.
src/components/admin/products/ProductFormStepContent.tsx Forwards the ref to the engraving step.
src/components/admin/products/sections/ProductEngravingSection.tsx Registers the flush callback and adds delete confirmation dialog.
src/components/admin/products/sections/engraving/useEngravingWizard.ts Adds local-area flushing and missing-technique warning.
src/components/admin/products/useProductsManager.ts Adds page-scoped selection label and passes filters on page change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +68 to +77
// BUG-03 FIX: register flushLocalAreas with the ref so AdminProductFormPage can call it
useEffect(() => {
if (engravingFlushRef) {
engravingFlushRef.current = w.flushLocalAreas;
}
return () => {
if (engravingFlushRef) {
engravingFlushRef.current = null;
}
};
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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/pages/admin/AdminProductFormPage.tsx (1)

90-147: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve supplier_product_url no carregamento do formulário.

Line 204 persiste supplier_product_url, mas productToFormData() nunca preenche esse campo. Em edição, ele cai no default '' do schema e o próximo save apaga a URL já salva.

Diff sugerido
       supplier_id: p.supplier_id ?? '',
       supplier_reference: p.supplier_reference ?? '',
+      supplier_product_url: p.supplier_product_url ?? '',
       sale_price: getProductPrice(p) ?? 0,
🤖 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/pages/admin/AdminProductFormPage.tsx` around lines 90 - 147,
productToFormData currently omits supplier_product_url so editing an existing
product overwrites the saved URL with the form schema default; update
productToFormData (the function) to include supplier_product_url:
p.supplier_product_url ?? '' so the existing value is loaded into the form and
not cleared on save.
src/components/admin/products/ProductFormFullscreen.tsx (1)

251-290: ⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

Não desmonte a etapa de gravação antes do submit.

Aqui só a etapa ativa fica montada. Como ProductEngravingSection guarda o wizard em estado local e limpa engravingFlushRef no unmount (src/components/admin/products/sections/ProductEngravingSection.tsx, Lines 68-78), sair de “Gravação” apaga as áreas locais antes do create. Na prática, o BUG-03 continua falhando se o usuário avançar para outra etapa e salvar de lá.

O conserto precisa manter esse estado vivo até o submit — por exemplo, levantando useEngravingWizard para cima do switch de etapas ou mantendo ProductEngravingSection montado fora da troca de steps.

🤖 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/products/ProductFormFullscreen.tsx` around lines 251 -
290, O componente de gravação (ProductEngravingSection) está sendo desmontado
quando a etapa muda, o que limpa engravingFlushRef e perde o estado local antes
do submit; mantenha esse estado vivo movendo a lógica do wizard para cima do
switch de etapas: levantar useEngravingWizard para ProductFormFullscreen e
passar os handlers/refs (ex: engravingFlushRef, qualquer onFlush/onSubmit do
wizard) via props para ProductFormStepContent/ProductEngravingSection, ou
alternativamente renderizar ProductEngravingSection fora do AnimatePresence
(sempre montado) e só limpar engravingFlushRef após o submit; atualize
ProductFormFullscreen (onde AnimatePresence/motion.div é usado e onde
ProductFormStepContent é instanciado) e ProductEngravingSection (onde
engravingFlushRef era limpo no unmount) para corresponder a essa abordagem.
🧹 Nitpick comments (1)
src/components/admin/products/useProductsManager.ts (1)

353-359: ⚡ Quick win

Fix do BUG-27 correto, mas falta consistência em outros call sites.

O fix está correto: passar advancedFilters explicitamente evita stale closure quando filtros mudam rapidamente. Porém, outros call sites de fetchProducts não seguem o mesmo padrão:

  • Linha 365 (handlePageSizeChange): não passa advancedFilters
  • Linha 392 (handleDelete): não passa advancedFilters
  • Linha 446 (handleBulkToggleActive): não passa advancedFilters

Funcionalmente não quebra (closure deveria estar atualizado), mas por consistência de código e manutenibilidade futura, recomendo aplicar o mesmo padrão explícito em todos os lugares.

♻️ Refactor sugerido para consistência

Linha 365 (handlePageSizeChange):

-    fetchProducts(1, size, searchTerm);
+    fetchProducts(1, size, searchTerm, advancedFilters);

Linha 392 (handleDelete):

-      fetchProducts(currentPage, pageSize, searchTerm);
+      fetchProducts(currentPage, pageSize, searchTerm, advancedFilters);

Linha 446 (handleBulkToggleActive):

-        fetchProducts(currentPage, pageSize, searchTerm);
+        fetchProducts(currentPage, pageSize, searchTerm, advancedFilters);
🤖 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/products/useProductsManager.ts` around lines 353 - 359,
The fix in handlePageChange correctly passes advancedFilters to fetchProducts to
avoid stale closures; make the same explicit change in the other call sites:
update handlePageSizeChange, handleDelete, and handleBulkToggleActive so each
call to fetchProducts includes the current advancedFilters argument (i.e., call
fetchProducts(page, pageSize, searchTerm, advancedFilters) or the equivalent
parameters for that handler) rather than relying on the closure.
🤖 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.

Inline comments:
In `@src/components/admin/products/sections/engraving/useEngravingWizard.ts`:
- Around line 204-226: The current flush clears all local areas unconditionally
(setLocalAreas([])) after Promise.allSettled, which loses areas that failed to
persist; modify the logic around Promise.allSettled/results so you identify
which items succeeded (e.g., correlate each result to the corresponding area
from areas via index or id), and only remove those successfully saved from local
state while keeping failed areas for retry; update setLocalAreas to filter out
the saved areas (or set it to the subset of failed areas) instead of clearing
everything, and keep the existing toast behavior using the computed failed
count.

In `@src/pages/admin/AdminProductFormPage.tsx`:
- Around line 176-180: When building the payload for save in
AdminProductFormPage.tsx, persist the actual kit toggle instead of deriving it
only from product_type: set is_kit from data.is_kit (falling back to the
existing product_type check if needed) and ensure product_type is set
consistently (e.g., default to 'kit' when data.is_kit is true, otherwise
'product') so the "É Kit" toggle actually reaches the backend; update the fields
around is_kit and product_type in the object construction where sale_price,
cost_price, etc. are assembled.

---

Outside diff comments:
In `@src/components/admin/products/ProductFormFullscreen.tsx`:
- Around line 251-290: O componente de gravação (ProductEngravingSection) está
sendo desmontado quando a etapa muda, o que limpa engravingFlushRef e perde o
estado local antes do submit; mantenha esse estado vivo movendo a lógica do
wizard para cima do switch de etapas: levantar useEngravingWizard para
ProductFormFullscreen e passar os handlers/refs (ex: engravingFlushRef, qualquer
onFlush/onSubmit do wizard) via props para
ProductFormStepContent/ProductEngravingSection, ou alternativamente renderizar
ProductEngravingSection fora do AnimatePresence (sempre montado) e só limpar
engravingFlushRef após o submit; atualize ProductFormFullscreen (onde
AnimatePresence/motion.div é usado e onde ProductFormStepContent é instanciado)
e ProductEngravingSection (onde engravingFlushRef era limpo no unmount) para
corresponder a essa abordagem.

In `@src/pages/admin/AdminProductFormPage.tsx`:
- Around line 90-147: productToFormData currently omits supplier_product_url so
editing an existing product overwrites the saved URL with the form schema
default; update productToFormData (the function) to include
supplier_product_url: p.supplier_product_url ?? '' so the existing value is
loaded into the form and not cleared on save.

---

Nitpick comments:
In `@src/components/admin/products/useProductsManager.ts`:
- Around line 353-359: The fix in handlePageChange correctly passes
advancedFilters to fetchProducts to avoid stale closures; make the same explicit
change in the other call sites: update handlePageSizeChange, handleDelete, and
handleBulkToggleActive so each call to fetchProducts includes the current
advancedFilters argument (i.e., call fetchProducts(page, pageSize, searchTerm,
advancedFilters) or the equivalent parameters for that handler) rather than
relying on the closure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0c49fe73-14b5-4f0f-88de-759e53a2b543

📥 Commits

Reviewing files that changed from the base of the PR and between 47955fe and cf9893c.

📒 Files selected for processing (6)
  • src/components/admin/products/ProductFormFullscreen.tsx
  • src/components/admin/products/ProductFormStepContent.tsx
  • src/components/admin/products/sections/ProductEngravingSection.tsx
  • src/components/admin/products/sections/engraving/useEngravingWizard.ts
  • src/components/admin/products/useProductsManager.ts
  • src/pages/admin/AdminProductFormPage.tsx

Comment on lines +204 to +226
const results = await Promise.allSettled(
areas.map(async (area) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { id: _id, _techData: _td, ...areaData } = area as PrintAreaTechnique & { _techData?: ExternalTechnique };
const { data, error } = await supabase.functions.invoke('external-db-bridge', {
body: {
table: 'print_area_techniques',
operation: 'insert',
data: { ...areaData, product_id: newProductId },
},
});
if (error) throw new Error(error.message);
if (!data?.success) throw new Error(data?.error || 'Erro ao salvar área de gravação');
}),
);
const failed = results.filter((r) => r.status === 'rejected').length;
if (failed > 0) {
toast.warning(`${areas.length - failed}/${areas.length} áreas de gravação salvas — ${failed} falha(s).`);
} else {
toast.success(`${areas.length} área(s) de gravação salvas com o produto`);
}
setLocalAreas([]); // clear after flush
}, []); // stable — reads localAreasRef.current which is always up-to-date
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Não limpe as áreas que falharam no flush.

Se parte do Promise.allSettled falhar, a Line 225 apaga também as áreas que não foram persistidas. Isso recria perda de dados no fluxo de criação: o toast avisa falha parcial, mas não sobra nada para retry depois da navegação.

💡 Ajuste sugerido
   const results = await Promise.allSettled(
     areas.map(async (area) => {
       // eslint-disable-next-line `@typescript-eslint/no-unused-vars`
       const { id: _id, _techData: _td, ...areaData } = area as PrintAreaTechnique & { _techData?: ExternalTechnique };
       const { data, error } = await supabase.functions.invoke('external-db-bridge', {
         body: {
           table: 'print_area_techniques',
           operation: 'insert',
           data: { ...areaData, product_id: newProductId },
         },
       });
       if (error) throw new Error(error.message);
       if (!data?.success) throw new Error(data?.error || 'Erro ao salvar área de gravação');
     }),
   );
-  const failed = results.filter((r) => r.status === 'rejected').length;
+  const failedIds = new Set(
+    areas.flatMap((area, index) => (results[index]?.status === 'rejected' ? [area.id] : [])),
+  );
+  const failed = failedIds.size;
   if (failed > 0) {
     toast.warning(`${areas.length - failed}/${areas.length} áreas de gravação salvas — ${failed} falha(s).`);
   } else {
     toast.success(`${areas.length} área(s) de gravação salvas com o produto`);
   }
-  setLocalAreas([]); // clear after flush
+  setLocalAreas((prev) => prev.filter((area) => failedIds.has(area.id)));
🤖 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/products/sections/engraving/useEngravingWizard.ts`
around lines 204 - 226, The current flush clears all local areas unconditionally
(setLocalAreas([])) after Promise.allSettled, which loses areas that failed to
persist; modify the logic around Promise.allSettled/results so you identify
which items succeeded (e.g., correlate each result to the corresponding area
from areas via index or id), and only remove those successfully saved from local
state while keeping failed areas for retry; update setLocalAreas to filter out
the saved areas (or set it to the subset of failed areas) instead of clearing
everything, and keep the existing toast behavior using the computed failed
count.

Comment on lines +176 to 180
sale_price: data.sale_price ?? 0, cost_price: data.cost_price ?? null,
suggested_price: data.suggested_price ?? null, stock_quantity: data.stock_quantity ?? 0,
stock_unit: data.stock_unit || 'un', product_type: data.product_type || 'product',
is_kit: data.product_type === 'kit', min_quantity: data.min_quantity ?? 1,
min_order_quantity: data.min_order_quantity ?? null,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use o toggle real de kit ao persistir is_kit.

A etapa de kits altera is_kit, mas aqui o valor salvo é derivado só de product_type. No create, product_type continua 'product' por default, então marcar “É Kit” não chega no banco.

Diff sugerido
-        stock_unit: data.stock_unit || 'un', product_type: data.product_type || 'product',
-        is_kit: data.product_type === 'kit', min_quantity: data.min_quantity ?? 1,
+        stock_unit: data.stock_unit || 'un',
+        product_type: data.is_kit ? 'kit' : (data.product_type || 'product'),
+        is_kit: data.is_kit,
+        min_quantity: data.min_quantity ?? 1,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sale_price: data.sale_price ?? 0, cost_price: data.cost_price ?? null,
suggested_price: data.suggested_price ?? null, stock_quantity: data.stock_quantity ?? 0,
stock_unit: data.stock_unit || 'un', product_type: data.product_type || 'product',
is_kit: data.product_type === 'kit', min_quantity: data.min_quantity ?? 1,
min_order_quantity: data.min_order_quantity ?? null,
sale_price: data.sale_price ?? 0, cost_price: data.cost_price ?? null,
suggested_price: data.suggested_price ?? null, stock_quantity: data.stock_quantity ?? 0,
stock_unit: data.stock_unit || 'un',
product_type: data.is_kit ? 'kit' : (data.product_type || 'product'),
is_kit: data.is_kit,
min_quantity: data.min_quantity ?? 1,
min_order_quantity: data.min_order_quantity ?? null,
🤖 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/pages/admin/AdminProductFormPage.tsx` around lines 176 - 180, When
building the payload for save in AdminProductFormPage.tsx, persist the actual
kit toggle instead of deriving it only from product_type: set is_kit from
data.is_kit (falling back to the existing product_type check if needed) and
ensure product_type is set consistently (e.g., default to 'kit' when data.is_kit
is true, otherwise 'product') so the "É Kit" toggle actually reaches the
backend; update the fields around is_kit and product_type in the object
construction where sale_price, cost_price, etc. are assembled.

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.

2 participants