Skip to content

feat(catalog): exibir categoria-folha (filha/neta) no produto#539

Merged
adm01-debug merged 2 commits into
mainfrom
claude/db-schema-frontend-validation-Vyf0n
May 31, 2026
Merged

feat(catalog): exibir categoria-folha (filha/neta) no produto#539
adm01-debug merged 2 commits into
mainfrom
claude/db-schema-frontend-validation-Vyf0n

Conversation

@adm01-debug
Copy link
Copy Markdown
Owner

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

Objetivo

Exibir no produto a categoria-FOLHA — a última/mais específica em que ele se encaixa (filha, neta, bisneta…) — no card do catálogo e na página de detalhe. Antes, o produto mostrava frequentemente a categoria raiz ou intermediária.

Diagnóstico (centenas de simulações SQL no banco oficial doufsxqlfjyuvxuezpln)

  • Hierarquia de até 6 níveis, 6.123 produtos, 21.665 vínculos N:N.
  • 57% dos produtos tinham main_category_id em nó não-folha; 821 na própria raiz.
  • 366 produtos (6%) passam a exibir categoria diferente (mais específica). Ex.: "Caderneta percalux" ia de "Cadernetas | Cadernos | Blocos" (nível 2) → "Com Pauta" (nível 6).
  • A folha vem do assignment de maior level; em 227 produtos ela não descende da main_category_id, então não basta "descer a árvore" — usa-se os assignments.
  • 686 produtos têm empate de folha → desempate determinístico.
  • Integridade da hierarquia perfeita: 0 ciclos, 0 órfãs, 0 níveis nulos.

Como funciona

  • useProductLeafCategories (hook + provider): resolve as folhas em lote — 1 query nos product_category_assignments + 1 nas categories (sem N+1), via PostgREST nativo no doufsxqlfjyuvxuezpln (o external-db-bridge/EXTERNAL_PROMOBRIND_URL foi descontinuado).
  • Desempate (≥2 categorias no nível máximo): level DESC → is_primary → display_order → nome.
  • Caminho raiz→folha montado em memória (subindo por parent_id, com guarda anti-ciclo) para o tooltip.
  • ProductCard e ProductDetailHero passam folha + caminho ao ProductCategoryBadges, que mostra a folha no badge e o caminho completo no tooltip; o deep-link /filtros usa a folha.
  • Fallback suave: em erro/RLS, mantém category_id || main_category_id — sem quebrar a listagem.

Decisões (confirmadas com o usuário)

  1. Resolver no front (acesso nativo ao banco). 2. Empate: is_primary → display_order → nome. 3. Exibição: folha no badge + caminho no tooltip.

Mudanças

  • src/hooks/products/useProductLeafCategories.tsx (hook + provider + lógica pickLeaves/buildPath).
  • ➕ testes: pickLeaves/buildPath (8) + ProductCategoryBadges (caminho no tooltip, deep-link na folha).
  • 🔧 ProductCard.tsx, ProductDetailHero.tsx, ProductCategoryBadges.tsx, CatalogContent.tsx (provider).
  • 🔧 scripts/lint-untyped-from.sh: allowlist += categories, product_category_assignments (existem no banco, ausentes do types.ts).

Verificação

  • ✅ Validado contra dados reais (folha + caminho de 6 níveis batem com o banco).
  • ✅ 18 testes passam (8 lógica de folha + 10 badge).
  • typecheck baseline: as 6 regressões reportadas já existem em HEAD (provado com mudanças stashed) — este PR é TS-neutro.
  • lint:baseline e lint-untyped-from: sem regressões.

https://claude.ai/code/session_019e55kaN6FDxXsz88gw751L


Generated by Claude Code


Summary by cubic

Mostra a categoria-folha (mais específica) do produto no card do catálogo e na página de detalhe, com tooltip do caminho completo e deep-link filtrando pela folha. Resolve em lote via PostgREST, sem N+1, e mantém fallback seguro.

  • New Features

    • Adicionados useProductLeafCategories e ProductLeafCategoryProvider para buscar folhas em lote de product_category_assignments e categories, com desempate determinístico (level → is_primary → display_order → nome) e caminho raiz→folha em memória.
    • Integração em CatalogContent, ProductCard e ProductDetailHero; ProductCategoryBadges exibe a folha e o caminho no tooltip; o link de filtro usa o ID da folha.
    • Testes cobrindo escolha de folha/caminho e comportamento do badge; atualizada allowlist do scripts/lint-untyped-from.sh com categories e product_category_assignments.
  • Bug Fixes

    • Corrigido usePrintAreas para consultar tecnicas_gravacao (nome real da tabela) em vez de tecnica_gravacao.

