import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:barber_app/core/database/database_service.dart'; import 'package:barber_app/core/theme/app_theme.dart'; import 'package:barber_app/core/constants/app_strings.dart'; import 'package:barber_app/features/haircuts/data/models/haircut_model.dart'; import 'package:barber_app/features/haircuts/data/repositories/haircut_repository.dart'; import 'package:barber_app/features/haircuts/presentation/pages/add_haircut_page.dart'; class HaircutsPage extends StatefulWidget { const HaircutsPage({super.key}); @override State createState() => _HaircutsPageState(); } class _HaircutsPageState extends State with SingleTickerProviderStateMixin { late TabController _tabController; final _haircutRepo = HaircutRepository(); final _currencyFormat = NumberFormat.currency(locale: 'pt_BR', symbol: 'R\$'); String _searchQuery = ''; DateTime? _selectedDate; @override void initState() { super.initState(); _tabController = TabController(length: 3, vsync: this); } @override void dispose() { _tabController.dispose(); super.dispose(); } void _refreshData() { setState(() {}); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text(AppStrings.haircuts), bottom: PreferredSize( preferredSize: const Size.fromHeight(110), child: Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), child: TextField( onChanged: (value) => setState(() => _searchQuery = value), decoration: InputDecoration( hintText: 'Buscar cliente ou serviço...', prefixIcon: Icon( Icons.search, color: AppColors.textSecondary, ), filled: true, fillColor: AppColors.surface, contentPadding: const EdgeInsets.symmetric(vertical: 0), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ), ), ), ), TabBar( controller: _tabController, labelColor: AppColors.primaryColor, unselectedLabelColor: AppColors.textSecondary, indicatorColor: AppColors.primaryColor, tabs: const [ Tab(text: 'Hoje'), Tab(text: 'Semana'), Tab(text: 'Mês'), ], ), ], ), ), actions: [ IconButton( icon: Icon( Icons.calendar_month, color: _selectedDate != null ? AppColors.primaryColor : null, ), onPressed: () async { final picked = await showDatePicker( context: context, initialDate: _selectedDate ?? DateTime.now(), firstDate: DateTime(2020), lastDate: DateTime(2030), ); setState(() => _selectedDate = picked); }, ), ], ), body: ValueListenableBuilder( valueListenable: DatabaseService.haircutsBoxInstance.listenable(), builder: (context, _, _) { return TabBarView( controller: _tabController, children: [ _buildHaircutList( _filterHaircuts(_haircutRepo.getTodayHaircuts()), ), _buildHaircutList( _filterHaircuts(_haircutRepo.getWeekHaircuts()), ), _buildHaircutList( _filterHaircuts(_haircutRepo.getMonthHaircuts()), ), ], ); }, ), floatingActionButton: Padding( padding: const EdgeInsets.only(bottom: 80), child: FloatingActionButton.extended( heroTag: 'haircuts_fab', onPressed: () async { await Navigator.push( context, MaterialPageRoute(builder: (_) => const AddHaircutPage()), ); _refreshData(); }, icon: const Icon(Icons.add), label: const Text(AppStrings.newHaircut), ), ), ); } List _filterHaircuts(List haircuts) { var filtered = haircuts; if (_selectedDate != null) { filtered = filtered .where( (h) => h.dateTime.year == _selectedDate!.year && h.dateTime.month == _selectedDate!.month && h.dateTime.day == _selectedDate!.day, ) .toList(); } if (_searchQuery.isNotEmpty) { filtered = filtered .where( (h) => h.clientName.toLowerCase().contains( _searchQuery.toLowerCase(), ) || h.serviceType.toLowerCase().contains( _searchQuery.toLowerCase(), ), ) .toList(); } return filtered; } Widget _buildHaircutList(List haircuts) { final revenue = haircuts.fold(0.0, (sum, h) => sum + h.price); if (haircuts.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.content_cut, size: 64, color: AppColors.textSecondary.withValues(alpha: 0.5), ), const SizedBox(height: 16), const Text( 'Nenhum corte registrado', style: TextStyle(color: AppColors.textSecondary, fontSize: 16), ), ], ), ); } return Column( children: [ // Resumo Container( padding: const EdgeInsets.all(16), margin: const EdgeInsets.all(16), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.primaryColor, AppColors.primaryColor.withValues(alpha: 0.7), ], ), borderRadius: BorderRadius.circular(16), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column( children: [ Text( '${haircuts.length}', style: const TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: AppColors.background, ), ), const Text( 'Cortes', style: TextStyle(color: AppColors.background), ), ], ), Container( width: 1, height: 40, color: AppColors.background.withValues(alpha: 0.3), ), Column( children: [ Text( _currencyFormat.format(revenue), style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: AppColors.background, ), ), const Text( 'Faturamento', style: TextStyle(color: AppColors.background), ), ], ), ], ), ), // Lista Expanded( child: ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: haircuts.length, itemBuilder: (context, index) { final haircut = haircuts[index]; return _buildHaircutCard(haircut); }, ), ), ], ); } Widget _buildHaircutCard(HaircutModel haircut) { final dateFormat = DateFormat('dd/MM HH:mm'); return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.surfaceLight), ), child: Row( children: [ Container( width: 50, height: 50, decoration: BoxDecoration( color: AppColors.primaryColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Center( child: Text( haircut.clientName[0].toUpperCase(), style: TextStyle( color: AppColors.primaryColor, fontWeight: FontWeight.bold, fontSize: 20, ), ), ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( haircut.clientName, style: TextStyle( fontWeight: FontWeight.w600, fontSize: 16, color: AppColors.textPrimary, ), ), const SizedBox(height: 4), Text( haircut.serviceType, style: TextStyle(color: AppColors.textSecondary), ), const SizedBox(height: 4), Text( dateFormat.format(haircut.dateTime), style: TextStyle( fontSize: 12, color: AppColors.textSecondary.withValues(alpha: 0.7), ), ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( _currencyFormat.format(haircut.price), style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, color: AppColors.primaryColor, ), ), IconButton( icon: Icon(Icons.delete_outline, color: AppColors.error), onPressed: () => _confirmDelete(haircut), ), ], ), ], ), ); } void _confirmDelete(HaircutModel haircut) { showDialog( context: context, builder: (context) => AlertDialog( backgroundColor: AppColors.surface, title: const Text('Excluir Corte?'), content: Text('Deseja excluir o corte de ${haircut.clientName}?'), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text(AppStrings.cancel), ), TextButton( onPressed: () async { final navigator = Navigator.of(context); final scaffoldMessenger = ScaffoldMessenger.of(context); await _haircutRepo.deleteHaircut(haircut.id); navigator.pop(); _refreshData(); scaffoldMessenger.showSnackBar( const SnackBar(content: Text(AppStrings.deletedSuccessfully)), ); }, child: Text( AppStrings.delete, style: TextStyle(color: AppColors.error), ), ), ], ), ); } }