sheet_page.dart 9,15 ko
Newer Older
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<SheetPage> createState() => _SheetPageState();
class _SheetPageState extends State<SheetPage> {
  late Future<List<Student>> _students;

  @override
  void initState() {
    super.initState();
    _students = _getStudents();
  }

  Future<List<Student>> _getStudents() async {
    final List<Map<String, dynamic>> 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<int>? 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<int>? 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<List<Student>>(
        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,