feat: Implement account management features

- Added ExpenseDetailDialog for displaying expense details and actions.
- Created ExpensesTab to list expenses for a group.
- Developed GroupExpensesPage to manage group expenses with tabs for expenses, balances, and settlements.
- Introduced SettlementsTab to show optimized repayment plans.
- Refactored create_trip_content.dart to remove CountBloc and related logic.
- Added Account model to manage user accounts and group members.
- Replaced CountRepository with AccountRepository for account-related operations.
- Removed CountService and CountRepository as part of the refactor.
- Updated main.dart and home.dart to integrate new account management components.
This commit is contained in:
Dayron
2025-10-21 00:42:36 +02:00
parent a3ced0e812
commit c69618cbd9
21 changed files with 182 additions and 747 deletions

View File

@@ -0,0 +1,116 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../blocs/account/account_bloc.dart';
import '../../blocs/account/account_event.dart';
import '../../blocs/account/account_state.dart';
import '../../blocs/user/user_bloc.dart';
import '../../blocs/user/user_state.dart' as user_state;
import '../../data/models/group.dart';
import 'add_expense_dialog.dart';
import 'balances_tab.dart';
import 'expenses_tab.dart';
import 'settlements_tab.dart';
class GroupExpensesPage extends StatefulWidget {
final Group group;
const GroupExpensesPage({
super.key,
required this.group,
});
@override
State<GroupExpensesPage> createState() => _GroupExpensesPageState();
}
class _GroupExpensesPageState extends State<GroupExpensesPage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
context.read<CountBloc>().add(LoadExpenses(widget.group.id));
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.group.name),
bottom: TabBar(
controller: _tabController,
tabs: const [
Tab(text: 'Dépenses', icon: Icon(Icons.receipt_long)),
Tab(text: 'Balances', icon: Icon(Icons.account_balance)),
Tab(text: 'Remboursements', icon: Icon(Icons.payments)),
],
),
),
body: BlocConsumer<CountBloc, CountState>(
listener: (context, state) {
if (state is CountError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.message),
backgroundColor: Colors.red,
),
);
}
},
builder: (context, state) {
if (state is CountLoading) {
return const Center(child: CircularProgressIndicator());
}
if (state is ExpensesLoaded) {
return TabBarView(
controller: _tabController,
children: [
ExpensesTab(
expenses: state.expenses,
group: widget.group,
),
BalancesTab(balances: state.balances),
SettlementsTab(settlements: state.settlements),
],
);
}
return const Center(child: Text('Aucune donnée'));
},
),
floatingActionButton: BlocBuilder<UserBloc, user_state.UserState>(
builder: (context, userState) {
if (userState is! user_state.UserLoaded) return const SizedBox();
return FloatingActionButton.extended(
onPressed: () => _showAddExpenseDialog(context, userState.user),
icon: const Icon(Icons.add),
label: const Text('Dépense'),
);
},
),
);
}
void _showAddExpenseDialog(BuildContext context, user_state.UserModel currentUser) {
showDialog(
context: context,
builder: (dialogContext) => BlocProvider.value(
value: context.read<CountBloc>(),
child: AddExpenseDialog(
group: widget.group,
currentUser: currentUser,
),
),
);
}
}