import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:logging/logging.dart'; import 'package:moneymgr_mobile/services/storage/expenses.dart'; import 'package:moneymgr_mobile/utils/extensions.dart'; import 'package:moneymgr_mobile/widgets/expense_editor.dart'; import 'package:moneymgr_mobile/widgets/full_screen_error.dart'; import 'package:moneymgr_mobile/widgets/loading_scaffold.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'scan_details.g.dart'; @riverpod Future<(Expense, Uint8List)?> _getExpense(Ref ref, {required int id}) async { final expProvider = ref.watch(expensesProvider).requireValue; final expense = await expProvider.getById(id); if (expense == null) return null; final file = await expProvider.loadFile(expense); return (expense, file); } class ScanDetailScreen extends HookConsumerWidget { final int id; const ScanDetailScreen({super.key, required this.id}); @override Widget build(BuildContext context, WidgetRef ref) { final expenses = ref.watch(expensesProvider).requireValue; final expense = ref.watch(_getExpenseProvider(id: id)); handleUpdate(BaseExpenseInfo newInfo) async { try { await expenses.updateExpense(expense.requireValue!.$1, newInfo); if (context.mounted) { context.pop(); } ref.invalidate(expensesProvider); } catch (e, s) { Logger.root.warning("Failed to update expense! $e$s"); if (context.mounted) { context.showTextSnackBar("Failed to update expense! $e"); } } } handleDelete() async { try { await expenses.deleteExpense(expense.requireValue!.$1); if (context.mounted) { context.pop(); } ref.invalidate(expensesProvider); } catch (e, s) { Logger.root.warning("Failed to delete expense! $e$s"); if (context.mounted) { context.showTextSnackBar("Failed to delete expense! $e"); } } } return switch (expense) { AsyncData(:final value) when value == null => FullScreenError( message: "Expense does not exists!", error: 'NONE', ), AsyncData(:final value) => ExpenseEditor( file: value!.$2, initialData: value.$1.baseExpense, onFinished: handleUpdate, onDelete: handleDelete, ), AsyncError(:final error) => FullScreenError( message: "Failed to load expense information!", error: error.toString(), ), _ => LoadingScaffold(title: "Expense $id"), }; } }