manager-app/lib/Screens/Configurations/section_reorderList.dart
Thomas Fransolet 0054122829 Carte : filtre par categorie, editeur de point, et corrections users/quotas
Regroupe la configuration de carte en deux blocs (Carte / Points d'interet),
ajoute le filtre par categorie et l'editeur de point geographique, et passe
les ecrans Users et les jauges de quota par AppLocalizations (FR/EN/NL).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 16:22:39 +02:00

153 lines
5.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:diacritic/diacritic.dart';
import 'package:manager_app/l10n/app_localizations.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/message_notification.dart';
import 'package:manager_app/Components/rounded_input_field.dart';
import 'package:manager_app/Models/managerContext.dart';
import 'package:manager_app/Screens/Configurations/listView_card_section.dart';
import 'package:manager_app/Screens/Configurations/new_section_popup.dart';
import 'package:manager_app/app_context.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_api_new/api.dart';
import 'package:provider/provider.dart';
/// Grille des sections d'une configuration, réordonnable.
///
/// Elle était une liste horizontale enfermée dans `0,3 × hauteur d'écran` :
/// 30 % de l'écran réservés quoi qu'il arrive, et les sections au-delà de la
/// huitième hors champ à droite sans indice. Ici la grille se remplit sur toute
/// la largeur et la hauteur suit le contenu.
///
/// Le réordonnancement se fait par la poignée de chaque tuile
/// (`Draggable` → `DragTarget`) : `ReorderableListView` ne sait pas faire de
/// grille, et la maquette interdit une dépendance nouvelle.
class SectionReorderList extends StatefulWidget {
final String configurationId;
final List<SectionDTO> sectionsIn;
final ValueChanged<List<SectionDTO>> onChangedOrder;
final Function askReload;
const SectionReorderList({
Key? key,
required this.configurationId,
required this.sectionsIn,
required this.onChangedOrder,
required this.askReload,
}) : super(key: key);
@override
_SectionReorderListState createState() => _SectionReorderListState();
}
class _SectionReorderListState extends State<SectionReorderList> {
late List<SectionDTO> sections;
String filterSearch = '';
@override
void initState() {
super.initState();
sections = new List<SectionDTO>.from(widget.sectionsIn);
}
void _onReorder(int oldIndex, int newIndex) {
setState(() {
final SectionDTO item = sections.removeAt(oldIndex);
sections.insert(newIndex, item);
var i = 0;
sections.forEach((section) {
section.order = i;
i++;
});
widget.onChangedOrder(sections);
});
}
Future<void> _createSection(AppContext appContext) async {
var sectionToCreate =
await showNewSection(widget.configurationId, appContext, context, false);
if (sectionToCreate != null) {
ManagerAppContext managerAppContext = appContext.getContext();
sectionToCreate.instanceId = managerAppContext.instanceId;
sectionToCreate.isBeacon = false;
sectionToCreate.dateCreation = DateTime.now();
await managerAppContext.clientAPI!.sectionApi!
.sectionCreate(sectionToCreate);
showNotification(kSuccess, kWhite,
AppLocalizations.of(context)!.sectionCreatedSuccess, context, null);
widget.askReload();
}
}
/// Retirer une section de l'app sans la supprimer. Le champ existe depuis
/// toujours côté serveur et les apps visiteur le respectent déjà — il n'avait
/// simplement aucun geste dans le manager.
Future<void> _toggleVisibility(
AppContext appContext, SectionDTO section) async {
final l = AppLocalizations.of(context)!;
final newValue = section.isActive == false;
setState(() => section.isActive = newValue);
try {
ManagerAppContext managerAppContext = appContext.getContext();
await managerAppContext.clientAPI!.sectionApi!
.sectionSetVisibility(section.id!, newValue);
showNotification(
kSuccess,
kWhite,
newValue ? l.sectionShownSuccess : l.sectionHiddenSuccess,
context,
null);
} catch (e) {
setState(() => section.isActive = !newValue);
showNotification(kError, kWhite, l.sectionVisibilityError, context, null);
}
}
@override
Widget build(BuildContext context) {
final appContext = Provider.of<AppContext>(context);
final l = AppLocalizations.of(context)!;
final canEdit = (appContext.getContext() as ManagerAppContext).canEdit;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RoundedInputField(
hintText: l.searchLabel,
icon: Icons.search,
onChanged: (String value) {
setState(() {
filterSearch = value;
filterResource();
});
},
),
const SizedBox(height: kSpace4),
SectionGrid(
sections: sections,
onReorder: _onReorder,
onAdd: () => _createSection(appContext),
onToggleVisibility: canEdit
? (section) => _toggleVisibility(appContext, section)
: null,
onTap: (section, index) {
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
ManagerAppContext managerAppContext = appContext.getContext();
managerAppContext.selectedSection = section;
appContext.setContext(managerAppContext);
});
});
},
),
],
);
}
void filterResource() {
sections = filterSearch.isEmpty ? widget.sectionsIn: widget.sectionsIn.where((SectionDTO section) => removeDiacritics(section.label!.toUpperCase()).contains(removeDiacritics(filterSearch.toUpperCase()))).toList();
}
}