Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d02d47fb87 |
@@ -2238,6 +2238,57 @@ class _PanelEmptyState extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _TableauAvecDefilementHorizontal extends StatefulWidget {
|
||||||
|
const _TableauAvecDefilementHorizontal({
|
||||||
|
required this.largeurMinimale,
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
|
final double largeurMinimale;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_TableauAvecDefilementHorizontal> createState() =>
|
||||||
|
_TableauAvecDefilementHorizontalState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TableauAvecDefilementHorizontalState
|
||||||
|
extends State<_TableauAvecDefilementHorizontal> {
|
||||||
|
final ScrollController _controleur = ScrollController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controleur.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Scrollbar(
|
||||||
|
controller: _controleur,
|
||||||
|
thumbVisibility: true,
|
||||||
|
trackVisibility: true,
|
||||||
|
interactive: true,
|
||||||
|
thickness: 8,
|
||||||
|
radius: const Radius.circular(4),
|
||||||
|
scrollbarOrientation: ScrollbarOrientation.bottom,
|
||||||
|
notificationPredicate: (notification) =>
|
||||||
|
notification.metrics.axis == Axis.horizontal,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
controller: _controleur,
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
padding: const EdgeInsets.only(bottom: 14),
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(minWidth: widget.largeurMinimale),
|
||||||
|
child: widget.child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _VueEmpruntsTableau extends StatelessWidget {
|
class _VueEmpruntsTableau extends StatelessWidget {
|
||||||
const _VueEmpruntsTableau({
|
const _VueEmpruntsTableau({
|
||||||
required this.items,
|
required this.items,
|
||||||
@@ -2556,56 +2607,51 @@ class _VueEmpruntsTableau extends StatelessWidget {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
border: Border.all(color: EnsupColors.line),
|
border: Border.all(color: EnsupColors.line),
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(
|
child: _TableauAvecDefilementHorizontal(
|
||||||
child: SingleChildScrollView(
|
largeurMinimale: largeurDisponible,
|
||||||
scrollDirection: Axis.horizontal,
|
child: DataTable(
|
||||||
child: ConstrainedBox(
|
sortColumnIndex: _sortColumnIndex,
|
||||||
constraints: BoxConstraints(minWidth: largeurDisponible),
|
sortAscending: ordre == "asc",
|
||||||
child: DataTable(
|
headingRowColor: WidgetStatePropertyAll(
|
||||||
sortColumnIndex: _sortColumnIndex,
|
EnsupColors.soft.withValues(alpha: 0.8),
|
||||||
sortAscending: ordre == "asc",
|
|
||||||
headingRowColor: WidgetStatePropertyAll(
|
|
||||||
EnsupColors.soft.withValues(alpha: 0.8),
|
|
||||||
),
|
|
||||||
headingTextStyle: GoogleFonts.titilliumWeb(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
color: EnsupColors.text2,
|
|
||||||
),
|
|
||||||
dataTextStyle: GoogleFonts.titilliumWeb(
|
|
||||||
fontSize: 12,
|
|
||||||
color: EnsupColors.text,
|
|
||||||
),
|
|
||||||
columns: [
|
|
||||||
const DataColumn(label: Text("N°")),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Matériel"),
|
|
||||||
onSort: (_, _) => onTri("materiel"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Étudiant"),
|
|
||||||
onSort: (_, _) => onTri("etudiant"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Date d’emprunt"),
|
|
||||||
onSort: (_, _) => onTri("dateEmprunt"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Retour prévu"),
|
|
||||||
onSort: (_, _) => onTri("dateRetourPrevue"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Retour réel"),
|
|
||||||
onSort: (_, _) => onTri("dateRetourReelle"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Statut"),
|
|
||||||
onSort: (_, _) => onTri("statut"),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
rows: items.map(_ligneTableau).toList(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
headingTextStyle: GoogleFonts.titilliumWeb(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: EnsupColors.text2,
|
||||||
|
),
|
||||||
|
dataTextStyle: GoogleFonts.titilliumWeb(
|
||||||
|
fontSize: 12,
|
||||||
|
color: EnsupColors.text,
|
||||||
|
),
|
||||||
|
columns: [
|
||||||
|
const DataColumn(label: Text("N°")),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Matériel"),
|
||||||
|
onSort: (_, _) => onTri("materiel"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Étudiant"),
|
||||||
|
onSort: (_, _) => onTri("etudiant"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Date d’emprunt"),
|
||||||
|
onSort: (_, _) => onTri("dateEmprunt"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Retour prévu"),
|
||||||
|
onSort: (_, _) => onTri("dateRetourPrevue"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Retour réel"),
|
||||||
|
onSort: (_, _) => onTri("dateRetourReelle"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Statut"),
|
||||||
|
onSort: (_, _) => onTri("statut"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
rows: items.map(_ligneTableau).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -3098,55 +3144,50 @@ class _VueMaterielsTableau extends StatelessWidget {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
border: Border.all(color: EnsupColors.line),
|
border: Border.all(color: EnsupColors.line),
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(
|
child: _TableauAvecDefilementHorizontal(
|
||||||
child: SingleChildScrollView(
|
largeurMinimale: largeurDisponible,
|
||||||
scrollDirection: Axis.horizontal,
|
child: DataTable(
|
||||||
child: ConstrainedBox(
|
sortColumnIndex: _sortColumnIndex,
|
||||||
constraints: BoxConstraints(minWidth: largeurDisponible),
|
sortAscending: ordre == "asc",
|
||||||
child: DataTable(
|
headingRowColor: WidgetStatePropertyAll(
|
||||||
sortColumnIndex: _sortColumnIndex,
|
EnsupColors.soft.withValues(alpha: 0.8),
|
||||||
sortAscending: ordre == "asc",
|
|
||||||
headingRowColor: WidgetStatePropertyAll(
|
|
||||||
EnsupColors.soft.withValues(alpha: 0.8),
|
|
||||||
),
|
|
||||||
headingTextStyle: GoogleFonts.titilliumWeb(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
color: EnsupColors.text2,
|
|
||||||
),
|
|
||||||
dataTextStyle: GoogleFonts.titilliumWeb(
|
|
||||||
fontSize: 12,
|
|
||||||
color: EnsupColors.text,
|
|
||||||
),
|
|
||||||
columns: [
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Référence"),
|
|
||||||
onSort: (_, _) => onTri("reference"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Matériel"),
|
|
||||||
onSort: (_, _) => onTri("nom"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Catégorie"),
|
|
||||||
onSort: (_, _) => onTri("categorie"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Marque / modèle"),
|
|
||||||
onSort: (_, _) => onTri("marque"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("État"),
|
|
||||||
onSort: (_, _) => onTri("etatGeneral"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Statut"),
|
|
||||||
onSort: (_, _) => onTri("statut"),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
rows: items.map(_ligneTableau).toList(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
headingTextStyle: GoogleFonts.titilliumWeb(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: EnsupColors.text2,
|
||||||
|
),
|
||||||
|
dataTextStyle: GoogleFonts.titilliumWeb(
|
||||||
|
fontSize: 12,
|
||||||
|
color: EnsupColors.text,
|
||||||
|
),
|
||||||
|
columns: [
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Référence"),
|
||||||
|
onSort: (_, _) => onTri("reference"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Matériel"),
|
||||||
|
onSort: (_, _) => onTri("nom"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Catégorie"),
|
||||||
|
onSort: (_, _) => onTri("categorie"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Marque / modèle"),
|
||||||
|
onSort: (_, _) => onTri("marque"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("État"),
|
||||||
|
onSort: (_, _) => onTri("etatGeneral"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Statut"),
|
||||||
|
onSort: (_, _) => onTri("statut"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
rows: items.map(_ligneTableau).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -3626,52 +3667,47 @@ class _VueAnomaliesTableau extends StatelessWidget {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
border: Border.all(color: EnsupColors.line),
|
border: Border.all(color: EnsupColors.line),
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(
|
child: _TableauAvecDefilementHorizontal(
|
||||||
child: SingleChildScrollView(
|
largeurMinimale: largeurDisponible,
|
||||||
scrollDirection: Axis.horizontal,
|
child: DataTable(
|
||||||
child: ConstrainedBox(
|
sortColumnIndex: _sortColumnIndex,
|
||||||
constraints: BoxConstraints(minWidth: largeurDisponible),
|
sortAscending: ordre == "asc",
|
||||||
child: DataTable(
|
headingRowColor: WidgetStatePropertyAll(
|
||||||
sortColumnIndex: _sortColumnIndex,
|
EnsupColors.soft.withValues(alpha: 0.8),
|
||||||
sortAscending: ordre == "asc",
|
|
||||||
headingRowColor: WidgetStatePropertyAll(
|
|
||||||
EnsupColors.soft.withValues(alpha: 0.8),
|
|
||||||
),
|
|
||||||
headingTextStyle: GoogleFonts.titilliumWeb(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
color: EnsupColors.text2,
|
|
||||||
),
|
|
||||||
dataTextStyle: GoogleFonts.titilliumWeb(
|
|
||||||
fontSize: 12,
|
|
||||||
color: EnsupColors.text,
|
|
||||||
),
|
|
||||||
columns: [
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Détection"),
|
|
||||||
onSort: (_, _) => onTri("dateDetection"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Anomalie"),
|
|
||||||
onSort: (_, _) => onTri("type"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Matériel"),
|
|
||||||
onSort: (_, _) => onTri("materiel"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Étudiant"),
|
|
||||||
onSort: (_, _) => onTri("etudiant"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Statut"),
|
|
||||||
onSort: (_, _) => onTri("statut"),
|
|
||||||
),
|
|
||||||
const DataColumn(label: Text("Action")),
|
|
||||||
],
|
|
||||||
rows: items.map(_ligneTableau).toList(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
headingTextStyle: GoogleFonts.titilliumWeb(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: EnsupColors.text2,
|
||||||
|
),
|
||||||
|
dataTextStyle: GoogleFonts.titilliumWeb(
|
||||||
|
fontSize: 12,
|
||||||
|
color: EnsupColors.text,
|
||||||
|
),
|
||||||
|
columns: [
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Détection"),
|
||||||
|
onSort: (_, _) => onTri("dateDetection"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Anomalie"),
|
||||||
|
onSort: (_, _) => onTri("type"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Matériel"),
|
||||||
|
onSort: (_, _) => onTri("materiel"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Étudiant"),
|
||||||
|
onSort: (_, _) => onTri("etudiant"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Statut"),
|
||||||
|
onSort: (_, _) => onTri("statut"),
|
||||||
|
),
|
||||||
|
const DataColumn(label: Text("Action")),
|
||||||
|
],
|
||||||
|
rows: items.map(_ligneTableau).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -4250,52 +4286,47 @@ class _VueHistoriqueTableau extends StatelessWidget {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
border: Border.all(color: EnsupColors.line),
|
border: Border.all(color: EnsupColors.line),
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(
|
child: _TableauAvecDefilementHorizontal(
|
||||||
child: SingleChildScrollView(
|
largeurMinimale: largeurDisponible,
|
||||||
scrollDirection: Axis.horizontal,
|
child: DataTable(
|
||||||
child: ConstrainedBox(
|
sortColumnIndex: _sortColumnIndex,
|
||||||
constraints: BoxConstraints(minWidth: largeurDisponible),
|
sortAscending: ordre == "asc",
|
||||||
child: DataTable(
|
headingRowColor: WidgetStatePropertyAll(
|
||||||
sortColumnIndex: _sortColumnIndex,
|
EnsupColors.soft.withValues(alpha: 0.8),
|
||||||
sortAscending: ordre == "asc",
|
|
||||||
headingRowColor: WidgetStatePropertyAll(
|
|
||||||
EnsupColors.soft.withValues(alpha: 0.8),
|
|
||||||
),
|
|
||||||
headingTextStyle: GoogleFonts.titilliumWeb(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
color: EnsupColors.text2,
|
|
||||||
),
|
|
||||||
dataTextStyle: GoogleFonts.titilliumWeb(
|
|
||||||
fontSize: 12,
|
|
||||||
color: EnsupColors.text,
|
|
||||||
),
|
|
||||||
columns: [
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Date"),
|
|
||||||
onSort: (_, _) => onTri("dateAction"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Action"),
|
|
||||||
onSort: (_, _) => onTri("action"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Utilisateur"),
|
|
||||||
onSort: (_, _) => onTri("utilisateur"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Matériel"),
|
|
||||||
onSort: (_, _) => onTri("materiel"),
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: const Text("Emprunt"),
|
|
||||||
onSort: (_, _) => onTri("emprunt"),
|
|
||||||
),
|
|
||||||
const DataColumn(label: Text("Point d’opération")),
|
|
||||||
],
|
|
||||||
rows: items.map(_ligneTableau).toList(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
headingTextStyle: GoogleFonts.titilliumWeb(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: EnsupColors.text2,
|
||||||
|
),
|
||||||
|
dataTextStyle: GoogleFonts.titilliumWeb(
|
||||||
|
fontSize: 12,
|
||||||
|
color: EnsupColors.text,
|
||||||
|
),
|
||||||
|
columns: [
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Date"),
|
||||||
|
onSort: (_, _) => onTri("dateAction"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Action"),
|
||||||
|
onSort: (_, _) => onTri("action"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Utilisateur"),
|
||||||
|
onSort: (_, _) => onTri("utilisateur"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Matériel"),
|
||||||
|
onSort: (_, _) => onTri("materiel"),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: const Text("Emprunt"),
|
||||||
|
onSort: (_, _) => onTri("emprunt"),
|
||||||
|
),
|
||||||
|
const DataColumn(label: Text("Point d’opération")),
|
||||||
|
],
|
||||||
|
rows: items.map(_ligneTableau).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -525,6 +525,14 @@ En terminal interactif (VS Code), `migrate dev` fonctionne normalement (taper `y
|
|||||||
- La confirmation reste enregistrée, le message de succès reste visible et les données de supervision sont rechargées normalement.
|
- La confirmation reste enregistrée, le message de succès reste visible et les données de supervision sont rechargées normalement.
|
||||||
- Vérifications réussies : `dart analyze` sans erreur et serveur Flutter opérationnel sur le port 5000.
|
- Vérifications réussies : `dart analyze` sans erreur et serveur Flutter opérationnel sur le port 5000.
|
||||||
|
|
||||||
|
### Étape 55 — Défilement horizontal visible des tableaux responsable
|
||||||
|
- Les tableaux Emprunts, Stock matériel, Anomalies et Historique restent accessibles sur les écrans de largeur intermédiaire.
|
||||||
|
- Un composant partagé gère le défilement horizontal avec son propre contrôleur Flutter.
|
||||||
|
- La barre horizontale est visible, interactive et positionnée sous le contenu de chaque tableau.
|
||||||
|
- Les dernières colonnes, notamment les statuts et les actions, peuvent être atteintes sans modifier la disposition sur grand écran.
|
||||||
|
- Les listes compactes mobiles existantes sont conservées sous leurs seuils responsifs.
|
||||||
|
- Vérifications réussies : les quatre tableaux utilisent le composant partagé, `dart analyze` est sans erreur et le serveur Flutter répond sur le port 5000.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Dernière mise à jour : 2026-07-24 — Rafraîchissement après décision responsable corrigé.*
|
*Dernière mise à jour : 2026-07-24 — Défilement horizontal des tableaux responsable ajouté.*
|
||||||
|
|||||||
Reference in New Issue
Block a user