311 lines
16 KiB
Dart
311 lines
16 KiB
Dart
|
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||
|
|
import 'package:flutter/material.dart';
|
||
|
|
import 'global_data.dart';
|
||
|
|
import 'models.dart';
|
||
|
|
|
||
|
|
class CidDataManager {
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// METODI PER SCAMBIO DATI (QR/P2P)
|
||
|
|
// ===========================================================================
|
||
|
|
|
||
|
|
static Map<String, dynamic> estraiDatiPerExport() {
|
||
|
|
String lato = GlobalData.latoCorrente;
|
||
|
|
|
||
|
|
String val(String vA, String vB, String l) => l == 'A' ? vA : vB;
|
||
|
|
bool valB(bool bA, bool bB, String l) => l == 'A' ? bA : bB;
|
||
|
|
|
||
|
|
return {
|
||
|
|
'lato': lato,
|
||
|
|
'generali': {
|
||
|
|
'data': GlobalData.data_incidente,
|
||
|
|
'ora': GlobalData.ora,
|
||
|
|
'luogo': GlobalData.luogo,
|
||
|
|
'feriti': GlobalData.feriti,
|
||
|
|
'testimoni': GlobalData.testimoni,
|
||
|
|
'danni_materiali': GlobalData.Veicoli_danni_materiali_oltre,
|
||
|
|
'oggetti_diversi': GlobalData.Oggetti_diversi_danni_materiali,
|
||
|
|
},
|
||
|
|
|
||
|
|
'circostanze': _serializeCircostanze(lato == 'A' ? GlobalData.circostanzeA : GlobalData.circostanzeB),
|
||
|
|
'punti_urto': lato == 'A' ? GlobalData.puntiUrtoA_List : GlobalData.puntiUrtoB_List,
|
||
|
|
|
||
|
|
// CASSETTO 1: GRAFICO INCIDENTE (Strade, Auto)
|
||
|
|
'grafico': {
|
||
|
|
'tratti_dinamica': GlobalData.tratti.map((t) => t.toMap()).toList(),
|
||
|
|
'elementi_dinamica': GlobalData.elementi.map((e) => e.toMap()).toList(),
|
||
|
|
},
|
||
|
|
|
||
|
|
// CASSETTO 2: FIRMA (Dati grafici personali)
|
||
|
|
'firma': _serializePunti(lato == 'A' ? GlobalData.puntiFirmaA : GlobalData.puntiFirmaB),
|
||
|
|
|
||
|
|
'contraente': {
|
||
|
|
'cognome': val(GlobalData.Cognome_contraente_A, GlobalData.Cognome_contraente_B, lato),
|
||
|
|
'nome': val(GlobalData.Nome_contraente_A, GlobalData.Nome_contraente_B, lato),
|
||
|
|
'cf': val(GlobalData.Codice_Fiscale_contraente_A, GlobalData.Codice_Fiscale_contraente_B, lato),
|
||
|
|
'indirizzo': val(GlobalData.Indirizzo_contraente_A, GlobalData.Indirizzo_contraente_B, lato),
|
||
|
|
'cap': val(GlobalData.CAP_contraente_A, GlobalData.CAP_contraente_B, lato),
|
||
|
|
'stato': val(GlobalData.Stato_contraente_A, GlobalData.Stato_contraente_B, lato),
|
||
|
|
'tel': val(GlobalData.N_telefono_mail_contraente_A, GlobalData.N_telefono_mail_contraente_B, lato),
|
||
|
|
},
|
||
|
|
'veicolo': {
|
||
|
|
'marca': val(GlobalData.Marca_e_Tipo_A, GlobalData.Marca_e_Tipo_B, lato),
|
||
|
|
'targa': val(GlobalData.Targa_A, GlobalData.Targa_B, lato),
|
||
|
|
'stato_imm': val(GlobalData.Stato_immatricolazione_A, GlobalData.Stato_immatricolazione_B, lato),
|
||
|
|
'stato_imm2': val(GlobalData.Stato_immatricolazione2_A, GlobalData.Stato_immatricolazione2_B, lato),
|
||
|
|
'rimorchio': val(GlobalData.Rimorchio_A, GlobalData.Rimorchio_B, lato),
|
||
|
|
},
|
||
|
|
'assicurazione': {
|
||
|
|
'denominazione': val(GlobalData.Denominazione_A, GlobalData.Denominazione_B, lato),
|
||
|
|
'polizza': val(GlobalData.Numero_Polizza_A, GlobalData.Numero_Polizza_B, lato),
|
||
|
|
'agenzia': val(GlobalData.Agenzia_A, GlobalData.Agenzia_B, lato),
|
||
|
|
'denom_agenzia': val(GlobalData.Denominazione_agenzia_A, GlobalData.Denominazione_agenzia_B, lato),
|
||
|
|
'indirizzo_agenzia': val(GlobalData.Indirizzo_agenzia_A, GlobalData.Indirizzo_agenzia_B, lato),
|
||
|
|
'stato_agenzia': val(GlobalData.Stato_agenzia_A, GlobalData.Stato_agenzia_B, lato),
|
||
|
|
'tel_agenzia': val(GlobalData.N_tel_mail_agenzia_A, GlobalData.N_tel_mail_agenzia_B, lato),
|
||
|
|
'carta_verde': val(GlobalData.N_carta_verde_A, GlobalData.N_carta_verde_B, lato),
|
||
|
|
'validita_dal': val(GlobalData.Data_Inizio_Dal_A, GlobalData.Data_Inizio_Dal_B, lato),
|
||
|
|
'validita_al': val(GlobalData.Data_Scadenza_Al_A, GlobalData.Data_Scadenza_Al_B, lato),
|
||
|
|
'flag_danni': valB(GlobalData.FLAG_danni_mat_assicurati_A, GlobalData.FLAG_danni_mat_assicurati_B, lato),
|
||
|
|
},
|
||
|
|
'conducente': {
|
||
|
|
'cognome': val(GlobalData.Cognome_cond_A, GlobalData.Cognome_cond_B, lato),
|
||
|
|
'nome': val(GlobalData.Nome_cond_A, GlobalData.Nome_cond_B, lato),
|
||
|
|
'nascita': val(GlobalData.Data_nascita_cond_A, GlobalData.Data_nascita_cond_B, lato),
|
||
|
|
'cf': val(GlobalData.Cod_fiscale_cond_A, GlobalData.Cod_fiscale_cond_B, lato),
|
||
|
|
'indirizzo': val(GlobalData.Indirizzo_cond_A, GlobalData.Indirizzo_cond_B, lato),
|
||
|
|
'stato': val(GlobalData.Stato_cond_A, GlobalData.Stato_cond_B, lato),
|
||
|
|
'tel': val(GlobalData.N_tel_mail_cond_A, GlobalData.N_tel_mail_cond_B, lato),
|
||
|
|
'patente': val(GlobalData.N_Patente_cond_A, GlobalData.N_Patente_cond_B, lato),
|
||
|
|
'cat_patente': val(GlobalData.Categoria_cond_A, GlobalData.Categoria_cond_B, lato),
|
||
|
|
'scad_patente': val(GlobalData.Scadenza_cond_A, GlobalData.Scadenza_cond_B, lato),
|
||
|
|
},
|
||
|
|
'danni_osservazioni': {
|
||
|
|
'visibili': val(GlobalData.danni_visibili_A, GlobalData.danni_visibili_B, lato),
|
||
|
|
'osservazioni': val(GlobalData.osservazioni_A, GlobalData.osservazioni_B, lato),
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
static void importaDati(Map<String, dynamic> data) {
|
||
|
|
String latoRemoto = data['lato'] ?? 'B';
|
||
|
|
|
||
|
|
// 1. Dati Comuni
|
||
|
|
if (data['generali'] != null) {
|
||
|
|
var gen = data['generali'];
|
||
|
|
if ((gen['data'] ?? "").isNotEmpty) GlobalData.data_incidente = gen['data'];
|
||
|
|
if ((gen['ora'] ?? "").isNotEmpty) GlobalData.ora = gen['ora'];
|
||
|
|
if ((gen['luogo'] ?? "").isNotEmpty) GlobalData.luogo = gen['luogo'];
|
||
|
|
if (gen['feriti'] != null) GlobalData.feriti = gen['feriti'];
|
||
|
|
if (gen['testimoni'] != null) GlobalData.testimoni = gen['testimoni'];
|
||
|
|
if (gen['danni_materiali'] != null) GlobalData.Veicoli_danni_materiali_oltre = gen['danni_materiali'];
|
||
|
|
if (gen['oggetti_diversi'] != null) GlobalData.Oggetti_diversi_danni_materiali = gen['oggetti_diversi'];
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- PROTEZIONE GRAFICO (CASSETTO 1) ---
|
||
|
|
// Solo se i dati arrivano da A, permettiamo di sovrascrivere il grafico comune.
|
||
|
|
// Se arrivano da B, IGNORIAMO questa chiave (così il disegno di A resta intatto).
|
||
|
|
if (latoRemoto == 'A' && data['grafico'] != null) {
|
||
|
|
var graf = data['grafico'];
|
||
|
|
|
||
|
|
if (graf['tratti_dinamica'] != null) {
|
||
|
|
List<dynamic> listRaw = graf['tratti_dinamica'];
|
||
|
|
GlobalData.tratti = listRaw.map((x) => TrattoPenna.fromMap(x)).toList();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (graf['elementi_dinamica'] != null) {
|
||
|
|
List<dynamic> listRaw = graf['elementi_dinamica'];
|
||
|
|
GlobalData.elementi = listRaw.map((x) => ElementoGrafico.fromMap(x)).toList();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- PROTEZIONE FIRMA (CASSETTO 2) ---
|
||
|
|
// La firma NON viene bloccata. Ognuno ha la sua firma e deve poterla inviare.
|
||
|
|
// Viene salvata in variabili distinte (puntiFirmaA e puntiFirmaB).
|
||
|
|
if (data['firma'] != null) {
|
||
|
|
List<Offset?> puntiFirma = _deserializePunti(data['firma']);
|
||
|
|
if (latoRemoto == 'A') GlobalData.puntiFirmaA = puntiFirma;
|
||
|
|
else GlobalData.puntiFirmaB = puntiFirma; // Qui B salva la sua firma
|
||
|
|
}
|
||
|
|
|
||
|
|
// 3. Circostanze
|
||
|
|
if (data['circostanze'] != null) {
|
||
|
|
Map<String, dynamic> rawCirc = data['circostanze'];
|
||
|
|
Map<int, bool> mappaCirc = {};
|
||
|
|
rawCirc.forEach((k, v) => mappaCirc[int.tryParse(k) ?? 0] = v as bool);
|
||
|
|
if (latoRemoto == 'A') GlobalData.circostanzeA = mappaCirc;
|
||
|
|
else GlobalData.circostanzeB = mappaCirc;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 4. Punti Urto
|
||
|
|
if (data['punti_urto'] != null) {
|
||
|
|
List<String> puntiRecuperati = List<String>.from(data['punti_urto']);
|
||
|
|
if (latoRemoto == 'A') {
|
||
|
|
GlobalData.puntiUrtoA_List = puntiRecuperati;
|
||
|
|
} else {
|
||
|
|
GlobalData.puntiUrtoB_List = puntiRecuperati;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void setVal(Function(String) setA, Function(String) setB, dynamic val) {
|
||
|
|
if (val == null) return;
|
||
|
|
if (latoRemoto == 'A') setA(val.toString()); else setB(val.toString());
|
||
|
|
}
|
||
|
|
void setBool(Function(bool) setA, Function(bool) setB, dynamic val) {
|
||
|
|
if (val == null) return;
|
||
|
|
if (latoRemoto == 'A') setA(val as bool); else setB(val as bool);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (data['contraente'] != null) {
|
||
|
|
var c = data['contraente'];
|
||
|
|
setVal((v) => GlobalData.Cognome_contraente_A = v, (v) => GlobalData.Cognome_contraente_B = v, c['cognome']);
|
||
|
|
setVal((v) => GlobalData.Nome_contraente_A = v, (v) => GlobalData.Nome_contraente_B = v, c['nome']);
|
||
|
|
setVal((v) => GlobalData.Codice_Fiscale_contraente_A = v, (v) => GlobalData.Codice_Fiscale_contraente_B = v, c['cf']);
|
||
|
|
setVal((v) => GlobalData.Indirizzo_contraente_A = v, (v) => GlobalData.Indirizzo_contraente_B = v, c['indirizzo']);
|
||
|
|
setVal((v) => GlobalData.CAP_contraente_A = v, (v) => GlobalData.CAP_contraente_B = v, c['cap']);
|
||
|
|
setVal((v) => GlobalData.Stato_contraente_A = v, (v) => GlobalData.Stato_contraente_B = v, c['stato']);
|
||
|
|
setVal((v) => GlobalData.N_telefono_mail_contraente_A = v, (v) => GlobalData.N_telefono_mail_contraente_B = v, c['tel']);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (data['veicolo'] != null) {
|
||
|
|
var v = data['veicolo'];
|
||
|
|
setVal((v) => GlobalData.Marca_e_Tipo_A = v, (v) => GlobalData.Marca_e_Tipo_B = v, v['marca']);
|
||
|
|
setVal((v) => GlobalData.Targa_A = v, (v) => GlobalData.Targa_B = v, v['targa']);
|
||
|
|
setVal((v) => GlobalData.Stato_immatricolazione_A = v, (v) => GlobalData.Stato_immatricolazione_B = v, v['stato_imm']);
|
||
|
|
setVal((v) => GlobalData.Stato_immatricolazione2_A = v, (v) => GlobalData.Stato_immatricolazione2_B = v, v['stato_imm2']);
|
||
|
|
setVal((v) => GlobalData.Rimorchio_A = v, (v) => GlobalData.Rimorchio_B = v, v['rimorchio']);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (data['assicurazione'] != null) {
|
||
|
|
var a = data['assicurazione'];
|
||
|
|
setVal((v) => GlobalData.Denominazione_A = v, (v) => GlobalData.Denominazione_B = v, a['denominazione']);
|
||
|
|
setVal((v) => GlobalData.Numero_Polizza_A = v, (v) => GlobalData.Numero_Polizza_B = v, a['polizza']);
|
||
|
|
setVal((v) => GlobalData.Agenzia_A = v, (v) => GlobalData.Agenzia_B = v, a['agenzia']);
|
||
|
|
setVal((v) => GlobalData.Denominazione_agenzia_A = v, (v) => GlobalData.Denominazione_agenzia_B = v, a['denom_agenzia']);
|
||
|
|
setVal((v) => GlobalData.Indirizzo_agenzia_A = v, (v) => GlobalData.Indirizzo_agenzia_B = v, a['indirizzo_agenzia']);
|
||
|
|
setVal((v) => GlobalData.Stato_agenzia_A = v, (v) => GlobalData.Stato_agenzia_B = v, a['stato_agenzia']);
|
||
|
|
setVal((v) => GlobalData.N_tel_mail_agenzia_A = v, (v) => GlobalData.N_tel_mail_agenzia_B = v, a['tel_agenzia']);
|
||
|
|
setVal((v) => GlobalData.N_carta_verde_A = v, (v) => GlobalData.N_carta_verde_B = v, a['carta_verde']);
|
||
|
|
setVal((v) => GlobalData.Data_Inizio_Dal_A = v, (v) => GlobalData.Data_Inizio_Dal_B = v, a['validita_dal']);
|
||
|
|
setVal((v) => GlobalData.Data_Scadenza_Al_A = v, (v) => GlobalData.Data_Scadenza_Al_B = v, a['validita_al']);
|
||
|
|
setBool((v) => GlobalData.FLAG_danni_mat_assicurati_A = v, (v) => GlobalData.FLAG_danni_mat_assicurati_B = v, a['flag_danni']);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (data['conducente'] != null) {
|
||
|
|
var c = data['conducente'];
|
||
|
|
setVal((v) => GlobalData.Cognome_cond_A = v, (v) => GlobalData.Cognome_cond_B = v, c['cognome']);
|
||
|
|
setVal((v) => GlobalData.Nome_cond_A = v, (v) => GlobalData.Nome_cond_B = v, c['nome']);
|
||
|
|
setVal((v) => GlobalData.Data_nascita_cond_A = v, (v) => GlobalData.Data_nascita_cond_B = v, c['nascita']);
|
||
|
|
setVal((v) => GlobalData.Cod_fiscale_cond_A = v, (v) => GlobalData.Cod_fiscale_cond_B = v, c['cf']);
|
||
|
|
setVal((v) => GlobalData.Indirizzo_cond_A = v, (v) => GlobalData.Indirizzo_cond_B = v, c['indirizzo']);
|
||
|
|
setVal((v) => GlobalData.Stato_cond_A = v, (v) => GlobalData.Stato_cond_B = v, c['stato']);
|
||
|
|
setVal((v) => GlobalData.N_tel_mail_cond_A = v, (v) => GlobalData.N_tel_mail_cond_B = v, c['tel']);
|
||
|
|
setVal((v) => GlobalData.N_Patente_cond_A = v, (v) => GlobalData.N_Patente_cond_B = v, c['patente']);
|
||
|
|
setVal((v) => GlobalData.Categoria_cond_A = v, (v) => GlobalData.Categoria_cond_B = v, c['cat_patente']);
|
||
|
|
setVal((v) => GlobalData.Scadenza_cond_A = v, (v) => GlobalData.Scadenza_cond_B = v, c['scad_patente']);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (data['danni_osservazioni'] != null) {
|
||
|
|
var d = data['danni_osservazioni'];
|
||
|
|
setVal((v) => GlobalData.danni_visibili_A = v, (v) => GlobalData.danni_visibili_B = v, d['visibili']);
|
||
|
|
setVal((v) => GlobalData.osservazioni_A = v, (v) => GlobalData.osservazioni_B = v, d['osservazioni']);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// METODI PER SALVATAGGIO CLOUD (FIREBASE)
|
||
|
|
// ===========================================================================
|
||
|
|
|
||
|
|
static Future<String> salvaDati(String sessionId, String lato) async {
|
||
|
|
final docRef = FirebaseFirestore.instance.collection('scambi_cid').doc(sessionId);
|
||
|
|
|
||
|
|
// Estrae tutti i dati dalla memoria locale
|
||
|
|
Map<String, dynamic> datiExport = estraiDatiPerExport();
|
||
|
|
|
||
|
|
// Prepariamo i dati da inviare al server
|
||
|
|
Map<String, dynamic> updateData = {
|
||
|
|
'generali': datiExport['generali'],
|
||
|
|
'lato_$lato': {
|
||
|
|
...datiExport['contraente'],
|
||
|
|
...datiExport['veicolo'],
|
||
|
|
...datiExport['assicurazione'],
|
||
|
|
...datiExport['conducente'],
|
||
|
|
'danni_visibili': datiExport['danni_osservazioni']['visibili'],
|
||
|
|
'osservazioni': datiExport['danni_osservazioni']['osservazioni'],
|
||
|
|
'circostanze': datiExport['circostanze'],
|
||
|
|
'punti_urto': datiExport['punti_urto'],
|
||
|
|
'firma': datiExport['firma'], // <-- La firma è dentro "lato_A" o "lato_B", quindi è al sicuro
|
||
|
|
'completo': true,
|
||
|
|
},
|
||
|
|
'timestamp': FieldValue.serverTimestamp(),
|
||
|
|
};
|
||
|
|
|
||
|
|
// --- PROTEZIONE AGGIUNTIVA PER IL CLOUD ---
|
||
|
|
// Il GRAFICO lo aggiorniamo nel DB solo se siamo il LATO A.
|
||
|
|
// Il LATO B non ha diritto di toccare questa chiave.
|
||
|
|
if (lato == 'A') {
|
||
|
|
updateData['grafico'] = datiExport['grafico'];
|
||
|
|
}
|
||
|
|
|
||
|
|
await docRef.set(updateData, SetOptions(merge: true));
|
||
|
|
|
||
|
|
return sessionId;
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- METODO RECUPERA DATI CLOUD ---
|
||
|
|
static Future<void> caricaDati(String sessionId, String latoDaCaricare) async {
|
||
|
|
final doc = await FirebaseFirestore.instance.collection('scambi_cid').doc(sessionId).get();
|
||
|
|
if (!doc.exists) return;
|
||
|
|
|
||
|
|
final data = doc.data()!;
|
||
|
|
|
||
|
|
Map<String, dynamic> datiDaImportare = {};
|
||
|
|
datiDaImportare['lato'] = latoDaCaricare;
|
||
|
|
|
||
|
|
if (data['generali'] != null) datiDaImportare['generali'] = data['generali'];
|
||
|
|
if (data['grafico'] != null) datiDaImportare['grafico'] = data['grafico'];
|
||
|
|
|
||
|
|
if (data['lato_$latoDaCaricare'] != null) {
|
||
|
|
Map<String, dynamic> latoData = data['lato_$latoDaCaricare'];
|
||
|
|
|
||
|
|
datiDaImportare['contraente'] = latoData;
|
||
|
|
datiDaImportare['veicolo'] = latoData;
|
||
|
|
datiDaImportare['assicurazione'] = latoData;
|
||
|
|
datiDaImportare['conducente'] = latoData;
|
||
|
|
|
||
|
|
datiDaImportare['danni_osservazioni'] = {
|
||
|
|
'visibili': latoData['danni_visibili'],
|
||
|
|
'osservazioni': latoData['osservazioni'],
|
||
|
|
};
|
||
|
|
datiDaImportare['circostanze'] = latoData['circostanze'];
|
||
|
|
datiDaImportare['punti_urto'] = latoData['punti_urto'];
|
||
|
|
datiDaImportare['firma'] = latoData['firma']; // Recupera la firma specifica dal lato
|
||
|
|
}
|
||
|
|
|
||
|
|
importaDati(datiDaImportare);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ===========================================================================
|
||
|
|
// HELPER SERIALIZZAZIONE
|
||
|
|
// ===========================================================================
|
||
|
|
|
||
|
|
static Map<String, bool> _serializeCircostanze(Map<int, bool> circ) {
|
||
|
|
return circ.map((key, value) => MapEntry(key.toString(), value));
|
||
|
|
}
|
||
|
|
|
||
|
|
static List<Map<String, double>> _serializePunti(List<Offset?> punti) {
|
||
|
|
List<Map<String, double>> res = [];
|
||
|
|
for (var p in punti) {
|
||
|
|
if (p != null) res.add({'dx': p.dx, 'dy': p.dy});
|
||
|
|
}
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
|
||
|
|
static List<Offset?> _deserializePunti(dynamic lista) {
|
||
|
|
if (lista is! List) return [];
|
||
|
|
return lista.map<Offset?>((item) {
|
||
|
|
if (item == null) return null;
|
||
|
|
return Offset((item['dx'] as num).toDouble(), (item['dy'] as num).toDouble());
|
||
|
|
}).toList();
|
||
|
|
}
|
||
|
|
}
|