feat(#153): onglet permanent Dossiers — liste unifiée + pending.

Remplace l’onglet conditionnel « À valider » par un onglet Dossiers
(pending en haut, familles + AM en dessous), avec GET /dossiers,
recherche, et libellés pending NOM Prénom.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-24 19:41:44 +02:00
co-authored by Cursor
parent 14580c34e0
commit 84e46162fd
16 changed files with 1462 additions and 374 deletions
+41 -16
View File
@@ -8,6 +8,8 @@ class DashboardUserManagementSubBar extends StatelessWidget {
final ValueChanged<int> onSubTabChange;
final TextEditingController searchController;
final String searchHint;
/// Infobulle au survol de la barre de recherche (ex. critères de recherche).
final String? searchTooltip;
final Widget? filterControl;
final VoidCallback? onAddPressed;
final String addLabel;
@@ -22,12 +24,16 @@ class DashboardUserManagementSubBar extends StatelessWidget {
'Administrateurs',
];
/// Aligné sur la taille des libellés donglets.
static const double _searchFontSize = 13;
const DashboardUserManagementSubBar({
Key? key,
required this.selectedSubIndex,
required this.onSubTabChange,
required this.searchController,
required this.searchHint,
this.searchTooltip,
this.filterControl,
this.onAddPressed,
this.addLabel = '+ Ajouter',
@@ -54,22 +60,7 @@ class DashboardUserManagementSubBar extends StatelessWidget {
_buildSubNavItem(context, labels[i], i),
],
const SizedBox(width: 36),
_pillField(
width: 320,
child: TextField(
controller: searchController,
decoration: InputDecoration(
hintText: searchHint,
prefixIcon: const Icon(Icons.search, size: 18),
border: InputBorder.none,
isDense: true,
contentPadding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 8,
),
),
),
),
_buildSearchField(),
if (filterControl != null) ...[
const SizedBox(width: 12),
_pillField(width: 150, child: filterControl!),
@@ -81,6 +72,40 @@ class DashboardUserManagementSubBar extends StatelessWidget {
);
}
Widget _buildSearchField() {
final field = _pillField(
width: 320,
child: TextField(
controller: searchController,
style: const TextStyle(fontSize: _searchFontSize),
decoration: InputDecoration(
hintText: searchHint,
hintStyle: TextStyle(
fontSize: _searchFontSize,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.normal,
color: Colors.black45,
),
prefixIcon: const Icon(Icons.search, size: 18),
border: InputBorder.none,
isDense: true,
contentPadding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 8,
),
),
),
);
final tip = (searchTooltip ?? '').trim();
if (tip.isEmpty) return field;
return Tooltip(
message: tip,
preferBelow: false,
waitDuration: const Duration(milliseconds: 400),
child: field,
);
}
Widget _pillField({required double width, required Widget child}) {
return Container(
width: width,