Commits (2)
......@@ -42,6 +42,6 @@
<data android:mimeType="text/plain"/>
</intent>
</queries>
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.NFC"/>
<uses-feature android:name="android.hardware.nfc" android:required="true"/>
</manifest>
import 'package:flutter/material.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'dart:typed_data';
import 'google_sheets_api.dart';
import 'inscription_page.dart'; // <-- 1. IMPORTER LA NOUVELLE PAGE
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';
void main() {
WidgetsFlutterBinding.ensureInitialized();
......@@ -22,9 +23,11 @@ class SimpleNfcReader extends StatefulWidget {
class _SimpleNfcReaderState extends State<SimpleNfcReader> {
bool _isReading = false;
String _status = 'Appuyez sur le bouton pour vérifier un étudiant';
String? _lastScannedUid; // <-- 2. GARDER EN MÉMOIRE L'UID SCANNÉ
// Instance de notre API Google Sheets
final GoogleSheetsApi _sheetsApi = GoogleSheetsApi();
// Dernières informations lues (UID etc.)
final Map<String, String> _info = {};
Future<void> _startNfc() async {
bool available = await NfcManager.instance.isAvailable();
......@@ -36,7 +39,6 @@ class _SimpleNfcReaderState extends State<SimpleNfcReader> {
setState(() {
_isReading = true;
_status = '🔄 Approchez une carte étudiant...';
_lastScannedUid = null; // Réinitialiser à chaque scan
});
NfcManager.instance.startSession(
......@@ -48,6 +50,7 @@ class _SimpleNfcReaderState extends State<SimpleNfcReader> {
onDiscovered: (NfcTag tag) async {
String? uid;
try {
// --- 1. Récupérer le numéro de série (UID) ---
dynamic data;
try { data = (tag as dynamic).data; } catch (_) {}
......@@ -63,18 +66,21 @@ class _SimpleNfcReaderState extends State<SimpleNfcReader> {
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 !';
_lastScannedUid = null; // Trouvé, donc on n'inscrit pas
} else {
_status = '❌ Étudiant inexistant.\nN°: $uid';
_lastScannedUid = uid; // <-- 3. ON SAUVEGARDE L'UID POUR L'INSCRIPTION
}
});
......@@ -85,33 +91,14 @@ class _SimpleNfcReaderState extends State<SimpleNfcReader> {
await NfcManager.instance.stopSession();
}
// On a fini, on réactive le bouton
setState(() => _isReading = false);
},
);
}
// --- 4. FONCTION POUR OUVRIR LA PAGE D'INSCRIPTION ---
void _goToInscriptionPage() {
if (_lastScannedUid == null) return;
// Naviguer vers la page d'inscription et lui passer l'UID
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => InscriptionPage(prefilledMac: _lastScannedUid),
),
).then((inscriptionReussie) {
// Ce code s'exécute quand on revient de la page d'inscription
if (inscriptionReussie == true) {
setState(() {
_status = '✅ Nouvel étudiant enregistré !';
_lastScannedUid = null; // On nettoie
});
}
});
}
// --- Fonctions utilitaires (inchangées) ---
String _bytesToHexString(dynamic maybeBytes) {
try {
Uint8List bytes;
......@@ -119,7 +106,6 @@ class _SimpleNfcReaderState extends State<SimpleNfcReader> {
else if (maybeBytes is List<int>) bytes = Uint8List.fromList(maybeBytes);
else return maybeBytes.toString();
// SANS DEUX-POINTS
return bytes.map((b) => b.toRadixString(16).padLeft(2, '0').toUpperCase()).join('');
} catch (_) {
return maybeBytes.toString();
......@@ -144,10 +130,51 @@ class _SimpleNfcReaderState extends State<SimpleNfcReader> {
return null;
}
/// L'interface utilisateur
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('📡 Vérification Étudiant')),
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(
......@@ -165,32 +192,16 @@ class _SimpleNfcReaderState extends State<SimpleNfcReader> {
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
// --- 5. AFFICHAGE DU BOUTON D'INSCRIPTION ---
if (_lastScannedUid != null && !_isReading)
Padding(
padding: const EdgeInsets.only(top: 24.0),
child: ElevatedButton.icon(
onPressed: _goToInscriptionPage,
icon: const Icon(Icons.person_add),
label: const Text('Inscrire ce nouvel étudiant'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green, // Couleur différente
padding: const EdgeInsets.symmetric(vertical: 12),
),
),
),
const Spacer(),
Center(
child: ElevatedButton.icon(
onPressed: _isReading ? null : _startNfc,
icon: _isReading
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2)
)
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(
......@@ -198,6 +209,7 @@ class _SimpleNfcReaderState extends State<SimpleNfcReader> {
),
),
),
const SizedBox(height: 10),
],
),
),
......
......@@ -22,6 +22,8 @@ class _SheetViewPageState extends State<SheetViewPage> {
Future<void> _load() async {
setState(() => _loading = true);
final data = await _api.readData();
// afficher les données dans la console pour le débogage
print('Données chargées : $data');
setState(() {
_rows = data ?? [];
_loading = false;
......