import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:nfc_google_sheet/context/app_colors.dart'; import 'package:nfc_google_sheet/database/databaseHelper.dart'; import 'package:nfc_google_sheet/model/student.dart'; import 'package:nfc_google_sheet/services/google_drive_service.dart'; import 'package:file_picker/file_picker.dart'; class SheetPage extends StatefulWidget { const SheetPage({super.key}); static String? selectedProgram; static String? selectedSubject; @override State createState() => _SheetPageState(); } class _SheetPageState extends State { late Future> _students; @override void initState() { super.initState(); _students = _getStudents(); } Future> _getStudents() async { final List> maps = await DatabaseHelper.instance.queryAllUsers(); return List.generate(maps.length, (i) { return Student.fromMap(maps[i]); }); } String _buildFileName() { return '${SheetPage.selectedProgram ?? 'Program'}_${SheetPage.selectedSubject ?? 'Subject'}_${DateTime.now().year}'; } void _showExportDialog() { bool includeCardId = false; showDialog( context: context, builder: (BuildContext dialogContext) { return StatefulBuilder( builder: (context, setDialogState) { return AlertDialog( backgroundColor: AppColors.background, title: Text("Exporter les données", style: TextStyle(color: AppColors.selected)), content: Column( mainAxisSize: MainAxisSize.min, children: [ CheckboxListTile( title: Text("Inclure l'ID Carte", style: TextStyle(color: AppColors.unselected)), value: includeCardId, activeColor: AppColors.selected, checkColor: AppColors.background, contentPadding: EdgeInsets.zero, onChanged: (value) { setDialogState(() { includeCardId = value ?? false; }); }, ), SizedBox(height: 16), Row( children: [ Expanded( child: ElevatedButton.icon( style: ElevatedButton.styleFrom( backgroundColor: AppColors.selected, padding: EdgeInsets.symmetric(vertical: 12), ), icon: Icon(Icons.save, color: AppColors.background, size: 18), label: Text("Local", style: TextStyle(color: AppColors.background)), onPressed: () { Navigator.of(dialogContext).pop(); _exportLocal(includeCardId); }, ), ), SizedBox(width: 12), Expanded( child: ElevatedButton.icon( style: ElevatedButton.styleFrom( backgroundColor: Colors.blue.shade600, padding: EdgeInsets.symmetric(vertical: 12), ), icon: Icon(Icons.cloud_upload, color: Colors.white, size: 18), label: Text("Drive", style: TextStyle(color: Colors.white)), onPressed: () { Navigator.of(dialogContext).pop(); _exportToDrive(includeCardId); }, ), ), ], ), ], ), actions: [ TextButton( child: Text("Annuler", style: TextStyle(color: AppColors.unselected)), onPressed: () => Navigator.of(dialogContext).pop(), ), ], ); }, ); }, ); } void _exportLocal(bool includeCardId) async { final List? excelBytes = await DatabaseHelper.instance.generateExcel(includeCardId); if (excelBytes == null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Aucune donnée à exporter.'), backgroundColor: Colors.red, ), ); return; } String? filePath = await FilePicker.platform.saveFile( dialogTitle: 'Veuillez sélectionner un emplacement de sortie', fileName: '${_buildFileName()}.xlsx', bytes: Uint8List.fromList(excelBytes), ); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(filePath != null ? 'Fichier Excel enregistré avec succès !' : 'Enregistrement annulé.'), backgroundColor: filePath != null ? AppColors.selected : Colors.orange, ), ); } void _exportToDrive(bool includeCardId) async { final List? excelBytes = await DatabaseHelper.instance.generateExcel(includeCardId); if (excelBytes == null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Aucune donnée à exporter.'), backgroundColor: Colors.red, ), ); return; } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Connexion à Google Drive...'), backgroundColor: Colors.blue.shade600, duration: Duration(seconds: 2), ), ); try { final fileId = await GoogleDriveService.instance.uploadAsGoogleSheet( excelBytes, _buildFileName(), ); if (fileId != null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Fichier importé sur Google Drive avec succès !'), backgroundColor: AppColors.selected, ), ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Connexion annulée.'), backgroundColor: Colors.orange, ), ); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur lors de l\'import : $e'), backgroundColor: Colors.red, ), ); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.background, appBar: AppBar( title: Text('Données des étudiants', style: TextStyle(color: AppColors.selected)), backgroundColor: AppColors.background, elevation: 0, centerTitle: true, ), body: FutureBuilder>( future: _students, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return Center(child: CircularProgressIndicator(color: AppColors.selected)); } else if (snapshot.hasError) { return Center(child: Text('Erreur: ${snapshot.error}', style: TextStyle(color: Colors.red))); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return Center(child: Text('Aucun étudiant enregistré.', style: TextStyle(color: AppColors.unselected))); } else { final students = snapshot.data!; return SingleChildScrollView( child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: DataTable( columnSpacing: 20.0, headingRowColor: WidgetStateColor.resolveWith((states) => AppColors.subtitle), columns: [ DataColumn(label: Text('ID Étudiant', style: TextStyle(color: AppColors.selected, fontWeight: FontWeight.bold))), DataColumn(label: Text('Prénom', style: TextStyle(color: AppColors.selected, fontWeight: FontWeight.bold))), DataColumn(label: Text('Nom', style: TextStyle(color: AppColors.selected, fontWeight: FontWeight.bold))), DataColumn(label: Text('Promotion', style: TextStyle(color: AppColors.selected, fontWeight: FontWeight.bold))), ], rows: students.map((student) => DataRow( cells: [ DataCell(Text(student.studentId, style: TextStyle(color: AppColors.unselected))), DataCell(Text(student.firstName, style: TextStyle(color: AppColors.unselected))), DataCell(Text(student.name, style: TextStyle(color: AppColors.unselected))), DataCell(Text(student.promotion, style: TextStyle(color: AppColors.unselected))), ], )).toList(), ), ), ); } }, ), floatingActionButton: FloatingActionButton.extended( onPressed: _showExportDialog, label: Text('Générer le fichier', style: TextStyle(color: AppColors.background)), icon: Icon(Icons.download, color: AppColors.background), backgroundColor: AppColors.selected, ), ); } }