import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/features/tickets/blocs/ticket_list_cubit.dart'; import 'package:flux/features/tickets/blocs/ticket_list_state.dart'; import 'package:flux/features/tickets/models/ticket_model.dart'; import 'package:flux/features/tickets/models/ticket_status_extension.dart'; class TicketListScreen extends StatefulWidget { const TicketListScreen({super.key}); @override State createState() => _TicketListScreenState(); } class _TicketListScreenState extends State { final ScrollController _scrollController = ScrollController(); final TextEditingController _searchController = TextEditingController(); @override void initState() { super.initState(); // INFINITY SCROLL: Quando arriviamo quasi in fondo, chiediamo altri ticket _scrollController.addListener(() { if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent - 200) { context.read().fetchTickets(); } }); } @override void dispose() { _scrollController.dispose(); _searchController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Assistenza & Riparazioni'), actions: [ // Tasto per filtri avanzati (Data, Staff, Tipo) -> Da fare in un BottomSheet! IconButton( icon: const Icon(Icons.filter_list), onPressed: () { // TODO: Aprire BottomSheet filtri avanzati }, ), ], ), body: Column( children: [ // 1. BARRA DI RICERCA Padding( padding: const EdgeInsets.all(8.0), child: TextField( controller: _searchController, decoration: InputDecoration( hintText: 'Cerca per nome cliente...', prefixIcon: const Icon(Icons.search), suffixIcon: IconButton( icon: const Icon(Icons.clear), onPressed: () { _searchController.clear(); context.read().updateFilters( clearSearch: true, ); }, ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), ), onSubmitted: (value) { context.read().updateFilters( searchTerm: value, ); }, ), ), // 2. FILTRI RAPIDI PER STATO (CHIPS) BlocBuilder( buildWhen: (previous, current) => previous.statusFilter != current.statusFilter, builder: (context, state) { return SizedBox( height: 50, child: ListView( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 8.0), children: [ _buildStatusChip(context, state, null, 'Tutti'), ...TicketStatus.values.map( (status) => _buildStatusChip( context, state, status, status.displayValue, ), ), ], ), ); }, ), const Divider(), // 3. LA LISTA DEI TICKET Expanded( child: BlocBuilder( builder: (context, state) { if (state.isLoading && state.tickets.isEmpty) { return const Center(child: CircularProgressIndicator()); } if (state.tickets.isEmpty) { return const Center(child: Text('Nessun ticket trovato.')); } return ListView.builder( controller: _scrollController, itemCount: state.hasReachedMax ? state.tickets.length : state.tickets.length + 1, itemBuilder: (context, index) { // Se siamo all'ultimo elemento e non abbiamo raggiunto il max, mostriamo il loader if (index >= state.tickets.length) { return const Center( child: Padding( padding: EdgeInsets.all(16.0), child: CircularProgressIndicator(), ), ); } final ticket = state.tickets[index]; return _TicketCard(ticket: ticket); }, ); }, ), ), ], ), floatingActionButton: FloatingActionButton.extended( onPressed: () { // TODO: Navigare alla creazione di un nuovo ticket }, icon: const Icon(Icons.add), label: const Text('Nuovo Ticket'), ), ); } // Widget di supporto per creare le Chip di filtro Widget _buildStatusChip( BuildContext context, TicketListState state, TicketStatus? status, String label, ) { final isSelected = state.statusFilter == status; return Padding( padding: const EdgeInsets.only(right: 8.0), child: ChoiceChip( label: Text(label), selected: isSelected, selectedColor: status?.color.withValues(alpha: 0.2) ?? Colors.blue.withValues(alpha: 0.2), onSelected: (selected) { context.read().updateFilters( statusFilter: selected ? status : null, clearStatus: !selected && status != null, ); }, ), ); } } // --------------------------------------------------------- // LA CARD DEL TICKET (Il "Colpo d'Occhio") // --------------------------------------------------------- class _TicketCard extends StatelessWidget { final TicketModel ticket; const _TicketCard({required this.ticket}); @override Widget build(BuildContext context) { final statusColor = ticket.status?.color ?? Colors.grey; final statusIcon = ticket.status?.icon ?? Icons.help_outline; return Card( margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), clipBehavior: Clip .antiAlias, // Serve per tagliare il container laterale con gli angoli della card child: IntrinsicHeight( // Serve per far sì che il container laterale prenda tutta l'altezza child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // LA STRISCIA COLORATA LATERALE Container(width: 6, color: statusColor), Expanded( child: ListTile( contentPadding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( ticket.customerName ?? 'Cliente Sconosciuto', style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), overflow: TextOverflow.ellipsis, ), ), // IL BADGE DELLO STATO Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: statusColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), border: Border.all( color: statusColor.withValues(alpha: 0.5), ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(statusIcon, size: 14, color: statusColor), const SizedBox(width: 4), Text( ticket.status?.displayValue ?? 'N/D', style: TextStyle( fontSize: 12, color: statusColor, fontWeight: FontWeight.bold, ), ), ], ), ), ], ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 4), // MODELLO O TIPO DI INTERVENTO Text( ticket.targetModelName ?? ticket.ticketType.displayValue, style: const TextStyle(fontWeight: FontWeight.w500), ), const SizedBox(height: 4), // DATA CREAZIONE (Es: 04/05/2026) Text( ticket.createdAt != null ? 'Creato il: ${ticket.createdAt!.day}/${ticket.createdAt!.month}/${ticket.createdAt!.year}' : '', style: TextStyle( color: Colors.grey.shade600, fontSize: 12, ), ), ], ), onTap: () { // TODO: Aprire il dettaglio del ticket! }, ), ), ], ), ), ); } }