import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import 'package:uuid/uuid.dart'; import '../models/transaction_model.dart'; import '../providers/expense_provider.dart'; class AddTransactionScreen extends StatefulWidget { const AddTransactionScreen({super.key}); @override State createState() => _AddTransactionScreenState(); } class _AddTransactionScreenState extends State { final _formKey = GlobalKey(); final _amountController = TextEditingController(); final _noteController = TextEditingController(); DateTime _selectedDate = DateTime.now(); String _transactionType = 'expense'; int? _selectedCategoryId; @override Widget build(BuildContext context) { final provider = Provider.of(context); // Flatten categories with hierarchy logic for display final List> categoryItems = []; final rootCategories = provider.rootCategories.where((c) => c.type == _transactionType).toList(); for (var root in rootCategories) { // Add Root categoryItems.add( DropdownMenuItem( value: root.id, child: Row( children: [ Icon(_getIconData(root.icon), color: Color(root.color), size: 20), const SizedBox(width: 8), Text(root.name, style: const TextStyle(fontWeight: FontWeight.bold)), ], ), ), ); // Add Children final children = provider.getSubCategories(root.id!); for (var child in children) { categoryItems.add( DropdownMenuItem( value: child.id, child: Row( children: [ const SizedBox(width: 24), // Indent Icon(_getIconData(child.icon), color: Color(child.color), size: 16), const SizedBox(width: 8), Text(child.name), ], ), ), ); } } return Scaffold( appBar: AppBar( title: const Text('记一笔'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Form( key: _formKey, child: ListView( children: [ // Type Selection RadioGroup( groupValue: _transactionType, onChanged: (value) { setState(() { _transactionType = value!; _selectedCategoryId = null; }); }, child: Row( children: [ Expanded( child: RadioListTile( title: const Text('支出'), value: 'expense', ), ), Expanded( child: RadioListTile( title: const Text('收入'), value: 'income', ), ), ], ), ), // Amount TextFormField( controller: _amountController, keyboardType: TextInputType.number, decoration: const InputDecoration( labelText: '金额', prefixText: '¥ ', ), validator: (value) { if (value == null || value.isEmpty) { return '请输入金额'; } if (double.tryParse(value) == null) { return '请输入有效的数字'; } return null; }, ), const SizedBox(height: 16), // Category DropdownButtonFormField( key: ValueKey(_selectedCategoryId), initialValue: _selectedCategoryId, decoration: const InputDecoration(labelText: '分类'), items: categoryItems, onChanged: (value) { setState(() { _selectedCategoryId = value; }); }, validator: (value) { if (value == null) { return '请选择分类'; } return null; }, ), const SizedBox(height: 16), // Date Picker Row( children: [ Text('日期: ${DateFormat('yyyy-MM-dd').format(_selectedDate)}'), const Spacer(), TextButton( onPressed: () async { final pickedDate = await showDatePicker( context: context, initialDate: _selectedDate, firstDate: DateTime(2000), lastDate: DateTime(2100), helpText: '选择日期', ); if (pickedDate != null) { setState(() { _selectedDate = pickedDate; }); } }, child: const Text('选择日期'), ), ], ), const SizedBox(height: 16), // Note TextFormField( controller: _noteController, decoration: const InputDecoration(labelText: '备注'), ), const SizedBox(height: 32), ElevatedButton( onPressed: _saveTransaction, style: ElevatedButton.styleFrom( minimumSize: const Size(double.infinity, 50), ), child: const Text('保存', style: TextStyle(fontSize: 18)), ), ], ), ), ), ); } void _saveTransaction() { if (_formKey.currentState!.validate()) { final newTransaction = TransactionModel( id: const Uuid().v4(), amount: double.parse(_amountController.text), type: _transactionType, categoryId: _selectedCategoryId!, date: _selectedDate, note: _noteController.text, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); Provider.of(context, listen: false).addTransaction(newTransaction); Navigator.of(context).pop(); } } IconData _getIconData(String iconName) { switch (iconName) { case 'restaurant': return Icons.restaurant; case 'directions_bus': return Icons.directions_bus; case 'shopping_cart': return Icons.shopping_cart; case 'movie': return Icons.movie; case 'local_hospital': return Icons.local_hospital; case 'attach_money': return Icons.attach_money; case 'trending_up': return Icons.trending_up; case 'breakfast_dining': return Icons.breakfast_dining; case 'lunch_dining': return Icons.lunch_dining; case 'dinner_dining': return Icons.dinner_dining; case 'subway': return Icons.subway; case 'local_taxi': return Icons.local_taxi; default: return Icons.category; } } }