Written for commit e4d0c2e. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Melhoria na resolução e exibição de categorias de produtos com suporte a caminho completo raiz-folha em badges e componentes.
  • Bug Fixes

    • Corrigida consulta para tabela de técnicas de gravação.
  • Documentation

    • Adicionada auditoria completa de banco de dados e front-end. Documentação histórica marcada como desatualizada.
  • Tests

    • Adicionados testes para validação de categorias folha e badges.

claude added 2 commits May 31, 2026 00:36
Auditoria completa do banco oficial (doufsxqlfjyuvxuezpln): 299 tabelas,
119 views, 295 FKs, 767 RLS policies (0 tabelas sem RLS), 800 funções.
Mapeia 644 chamadas .from() (125 tabelas), 34 RPCs (todos existem) e a
arquitetura multi-banco (interno + catálogo/CRM via external-db-bridge).

- Novo relatório: docs/AUDITORIA_DB_FRONTEND_2026-05-31.md (classificação
  das 299 tabelas, gaps P0/P1/P2, diagrama ER).
- Fix P0: usePrintAreas.useTechniques() consultava 'tecnica_gravacao'
  (inexistente no banco) -> corrigido para 'tecnicas_gravacao' (tabela real).
- Marca docs/AUDIT_FRONTEND_DATABASE.md como superseded (apontava p/ projeto
  antigo nmojwpihnslkssljowjh).

https://claude.ai/code/session_019e55kaN6FDxXsz88gw751L
… e detalhe

Antes, o produto exibia frequentemente a categoria raiz ou intermediária
(57% dos produtos têm main_category_id em nó não-folha; 821 na própria raiz).
Agora resolve a categoria-FOLHA — a mais específica em que o produto se encaixa
(filha/neta/bisneta…) — a partir de product_category_assignments.

Como funciona:
- useProductLeafCategories: hook + provider que resolve as folhas em LOTE
  (1 query batch nos assignments + 1 nas categorias, sem N+1), via PostgREST
  nativo no banco doufsxqlfjyuvxuezpln (external-db-bridge descontinuado).
- Desempate determinístico quando há ≥2 categorias no nível máximo (686 produtos):
  maior level → is_primary → display_order → nome.
- Monta o caminho raiz→folha em memória (subindo por parent_id, com guarda
  anti-ciclo) para o tooltip do badge.
- ProductCard e ProductDetailHero passam a folha + caminho ao ProductCategoryBadges,
  que exibe a folha no badge e o caminho completo no tooltip.
- Fallback suave: em erro/RLS, mantém o comportamento atual (category_id ||
  main_category_id), sem quebrar a listagem.

Validado contra dados reais: "Caderneta percalux" passa de "Cadernetas | Cadernos
| Blocos" (nível 2) para "Com Pauta" (nível 6), tooltip com o caminho de 6 níveis.

Testes: pickLeaves/buildPath (8) + ProductCategoryBadges (caminho no tooltip e
deep-link na folha). Acesso via untypedFrom (tabelas fora do types.ts) + allowlist
do lint-untyped-from atualizada.

https://claude.ai/code/session_019e55kaN6FDxXsz88gw751L
@vercel
Copy link
Copy Markdown

vercel Bot commented May 31, 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 31, 2026 1:51am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 31, 2026

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 51c52924-9ab0-4342-bc5c-3c979910899b

📥 Commits

Reviewing files that changed from the base of the PR and between 9e1a96d and e4d0c2e.

📒 Files selected for processing (11)
  • docs/AUDITORIA_DB_FRONTEND_2026-05-31.md
  • docs/AUDIT_FRONTEND_DATABASE.md
  • scripts/lint-untyped-from.sh
  • src/components/catalog/CatalogContent.tsx
  • src/components/products/ProductCard.tsx
  • src/components/products/ProductCategoryBadges.test.tsx
  • src/components/products/ProductCategoryBadges.tsx
  • src/hooks/products/__tests__/useProductLeafCategories.test.ts
  • src/hooks/products/useProductLeafCategories.tsx
  • src/hooks/simulation/usePrintAreas.ts
  • src/pages/products/product-detail/ProductDetailHero.tsx

Walkthrough

PR integra novo relatório de auditoria DB-Frontend (2026-05-31) documentando acoplamento front-end com banco de dados, corrige query de tabela de técnicas de gravação identificada como erro crítico, e implementa resolução em lote de categorias mais específicas ("folha") para produtos via novo hook com React Context e caching via React Query.

