import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rluv/features/budget/widgets/transaction_list_item.dart'; import 'package:rluv/global/styles.dart'; import 'package:rluv/models/transaction_model.dart'; import '../../../global/store.dart'; import '../../../models/budget_category_model.dart'; class TransactionsListview extends ConsumerStatefulWidget { const TransactionsListview({super.key}); @override ConsumerState createState() => _TransactionsListviewState(); } class _TransactionsListviewState extends ConsumerState { final scaffoldKey = GlobalKey(); @override void initState() { // TODO: implement initState WidgetsBinding.instance.addPostFrameCallback((_) { ref.read(selectedTransactionSortProvider.notifier).state = TransactionSort.all; ref.read(selectedSortDateProvider.notifier).state = SortDate.decending; }); super.initState(); } @override Widget build(BuildContext context) { final budgetCategories = ref.watch(budgetCategoriesProvider); if (ref.read(selectedCategory) == null && budgetCategories.isNotEmpty) { WidgetsBinding.instance .addPostFrameCallback((_) => ref.read(selectedCategory.notifier).state = budgetCategories.first); } final sortType = ref.watch(selectedTransactionSortProvider); final sortDate = ref.watch(selectedSortDateProvider); List transactions = [...ref.watch(transactionsProvider)]; // Removes transactions by category switch (sortType) { case TransactionSort.income: transactions = transactions .where( (element) => element.type == TransactionType.income, ) .toList(); break; case TransactionSort.expense: transactions = transactions .where( (element) => element.type == TransactionType.expense, ) .toList(); break; case TransactionSort.category: if (ref.read(selectedCategory) != null) { transactions = transactions .where( (element) => element.budgetCategoryId == ref.read(selectedCategory)!.id, ) .toList(); } break; case TransactionSort.all: break; } // Sorts transactions by date switch (sortDate) { case SortDate.ascending: transactions.sort((a, b) => a.date.compareTo(b.date)); break; case SortDate.decending: transactions.sort((a, b) => b.date.compareTo(a.date)); break; } WidgetsBinding.instance .addPostFrameCallback((_) => ref.read(transactionHistoryListProvider.notifier).state = transactions); return Scaffold( endDrawer: Drawer( backgroundColor: Styles.purpleNurple, child: SafeArea( child: Column( children: [ SizedBox(height: MediaQuery.of(context).size.height * 0.15), DropdownButton( dropdownColor: Styles.lavender, value: ref.watch(selectedTransactionSortProvider), items: TransactionSort.values .map( (e) => DropdownMenuItem( value: e, child: Row( mainAxisSize: MainAxisSize.min, children: [ sortTypeToIcon(e), const SizedBox(width: 12), Text(e.name), ], ), ), ) .toList(), onChanged: (TransactionSort? value) { if (value != null) { ref.read(selectedTransactionSortProvider.notifier).state = value; } }), const SizedBox(height: 20), DropdownButton( dropdownColor: Styles.lavender, value: ref.watch(selectedSortDateProvider), items: SortDate.values .map( (e) => DropdownMenuItem( value: e, child: Row( mainAxisSize: MainAxisSize.min, children: [ sortDateToIcon(e), const SizedBox(width: 12), Text(e.name), ], ), ), ) .toList(), onChanged: (SortDate? value) { if (value != null) { ref.read(selectedSortDateProvider.notifier).state = value; } }), const SizedBox(height: 20), if (ref.read(selectedTransactionSortProvider) == TransactionSort.category) DropdownButton( dropdownColor: Styles.lavender, value: ref.watch(selectedCategory), items: budgetCategories .map( (e) => DropdownMenuItem( value: e, child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( height: 18, width: 18, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all(color: Colors.black, width: 1.5), color: e.color, ), ), const SizedBox(width: 12), Text(e.name), ], ), ), ) .toList(), onChanged: (BudgetCategory? value) { if (value != null) { ref.read(selectedCategory.notifier).state = value; } }, ), ], ), ), ), key: scaffoldKey, backgroundColor: Styles.purpleNurple, body: SafeArea( child: Stack( children: [ if (transactions.isEmpty) ...[ Align( alignment: Alignment.topLeft, child: Padding( padding: const EdgeInsets.only(left: 8.0, top: 16.0), child: IconButton(icon: const Icon(Icons.chevron_left), onPressed: () => Navigator.pop(context)), ), ), const Center( child: Text('No transactions'), ), ], if (transactions.isNotEmpty) Column( children: [ Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.only(left: 8.0, top: 16.0), child: IconButton(icon: const Icon(Icons.chevron_left), onPressed: () => Navigator.pop(context)), ), const Spacer(), const Padding( padding: EdgeInsets.symmetric(vertical: 18.0, horizontal: 0.0), child: Text( 'Transaction History', style: TextStyle(fontSize: 28), textAlign: TextAlign.center, ), ), const Spacer(), Padding( padding: const EdgeInsets.only(left: 8.0, top: 16.0), child: IconButton( icon: const Icon(Icons.sort), onPressed: () { toggleDrawer(); }), ), ]), Expanded( child: ListView.builder( physics: const BouncingScrollPhysics(), itemCount: transactions.length, itemBuilder: (BuildContext context, int index) { return TransactionListItem( index: index, ); }, ), ), ], ), ], ), ), ); } void toggleDrawer() { if (scaffoldKey.currentState != null && scaffoldKey.currentState!.isDrawerOpen) { scaffoldKey.currentState!.openDrawer(); } else if (scaffoldKey.currentState != null) { scaffoldKey.currentState!.openEndDrawer(); } } } enum TransactionSort { all, income, expense, category, } enum SortDate { decending, ascending, } Icon sortTypeToIcon(TransactionSort s) { switch (s) { case TransactionSort.all: return const Icon(Icons.donut_large); case TransactionSort.income: return const Icon(Icons.attach_money); case TransactionSort.expense: return const Icon(Icons.shopping_bag); case TransactionSort.category: return const Icon(Icons.sort); } } Icon sortDateToIcon(SortDate s) { switch (s) { case SortDate.ascending: return const Icon(Icons.arrow_circle_up); case SortDate.decending: return const Icon(Icons.arrow_circle_down); } } final selectedTransactionSortProvider = StateProvider( (ref) => TransactionSort.all, ); final selectedSortDateProvider = StateProvider((ref) => SortDate.decending); final transactionHistoryListProvider = StateProvider>( (ref) => [], ); final selectedCategory = StateProvider((ref) => null);