242 lines
No EOL
8.4 KiB
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();
|
|
}
|
|
}
|
|
} |