Skip to main content

Requisitos — [Front] Novo layout do card de produto

Task #196866

Task pai: US 196869 ADRs relacionados:Contrato de referência: cart-detail.json

Status: refinado Sessão de grilling: 25/06/2026


Visão geral

Criar um novo componente de card de produto para a tela de Status do Pedido do zzapp, com layout conforme Figma, substituindo CartStatusProductCard apenas na seção "Itens" do detalhe do pedido.

O componente legado (CartStatusProductCard) permanece no projeto sem alterações para as demais telas. A substituição global ocorrerá em task futura, após validação do novo layout.

O novo componente expõe factory methods para duas variantes — item do pedido e item recomendado — preparando a integração do bloco "Recomendados" (task 196865).

Componente AS-IS: CartStatusProductCard em lib/screens/cart_status/widgets/cart_status_product_card.dart Tela: CartStatusDetailScreen → seção _ContentProducts ("Itens")


Premissas

  • O card exibe valores unitários nas linhas Valor e Desconto, desconsiderando o campo quantity. A quantidade é exibida apenas como informação (Qtd), sem multiplicar os valores de preço ou desconto.
  • O valor exibido na linha Desconto é sempre monetário (R$), nunca percentual. Quando discount for 1 (percentage), o sistema calcula o valor monetário equivalente antes de renderizar.

Papéis

PapelResponsabilidade
VendedoraVisualizar itens do pedido e recomendações com layout atualizado na tela de Status do Pedido
Desenvolvedor Front-endCriar o novo componente, factory de variantes, enum DiscountType, atualizar ProductCartDetail e integrar na seção "Itens"

Requisitos

RF-01 — Novo componente com factory de variantes

User Story: Como desenvolvedor front-end, eu quero um novo componente de card com factory para variantes, para reutilizar o mesmo layout visual em itens do pedido e itens recomendados sem alterar o componente legado.

Acceptance Criteria:

  1. WHEN o novo componente for implementado THEN o sistema SHALL criá-lo em arquivo separado de CartStatusProductCard, sem remover nem alterar o componente legado.
  2. WHEN o novo componente for instanciado THEN o sistema SHALL expor factory methods para as variantes orderItem (item do pedido) e recommended (item recomendado).
  3. WHEN a tela de Status do Pedido exibir a seção "Itens" THEN o sistema SHALL utilizar exclusivamente o novo componente na variante orderItem.
  4. WHEN qualquer outra tela do app utilizar card de produto hoje THEN o sistema SHALL continuar usando CartStatusProductCard sem alteração.

Casos de Borda:

  • WHEN a factory receber dados incompletos para renderização mínima (nome, imagem, sku) THEN o componente SHALL renderizar os campos disponíveis sem quebrar o layout.

RF-02 — Layout visual conforme Figma

User Story: Como vendedora, eu quero visualizar os produtos com o novo layout de card para ter uma experiência visual atualizada e consistente com o design.

Acceptance Criteria:

  1. WHEN um card for renderizado na variante orderItem THEN o sistema SHALL exibir: thumbnail, nome do produto, SKU, quantidade (Qtd), tamanho (TAM), linha Valor, linha de desconto (label conforme DiscountType), e linha Preço final, conforme Figma e referências visuais.
  2. WHEN um card for renderizado na variante recommended THEN o sistema SHALL exibir: thumbnail, nome do produto, SKU, quantidade fixa 1, tamanho (TAM), linha Valor, linha de desconto (label conforme DiscountType), e linha Preço final, conforme Figma.
  3. WHEN o card for exibido para pedidos com estoque da loja ou Prateleira Infinita THEN o sistema SHALL aplicar o mesmo layout base, sem distinção visual por modalidade de estoque no nível do card.
  4. WHEN o novo layout for aplicado THEN o sistema SHALL NOT exibir a linha Remarcação (substituída pelo tipo sale).

Referência visual:

Novo card produto

Novo card produto que foi recomendado


RF-03 — Enum DiscountType e labels

User Story: Como vendedora, eu quero identificar o tipo de desconto aplicado a cada item, para compreender a composição do preço.

Acceptance Criteria:

  1. WHEN o novo componente for implementado THEN o sistema SHALL definir o enum DiscountType com os valores funcionario, manual, sale e none.
  2. WHEN DiscountType for none THEN o sistema SHALL exibir o label "Desconto" com valor R$ 0,00.
  3. WHEN DiscountType for manual THEN o sistema SHALL exibir o label "Desconto manual".
  4. WHEN DiscountType for funcionario THEN o sistema SHALL exibir o label "Desconto funcionário".
  5. WHEN DiscountType for sale THEN o sistema SHALL exibir o label "Desconto sale".

