import 'package:flutter/material.dart'; import 'package:nfc_google_sheet/components/selection_indicator.dart'; import 'package:nfc_google_sheet/components/student_form.dart'; import 'package:nfc_google_sheet/components/title.dart'; import 'package:nfc_google_sheet/components/wide_button.dart'; import 'package:flutter_nfc_kit/flutter_nfc_kit.dart'; import 'package:nfc_google_sheet/context/app_colors.dart'; import 'package:nfc_google_sheet/database/student_dao.dart'; import 'package:nfc_google_sheet/database/attendance_dao.dart'; import 'package:nfc_google_sheet/pages/sheet_page.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @override State createState() => _HomePageState(); } class _HomePageState extends State { String nfcData = "Appuyez sur une carte NFC"; ScanStatus _scanStatus = ScanStatus.idle; void _handleAttendanceResult(AttendanceResult result, String promotion) { switch (result) { case AttendanceResult.success: setState(() { nfcData = "Émargement enregistré !"; _scanStatus = ScanStatus.success; }); case AttendanceResult.alreadyScanned: setState(() { nfcData = "Cet étudiant a déjà émargé pour cet examen."; _scanStatus = ScanStatus.error; }); case AttendanceResult.wrongPromotion: setState(() { nfcData = "Mauvaise promotion : $promotion (attendu : ${SheetPage.selectedProgram})"; _scanStatus = ScanStatus.error; }); } } Future startNFC() async { if (SheetPage.selectedProgram == null || SheetPage.selectedSubject == null) { setState(() { nfcData = "Veuillez d'abord sélectionner une filière et une matière."; _scanStatus = ScanStatus.error; }); return; } try { var availability = await FlutterNfcKit.nfcAvailability; if (availability != NFCAvailability.available) { setState(() { nfcData = "NFC non disponible ou désactivé."; _scanStatus = ScanStatus.error; }); return; } setState(() { nfcData = "En attente d'une carte NFC..."; _scanStatus = ScanStatus.scanning; }); NFCTag tag = await FlutterNfcKit.poll(timeout: Duration(seconds: 15)); final cardId = tag.id; final existingStudent = await StudentDao.instance.getByCardId(cardId); if (existingStudent != null) { final result = await AttendanceDao.instance.register( cardId, existingStudent.promotion, SheetPage.selectedProgram!, SheetPage.selectedSubject!, ); _handleAttendanceResult(result, existingStudent.promotion); } else { setState(() { nfcData = "Nouvel étudiant détecté"; _scanStatus = ScanStatus.success; }); if (!mounted) return; showDialog( context: context, builder: (BuildContext context) { return StudentForm( cardId: cardId, onStudentSaved: (student) async { final result = await AttendanceDao.instance.register( cardId, student.promotion, SheetPage.selectedProgram!, SheetPage.selectedSubject!, ); _handleAttendanceResult(result, student.promotion); }, ); }, ); } } catch (e) { setState(() { nfcData = "Erreur ou scan annulé."; _scanStatus = ScanStatus.error; }); } finally { await FlutterNfcKit.finish(); if (_scanStatus == ScanStatus.scanning) { setState(() { _scanStatus = ScanStatus.idle; nfcData = "Appuyez sur une carte NFC"; }); } } } Widget _buildStatusIcon() { switch (_scanStatus) { case ScanStatus.scanning: return SizedBox( width: 120, height: 120, child: CircularProgressIndicator( color: AppColors.selected, strokeWidth: 6, ), ); case ScanStatus.success: return Icon(Icons.check_circle_outline, color: AppColors.selected, size: 120); case ScanStatus.error: return Icon(Icons.error_outline, color: Colors.red.shade400, size: 120); default: return Icon(Icons.nfc, color: AppColors.unselected.withValues(alpha: 0.7), size: 120); } } Widget _buildStatusText() { Color textColor; switch (_scanStatus) { case ScanStatus.success: textColor = AppColors.selected; case ScanStatus.error: textColor = Colors.red.shade400; default: textColor = AppColors.unselected; } return Container( padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: AppColors.subtitle.withValues(alpha: 0.5), borderRadius: BorderRadius.circular(12), ), child: Text( nfcData, textAlign: TextAlign.center, style: TextStyle(color: textColor, fontSize: 16, fontWeight: FontWeight.w500), ), ); } @override Widget build(BuildContext context) { bool isScanning = _scanStatus == ScanStatus.scanning; return Scaffold( backgroundColor: AppColors.background, body: SafeArea( child: Padding( padding: const EdgeInsets.all(24.0), child: Column( children: [ TitleCustom(content: 'ENREGISTREZ - VOUS'), SizedBox(height: 12), SelectionIndicator(), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ _buildStatusIcon(), SizedBox(height: 30), _buildStatusText(), ], ), ), WideButton( onPressed: isScanning ? null : startNFC, icon: Icons.nfc, label: isScanning ? "SCAN EN COURS..." : "ENREGISTRER SA CARTE", backgroundColor: AppColors.selected, foregroundColor: AppColors.background, disabledBackgroundColor: AppColors.selected.withValues(alpha: 0.5), letterSpacing: 1.1, ), ], ), ), ), ); } } enum ScanStatus { idle, scanning, success, error, }