WIP geopoints filter

This commit is contained in:
Thomas Fransolet 2024-04-12 23:24:57 +02:00
parent 59618c84e0
commit fbf051b23f
4 changed files with 222 additions and 27 deletions

View File

@ -0,0 +1,168 @@
import 'dart:ui';
//import 'package:animated_tree_view/animated_tree_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
import 'package:generate_tree/generate_tree.dart';
import 'package:generate_tree/treeNode.dart';
import 'package:manager_api/api.dart';
import 'package:provider/provider.dart';
import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/app_context.dart';
import 'package:tablet_app/constants.dart';
import 'package:html/parser.dart' show parse;
class GeoPointFilter extends StatefulWidget {
final String language;
final List<GeoPointDTO> geoPoints;
final List<CategorieDTO> categories;
final Function(List<GeoPointDTO>?) filteredPoints;
GeoPointFilter({required this.language, required this.geoPoints, required this.categories, required this.filteredPoints});
@override
_GeoPointFilterState createState() => _GeoPointFilterState();
}
class _GeoPointFilterState extends State<GeoPointFilter> {
List<GeoPointDTO> selectedGeoPoints = [];
//late List<TreeNode> treeNodes;
late List<TreeNode> _filteredNodes;
late ValueNotifier<String> _searchTextNotifier;
@override
void initState() {
super.initState();
_searchTextNotifier = ValueNotifier<String>('');
//_searchTextNotifier.addListener(_onSearchTextChanged); // Cause the setState ?
// Construire les nœuds de l'arborescence en utilisant les catégories et les géopoints
//treeNodes = buildTreeNodes(widget.categories, widget.geoPoints);
_filteredNodes = buildTreeNodes(widget.categories, widget.geoPoints);
}
void _onSearchTextChanged() {
filterNodes(_searchTextNotifier.value);
}
List<TreeNode> buildTreeNodes(List<CategorieDTO> categories, List<GeoPointDTO> geoPoints) {
List<TreeNode> nodes = [];
// Pour chaque catégorie, créez un nœud parent
for (var category in categories) {
TreeNode categoryNode = TreeNode(
id: category.id ?? 0,
title: parse(category.label!.firstWhere((l) => l.language == widget.language).value!).documentElement!.text,
children: [],
checked: false,
show: false,
pid: 0,
commonID: 0,
);
// Ajoutez les géopoints correspondant à cette catégorie en tant qu'enfants du nœud parent
for (var geoPoint in geoPoints) {
if (geoPoint.categorieId == category.id) {
TreeNode geoPointNode = TreeNode(
id: geoPoint.id ?? 0,
title: parse(geoPoint.title!.firstWhere((l) => l.language == widget.language).value!).documentElement!.text,
checked: false,
show: false,
children: [],
pid: 0,
commonID: 0,
);
categoryNode.children.add(geoPointNode);
}
}
nodes.add(categoryNode);
}
return nodes;
}
void filterNodes(String searchText) {
//setState(() {
_searchTextNotifier.value = searchText;
//_searchText = searchText;
// Filtrer les nœuds en fonction du texte de recherche
_filteredNodes = _searchTextNotifier.value.isEmpty
? buildTreeNodes(widget.categories, widget.geoPoints)
: _filterNodesBySearchText(_searchTextNotifier.value);
//});
}
List<TreeNode> _filterNodesBySearchText(String searchText) {
List<TreeNode> filteredNodes = [];
for (var node in buildTreeNodes(widget.categories, widget.geoPoints)) {
if (node.title.toLowerCase().contains(searchText.toLowerCase())) {
// Si le titre du nœud contient le texte de recherche, ajoutez-le aux nœuds filtrés
filteredNodes.add(node);
}
}
return filteredNodes;
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
final appContext = Provider.of<AppContext>(context);
TabletAppContext tabletAppContext = appContext.getContext();
var currentLanguage = tabletAppContext.language;
var primaryColor = tabletAppContext.configuration != null ? tabletAppContext.configuration!.primaryColor != null ? new Color(int.parse(tabletAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)) : kTestSecondColor : kTestSecondColor;
return Container(
decoration: BoxDecoration(
color: kBackgroundColor.withOpacity(0.78),
borderRadius: BorderRadius.all(Radius.circular(tabletAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextFormField(
//initialValue: 'Input text',
decoration: InputDecoration(
labelText: 'Recherche',
suffixIcon: Icon(
Icons.search,
),
),
onChanged: filterNodes,
),
ValueListenableBuilder<String>(
valueListenable: _searchTextNotifier,
builder: (context, value, _) {
return Container(
color: Colors.greenAccent,
height: size.height * 0.7,
width: size.width * 0.3,
child: GenerateTree(
data: _filteredNodes,
selectOneToAll: true,
textColor: Colors.black,
onChecked: (node, checked, commonID) {
if(checked) {
//node.
//var test =
//selectedGeoPoints.add();
}
print('isChecked : $checked');
print('common Node ID : ${commonID}');
print('children node data : ${node.children.map((e) => '${e.title}')}');
// Todo update selection
},
checkBoxColor: primaryColor,
childrenPadding: EdgeInsets.only(left: 20, top: 10, right: 0, bottom: 10),
),
);
}
),
],
),
),
);
}
}

