feat: Enhance documentation for AddExpenseDialog, BalancesTab, and ExpenseDetailDialog with detailed comments and usage examples
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
/// This file defines the `ExpenseDetailDialog` widget, which provides a detailed view of a specific expense
|
||||
/// within a group. It allows users to view expense details, such as the amount, payer, date, and splits, and
|
||||
/// perform actions like editing, deleting, or archiving the expense.
|
||||
///
|
||||
/// The dialog is highly interactive and adapts its UI based on the current user's permissions and the state
|
||||
/// of the expense. It also integrates with BLoC for state management and supports features like receipt display
|
||||
/// and split payment marking.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
@@ -10,10 +18,20 @@ import '../../models/expense.dart';
|
||||
import '../../models/group.dart';
|
||||
import 'add_expense_dialog.dart';
|
||||
|
||||
/// A stateless widget that displays detailed information about a specific expense.
|
||||
///
|
||||
/// The `ExpenseDetailDialog` widget shows the expense's amount, payer, date, splits, and receipt. It also
|
||||
/// provides actions for editing, deleting, or archiving the expense, depending on the current user's permissions.
|
||||
class ExpenseDetailDialog extends StatelessWidget {
|
||||
/// The expense to display details for.
|
||||
final Expense expense;
|
||||
|
||||
/// The group to which the expense belongs.
|
||||
final Group group;
|
||||
|
||||
/// Creates an `ExpenseDetailDialog` widget.
|
||||
///
|
||||
/// The [expense] and [group] parameters must not be null.
|
||||
const ExpenseDetailDialog({
|
||||
super.key,
|
||||
required this.expense,
|
||||
@@ -22,11 +40,13 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Formatters for displaying dates and times.
|
||||
final dateFormat = DateFormat('dd MMMM yyyy');
|
||||
final timeFormat = DateFormat('HH:mm');
|
||||
|
||||
return BlocBuilder<UserBloc, user_state.UserState>(
|
||||
builder: (context, userState) {
|
||||
// Determine the current user and their permissions.
|
||||
final currentUser = userState is user_state.UserLoaded ? userState.user : null;
|
||||
final canEdit = currentUser?.id == expense.paidById;
|
||||
|
||||
@@ -39,6 +59,7 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
automaticallyImplyLeading: false,
|
||||
actions: [
|
||||
if (canEdit) ...[
|
||||
// Edit button.
|
||||
IconButton(
|
||||
icon: const Icon(Icons.edit),
|
||||
onPressed: () {
|
||||
@@ -46,11 +67,13 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
_showEditDialog(context, currentUser!);
|
||||
},
|
||||
),
|
||||
// Delete button.
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete, color: Colors.red),
|
||||
onPressed: () => _confirmDelete(context),
|
||||
),
|
||||
],
|
||||
// Close button.
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
@@ -60,7 +83,7 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
// En-tête avec icône
|
||||
// Header with icon and description.
|
||||
Center(
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -99,7 +122,7 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Montant
|
||||
// Amount card.
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
@@ -127,11 +150,11 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Informations
|
||||
// Information rows.
|
||||
_buildInfoRow(Icons.person, 'Payé par', expense.paidByName),
|
||||
_buildInfoRow(Icons.calendar_today, 'Date', dateFormat.format(expense.date)),
|
||||
_buildInfoRow(Icons.access_time, 'Heure', timeFormat.format(expense.createdAt)),
|
||||
|
||||
|
||||
if (expense.isEdited && expense.editedAt != null)
|
||||
_buildInfoRow(
|
||||
Icons.edit,
|
||||
@@ -143,7 +166,7 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
const Divider(),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
// Divisions
|
||||
// Splits section.
|
||||
const Text(
|
||||
'Répartition',
|
||||
style: TextStyle(
|
||||
@@ -156,7 +179,7 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Reçu
|
||||
// Receipt section.
|
||||
if (expense.receiptUrl != null) ...[
|
||||
const Divider(),
|
||||
const SizedBox(height: 8),
|
||||
@@ -188,7 +211,7 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Bouton archiver
|
||||
// Archive button.
|
||||
if (!expense.isArchived && canEdit)
|
||||
OutlinedButton.icon(
|
||||
onPressed: () => _confirmArchive(context),
|
||||
@@ -204,6 +227,7 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// Builds a row displaying an icon, a label, and a value.
|
||||
Widget _buildInfoRow(IconData icon, String label, String value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
@@ -231,6 +255,10 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// Builds a tile displaying details about a split in the expense.
|
||||
///
|
||||
/// The tile shows the user's name, the split amount, and whether the split is paid. If the current user
|
||||
/// is responsible for the split and it is unpaid, a button is provided to mark it as paid.
|
||||
Widget _buildSplitTile(BuildContext context, ExpenseSplit split) {
|
||||
return BlocBuilder<UserBloc, user_state.UserState>(
|
||||
builder: (context, userState) {
|
||||
@@ -283,6 +311,7 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// Shows a dialog for editing the expense.
|
||||
void _showEditDialog(BuildContext context, user_state.UserModel currentUser) {
|
||||
showDialog(
|
||||
context: context,
|
||||
@@ -297,6 +326,7 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// Shows a confirmation dialog for deleting the expense.
|
||||
void _confirmDelete(BuildContext context) {
|
||||
showDialog(
|
||||
context: context,
|
||||
@@ -324,6 +354,7 @@ class ExpenseDetailDialog extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// Shows a confirmation dialog for archiving the expense.
|
||||
void _confirmArchive(BuildContext context) {
|
||||
showDialog(
|
||||
context: context,
|
||||
|
||||
Reference in New Issue
Block a user