v
This commit is contained in:
@@ -46,6 +46,11 @@ class _TicketListScreenState extends State<TicketListScreen> {
|
||||
appBar: AppBar(
|
||||
title: const Text('Assistenza & Riparazioni'),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () =>
|
||||
context.read<TicketListCubit>().loadTickets(refresh: true),
|
||||
icon: const Icon(Icons.refresh),
|
||||
),
|
||||
// Tasto per filtri avanzati (Data, Staff, Tipo) -> Da fare in un BottomSheet!
|
||||
IconButton(
|
||||
icon: const Icon(Icons.filter_list),
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flux/features/tickets/models/ticket_model.dart';
|
||||
|
||||
class LoanPhoneReturnDialog extends StatefulWidget {
|
||||
final List<TicketModel> ticketsWithLoans;
|
||||
|
||||
const LoanPhoneReturnDialog({super.key, required this.ticketsWithLoans});
|
||||
|
||||
@override
|
||||
State<LoanPhoneReturnDialog> createState() => _LoanPhoneReturnDialogState();
|
||||
}
|
||||
|
||||
class _LoanPhoneReturnDialogState extends State<LoanPhoneReturnDialog> {
|
||||
// Mappa per tenere traccia delle scelte: { ticketId: true/false }
|
||||
final Map<String, bool> _returnStatuses = {};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// Inizializziamo tutto a "true" (di default presumiamo che lo stia restituendo)
|
||||
for (var ticket in widget.ticketsWithLoans) {
|
||||
_returnStatuses[ticket.id!] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Row(
|
||||
children: [
|
||||
Icon(Icons.warning_amber_rounded, color: Colors.orange),
|
||||
SizedBox(width: 8),
|
||||
Text('Telefoni di cortesia'),
|
||||
],
|
||||
),
|
||||
content: SizedBox(
|
||||
width: double.maxFinite,
|
||||
// Usiamo ListView.builder in caso ce ne siano tanti
|
||||
child: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
itemCount: widget.ticketsWithLoans.length,
|
||||
separatorBuilder: (context, index) => const Divider(),
|
||||
itemBuilder: (context, index) {
|
||||
final ticket = widget.ticketsWithLoans[index];
|
||||
|
||||
final customerName = ticket.customer?.name ?? 'Cliente';
|
||||
|
||||
return SwitchListTile(
|
||||
title: Text(
|
||||
'$customerName ha un telefono di cortesia in prestito.',
|
||||
),
|
||||
subtitle: const Text('Confermi la riconsegna?'),
|
||||
value: _returnStatuses[ticket.id!] ?? true,
|
||||
activeThumbColor: Theme.of(context).colorScheme.primary,
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
_returnStatuses[ticket.id!] = value;
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(null), // Annulla tutto
|
||||
child: const Text('Annulla'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () =>
|
||||
Navigator.of(context).pop(_returnStatuses), // Passa la mappa
|
||||
child: const Text('Conferma'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
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/blocs/ticket_shipping_cubit.dart';
|
||||
import 'package:flux/features/tickets/ui/widgets/loan_phone_return_dialog.dart';
|
||||
import 'package:flux/features/tickets/ui/widgets/ticket_list_card.dart';
|
||||
import 'package:flux/features/tickets/ui/widgets/ticket_shipping_modal.dart';
|
||||
|
||||
@@ -17,6 +17,67 @@ class TicketList extends StatelessWidget {
|
||||
required this.state,
|
||||
});
|
||||
|
||||
void _showShippingModal(BuildContext context) async {
|
||||
// 1. Apriamo la modale e ASPETTIAMO il risultato (tipizzandolo come Record)
|
||||
final bool? result = await showModalBottomSheet<bool?>(
|
||||
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<TicketListCubit>().clearSelection();
|
||||
// (Se necessario, chiama il metodo per ricaricare la lista dei ticket dal DB)
|
||||
context.read<TicketListCubit>().loadTickets(refresh: true);
|
||||
}
|
||||
}
|
||||
|
||||
void _setStatusClosed(BuildContext context) async {
|
||||
// 1. Filtriamo solo i ticket che hanno un telefono in prestito
|
||||
final ticketsWithLoans = state.selectedTickets
|
||||
.where((t) => t.hasCourtesyDevice == true)
|
||||
.toList();
|
||||
|
||||
// Prepariamo la variabile per contenere i telefoni restituiti (se ce ne sono)
|
||||
Map<String, bool>? loanReturns;
|
||||
|
||||
// 2. Se ci sono telefoni in prestito, mostriamo il popup
|
||||
if (ticketsWithLoans.isNotEmpty) {
|
||||
loanReturns = await showDialog<Map<String, bool>>(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
LoanPhoneReturnDialog(ticketsWithLoans: ticketsWithLoans),
|
||||
);
|
||||
|
||||
// Se l'utente ha premuto fuori o ha fatto "Annulla", blocchiamo l'operazione bulk
|
||||
if (loanReturns == null) return;
|
||||
}
|
||||
|
||||
// 3. Se siamo qui, o non c'erano muletti, o l'utente ha confermato il popup.
|
||||
// Lanciamo l'azione sul Cubit! (Dovrai creare/adattare questo metodo nel tuo Cubit)
|
||||
if (context.mounted) {
|
||||
final ticketIds = state.selectedTickets.map((t) => t.id!).toList();
|
||||
|
||||
// Passiamo gli ID dei ticket da chiudere e la mappa delle restituzioni
|
||||
context.read<TicketListCubit>().closeTicketsBulk(
|
||||
ticketIds: ticketIds,
|
||||
loanReturns: loanReturns, // Può essere null se non c'erano muletti
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
@@ -87,42 +148,20 @@ class TicketList extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
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<bool?>(
|
||||
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<TicketListCubit>().clearSelection();
|
||||
// (Se necessario, chiama il metodo per ricaricare la lista dei ticket dal DB)
|
||||
context.read<TicketListCubit>().loadTickets(
|
||||
refresh: true,
|
||||
);
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.local_shipping),
|
||||
label: const Text('Spedisci'),
|
||||
Row(
|
||||
children: [
|
||||
FilledButton.icon(
|
||||
onPressed: () => _setStatusClosed(context),
|
||||
icon: const Icon(Icons.approval),
|
||||
label: const Text('Riconsegna'),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
FilledButton.icon(
|
||||
onPressed: () => _showShippingModal(context),
|
||||
icon: const Icon(Icons.local_shipping),
|
||||
label: const Text('Spedisci'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user