Skip to main content

Subtask 07 — Aviso de Alterações Não Salvas

Task pai: 197313 — Ajuste de layout nova vitrine Ordem de execução: 07 de 07 (última) Depende de: 04 — Detalhe: Regras de Negócio no Controller (enableEditButton já corrigido, updateShowCase() já com a lógica de PUT correta)

Objetivo

Implementar o aviso de alterações não salvas ao sair da tela de detalhe, visualizar, compartilhar ou copiar o link da vitrine — reaproveitando o BottomSheetAskLauncher já usado hoje só para "sair", através de um único helper compartilhado.

Requisitos atendidos

  • RF-06 — Aviso de alterações não salvas ao sair, visualizar, compartilhar ou copiar link: AC1 a AC12.

Relação com o design doc

  • Decisão #7 — Aviso de Alterações Não Salvas (desing-doc.md): contém o código completo de _confirmProceedWithPendingChanges() e as mudanças em onWillPop()/viewShowCase()/shareShowCase()/copyLink()/updateShowCase().
  • Fora de escopo (não fazer parte desta subtask): correção do botão de voltar da ZzAppBar que hoje ignora onWillPop() — ver context/bug-appbar-back-button-ignora-onwillpop.md (débito técnico registrado separadamente, sem solução decidida). O botão EXCLUIR VITRINE também fica fora — usa somente sua confirmação de exclusão já existente.

Arquivos a modificar

ArquivoModificação
lib/screens/show_case/show_case_detail/show_case_detail_controller.dart+ _confirmProceedWithPendingChanges(String actionDescription) (helper privado). onWillPop(), viewShowCase(), shareShowCase(), copyLink() passam a chamar esse helper antes de executar sua lógica atual. updateShowCase() muda de Future<void> para Future<bool> (retorna se salvou com sucesso).

Testes unitários a criar

  • test/screens/show_case/show_case_detail/show_case_detail_controller_test.dart (mesma suíte das subtasks anteriores, adicionando)
    • enableEditButton == false: as 4 ações (onWillPop, viewShowCase, shareShowCase, copyLink) prosseguem direto, sem exibir modal
    • enableEditButton == true + escolha Salvar com sucesso: updateShowCase() é chamado e retorna true; a ação original prossegue usando o dado atualizado
    • enableEditButton == true + escolha Salvar falhando (validação do form inválida, ou erro de API): updateShowCase() retorna false; a ação original não prossegue
    • enableEditButton == true + escolha Não salvar: a ação original prossegue com o dado já salvo anteriormente; campos editados (nameController, expirationDate) não são resetados (continuam com o valor pendente)
    • Modal fechada sem escolher (answer == null): a ação original não prossegue; tela permanece como está
    • isCreating == true durante loading/erro (detail.value == null): enableEditButton == false → sair não exibe modal (depende do comportamento já validado na subtask 05)
    • Descrição da modal varia corretamente por ação: 'sair', 'visualizar', 'compartilhar', 'copiar o link'
    • Vale para ShowCaseType.store e ShowCaseType.sellerStock (mesmo critério enableEditButton, sem diferenciação de comportamento entre os tipos)

Critérios de aceite (RF-06)

  1. Tentar sair da tela de detalhe com enableEditButton = true exibe modal com título A vitrine possui alterações não salvas e mensagem Deseja salvar as alterações antes de sair?, opções Salvar/Não salvar (comportamento já existente, sem mudança).
  2. Tocar em Visualizar com enableEditButton = true exibe a mesma modal com Deseja salvar as alterações antes de visualizar?.
  3. Tocar em Compartilhar com enableEditButton = true exibe a mesma modal com Deseja salvar as alterações antes de compartilhar?.
  4. Tocar em Copiar link com enableEditButton = true exibe a mesma modal com Deseja salvar as alterações antes de copiar o link?.
  5. Escolher Salvar: salva as alterações e, em caso de sucesso, prossegue com a ação original usando os dados atualizados.
  6. Escolher Não salvar: prossegue com a ação original usando os dados já salvos anteriormente (sem persistir a alteração pendente).
  7. enableEditButton = false: executa a ação normalmente, sem exibir modal.
  8. Fechar a modal sem escolher: permanece na tela, sem executar a ação original.
  9. Salvar falhando (validação ou erro de API): permanece na tela, sem prosseguir com a ação original.
  10. Comportamento vale para ShowCaseType.store e ShowCaseType.sellerStock.
  11. Após Não salvar, o campo editado continua exibindo o valor pendente na tela.
  12. Sem aviso durante o modo de criação em loading ou erro.

Definição de Pronto (Definition of Done)

  • _confirmProceedWithPendingChanges() criado; os 4 pontos de entrada atualizados; updateShowCase() retornando bool.
  • Botão ATUALIZAR VITRINE (que chama controller.updateShowCase) continua funcionando sem alteração de assinatura no onPressed.
  • flutter analyze sem erros novos.
  • flutter test executando os testes listados acima, 100% verdes.
  • Projeto compila.
  • Validado manualmente que o aviso dispara ao menos pelo botão/gesto físico de voltar do Android (a seta da AppBar tem limitação conhecida, documentada à parte, e não bloqueia esta subtask).