Adds a tag selection to transaction dialog and refines the display of transactions. The changes introduce the ability to tag transactions, improving categorization and filtering. It also modifies the transaction input dialog to include time, as well as refines the appearance of transaction items on the home page by using a custom widget wrapped in a card. The UI of the summary widget is also improved by using theme colors and increasing the overall visibility.
107 lines
4.5 KiB
Dart
107 lines
4.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
import '../../../l10n/app_localizations.dart';
|
|
import '../../../models/transaction_record.dart';
|
|
|
|
/// Виджет для отображения одной транзакции в списке.
|
|
///
|
|
/// Этот виджет представляет собой карточку с подробной информацией о транзакции,
|
|
/// включая поставщика, сумму, категорию, тег и дату.
|
|
class TransactionItem extends StatelessWidget {
|
|
final TransactionRecord transaction;
|
|
|
|
const TransactionItem({super.key, required this.transaction});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final localizations = AppLocalizations.of(context)!;
|
|
final theme = Theme.of(context);
|
|
// Форматируем дату в соответствии с локалью
|
|
final formattedDate = DateFormat.yMMMd(localizations.localeName).format(transaction.dateTime);
|
|
|
|
// Убираем Card, так как обертка будет в родительском виджете.
|
|
// Добавляем разделитель и уменьшаем отступы для компактности.
|
|
return Column(
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Верхняя строка: Название поставщика и сумма
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
// Название поставщика
|
|
Expanded(
|
|
child: Text(
|
|
transaction.vendor,
|
|
style: theme.textTheme.titleSmall?.copyWith(
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
// Сумма транзакции
|
|
// Используем .abs() чтобы избежать двойного минуса для расходов
|
|
Text(
|
|
'${transaction.isIncome ? '+' : '-'}${transaction.amount.abs().toStringAsFixed(2)} ${transaction.currency}',
|
|
style: theme.textTheme.titleSmall?.copyWith(
|
|
color: transaction.isIncome
|
|
? theme.colorScheme.primary
|
|
: theme.colorScheme.error,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 8.0),
|
|
// Средняя строка: Категория и тег
|
|
Row(
|
|
children: [
|
|
// Иконка категории
|
|
Icon(
|
|
transaction.category.icon,
|
|
color: transaction.category.color,
|
|
size: 20.0, // Уменьшаем размер иконки
|
|
),
|
|
const SizedBox(width: 8.0),
|
|
// Название категории и тега
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
transaction.category.name,
|
|
style: theme.textTheme.bodySmall,
|
|
),
|
|
if (transaction.tag != null)
|
|
Text(
|
|
'#${transaction.tag!.name}',
|
|
style: theme.textTheme.bodySmall?.copyWith(
|
|
color: theme.colorScheme.onSurface.withOpacity(0.6),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
// Дата в правом углу
|
|
Text(
|
|
formattedDate,
|
|
style: theme.textTheme.bodySmall?.copyWith(
|
|
color: theme.colorScheme.onSurface.withOpacity(0.5),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
// Разделитель между транзакциями
|
|
const Divider(height: 1, thickness: 1, indent: 16, endIndent: 16),
|
|
],
|
|
);
|
|
}
|
|
}
|