cid_app/lib/verifica_rca_screen.dart

242 lines
No EOL
8.4 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
class VerificaRcaScreen extends StatefulWidget {
final String targa;
const VerificaRcaScreen({super.key, required this.targa});
@override
_VerificaRcaScreenState createState() => _VerificaRcaScreenState();
}
class _VerificaRcaScreenState extends State<VerificaRcaScreen> {
InAppWebViewController? webViewController;
bool isLoading = true;
String? dataScadenzaTrovata;
bool ricercaFallita = false;
final String urlPortale = "https://www.ilportaledellautomobilista.it/web/portale-automobilista/verifica-copertura-rc";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Verifica Copertura RCA"),
backgroundColor: Colors.blue[900],
foregroundColor: Colors.white,
),
body: Stack(
children: [
// 1. WEBVIEW (Il motore nascosto/mascherato)
InAppWebView(
initialUrlRequest: URLRequest(url: WebUri(urlPortale)),
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
supportZoom: false,
),
onWebViewCreated: (controller) {
webViewController = controller;
},
onLoadStop: (controller, url) async {
setState(() { isLoading = false; });
// Appena caricata, nascondiamo la grafica del sito
await _preparaPagina();
},
onProgressChanged: (controller, progress) {
// Ogni volta che la pagina cambia (es. dopo il click su Cerca), controlliamo se c'è il risultato
if (progress == 100) {
_cercaRisultato();
}
},
),
// 2. LOADER / SCHERMATA SUCCESSO (Copre la WebView quando serve)
if (isLoading || dataScadenzaTrovata != null || ricercaFallita)
Container(
color: Colors.white,
width: double.infinity,
height: double.infinity,
child: Center(
child: _buildOverlayContent(),
),
),
],
),
);
}
Widget _buildOverlayContent() {
if (ricercaFallita) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error_outline, color: Colors.red, size: 60),
const SizedBox(height: 20),
const Text("Veicolo non assicurato\no targa errata", textAlign: TextAlign.center, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 30),
ElevatedButton(
onPressed: () {
setState(() {
ricercaFallita = false;
isLoading = false; // Rimostra la webview per riprovare
webViewController?.reload();
});
},
child: const Text("Riprova"),
)
],
);
}
if (dataScadenzaTrovata != null) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.check_circle, color: Colors.green, size: 80),
const SizedBox(height: 20),
const Text("Scadenza Trovata!", style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
Text(dataScadenzaTrovata!, style: TextStyle(fontSize: 30, color: Colors.blue[900], fontWeight: FontWeight.bold)),
const SizedBox(height: 40),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue[900],
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 15),
),
onPressed: () {
Navigator.pop(context, dataScadenzaTrovata);
},
child: const Text("USA QUESTA DATA", style: TextStyle(fontSize: 18)),
)
],
);
}
return const CircularProgressIndicator();
}
// --- FUNZIONI DI SCRAPING ---
Future<void> _preparaPagina() async {
if (webViewController == null) return;
// 1. INIEZIONE CSS: Stile "App Mobile"
await webViewController!.evaluateJavascript(source: """
// Nascondi tutto il contorno inutile
var elementsToHide = document.querySelectorAll('header, footer, .navbar, .breadcrumb, #cookie-bar, .portlet-title, .lfr-meta-actions');
elementsToHide.forEach(el => el.style.display = 'none');
var mainForm = document.querySelector('form');
if(mainForm) {
document.body.innerHTML = '';
document.body.appendChild(mainForm);
document.body.style.backgroundColor = '#ffffff';
document.body.style.padding = '20px';
document.body.style.fontFamily = 'sans-serif';
}
""");
// 2. INIEZIONE JS: Compilazione e UX
await webViewController!.evaluateJavascript(source: """
// A. Compila Targa
var campoTarga = document.getElementById('targa');
if (campoTarga) {
campoTarga.value = '${widget.targa}';
campoTarga.style.fontSize = '24px';
campoTarga.style.fontWeight = 'bold';
campoTarga.style.textAlign = 'center';
campoTarga.style.border = '2px solid #1565C0';
campoTarga.readOnly = true;
}
// B. Seleziona "Autoveicolo"
var selectVeicolo = document.querySelector('select');
if (selectVeicolo) {
for (var i = 0; i < selectVeicolo.options.length; i++) {
if (selectVeicolo.options[i].text.toLowerCase().includes('auto')) {
selectVeicolo.selectedIndex = i;
break;
}
}
// Nascondi la select e la sua label
selectVeicolo.style.display = 'none';
if(selectVeicolo.previousElementSibling) selectVeicolo.previousElementSibling.style.display = 'none';
}
// C. Restyling Bottone Ricerca
var btn = document.querySelector("input[name='ricercaCoperturaVeicolo']");
if (btn) {
btn.style.cssText = '';
btn.style.width = '100%';
btn.style.height = '60px';
btn.style.backgroundColor = '#1565C0';
btn.style.color = 'white';
btn.style.border = 'none';
btn.style.borderRadius = '12px';
btn.style.fontSize = '20px';
btn.style.marginTop = '30px';
btn.value = 'CERCA SCADENZA';
}
// D. Focus sul Captcha
var campoCaptcha = document.querySelector("input[name*='captcha']");
if(campoCaptcha) {
campoCaptcha.placeholder = 'Inserisci i caratteri qui';
campoCaptcha.style.height = '50px';
campoCaptcha.style.fontSize = '20px';
campoCaptcha.style.textAlign = 'center';
campoCaptcha.style.marginTop = '10px';
campoCaptcha.scrollIntoView();
}
""");
}
Future<void> _cercaRisultato() async {
if (webViewController == null) return;
// Leggiamo tutto l'HTML della pagina
String? html = await webViewController!.getHtml();
if (html == null) return;
// CASO 1: SUCCESSO
if (html.contains("Scadenza copertura")) {
// Eseguiamo JS per estrarre la data precisa
var dataEstratta = await webViewController!.evaluateJavascript(source: """
(function() {
// Cerca tutti i 'td' (celle di tabella)
var cells = document.querySelectorAll('td');
for (var i = 0; i < cells.length; i++) {
// Se la cella contiene la label...
if (cells[i].innerText.includes('Scadenza copertura')) {
// ...prendi il testo della cella successiva (dove c'è la data)
var nextCell = cells[i].nextElementSibling;
return nextCell ? nextCell.innerText : null;
}
}
return null;
})();
""");
if (dataEstratta != null && dataEstratta.toString().trim().isNotEmpty) {
setState(() {
dataScadenzaTrovata = dataEstratta.toString().trim();
});
}
}
// CASO 2: FALLIMENTO (Non assicurata o targa errata)
else if (html.contains("dal controllo non risulta coperto") || html.contains("Targa non trovata")) {
setState(() {
ricercaFallita = true;
});
}
// CASO 3: ANCORA NEL FORM (Es. captcha errato)
else {
// Riapplichiamo lo stile grafico perché il reload della pagina potrebbe averlo resettato
_preparaPagina();
}
}
}