View File

@ -9,9 +9,12 @@ import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart' as mapBox;
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tablet_app/Components/multi_select_container.dart'; import 'package:tablet_app/Components/multi_select_container.dart';
import 'package:tablet_app/Models/map-marker.dart'; import 'package:tablet_app/Models/map-marker.dart';
import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/Screens/Map/geo_point_filter.dart';
import 'package:tablet_app/Screens/Map/map_context.dart'; import 'package:tablet_app/Screens/Map/map_context.dart';
import 'package:html/parser.dart' show parse; import 'package:html/parser.dart' show parse;
import 'package:tablet_app/Screens/Map/map_view.dart'; import 'package:tablet_app/Screens/Map/map_view.dart';
import 'package:tablet_app/app_context.dart';
import 'package:tablet_app/constants.dart'; import 'package:tablet_app/constants.dart';
class MapBoxView extends StatefulWidget { class MapBoxView extends StatefulWidget {
@ -53,6 +56,7 @@ class AnnotationClickListener extends mapBox.OnPointAnnotationClickListener {
class _MapBoxViewState extends State<MapBoxView> { class _MapBoxViewState extends State<MapBoxView> {
late mapBox.MapboxMap? mapboxMap; late mapBox.MapboxMap? mapboxMap;
late mapBox.PointAnnotationManager? pointAnnotationManager; late mapBox.PointAnnotationManager? pointAnnotationManager;
bool filterZoneSelected = false;
createPoints() { createPoints() {
var options = <mapBox.PointAnnotationOptions>[]; var options = <mapBox.PointAnnotationOptions>[];
@ -126,6 +130,8 @@ class _MapBoxViewState extends State<MapBoxView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final mapContext = Provider.of<MapContext>(context); final mapContext = Provider.of<MapContext>(context);
final appContext = Provider.of<AppContext>(context);
TabletAppContext tabletAppContext = appContext.getContext() as TabletAppContext;
Size size = MediaQuery.of(context).size; Size size = MediaQuery.of(context).size;
var type = mapBox.MapboxStyles.STANDARD; var type = mapBox.MapboxStyles.STANDARD;
@ -173,31 +179,19 @@ class _MapBoxViewState extends State<MapBoxView> {
) )
), ),
Positioned( Positioned(
bottom: 35, left: 5,
left: 10, top: 35,
child: SizedBox( child: SizedBox(
width: size.width * 0.85, width: size.width * 0.3,
child: MultiSelectContainer( height: size.height * 0.76,
label: null, child: GeoPointFilter(
color: kBackgroundGrey, language: tabletAppContext.language!,
initialValue: selectedCategories!, geoPoints: widget.mapDTO!.points!,
isMultiple: true, categories: widget.mapDTO!.categories!,
values: widget.mapDTO!.categories!.map((categorie) => categorie.label!.firstWhere((element) => element.language == widget.language).value!).toList(), filteredPoints: (filteredPoints) {
onChanged: (value) { print("COUCOU FILTERED POINTS");
var tempOutput = new List<String>.from(value); print(filteredPoints);
print(tempOutput); }),
if(init) {
setState(() {
selectedCategories = tempOutput;
pointsToShow = widget.mapDTO!.points!.where((point) => tempOutput.any((tps) => point.categorie?.label?.firstWhere((lab) => lab.language == widget.language).value == tps) || point.categorie == null).toList();
//markers = getMarkers(widget.language, mapContext);
pointAnnotationManager!.deleteAll();
pointAnnotationManager!.createMulti(createPoints());
mapContext.notifyListeners();
});
}
},
),
), ),
), ),
], ],

View File

@ -33,6 +33,7 @@ class MenuView extends StatefulWidget {
class _MenuView extends State<MenuView> { class _MenuView extends State<MenuView> {
MenuDTO menuDTO = MenuDTO(); MenuDTO menuDTO = MenuDTO();
SectionDTO? selectedSection; SectionDTO? selectedSection;
bool isImageBackground = false;
@override @override
void initState() { void initState() {
@ -40,6 +41,8 @@ class _MenuView extends State<MenuView> {
menuDTO = MenuDTO.fromJson(jsonDecode(widget.section.data!))!; menuDTO = MenuDTO.fromJson(jsonDecode(widget.section.data!))!;
print(menuDTO); print(menuDTO);
isImageBackground = true; //widget.isImageBackground;
super.initState(); super.initState();
} }
@ -177,10 +180,10 @@ class _MenuView extends State<MenuView> {
}); });
}, },
child: Container( child: Container(
decoration: boxDecoration(appContext, menuDTO.sections![index], false), decoration: isImageBackground ? boxDecoration(appContext, menuDTO.sections![index], false) : null,
padding: const EdgeInsets.all(25), padding: const EdgeInsets.all(25),
margin: EdgeInsets.symmetric(vertical: 15, horizontal: 15), margin: EdgeInsets.symmetric(vertical: 15, horizontal: 15),
child: Align( child: isImageBackground ? Align(
alignment: Alignment.bottomRight, alignment: Alignment.bottomRight,
child: FractionallySizedBox( child: FractionallySizedBox(
heightFactor: 0.5, heightFactor: 0.5,
@ -209,6 +212,34 @@ class _MenuView extends State<MenuView> {
], ],
) )
), ),
) : Column(
children: [
Expanded(
flex: 8,
child: Container(
decoration: BoxDecoration(
color: menuDTO.sections![index].imageSource == null ? kBackgroundColor : null, // default color if no image
shape: BoxShape.rectangle,
image: menuDTO.sections![index].imageSource != null ? new DecorationImage(
fit: BoxFit.cover,
image: ImageCustomProvider.getImageProvider(appContext, menuDTO.sections![index].imageId!, menuDTO.sections![index].imageSource!),
): null,
),
)
),
Expanded(
flex: 2,
child: Center(
child: HtmlWidget(
menuDTO.sections![index].title!.firstWhere((translation) => translation.language == appContext.getContext().language).value ?? "",
customStylesBuilder: (element) {
return {'text-align': 'center', 'font-family': "Roboto"};
},
textStyle: TextStyle(fontSize: 25),//calculateFontSize(constraints.maxWidth, constraints.maxHeight, kIsWeb ? kWebMenuTitleDetailSize : kMenuTitleDetailSize)),
),
)
)
],
), ),
), ),
); );
@ -234,7 +265,7 @@ boxDecoration(AppContext appContext, SectionDTO section, bool isSelected) {
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: kBackgroundSecondGrey, color: kBackgroundSecondGrey,
spreadRadius: 0.5, spreadRadius: 0.3,
blurRadius: 5, blurRadius: 5,
offset: Offset(0, 1.5), // changes position of shadow offset: Offset(0, 1.5), // changes position of shadow
), ),

View File

@ -65,6 +65,8 @@ dependencies:
path_provider: ^2.1.2 path_provider: ^2.1.2
permission_handler: ^11.2.0 permission_handler: ^11.2.0
google_fonts: ^6.2.1 google_fonts: ^6.2.1
#animated_tree_view: ^2.2.0
generate_tree: ^2.2.2
openapi_generator_cli: ^4.13.1 openapi_generator_cli: ^4.13.1
openapi_generator: ^4.13.1 openapi_generator: ^4.13.1