cid_app/lib/comp_16.dart

688 lines
27 KiB
Dart
Raw Normal View History

2026-02-27 23:26:13 +01:00
import 'dart:io';
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:path_provider/path_provider.dart';
import 'package:printing/printing.dart';
import 'package:share_plus/share_plus.dart';
import 'scambio_dati_screen.dart';
import 'pdf_engine.dart';
import 'global_data.dart';
import 'main.dart';
import 'comp_6-7.dart';
import 'comp_1-5.dart';
class Comp16Screen extends StatefulWidget {
const Comp16Screen({super.key});
@override
State<Comp16Screen> createState() => _Comp16ScreenState();
}
class _Comp16ScreenState extends State<Comp16Screen> with WidgetsBindingObserver {
bool _scambioEffettuato = false;
bool _datiPresenti = false;
bool _ioHoApprovato = false;
bool _tuttiHannoApprovato = false;
bool _staCancellando = false;
bool _cancellazioneAvviataDaMe = false;
String _statusText = "Esegui lo Scambio Dati per iniziare.";
Color _statusColor = Colors.orange.shade800;
IconData _statusIcon = Icons.warning_amber_rounded;
File? _filePdfReale;
Uint8List? _immagineAnteprima;
bool _isLoading = false;
StreamSubscription? _roomSubscription;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
_puliziaIngresso();
WidgetsBinding.instance.addPostFrameCallback((_) {
_mostraInfoPopup(context);
});
}
void _mostraInfoPopup(BuildContext context) {
Color activeColor = Colors.blue.shade900;
showGeneralDialog(
context: context,
barrierDismissible: false,
barrierLabel: "Popup",
barrierColor: Colors.black.withOpacity(0.5),
transitionDuration: const Duration(milliseconds: 400),
pageBuilder: (context, animation, secondaryAnimation) {
return AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
title: Row(
children: [
Icon(Icons.sync_alt, color: activeColor, size: 28),
const SizedBox(width: 10),
const Expanded(child: Text("Scambio e Invio", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18))),
],
),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
const Text("Questa è la fase finale. Segui questi tre passaggi per concludere il modulo:", style: TextStyle(fontSize: 15)),
const SizedBox(height: 16),
_buildPopupRow(Icons.qr_code_scanner, "1. Scambio Dati", "Inquadra il QR Code dell'altro conducente oppure inserisci a mano il suo codice PIN."),
const SizedBox(height: 12),
_buildPopupRow(Icons.visibility, "2. Anteprima", "Apri l'anteprima per verificare che i dati di entrambi siano impaginati correttamente sul documento."),
const SizedBox(height: 12),
_buildPopupRow(Icons.check_circle, "3. Approvazione", "Se tutto è esatto, clicca su Approva. Quando entrambi avrete approvato, il file sarà pronto per l'invio."),
],
),
),
actions: [
SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: activeColor,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
padding: const EdgeInsets.symmetric(vertical: 14),
),
onPressed: () => Navigator.pop(context),
child: const Text("HO CAPITO", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
),
),
],
);
},
transitionBuilder: (context, animation, secondaryAnimation, child) {
var curvePosizione = CurvedAnimation(parent: animation, curve: Curves.easeOutBack, reverseCurve: Curves.easeInBack);
var curveOpacita = CurvedAnimation(parent: animation, curve: Curves.easeOut, reverseCurve: Curves.easeIn);
return SlideTransition(position: Tween<Offset>(begin: const Offset(0.0, 0.4), end: Offset.zero).animate(curvePosizione), child: FadeTransition(opacity: curveOpacita, child: child));
},
);
}
Widget _buildPopupRow(IconData icon, String title, String desc) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(icon, size: 24, color: Colors.blueGrey),
const SizedBox(width: 12),
Expanded(
child: RichText(
text: TextSpan(
style: const TextStyle(fontSize: 14, color: Colors.black87, height: 1.4),
children: [
TextSpan(text: "$title: ", style: const TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: desc),
],
),
),
),
],
);
}
Future<void> _puliziaIngresso() async {
if (GlobalData.idScambioTemporaneo == null && GlobalData.idSessione != null) {
GlobalData.idScambioTemporaneo = GlobalData.idSessione;
}
if (GlobalData.idScambioTemporaneo == null) {
if (GlobalData.latoCorrente == 'A') GlobalData.resetB(); else GlobalData.resetA();
}
if (mounted) _verificaStatoPostScambio();
}
void _verificaStatoPostScambio() {
bool datiOk = false;
if (GlobalData.latoCorrente == 'A') {
datiOk = GlobalData.Cognome_contraente_B.trim().isNotEmpty && GlobalData.Targa_B.trim().isNotEmpty;
} else {
datiOk = GlobalData.Cognome_contraente_A.trim().isNotEmpty && GlobalData.Targa_A.trim().isNotEmpty;
}
if (mounted) {
setState(() {
if (datiOk) {
_scambioEffettuato = true;
_datiPresenti = true;
_statusText = "Dati ricevuti. Generazione anteprima...";
_statusColor = Colors.blue.shade800;
_statusIcon = Icons.pending_actions;
_generaDocumenti();
_attivaAscoltoStanza();
} else {
_resetStatiUI();
}
});
}
}
void _resetStatiUI() {
_scambioEffettuato = false;
_datiPresenti = false;
_ioHoApprovato = false;
_tuttiHannoApprovato = false;
_statusText = "Esegui lo Scambio Dati per iniziare.";
_statusColor = Colors.orange.shade800;
_statusIcon = Icons.warning_amber_rounded;
_filePdfReale = null;
_immagineAnteprima = null;
}
void _attivaAscoltoStanza() {
String? idDaAscoltare = GlobalData.idScambioTemporaneo ?? GlobalData.idSessione;
if (idDaAscoltare == null || _roomSubscription != null) return;
_roomSubscription = FirebaseFirestore.instance
.collection('scambi_cid')
.doc(idDaAscoltare)
.snapshots()
.listen((snapshot) async {
if (!snapshot.exists) {
if (_ioHoApprovato) {
_roomSubscription?.cancel();
_roomSubscription = null;
return;
}
if (!_staCancellando && !_cancellazioneAvviataDaMe && mounted) {
_gestisciCancellazioneAltrui();
}
return;
}
final data = snapshot.data();
if (data == null) return;
if (data['status'] == 'retry') {
if (!_cancellazioneAvviataDaMe) _gestisciCancellazioneAltrui();
return;
}
bool appA = data['approved_A'] == true;
bool appB = data['approved_B'] == true;
if (appA && appB) {
if (mounted) {
setState(() {
_tuttiHannoApprovato = true;
_ioHoApprovato = true;
_statusText = "DATI APPROVATI!\nPDF creato, procedi con il salvataggio o l'invio";
_statusColor = Colors.green.shade800;
_statusIcon = Icons.check_circle;
});
String? id = GlobalData.idSessione ?? GlobalData.idScambioTemporaneo;
if (id != null) FirebaseFirestore.instance.collection('scambi_cid').doc(id).delete().catchError((_){});
}
}
else if (_ioHoApprovato) {
if (mounted) {
setState(() {
_statusText = "Hai approvato. In attesa dell'altro utente...";
_statusColor = Colors.amber.shade800;
_statusIcon = Icons.hourglass_top;
});
}
}
});
}
Future<void> _eseguiPuliziaFirebase({required bool notificaAltri}) async {
setState(() {
_isLoading = true;
_cancellazioneAvviataDaMe = true;
});
await _roomSubscription?.cancel();
_roomSubscription = null;
Set<String> idsDaCancellare = {};
if (GlobalData.idScambioTemporaneo != null) idsDaCancellare.add(GlobalData.idScambioTemporaneo!);
if (GlobalData.idSessione != null) idsDaCancellare.add(GlobalData.idSessione!);
for (String id in idsDaCancellare) {
if (notificaAltri) {
try {
await FirebaseFirestore.instance.collection('scambi_cid').doc(id).update({'status': 'retry'})
.timeout(const Duration(seconds: 2));
await Future.delayed(const Duration(milliseconds: 300));
} catch (_) {}
}
try {
await FirebaseFirestore.instance.collection('scambi_cid').doc(id).delete();
} catch (_) {}
}
}
Future<void> _tornaIndietroConPulizia() async {
await _eseguiPuliziaFirebase(notificaAltri: true);
_resetDatiLocali();
if (mounted) {
setState(() => _isLoading = false);
if (GlobalData.latoCorrente == 'A') {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (c) => const Comp1_5Screen()));
} else {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (c) => const Comp6_7Screen()));
}
}
}
Future<void> _abbandonaScambioEHome() async {
await _eseguiPuliziaFirebase(notificaAltri: true);
GlobalData.reset();
if (mounted) {
setState(() => _isLoading = false);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (c) => const HomeScreen()),
(route) => false
);
}
}
Future<void> _ioApprovo() async {
String? id = GlobalData.idSessione ?? GlobalData.idScambioTemporaneo;
if (id != null) {
try {
String field = (GlobalData.latoCorrente == 'A') ? 'approved_A' : 'approved_B';
await FirebaseFirestore.instance.collection('scambi_cid').doc(id).update({field: true});
} catch (_) {}
}
if (mounted) {
setState(() {
_ioHoApprovato = true;
});
}
}
Future<void> _concludiEHome() async {
await _eseguiPuliziaFirebase(notificaAltri: false);
GlobalData.reset();
if (mounted) {
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (c) => const HomeScreen()), (r) => false);
}
}
void _resetDatiLocali() {
if (GlobalData.latoCorrente == 'A') GlobalData.resetB(); else GlobalData.resetA();
GlobalData.idScambioTemporaneo = null;
GlobalData.idSessione = null;
}
void _gestisciCancellazioneAltrui() {
_roomSubscription?.cancel();
_roomSubscription = null;
if (mounted) {
Navigator.of(context).popUntil((route) => route.isFirst || route.settings.name == null);
showDialog(
context: context,
barrierDismissible: false,
builder: (ctx) => AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24.0)),
backgroundColor: Colors.white,
surfaceTintColor: Colors.transparent,
icon: Icon(Icons.warning_amber_rounded, size: 60, color: Colors.amber.shade800),
iconPadding: const EdgeInsets.only(top: 24, bottom: 16),
title: Text("Attenzione", textAlign: TextAlign.center, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 22, color: Colors.amber.shade900)),
content: const Padding(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: Text(
"L'altro utente ha deciso di modificare i propri dati o non ha accettato i tuoi.\n\nSarai riportato alla schermata iniziale dove potrai eventualmente apporre modifiche.",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, height: 1.4, color: Colors.black87),
),
),
actionsPadding: const EdgeInsets.fromLTRB(24, 0, 24, 24),
actions: [
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
Navigator.pop(ctx);
_resetDatiLocali();
if (GlobalData.latoCorrente == 'A') {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (c) => const Comp1_5Screen()));
} else {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (c) => const Comp6_7Screen()));
}
},
style: ElevatedButton.styleFrom(backgroundColor: Colors.amber.shade800, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), elevation: 0),
child: const Text("HO CAPITO", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16))
),
)
],
),
);
}
}
Future<void> _generaDocumenti() async {
if (!mounted) return;
setState(() => _isLoading = true);
try {
final List<int> pdfBytes = await PdfEngine.generaDocumentoCai();
if (pdfBytes.isEmpty) throw Exception("PDF vuoto");
final appDocDir = await getApplicationDocumentsDirectory();
final file = File('${appDocDir.path}/CID_${DateTime.now().millisecondsSinceEpoch}.pdf');
await file.writeAsBytes(pdfBytes, flush: true);
Uint8List? anteprima;
await for (final page in Printing.raster(Uint8List.fromList(pdfBytes), pages: [0], dpi: 150)) {
anteprima = await page.toPng(); break;
}
if (mounted) {
setState(() { _filePdfReale = file; _immagineAnteprima = anteprima; _isLoading = false; });
}
} catch (e) {
if (mounted) setState(() => _isLoading = false);
}
}
Future<void> _vaiAScambioDati() async {
await Navigator.push(context, MaterialPageRoute(builder: (context) => const ScambioDatiScreen()));
_verificaStatoPostScambio();
}
void _apriAnteprimaSchermoIntero() {
if (!_scambioEffettuato || !_datiPresenti || _immagineAnteprima == null || _filePdfReale == null) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Dati non pronti!")));
return;
}
Navigator.push(context, MaterialPageRoute(builder: (context) => ImageViewerScreen(
imageBytes: _immagineAnteprima!,
pdfFile: _filePdfReale!,
isAlreadyApproved: _ioHoApprovato,
onConfirmCorrection: _tornaIndietroConPulizia,
onConfirmApproval: _ioApprovo
)));
}
Future<void> _inviaMailConAllegato(BuildContext context) async {
if (_filePdfReale == null) return;
try {
bool isA = GlobalData.latoCorrente == 'A';
String polizzaChiScrive = (isA ? GlobalData.Numero_Polizza_A : GlobalData.Numero_Polizza_B).trim();
String targaChiScrive = (isA ? GlobalData.Targa_A : GlobalData.Targa_B).trim();
String firmaChiScrive = "${isA ? GlobalData.Nome_contraente_A : GlobalData.Nome_contraente_B} ${isA ? GlobalData.Cognome_contraente_A : GlobalData.Cognome_contraente_B}";
String contattoChiScrive = (isA ? GlobalData.N_telefono_mail_contraente_A : GlobalData.N_telefono_mail_contraente_B).trim();
String compagniaUtente = (isA ? GlobalData.Denominazione_A : GlobalData.Denominazione_B).trim().toUpperCase();
String emailDestinatario = "";
if (GlobalData.assicurazioni.containsKey(compagniaUtente)) {
emailDestinatario = GlobalData.assicurazioni[compagniaUtente]!;
} else {
for (var key in GlobalData.assicurazioni.keys) {
if (key.isNotEmpty && (compagniaUtente.contains(key) || key.contains(compagniaUtente))) {
emailDestinatario = GlobalData.assicurazioni[key]!;
break;
}
}
}
List<String> listaCC = [];
if (contattoChiScrive.contains("@")) listaCC.add(contattoChiScrive);
String oggetto = "DENUNCIA SINISTRO - Polizza n. $polizzaChiScrive - Targa $targaChiScrive";
String corpo = "Spett.le Compagnia,\n\n"
"Con la presente inoltro in allegato il modulo CAI relativo al sinistro avvenuto in data ${GlobalData.data_incidente} alle ore ${GlobalData.ora} nel comune di ${GlobalData.luogo}.\n\n"
"Rimaniamo in attesa dell'apertura del fascicolo.\n\n"
"Cordiali saluti,\n$firmaChiScrive\nContatto: $contattoChiScrive";
final Email email = Email(
subject: oggetto,
body: corpo,
recipients: emailDestinatario.isNotEmpty ? [emailDestinatario] : [],
cc: listaCC,
attachmentPaths: [_filePdfReale!.path],
isHTML: false,
);
await FlutterEmailSender.send(email);
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Nessuna app Mail predefinita trovata. Apro la condivisione..."), duration: Duration(seconds: 3), backgroundColor: Colors.orange));
_apriCondivisione(context);
}
}
}
Future<void> _apriCondivisione(BuildContext context) async {
if (_filePdfReale == null) return;
final box = context.findRenderObject() as RenderBox?;
await Share.shareXFiles(
[XFile(_filePdfReale!.path, mimeType: 'application/pdf')],
subject: 'Modulo CAI',
text: 'Ecco il modulo CAI compilato.',
sharePositionOrigin: box != null ? (box.localToGlobal(Offset.zero) & box.size) : null,
);
}
Future<void> _salvaPdfLocale(BuildContext context) async {
await _apriCondivisione(context);
}
@override
void dispose() {
_roomSubscription?.cancel();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
bool pdfPronto = !_isLoading && _filePdfReale != null && _immagineAnteprima != null;
bool abilitaAnteprima = _scambioEffettuato && _datiPresenti && pdfPronto;
bool abilitaFinali = _tuttiHannoApprovato && pdfPronto;
String testoAnteprima = !_scambioEffettuato ? "2. ANTEPRIMA (Prima fai Scambio)" :
(_ioHoApprovato ? "ANTEPRIMA (IN ATTESA...)" : "2. APRI ANTEPRIMA E APPROVA");
if (_tuttiHannoApprovato) testoAnteprima = "ANTEPRIMA (COMPLETATA)";
return Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
color: const Color(0xFFF0F4F8),
image: DecorationImage(
image: const AssetImage('assets/sfondo_mappa.jpg'),
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
const Color(0xFFF0F4F8).withOpacity(0.6),
BlendMode.lighten,
),
),
),
child: PopScope(
canPop: false,
onPopInvoked: (didPop) async {
if (didPop) return;
if (_ioHoApprovato) _concludiEHome(); else _tornaIndietroConPulizia();
},
child: Scaffold(
backgroundColor: Colors.transparent,
extendBodyBehindAppBar: true,
appBar: AppBar(
title: const Text("Invio e Salvataggio", style: TextStyle(fontWeight: FontWeight.w800, fontSize: 20)),
centerTitle: true,
backgroundColor: Colors.blue.shade900.withOpacity(0.95),
foregroundColor: Colors.white,
elevation: 10,
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: _ioHoApprovato ? _concludiEHome : _tornaIndietroConPulizia
),
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(bottom: Radius.circular(20))),
),
body: Stack(children: [
SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20),
child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
_buildStatusCard(),
const SizedBox(height: 20),
// VA DIRETTO ALLA PAGINA DI SCAMBIO
_btn("1. SCAMBIO DATI", Icons.sync_alt, Colors.orange.shade800, onTap: _vaiAScambioDati, disabled: _ioHoApprovato),
const SizedBox(height: 20),
_btn(testoAnteprima, Icons.visibility, _statusColor, onTap: abilitaAnteprima ? _apriAnteprimaSchermoIntero : null, disabled: !abilitaAnteprima),
const SizedBox(height: 8),
Divider(color: Colors.white.withOpacity(0.5), thickness: 1),
const SizedBox(height: 8),
Builder(builder: (ctx) => _btn("SALVA SUL DISPOSITIVO", Icons.save_alt, Colors.green.shade700, onTap: abilitaFinali ? () => _salvaPdfLocale(ctx) : null, disabled: !abilitaFinali)),
const SizedBox(height: 20),
Builder(builder: (ctx) => _btn("INVIA ALL'ASSICURAZIONE", Icons.send_rounded, Colors.green.shade700, onTap: abilitaFinali ? () => _inviaMailConAllegato(ctx) : null, disabled: !abilitaFinali)),
const SizedBox(height: 40),
_btn(
_tuttiHannoApprovato ? "TORNA ALLA HOME" : "CANCELLA TUTTO E ESCI",
_tuttiHannoApprovato ? Icons.home : Icons.delete_sweep,
_tuttiHannoApprovato ? Colors.green.shade800 : Colors.red.shade900,
onTap: _tuttiHannoApprovato ? _concludiEHome : _abbandonaScambioEHome,
disabled: false
),
const SizedBox(height: 30)
]))),
if (_isLoading)
Container(color: Colors.black54, child: const Center(child: Column(mainAxisSize: MainAxisSize.min, children: [CircularProgressIndicator(color: Colors.white), SizedBox(height: 20), Text("Elaborazione in corso...", style: TextStyle(color: Colors.white))]))),
]),
),
),
);
}
Widget _btn(String label, IconData icon, Color color, {VoidCallback? onTap, bool disabled = false}) {
bool on = onTap != null && !disabled;
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
boxShadow: on ? [BoxShadow(color: Colors.black.withOpacity(0.3), offset: const Offset(0, 4), blurRadius: 5)] : [],
),
child: ElevatedButton(
onPressed: on ? onTap : null,
style: ElevatedButton.styleFrom(
backgroundColor: on ? color : Colors.grey,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 20),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
),
child: Row(children: [
Icon(icon, size: 28), const SizedBox(width: 20),
Expanded(child: Text(label, textAlign: TextAlign.center, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16))),
const Icon(Icons.lock, size: 20, color: Colors.transparent)
])
),
);
}
Widget _buildStatusCard() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(color: Colors.white.withOpacity(0.9), borderRadius: BorderRadius.circular(16), border: Border.all(color: _statusColor, width: 2), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.1), blurRadius: 6, offset: const Offset(0, 3))]),
child: Row(children: [
Icon(_statusIcon, color: _statusColor, size: 36), const SizedBox(width: 15),
Expanded(child: Text(_statusText, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: _statusColor)))
])
);
}
}
class ImageViewerScreen extends StatelessWidget {
final Uint8List imageBytes;
final File pdfFile;
final bool isAlreadyApproved;
final Function onConfirmCorrection;
final Function onConfirmApproval;
const ImageViewerScreen({super.key, required this.imageBytes, required this.pdfFile, required this.isAlreadyApproved, required this.onConfirmCorrection, required this.onConfirmApproval});
Future<void> _askCorrection(BuildContext context) async {
String titolo = isAlreadyApproved ? "Chiudere?" : "Richiedere correzione?";
String testo = isAlreadyApproved
? "Hai già approvato. Uscendo tornerai alla schermata precedente in attesa dell'altro utente."
: "Questo annullerà lo scambio per entrambi e vi riporterà alla modifica.";
String tasto = isAlreadyApproved ? "CHIUDI" : "CORREGGI";
bool? conf = await showDialog(context: context, builder: (c) => AlertDialog(
title: Text(titolo),
content: Text(testo),
actions: [
TextButton(onPressed: () => Navigator.pop(c, false), child: const Text("ANNULLA")),
ElevatedButton(onPressed: () => Navigator.pop(c, true), child: Text(tasto))
]
));
if (conf == true) {
Navigator.pop(context);
if (!isAlreadyApproved) onConfirmCorrection();
}
}
Future<void> _askApproval(BuildContext context) async { Navigator.pop(context); onConfirmApproval(); }
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(title: const Text("Verifica Dati"), backgroundColor: Colors.black, foregroundColor: Colors.white),
body: Column(children: [
Expanded(child: InteractiveViewer(minScale: 0.5, maxScale: 4.0, child: Center(child: Container(color: Colors.white, child: Image.memory(imageBytes, fit: BoxFit.contain))))),
Container(
padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(color: Colors.white, boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10, offset: const Offset(0, -2))]),
child: SafeArea(
child: Row(children: [
Expanded(
child: ElevatedButton.icon(
onPressed: () => _askCorrection(context),
icon: Icon(isAlreadyApproved ? Icons.arrow_back : Icons.edit),
label: Text(isAlreadyApproved ? "INDIETRO" : "CORREGGI"),
style: ElevatedButton.styleFrom(backgroundColor: Colors.orange.shade800, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))),
),
),
const SizedBox(width: 16),
Expanded(
child: ElevatedButton.icon(
onPressed: isAlreadyApproved ? null : () => _askApproval(context),
icon: isAlreadyApproved ? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white)) : const Icon(Icons.check_circle),
label: Text(isAlreadyApproved ? "IN ATTESA..." : "APPROVA"),
style: ElevatedButton.styleFrom(backgroundColor: isAlreadyApproved ? Colors.grey : Colors.green.shade700, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))),
),
),
]),
),
)
]),
);
}
}