Changes

Auditoria DB-Frontend e Correções Identificadas

Layer / File(s) Summary
Relatório de auditoria DB-Frontend 2026-05-31
docs/AUDITORIA_DB_FRONTEND_2026-05-31.md
Novo relatório completo mapeando acoplamento front-end com banco de dados: alerta crítico de ambiente de MCP multi-banco, panorama do schema public, contagens de .from() e RPCs, validação de relacionamentos por FKs, cobertura tabela↔front de 299 tabelas, classificação de ~9 órfãs reais, gaps priorizados (P0: queries quebradas em tecnicas_gravacao/v_technique_stats; P1: migration visual_search_feedback não aplicada; P2: docs desatualizado), diagrama ER, consolidação em 30 tarefas e instruções de reprodução.
Obsolescência de relatório antigo, allowlist de lint e correção de tabela
docs/AUDIT_FRONTEND_DATABASE.md, scripts/lint-untyped-from.sh, src/hooks/simulation/usePrintAreas.ts
Marca relatório anterior como supersedido (2026-05-31) com encaminhamento para auditoria vigente; adiciona categories e product_category_assignments à allowlist de lint para evitar CI fails em untypedFrom(); corrige query em useTechniques() de .from('tecnica_gravacao') para .from('tecnicas_gravacao') conforme tabela real no banco.

Resolução de Categorias Folha para Produtos

Layer / File(s) Summary
Hook useProductLeafCategories e provider React
src/hooks/products/useProductLeafCategories.tsx
Implementa useProductLeafCategories(productIds) que resolve categoria mais profunda de cada produto via pickLeaves (desempate: level > is_primary > display_order > nome) + buildPath (traversal up parent_id com anti-ciclo). Usa fetchLeaves com chunks PostgREST (évita URLs grandes) e ondas de carregamento. React Query cache com queryKey ordenada, staleTime/gcTime, sem refetchOnWindowFocus, fallback para Map vazio em erro RLS. Exporta LeafCategory, LeafCategoryMap, pickLeaves, provider ProductLeafCategoryProvider e hook consumidor useLeafCategory.
Testes de pickLeaves e seleção de categorias folha
src/hooks/products/__tests__/useProductLeafCategories.test.ts
Valida lógica pura com árvore de teste (raiz → intermediária → 2 folhas): seleção de folha mais profunda, montagem de path raiz→folha, desempates (is_primary, display_order, nome), ignorância de categorias sem metadados, exclusão de produtos sem categorias, resolução independente de múltiplos produtos.
Contrato ProductCategoryBadges e renderização com categoryPath
src/components/products/ProductCategoryBadges.tsx
Adiciona prop categoryPath?: string[] (raiz→folha). Renderiza tooltip com "ancestrais › folha" para categoria principal quando categoryPath tem ≥2 níveis; fallback para "Ver todos os produtos de {name}". Navegação via /filtros?categories=categoryUuid inalterada.
Testes de ProductCategoryBadges com categoryPath
src/components/products/ProductCategoryBadges.test.tsx
Valida tooltip com trilha raiz→folha ao disparar pointerEnter/focus; valida deep-link usando categoryUuid ao clicar no badge "Folha".
Integração em ProductCard e ProductDetailHero
src/components/products/ProductCard.tsx, src/pages/products/product-detail/ProductDetailHero.tsx
ProductCard resolve categoria folha via useLeafCategory(product.id), passando id/nome/path/categoryUuid aos badges quando disponível (fallback para product.category). ProductDetailHero inicializa hook para product.id e fornece leafCategory aos badges. Ambos mantêm fallback original em ausência de leaf.
Integração com ProductLeafCategoryProvider em CatalogContent
src/components/catalog/CatalogContent.tsx
Envolve bloco de renderização (ProductGrid, ProductList, ProductTableView) com ProductLeafCategoryProvider, passando productIds de paginatedProducts, habilitando contexto para componentes filhos sem prop-drilling.

Sequence Diagram(s)

