Subtask 05 — Criação da Vitrine de Estoque da Loja (sem tela intermediária)
Task pai: 197313 — Ajuste de layout nova vitrine
Ordem de execução: 05 de 07
Depende de: 01b, 03, 04 — a tela de detalhe precisa já saber renderizar e tratar ShowCaseType.sellerStock corretamente antes de ganhar um modo de criação que termina exibindo exatamente essa tela.
Objetivo
Implementar o fluxo de criação da Vitrine de Estoque da Loja sem nenhuma tela/controller/rota nova: a própria ShowCaseDetailScreen/ShowCaseDetailController ganham um modo de criação (isCreating), que faz POST (criação) encadeado com GET (carregamento completo), reaproveitando o skeleton de loading e introduzindo um estado de erro com retry (mesma dinâmica do UpsellRecommendationScreen).
Requisitos atendidos
- RF-03 — Criação da Vitrine de Estoque da Loja: AC1 a AC7.
Relação com o design doc
- Decisão #3 — Criação da Vitrine de Estoque da Loja — Sem Tela Intermediária (
desing-doc.md): contém o código completo deShowCaseDetailScreenArguments,MyShowCaseController.createSellerStock(),ShowCaseDetailController.onInit()/createAndLoad()/retryCreate(). - Contrato atualizado (
context/frontend-contract-diff.md): o POST não retorna mais erro de duplicata — comportamento "get-or-create" (retorna os dados da vitrine existente com200 OK). O único caminho de erro tratado aqui é falha inesperada (rede, 5xx). - Ver também
context/fluxo-pos-criacao-e-dependencia-rewards.md(achado que documenta a decisão completa).
Arquivos a modificar
| Arquivo | Modificação |
|---|---|
lib/screens/show_case/show_case_detail/show_case_detail_screen.dart | ShowCaseDetailScreenArguments ganha catalogId opcional (String?) e isCreating (bool, default false). Tela passa a checar controller.hasError.value (antes de isLoading), renderizando ZzErrorState (title/description genéricos, retryText: 'TENTE NOVAMENTE', onRetry: controller.retryCreate) no lugar do ShowCaseDetailLayout quando hasError == true. |
lib/screens/show_case/show_case_detail/show_case_detail_controller.dart | + isLoading (RxBool), + hasError (RxBool), + createAndLoad() (POST com showCaseType: ShowCaseType.sellerStock, name='Estoque da loja', showCaseItems=[], dateExpiration=hoje+30 dias, demais campos obrigatórios; encadeia com loadData() usando o id retornado), + retryCreate(). onInit() ramifica por arguments.isCreating (chama createAndLoad() ou loadData()). |
lib/screens/show_case/show_case/my_show_case_controller.dart | + createSellerStock(): navega para AppRoutes.storeShowCaseDetail com ShowCaseDetailScreenArguments(catalogName: 'Estoque da loja', isCreating: true); ao voltar, recarrega a listagem (mesmo padrão de goToDetailFastCatalog()). |
Testes unitários a criar
test/screens/show_case/show_case_detail/show_case_detail_controller_test.dart(mesma suíte das subtasks 03/04, adicionando)onInit()comarguments.isCreating == true→ chamacreateAndLoad()(nãoloadData()diretamente)onInit()comarguments.isCreating == false(default) → chamaloadData()normalmente (sem regressão do fluxo existente)createAndLoad(): montaCreateShowCaseRequestcomshowCaseType: ShowCaseType.sellerStock,name: 'Estoque da loja',showCaseItems: [],dateExpiration= hoje + 30 diascreateAndLoad()sucesso: extraiiddeCreateShowCaseResponse, encadeialoadData()com esseid; ao final,detail.valuepopulado,isLoading == false,hasError == falsecreateAndLoad()sucesso com dados de vitrine já existente (contrato get-or-create) → tratado como sucesso normal, sem diferenciaçãocreateAndLoad()erro inesperado (POST falha) →hasError == true,isLoading == falseretryCreate()→ chamacreateAndLoad()novamenteenableEditButtoncomdetail.value == null(durante loading ou erro) →false(garantindo que nenhuma ação dependente dispare aviso nesse meio-tempo — usado pela subtask 07)
test/screens/show_case/show_case/my_show_case_controller_test.dartcreateSellerStock(): navega paraAppRoutes.storeShowCaseDetailcomarguments.isCreating == trueecatalogId == nullcreateSellerStock(): ao retornar da navegação,_hasNextPageé resetado e a listagem é recarregada (mesmo padrão degoToDetailFastCatalog())
Critérios de aceite (RF-03)
- Selecionar
Vitrine do estoque da lojano bottom sheet (comhasSellerStock = false) navega diretamente para a tela de detalhe em modo de criação, sem tela intermediária. - A tela de detalhe em modo de criação envia
POST /api/show-case-newcomshowCaseType = "SellerStock",name = "Estoque da loja",showCaseItems = [],dateExpiration= hoje + 30 dias, e os demais campos obrigatórios deCreateShowCaseRequest. - Durante o POST, o App exibe o estado de carregamento (skeleton) já usado na tela de detalhe.
- Sucesso no POST (inclusive get-or-create) → usa o
idretornado para carregar o detalhe completo via GET, renderizando a tela normalmente. - Erro inesperado no POST → estado de erro genérico com botão de tentar novamente (
retryCreate()reenvia o POST). - Nenhuma etapa de busca/seleção de produtos, nem tela intermediária com campos de nome/data.
- Nenhum reward event de criação é registrado (aguardando task 197192).
Definição de Pronto (Definition of Done)
- Nenhuma tela/controller/rota nova criada — apenas adaptação da
ShowCaseDetailScreen/Controllere um novo método emMyShowCaseController. - Fluxo POST + GET encadeado funcionando, com loading e erro cobertos.
-
flutter analyzesem erros novos. -
flutter testexecutando os testes listados acima, 100% verdes. - Projeto compila.
- Fluxo de visualização de vitrine existente (
isCreating = false) sem nenhuma regressão.