Newer
Older
import 'dart:typed_data';
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 {
static String? selectedProgram;
static String? selectedSubject;
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}';
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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,
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
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,
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),
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,