sequenceDiagram
  participant CatalogContent as CatalogContent
  participant ProductLeafCategoryProvider as ProductLeafCategoryProvider
  participant useProductLeafCategories as useProductLeafCategories Hook
  participant ReactQuery as React Query
  participant PostgREST as PostgREST
  participant ProductCard as ProductCard
  participant ProductCategoryBadges as ProductCategoryBadges
  
  CatalogContent->>ProductLeafCategoryProvider: Wraps with productIds
  ProductLeafCategoryProvider->>useProductLeafCategories: Initialize with productIds
  useProductLeafCategories->>ReactQuery: queryKey = sorted unique IDs
  ReactQuery->>PostgREST: fetchLeaves() - assignments chunk
  PostgREST-->>ReactQuery: product_category_assignments batch
  ReactQuery->>PostgREST: Wave 1: category metadata
  PostgREST-->>ReactQuery: catById entries
  ReactQuery->>PostgREST: Wave 2: ancestors (parent_id traversal)
  PostgREST-->>ReactQuery: ancestor metadata
  ReactQuery-->>useProductLeafCategories: pickLeaves() - category_leaf Map
  useProductLeafCategories-->>ProductLeafCategoryProvider: leafById + isLoading
  ProductLeafCategoryProvider->>ProductCard: Provide LeafCategoryCtx
  ProductCard->>ProductCard: useLeafCategory(product.id)
  ProductCard->>ProductCategoryBadges: Pass id/name/path/categoryUuid
  ProductCategoryBadges->>ProductCategoryBadges: Render with categoryPath tooltip
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Rationale: PR combina múltiplos tipos de mudanças (documentação de auditoria + bug fix simples + nova feature de hook/provider de categorias) com cobertura diversa (hook puro com lógica de desempate determinística, React Query, contexto, testes, integrações em 4+ componentes). A lógica de pickLeaves + fetchLeaves requer cuidado com anti-ciclo, orderação de chunks e regras de desempate; a integração via provider em CatalogContent é simples. Sem lógica de criptografia, SQL injection, ou promises perigosas. Testes cobrem casos principais.

Possibly related PRs

  • adm01-debug/promo-gifts-v4#428: Modifica as mesmas estruturas e contratos de ProductCategoryBadges.tsx (props e renderização), logo há potencial sobrescrita ou compatibilidade entre os dois PRs.
✨ 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/db-schema-frontend-validation-Vyf0n

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

@supabase
Copy link
Copy Markdown

supabase Bot commented May 31, 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 31, 2026 10:16
Copilot AI review requested due to automatic review settings May 31, 2026 10:16
@adm01-debug adm01-debug merged commit 921fd7b into main May 31, 2026
42 of 54 checks passed
@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.

@adm01-debug adm01-debug deleted the claude/db-schema-frontend-validation-Vyf0n branch May 31, 2026 10:16
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

Adds a leaf-category resolver so product cards and the product detail page display the most specific (leaf) category from product_category_assignments (with a root→leaf tooltip and a deep-link to the leaf), instead of the often shallow category_id/main_category_id. Also fixes a broken tecnica_gravacaotecnicas_gravacao table name in usePrintAreas.

Changes:

  • New useProductLeafCategories hook + ProductLeafCategoryProvider that batch-fetches assignments and category metadata via PostgREST (chunked, with deterministic tie-break: level → is_primary → display_order → name) and builds a root→leaf path via parent walk with cycle guard.
  • Wire the provider into CatalogContent and consume the leaf in ProductCard, ProductDetailHero, and ProductCategoryBadges (which now renders the path in the tooltip and uses the leaf id for the filter deep-link). Includes unit tests for pickLeaves and the badge.
  • Allowlist categories/product_category_assignments in scripts/lint-untyped-from.sh; fix useTechniques() to query the real table tecnicas_gravacao; add audit docs.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/hooks/products/useProductLeafCategories.tsx New batch hook + provider + pickLeaves/buildPath logic.
src/hooks/products/tests/useProductLeafCategories.test.ts Unit tests for leaf selection, tie-break and path.
src/components/products/ProductCategoryBadges.tsx Renders root→leaf path in tooltip; uses leaf id in deep-link.
src/components/products/ProductCategoryBadges.test.tsx Tests for tooltip path and leaf-uuid deep-link.
src/components/products/ProductCard.tsx Consumes useLeafCategory from provider; passes leaf to badges.
src/pages/products/product-detail/ProductDetailHero.tsx Resolves the leaf for the single product on detail page.
src/components/catalog/CatalogContent.tsx Wraps grid/list/table in ProductLeafCategoryProvider.
src/hooks/simulation/usePrintAreas.ts Fixes table name tecnica_gravacaotecnicas_gravacao.
scripts/lint-untyped-from.sh Adds categories, product_category_assignments to allowlist.
docs/AUDITORIA_DB_FRONTEND_2026-05-31.md, docs/AUDIT_FRONTEND_DATABASE.md New audit doc + supersede note on old doc.

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

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