import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:helpers/helpers.dart'; import 'package:rluv/features/budget/screens/transactions_listview.dart'; import 'package:rluv/features/budget/widgets/add_transaction_dialog.dart'; import 'package:rluv/features/budget/widgets/budget_category_bar.dart'; import 'package:rluv/features/budget/widgets/budget_net_bar.dart'; import 'package:rluv/global/styles.dart'; import 'package:rluv/global/utils.dart'; import '../../../global/store.dart'; import '../../../global/widgets/ui_button.dart'; import '../../../models/transaction_model.dart'; import '../widgets/add_budget_category_dialog.dart'; class BudgetOverviewScreen extends ConsumerStatefulWidget { const BudgetOverviewScreen({super.key, required this.initialData}); final Map initialData; @override ConsumerState createState() => _BudgetOverviewScreenState(); } class _BudgetOverviewScreenState extends ConsumerState { final budgetListScrollController = ScrollController(); @override Widget build(BuildContext context) { final budget = ref.watch(budgetProvider); final budgetCategories = ref.watch(budgetCategoriesProvider); final transactions = ref.watch(transactionsProvider); final screen = BuildMedia(context).size; double netExpense = 0.0; double netIncome = 0.0; double expectedExpenses = 0.0; Map budgetCategoryNetMap = {}; netExpense = transactions .where((t) => t.type == TransactionType.expense) .fold(netExpense, (net, t) => net + t.amount); netIncome = transactions .where((t) => t.type == TransactionType.income) .fold(netIncome, (net, t) => net + t.amount); for (final bud in budgetCategories) { double net = 0.0; expectedExpenses += bud.amount; net = transactions .where((t) => t.budgetCategoryId == bud.id) .fold(net, (net, t) => net + t.amount); budgetCategoryNetMap[bud.id!] = net; } return Stack( children: [ Column( children: [ /// TOP HALF, TITLE & OVERVIEW Container( height: screen.height * 0.3, width: screen.width, color: Styles.purpleNurple, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ const Spacer(flex: 2), Text( formatDate(DateTime.now()), style: const TextStyle( fontSize: 16, color: Styles.electricBlue), ), const Spacer(), const Text('MONTHLY', style: TextStyle(fontSize: 42, color: Styles.electricBlue)), const Spacer(flex: 2), BudgetNetBar( isPositive: true, net: netIncome, expected: budget?.expectedIncome ?? 0.0), const Spacer(), BudgetNetBar( isPositive: false, net: netExpense, expected: expectedExpenses), const Spacer(), ], ), ), /// BOTTOM HALF, BUDGET BREAKDOWN Expanded( child: Container( color: Styles.sunflower, width: screen.width, child: Column( mainAxisSize: MainAxisSize.max, children: [ Padding( padding: const EdgeInsets.all(14.0), child: Container( decoration: BoxDecoration( color: Styles.blushingPink, borderRadius: BorderRadius.circular(16.0), ), child: Column( children: [ const Padding( padding: EdgeInsets.all(8.0), child: Text( 'BUDGET', style: TextStyle( fontSize: 28, color: Styles.electricBlue), ), ), budgetCategories.isEmpty ? Padding( padding: const EdgeInsets.all(8.0), child: SizedBox( width: screen.width * 0.8, child: Column( children: [ const Padding( padding: EdgeInsets.all(8.0), child: Text( 'No budget categories created yet, add some!'), ), UiButton( onPressed: ref.watch(budgetProvider) == null ? null : () => showDialog( context: context, builder: (context) => Dialog( shape: Styles .dialogShape, backgroundColor: Styles .dialogColor, child: const BudgetCategoryDialog()), ), text: 'Add Category', ), ], ), ), ) : Padding( padding: const EdgeInsets.symmetric( horizontal: 2.0, vertical: 4.0), child: SizedBox( height: screen.height * 0.36, child: Scrollbar( controller: budgetListScrollController, thumbVisibility: true, child: ListView( physics: const BouncingScrollPhysics(), controller: budgetListScrollController, shrinkWrap: true, children: [ ...budgetCategories .mapIndexed((i, category) { return BudgetCategoryBar( budgetCategory: category, currentAmount: budgetCategoryNetMap[ category.id]!, index: i, ); }).toList(), const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 140, child: ElevatedButton( onPressed: ref.watch( budgetProvider) == null ? null : () => showDialog( context: context, builder: (context) => Dialog( shape: Styles .dialogShape, backgroundColor: Styles .dialogColor, child: const BudgetCategoryDialog()), ), child: const Text( 'Add Category'), ), ), ], ), const SizedBox(height: 20), ], ), ), ), ), ], ), ), ), const Spacer(), Row( children: [ Expanded( child: Padding( padding: const EdgeInsets.only(left: 20.0, right: 15.0), child: Container( height: 70, decoration: BoxDecoration( color: Styles.seaweedGreen, borderRadius: BorderRadius.circular(15.0), ), child: InkWell( child: const Center( child: Padding( padding: EdgeInsets.symmetric( horizontal: 20.0, vertical: 14.0), child: FittedBox( child: Text( 'Transaction History', textAlign: TextAlign.center, style: TextStyle(fontSize: 25), ), ), ), ), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => const TransactionsListview())); }, ), ), ), ), Padding( padding: const EdgeInsets.only(right: 20.0), child: Container( decoration: BoxDecoration( color: Styles.purpleNurple, borderRadius: BorderRadius.circular(40.0), ), height: 80, width: 80, child: IconButton( icon: const Icon( Icons.add, size: 48, color: Styles.lavender, ), onPressed: () { showDialog( context: context, builder: (BuildContext context) { return Dialog( backgroundColor: Styles.dialogColor, shape: Styles.dialogShape, child: const TransactionDialog()); }, ); }, ), ), ), ], ), const Spacer(), ], ), ), ) ], ), Align( alignment: Alignment.topRight, child: Padding( padding: const EdgeInsets.only(top: 5.0, right: 5.0), child: IconButton( icon: const Icon(Icons.loop), color: Styles.seaweedGreen, onPressed: () => ref.read(dashboardProvider.notifier).fetchDashboard(), ), ), ), IgnorePointer( child: AnimatedOpacity( duration: const Duration(milliseconds: 150), opacity: ref.watch(loadingStateProvider) ? 0.75 : 0.0, child: Container( color: Colors.black12, height: screen.height, width: screen.width, child: const Center( child: CircularProgressIndicator( color: Styles.lavender, strokeWidth: 2.5, ), ), ), ), ) ], ); } }