import 'package:flutter/material.dart'; import '../di/injector.dart'; import '../i18n/strings.g.dart'; import '../services/export_import_service.dart'; /// The three backup actions shown in Settings: export CSV, export JSON and /// import JSON. Import asks for confirmation first (it merges into the live /// inventory), then reports what happened in a SnackBar. class BackupSection extends StatelessWidget { const BackupSection({this.service, super.key}); /// Injectable for widget tests; the app resolves it lazily (on tap) from /// the service locator so merely mounting Settings needs no DI setup. final ExportImportService? service; ExportImportService get _service => service ?? getIt(); @override Widget build(BuildContext context) { final t = context.t; return Column( children: [ ListTile( leading: const Icon(Icons.table_view_outlined), title: Text(t.backup.exportCsv), subtitle: Text(t.backup.exportCsvSubtitle), onTap: () => _runExport(context, () => _service.exportCsv()), ), ListTile( leading: const Icon(Icons.file_download_outlined), title: Text(t.backup.exportJson), subtitle: Text(t.backup.exportJsonSubtitle), onTap: () => _runExport(context, () => _service.exportJson()), ), ListTile( leading: const Icon(Icons.file_upload_outlined), title: Text(t.backup.importJson), subtitle: Text(t.backup.importJsonSubtitle), onTap: () => _runImport(context), ), ListTile( leading: const Icon(Icons.playlist_add_outlined), title: Text(t.backup.importCsv), subtitle: Text(t.backup.importCsvSubtitle), onTap: () => _runImportCsv(context), ), ], ); } Future _runExport( BuildContext context, Future Function() export, ) async { final t = context.t; final messenger = ScaffoldMessenger.of(context); try { final saved = await export(); _show(messenger, saved ? t.backup.exportSaved : t.backup.cancelled); } on Object { _show(messenger, t.backup.failed); } } Future _runImport(BuildContext context) async { final t = context.t; final messenger = ScaffoldMessenger.of(context); final confirmed = await showDialog( context: context, builder: (dialogContext) => AlertDialog( title: Text(t.backup.importConfirmTitle), content: Text(t.backup.importConfirmBody), actions: [ TextButton( onPressed: () => Navigator.of(dialogContext).pop(false), child: Text(t.common.cancel), ), FilledButton( onPressed: () => Navigator.of(dialogContext).pop(true), child: Text(t.backup.importAction), ), ], ), ); if (confirmed != true) return; try { final summary = await _service.importJson(); _show( messenger, summary == null ? t.backup.cancelled : t.backup.importDone( added: summary.inserted, updated: summary.updated, ), ); } on FormatException { _show(messenger, t.backup.importFailed); } on Object { _show(messenger, t.backup.failed); } } Future _runImportCsv(BuildContext context) async { final t = context.t; final messenger = ScaffoldMessenger.of(context); final confirmed = await showDialog( context: context, builder: (dialogContext) => AlertDialog( title: Text(t.backup.importCsvConfirmTitle), content: Text(t.backup.importCsvConfirmBody), actions: [ TextButton( onPressed: () => Navigator.of(dialogContext).pop(false), child: Text(t.common.cancel), ), FilledButton( onPressed: () => Navigator.of(dialogContext).pop(true), child: Text(t.backup.importAction), ), ], ), ); if (confirmed != true) return; try { final summary = await _service.importCsv(); _show( messenger, summary == null ? t.backup.cancelled : t.backup.importCsvDone(count: summary.inserted), ); } on FormatException { _show(messenger, t.backup.importFailed); } on Object { _show(messenger, t.backup.failed); } } void _show(ScaffoldMessengerState messenger, String message) { messenger.showSnackBar(SnackBar(content: Text(message))); } }