import 'dart:ffi'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/core/blocs/session/session_cubit.dart'; import 'package:flux/features/tickets/models/shipment_document_model.dart'; import 'package:flux/features/master_data/providers/models/provider_location_model.dart'; import 'package:flux/features/master_data/providers/models/provider_model.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/blocs/ticket_shipping_cubit.dart'; import 'package:flux/features/tickets/models/ticket_model.dart'; import 'package:flux/features/tickets/ui/widgets/ticket_list_card.dart'; import 'package:flux/features/tickets/ui/widgets/ticket_shipping_modal.dart'; import 'package:flux/features/tickets/utils/ticket_shipping_pdf_service.dart'; import 'package:pdf/pdf.dart'; import 'package:printing/printing.dart'; class TicketList extends StatelessWidget { final ScrollController scrollController; final TicketListState state; const TicketList({ super.key, required this.scrollController, required this.state, }); @override Widget build(BuildContext context) { return Stack( children: [ 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]; final isSelected = state.selectedTickets.contains(ticket); final isSelectionMode = state.selectedTickets.isNotEmpty; // Per Desktop mostriamo la checkbox vera e propria final isDesktop = MediaQuery.of(context).size.width > 800; return TicketListCard( ticket: ticket, isSelected: isSelected, isSelectionMode: isSelectionMode, isDesktop: isDesktop, ); }, ), // 2. LA BARRA DELLE AZIONI BULK (Appare magicamente dal basso) AnimatedPositioned( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, bottom: state.selectedTickets.isNotEmpty ? 90 : -100, // Nasconde o mostra left: 16, right: 16, child: Card( elevation: 8, color: Theme.of(context).colorScheme.inverseSurface, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), child: Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), child: Row( children: [ IconButton( icon: const Icon(Icons.close), onPressed: () => context.read().clearSelection(), ), Text( '${state.selectedTickets.length} selezionati', style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), const Spacer(), // IL NOSTRO FAMOSO BOTTONE SPEDISCI // IL BOTTONE SPEDISCI NELLA BARRA IN BASSO FilledButton.icon( onPressed: () async { // 1. Apriamo la modale e ASPETTIAMO il risultato (tipizzandolo come Record) final bool? result = await showModalBottomSheet( context: context, isScrollControlled: true, builder: (context) { return BlocProvider( create: (context) => TicketShippingCubit( tickets: state.selectedTickets.toList(), )..loadRepairCenters(), child: TicketShippingModal( ticketIds: state.selectedTickets .map((t) => t.id!) .toList(), ), ); }, ); // 2. Se l'utente ha chiuso trascinando giù, result è null. // Se ha salvato con successo, result contiene il nostro Record! if (result != null && context.mounted) { // 5. Pulizia finale: Deselezioniamo tutti i ticket e ricarichiamo la lista context.read().clearSelection(); // (Se necessario, chiama il metodo per ricaricare la lista dei ticket dal DB) context.read().loadTickets( refresh: true, ); } }, icon: const Icon(Icons.local_shipping), label: const Text('Spedisci'), ), ], ), ), ), ), ], ); } }