RF-04 — Valor exibido na linha de desconto (lógica comum)

User Story: Como vendedora, eu quero ver o valor do desconto formatado corretamente, para entender o abatimento aplicado ao item.

Acceptance Criteria:

  1. WHEN o item não possuir desconto aplicável (sem valor de abatimento) THEN o sistema SHALL exibir a linha de desconto com valor R$ 0,00, sem prefixo "-", na cor ZZColors.neutralDark (color-neutral-dark).
  2. WHEN o campo discount for 1 (percentage) e o valor monetário calculado for maior que zero THEN o sistema SHALL calcular o desconto como fullPrice × (discountValue / 100) (valor unitário, conforme premissa) e exibir como moeda (- R$ {valor calculado}), prefixado com "-", na cor ZZColors.successMedium (color-feedback-success-medium).
  3. WHEN o campo discount for 2 (value) e discountValue for maior que zero THEN o sistema SHALL exibir o valor como moeda (- R$ {discountValue}), prefixado com "-", na cor ZZColors.successMedium (color-feedback-success-medium).
  4. WHEN o valor calculado do desconto for menor ou igual a zero (incluindo casos sale com fullPrice - price igual a zero) THEN o sistema SHALL exibir R$ 0,00, sem prefixo "-", na cor ZZColors.neutralDark (color-neutral-dark).
  5. WHEN o desconto for do tipo sale e fullPrice - price for maior que zero THEN o sistema SHALL exibir o valor como moeda (- R$ {fullPrice - price}), prefixado com "-", na cor ZZColors.successMedium (color-feedback-success-medium).

Nota: A linha de desconto nunca exibe percentual (%). O campo discountValue em modo percentage representa o percentual aplicado; o valor renderizado é sempre o equivalente monetário unitário.


RF-05 — Mapeamento discountOrigin para itens do pedido

User Story: Como desenvolvedor front-end, eu quero derivar o DiscountType a partir dos dados da API, para exibir o label correto em itens do pedido.

Acceptance Criteria:

  1. WHEN discountOrigin for None THEN o sistema SHALL definir DiscountType como none.
  2. WHEN discountOrigin for Markdown THEN o sistema SHALL definir DiscountType como sale.
  3. WHEN discountOrigin for Manual e hasEmployeeDiscount for false THEN o sistema SHALL definir DiscountType como manual.
  4. WHEN discountOrigin for Manual e hasEmployeeDiscount for true THEN o sistema SHALL definir DiscountType como funcionario.
  5. WHEN discountOrigin for Both e hasEmployeeDiscount for false THEN o sistema SHALL definir DiscountType como manual.
  6. WHEN discountOrigin for Both e hasEmployeeDiscount for true THEN o sistema SHALL definir DiscountType como funcionario.
  7. WHEN o valor do desconto for calculado THEN o sistema SHALL aplicar a lógica de RF-04 com base em discount e discountValue de ProductCartDetail.

Enum da API:

CartItemDiscountOrigin: None | Markdown | Manual | Both

Significado de Both: item estava remarcado e a vendedora alterou o valor do desconto.


RF-06 — Linhas de preço em itens do pedido (orderItem)

User Story: Como vendedora, eu quero ver o valor, desconto e preço final de cada item do pedido, para acompanhar a composição do pedido.

Acceptance Criteria:

  1. WHEN um card orderItem for renderizado THEN o sistema SHALL exibir Valor com fullPrice (valor unitário, conforme premissa).
  2. WHEN um card orderItem for renderizado THEN o sistema SHALL exibir Preço final com total.
  3. WHEN um card orderItem for renderizado THEN o sistema SHALL exibir Qtd com quantity e TAM com size.

User Story: Como vendedora, eu quero visualizar o desconto de itens recomendados de forma clara, para apresentar opções complementares à cliente.

Acceptance Criteria:

  1. WHEN um card recommended for renderizado THEN o sistema SHALL exibir quantidade fixa 1.
  2. WHEN hasEmployeeDiscount for true THEN o sistema SHALL definir DiscountType como funcionario e aplicar RF-04.
  3. WHEN hasEmployeeDiscount for false e discount for maior que 0 THEN o sistema SHALL definir DiscountType como manual e exibir o desconto monetário conforme RF-04.
  4. WHEN price for menor que fullPrice e discount for 0 THEN o sistema SHALL definir DiscountType como sale e exibir na linha de desconto o valor fullPrice - price.
  5. WHEN o valor fullPrice - price for menor ou igual a zero no caso sale THEN o sistema SHALL exibir R$ 0,00 na linha de desconto, conforme RF-04.4.
  6. WHEN nenhuma das condições acima se aplicar THEN o sistema SHALL definir DiscountType como none e exibir R$ 0,00 na linha de desconto, conforme RF-04.1.

