import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../models/budget.dart'; import '../models/transaction.dart'; import '../services/hive_service.dart'; class CreateBudgetScreen extends StatefulWidget { const CreateBudgetScreen({super.key}); @override State createState() => _CreateBudgetScreenState(); } class _CreateBudgetScreenState extends State { final _formKey = GlobalKey(); TransactionCategory? _selectedCategory; BudgetPeriod? _selectedPeriod; final _amountController = TextEditingController(); DateTime? _selectedStartDate; DateTime? _selectedEndDate; bool _repeatBudget = false; final _noteController = TextEditingController(); late HiveService _hiveService; @override void initState() { super.initState(); _hiveService = HiveService(); } Future _selectDate(BuildContext context, bool isStart) async { final now = DateTime.now(); final initialDate = isStart ? (_selectedStartDate ?? now) : (_selectedEndDate ?? now); final picked = await showDatePicker( context: context, initialDate: initialDate, firstDate: DateTime(now.year - 5), lastDate: DateTime(now.year + 5), builder: (context, child) { return Theme( data: ThemeData.light().copyWith( colorScheme: ColorScheme.light( primary: Theme.of(context).colorScheme.primary, onPrimary: Theme.of(context).colorScheme.onPrimary, onSurface: Theme.of(context).colorScheme.onSurface, ), dialogBackgroundColor: Theme.of(context).colorScheme.surface, ), child: child!, ); }, ); if (picked != null) { setState(() { if (isStart) { _selectedStartDate = picked; } else { _selectedEndDate = picked; } }); } } Future _saveBudget() async { if (_formKey.currentState!.validate() && _selectedCategory != null && _selectedPeriod != null && _selectedStartDate != null && _selectedEndDate != null) { final budget = Budget( category: _selectedCategory!, amount: double.tryParse(_amountController.text) ?? 0.0, period: _selectedPeriod!, startDate: _selectedStartDate!, endDate: _selectedEndDate!, repeatBudget: _repeatBudget, note: _noteController.text.isNotEmpty ? _noteController.text : null, ); await _hiveService.insertBudget(budget); if (mounted) Navigator.pop(context); } } @override Widget build(BuildContext context) { final theme = Theme.of(context); return Scaffold( appBar: AppBar( title: const Text('Criar Orçamento', style: TextStyle(fontWeight: FontWeight.bold)), centerTitle: true, backgroundColor: theme.colorScheme.primary, foregroundColor: theme.colorScheme.onPrimary, ), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(24.0), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ DropdownButtonFormField( value: _selectedCategory, decoration: InputDecoration( labelText: 'Categoria', labelStyle: TextStyle(color: theme.colorScheme.onSurface), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), filled: true, fillColor: theme.colorScheme.surfaceVariant, ), items: TransactionCategory.values .map((cat) => DropdownMenuItem( value: cat, child: Text( _getCategoryName(cat), style: TextStyle(color: theme.colorScheme.onSurface), ), )) .toList(), onChanged: (val) => setState(() => _selectedCategory = val), validator: (val) => val == null ? 'Selecione a categoria' : null, ), const SizedBox(height: 16), TextFormField( controller: _amountController, keyboardType: TextInputType.number, decoration: InputDecoration( labelText: 'Valor do orçamento', labelStyle: TextStyle(color: theme.colorScheme.onSurface), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), prefixText: '€ ', filled: true, fillColor: theme.colorScheme.surfaceVariant, ), validator: (val) { if (val == null || val.isEmpty) { return 'Informe o valor'; } if (double.tryParse(val) == null) { return 'Insira um número válido'; } return null; }, ), const SizedBox(height: 16), DropdownButtonFormField( value: _selectedPeriod, decoration: InputDecoration( labelText: 'Período', labelStyle: TextStyle(color: theme.colorScheme.onSurface), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), filled: true, fillColor: theme.colorScheme.surfaceVariant, ), items: BudgetPeriod.values .map((period) => DropdownMenuItem( value: period, child: Text( _getPeriodName(period), style: TextStyle(color: theme.colorScheme.onSurface), ), )) .toList(), onChanged: (val) => setState(() => _selectedPeriod = val), validator: (val) => val == null ? 'Selecione o período' : null, ), const SizedBox(height: 16), _buildDateSelectionTile( context, isStart: true, label: 'Data inicial', date: _selectedStartDate, ), const SizedBox(height: 16), _buildDateSelectionTile( context, isStart: false, label: 'Data final', date: _selectedEndDate, ), const SizedBox(height: 16), SwitchListTile( title: const Text('Repetir orçamento'), value: _repeatBudget, onChanged: (val) => setState(() => _repeatBudget = val), tileColor: theme.colorScheme.surfaceVariant, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), const SizedBox(height: 16), TextFormField( controller: _noteController, decoration: InputDecoration( labelText: 'Observação (opcional)', labelStyle: TextStyle(color: theme.colorScheme.onSurface), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), filled: true, fillColor: theme.colorScheme.surfaceVariant, ), maxLines: 2, ), const SizedBox(height: 32), ElevatedButton( onPressed: _saveBudget, style: ElevatedButton.styleFrom( backgroundColor: theme.colorScheme.primary, foregroundColor: theme.colorScheme.onPrimary, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: const Text('Salvar'), ), ], ), ), ), ), ); } Widget _buildDateSelectionTile(BuildContext context, {required bool isStart, required String label, DateTime? date}) { final theme = Theme.of(context); final isSelected = date != null; return InkWell( onTap: () => _selectDate(context, isStart), borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: theme.colorScheme.surfaceVariant, borderRadius: BorderRadius.circular(12), border: Border.all( color: isSelected ? theme.colorScheme.primary : Colors.transparent, width: 2, ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: theme.textTheme.labelMedium!.copyWith( color: theme.colorScheme.onSurface.withOpacity(0.6)), ), const SizedBox(height: 4), Text( isSelected ? DateFormat('dd/MM/yyyy').format(date!) : 'Selecione a data', style: theme.textTheme.bodyLarge!.copyWith( color: isSelected ? theme.colorScheme.onSurface : theme.colorScheme.onSurface.withOpacity(0.8)), ), ], ), Icon(Icons.calendar_today, color: theme.colorScheme.primary), ], ), ), ); } String _getCategoryName(TransactionCategory category) { switch (category) { case TransactionCategory.food: return 'Alimentação'; case TransactionCategory.utilities: return 'Contas'; case TransactionCategory.shopping: return 'Compras'; case TransactionCategory.education: return 'Educação'; case TransactionCategory.salary: return 'Salário'; case TransactionCategory.freelance: return 'Freelance'; case TransactionCategory.invest: return 'Investimentos'; case TransactionCategory.business: return 'Negócios'; case TransactionCategory.transport: return 'Transporte'; case TransactionCategory.medical: return 'Saúde'; case TransactionCategory.social: return 'Social'; case TransactionCategory.leisure: return 'Lazer'; case TransactionCategory.others: return 'Outros'; case TransactionCategory.house: return 'Casa'; case TransactionCategory.subscriptions: return 'Assinaturas'; default: return category.name; } } String _getPeriodName(BudgetPeriod period) { switch (period) { case BudgetPeriod.week: return 'Semanal'; case BudgetPeriod.month: return 'Mensal'; case BudgetPeriod.quarter: return 'Trimestral'; case BudgetPeriod.year: return 'Anual'; default: return period.name; } } }