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 emonWillPop()/viewShowCase()/shareShowCase()/copyLink()/updateShowCase(). - Fora de escopo (não fazer parte desta subtask): correção do botão de voltar da
ZzAppBarque hoje ignoraonWillPop()— vercontext/bug-appbar-back-button-ignora-onwillpop.md(débito técnico registrado separadamente, sem solução decidida). O botãoEXCLUIR VITRINEtambém fica fora — usa somente sua confirmação de exclusão já existente.
Arquivos a modificar
| Arquivo | Modificaçã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 modalenableEditButton == true+ escolhaSalvarcom sucesso:updateShowCase()é chamado e retornatrue; a ação original prossegue usando o dado atualizadoenableEditButton == true+ escolhaSalvarfalhando (validação do form inválida, ou erro de API):updateShowCase()retornafalse; a ação original não prossegueenableEditButton == true+ escolhaNã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 == truedurante 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.storeeShowCaseType.sellerStock(mesmo critérioenableEditButton, sem diferenciação de comportamento entre os tipos)
Critérios de aceite (RF-06)
- Tentar sair da tela de detalhe com
enableEditButton = trueexibe modal com títuloA vitrine possui alterações não salvase mensagemDeseja salvar as alterações antes de sair?, opçõesSalvar/Não salvar(comportamento já existente, sem mudança). - Tocar em
VisualizarcomenableEditButton = trueexibe a mesma modal comDeseja salvar as alterações antes de visualizar?. - Tocar em
CompartilharcomenableEditButton = trueexibe a mesma modal comDeseja salvar as alterações antes de compartilhar?. - Tocar em
Copiar linkcomenableEditButton = trueexibe a mesma modal comDeseja salvar as alterações antes de copiar o link?. - Escolher
Salvar: salva as alterações e, em caso de sucesso, prossegue com a ação original usando os dados atualizados. - Escolher
Não salvar: prossegue com a ação original usando os dados já salvos anteriormente (sem persistir a alteração pendente). enableEditButton = false: executa a ação normalmente, sem exibir modal.- Fechar a modal sem escolher: permanece na tela, sem executar a ação original.
Salvarfalhando (validação ou erro de API): permanece na tela, sem prosseguir com a ação original.- Comportamento vale para
ShowCaseType.storeeShowCaseType.sellerStock. - Após
Não salvar, o campo editado continua exibindo o valor pendente na tela. - 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()retornandobool. - Botão
ATUALIZAR VITRINE(que chamacontroller.updateShowCase) continua funcionando sem alteração de assinatura noonPressed. -
flutter analyzesem erros novos. -
flutter testexecutando 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).