main.dart 7,02 ko
Newer Older
Papa THIAM's avatar
Papa THIAM a validé
import 'package:flutter/material.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'dart:typed_data'; // Pour convertir l'UID
import 'google_sheets_api.dart'; // <-- ON IMPORTE NOTRE API
import 'inscription_page.dart';
import 'sheet_view_page.dart';
Papa THIAM's avatar
Papa THIAM a validé

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MaterialApp(
    debugShowCheckedModeBanner: false,
    home: SimpleNfcReader(),
  ));
Papa THIAM's avatar
Papa THIAM a validé
}

class SimpleNfcReader extends StatefulWidget {
  const SimpleNfcReader({super.key});
Papa THIAM's avatar
Papa THIAM a validé

  State<SimpleNfcReader> createState() => _SimpleNfcReaderState();
Papa THIAM's avatar
Papa THIAM a validé

class _SimpleNfcReaderState extends State<SimpleNfcReader> {
  bool _isReading = false;
  String _status = 'Appuyez sur le bouton pour vérifier un étudiant';

  // Instance de notre API Google Sheets
  final GoogleSheetsApi _sheetsApi = GoogleSheetsApi();
  // Dernières informations lues (UID etc.)
  final Map<String, String> _info = {};
Papa THIAM's avatar
Papa THIAM a validé

  Future<void> _startNfc() async {
    bool available = await NfcManager.instance.isAvailable();
    if (!available) {
      setState(() => _status = '❌ NFC non disponible sur cet appareil');
      return;
    }
      _status = '🔄 Approchez une carte étudiant...';
    NfcManager.instance.startSession(
      pollingOptions: {
        NfcPollingOption.iso14443,
        NfcPollingOption.iso15693,
        NfcPollingOption.iso18092,
      },
      onDiscovered: (NfcTag tag) async {
          // --- 1. Récupérer le numéro de série (UID) ---
          dynamic data;
          try { data = (tag as dynamic).data; } catch (_) {}
Papa THIAM's avatar
Papa THIAM a validé

          final idBytes = _safeLookup(data, 'id');
          if (idBytes != null) {
            uid = _bytesToHexString(idBytes);
          if (uid == null) {
            setState(() => _status = '❌ Impossible de lire le N° de série.');
            await NfcManager.instance.stopSession();
            setState(() => _isReading = false);
            return;
          // --- 2. Vérifier dans Google Sheets ---
          setState(() => _status = '🔄 N° de série: $uid\nVérification en cours...');
          // On arrête le scan NFC pendant qu'on contacte la base de données
          await NfcManager.instance.stopSession();
          // Appel de notre NOUVELLE fonction
          String? nomEtudiant = await _sheetsApi.findStudentNameByNfcUid(uid);
          // --- 3. Afficher le résultat final ---
          setState(() {
            if (nomEtudiant != null) {
              _status = '✅ Bienvenue, $nomEtudiant !';
            } else {
              _status = '❌ Étudiant inexistant.\nN°: $uid';
            }
          });
        } catch (e) {
          setState(() {
            _status = 'Erreur: ${e.toString()}';
          });
          await NfcManager.instance.stopSession();
        }
        // On a fini, on réactive le bouton
        setState(() => _isReading = false);
      },
    );
  // --- Fonctions utilitaires (inchangées) ---

  String _bytesToHexString(dynamic maybeBytes) {
    try {
      Uint8List bytes;
      if (maybeBytes is Uint8List) bytes = maybeBytes;
      else if (maybeBytes is List<int>) bytes = Uint8List.fromList(maybeBytes);
      else return maybeBytes.toString();

      return bytes.map((b) => b.toRadixString(16).padLeft(2, '0').toUpperCase()).join('');
    } catch (_) {
      return maybeBytes.toString();
    }
  }

  dynamic _safeLookup(dynamic obj, String key) {
    if (obj == null) return null;
    try {
      if (obj is Map) {
        if (obj.containsKey(key)) return obj[key];
        final lower = key.toLowerCase();
        if (obj.containsKey(lower)) return obj[lower];
    } catch (_) {}
    try {
      return (obj as dynamic)[key];
    } catch (_) {}
    try {
      if (key == 'id') return (obj as dynamic).id;
    } catch (_) {}
    return null;
Papa THIAM's avatar
Papa THIAM a validé
  }

Papa THIAM's avatar
Papa THIAM a validé
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('📡 Lecteur NFC simple')),
      drawer: Drawer(
        child: SafeArea(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              DrawerHeader(
                decoration: BoxDecoration(color: Theme.of(context).colorScheme.primaryContainer),
                child: const Center(child: Text('Menu', style: TextStyle(fontSize: 20))),
              ),
              ListTile(
                leading: const Icon(Icons.person_add),
                title: const Text('Inscription'),
                onTap: () async {
                  Navigator.of(context).pop();
                  final prefMac = _info['Numéro de série'] ?? _info['UID brute'];
                  await Navigator.of(context).push(MaterialPageRoute(builder: (_) => InscriptionPage(prefilledMac: prefMac)));
                },
              ),
              ListTile(
                leading: const Icon(Icons.table_chart),
                title: const Text('Liste des données'),
                onTap: () async {
                  Navigator.of(context).pop();
                  await Navigator.of(context).push(MaterialPageRoute(builder: (_) => const SheetViewPage()));
                },
              ),
              const Divider(),
              ListTile(
                leading: const Icon(Icons.info_outline),
                title: const Text('A propos'),
                onTap: () => showAboutDialog(
                  context: context,
                  applicationName: 'NFC Reader',
                  children: [const Text('Lecteur NFC et gestion des inscriptions')],
                ),
              ),
            ],
          ),
        ),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.stretch,
            Icon(
              _isReading ? Icons.nfc : Icons.school,
              size: 100,
              color: Colors.blueAccent,
            const SizedBox(height: 30),
            Text(
              _status,
              style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
              textAlign: TextAlign.center,
            ),
            const Spacer(),
            Center(
              child: ElevatedButton.icon(
                onPressed: _isReading ? null : _startNfc,
                        width: 20,
                        height: 20,
                        child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2),
                      )
                    : const Icon(Icons.nfc),
                label: Text(_isReading ? 'Lecture en cours...' : 'Vérifier la carte'),
                style: ElevatedButton.styleFrom(
                  padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 15),
                ),
Papa THIAM's avatar
Papa THIAM a validé
        ),
      ),
    );
  }