Exemplos de referência:

Item recomendado com desconto manual:

{
"discount": 2,
"discountValue": 159.90,
"fullPrice": 359.90,
"price": 279.90,
"hasEmployeeDiscount": false
}

Item recomendado com desconto sale:

{
"discount": 0,
"discountValue": 0.00,
"fullPrice": 359.90,
"price": 279.90,
"hasEmployeeDiscount": false
}

Item recomendado com desconto funcionário:

{
"discount": 1,
"discountValue": 40.00,
"fullPrice": 239.90,
"price": 239.90,
"hasEmployeeDiscount": true
}

User Story: Como vendedora, eu quero ver o valor de referência e o preço final de itens recomendados, para entender a proposta de compra.

Acceptance Criteria:

  1. WHEN um card recommended for renderizado THEN o sistema SHALL exibir Valor com fullPrice.
  2. WHEN discount for 0 (none) ou 2 (value) THEN o sistema SHALL exibir Preço final com price.
  3. WHEN discount for 1 (percentage) THEN o sistema SHALL exibir Preço final calculado como fullPrice menos o valor percentual de discountValue.
  4. WHEN o desconto for do tipo sale (RF-07.4) THEN o sistema SHALL exibir Preço final com price.

RF-09 — Tag "Item recomendado adicionado ao pedido"

User Story: Como vendedora, eu quero identificar visualmente itens que foram recomendados e adicionados ao pedido pela cliente, para acompanhar a conversão de upsell.

Acceptance Criteria:

  1. WHEN fromRecommendation for true THEN o componente SHALL exibir a tag "Item recomendado adicionado ao pedido" conforme Figma (faixa verde com ícone de confirmação).
  2. WHEN fromRecommendation for false THEN o componente SHALL NOT exibir a tag.
  3. WHEN a tag for exibida THEN o componente SHALL controlar a renderização exclusivamente com base na prop fromRecommendation, sem implementar a lógica de movimentação entre blocos (task 196865).

RF-10 — Atualização do model ProductCartDetail

User Story: Como desenvolvedor front-end, eu quero consumir os novos campos da API de detalhe do pedido, para alimentar o novo componente com dados corretos.

Acceptance Criteria:

  1. WHEN a resposta da API de detalhe do pedido for parseada THEN o model ProductCartDetail SHALL mapear os campos discountOrigin, fromRecommendation e hasEmployeeDiscount conforme cart-detail.json.
  2. WHEN discountOrigin for deserializado THEN o sistema SHALL mapeá-lo para o enum CartItemDiscountOrigin (None, Markdown, Manual, Both).
  3. WHEN campos legados ausentes na resposta THEN o sistema SHALL aplicar defaults seguros (discountOrigin: None, fromRecommendation: false, hasEmployeeDiscount: false).

RF-11 — Preservação de comportamentos AS-IS

User Story: Como vendedora, eu quero que a troca visual do card não altere o funcionamento da tela de acompanhamento do pedido.

Acceptance Criteria:

  1. WHEN o novo card for exibido na seção "Itens" THEN o sistema SHALL NOT adicionar ações de toque ou navegação no card (comportamento AS-IS: card sem onTap).
  2. WHEN o detalhe do pedido for carregado THEN o sistema SHALL manter o fluxo atual de fetch via CartController.find e FutureBuilder.
  3. WHEN o pedido for de Prateleira Infinita (saleEcommerce: true) THEN o sistema SHALL manter o comportamento AS-IS de ocultar o bloco "Resumo do pedido" sem alterar o card de produto.
  4. WHEN a listagem de pedidos for atualizada ao retornar do detalhe THEN o sistema SHALL manter o refresh existente em cartStoreController.findSearchCartStore.

Fora de Escopo

  • Exibição e lógica do bloco "Recomendados" na tela (task 196865) — esta task entrega o componente com factory recommended, mas não integra o bloco
  • Lógica de movimentação de item entre blocos "Recomendados" e "Itens" quando a cliente adiciona via zzlink (task 196865)
  • Substituição de CartStatusProductCard em outras telas do app (task futura, pós-validação)
  • Alterações no fluxo de criação de carrinho
  • Alterações no zzlink
  • Alterações de contrato ou lógica de backend

Dependências

DependênciaDescriçãoStatus
API Cart DetailEndpoint deve retornar discountOrigin, fromRecommendation, hasEmployeeDiscount em productCartDetails e cartItemRecommendationsDisponível (ver cart-detail.json)
Figma ZZAPP 2.0Layout visual do card e tag de recomendadoDisponível
Task 196865Integração do bloco "Recomendados" usando factory recommendedPendente
CartStatusProductCard (legado)Mantido sem alteração nas demais telasExistente