541 lines
22 KiB
Dart
541 lines
22 KiB
Dart
import 'package:diacritic/diacritic.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
|
import 'package:location_picker_flutter_map/location_picker_flutter_map.dart';
|
|
import 'package:manager_app/Components/geoloc_input_container.dart';
|
|
import 'package:manager_app/Components/multi_select_dropdown_language_container.dart';
|
|
import 'package:manager_app/Screens/Configurations/Section/SubSection/Map/category_input_container.dart';
|
|
import 'package:manager_app/Components/dropDown_input_container.dart';
|
|
import 'package:manager_app/Components/fetch_section_icon.dart';
|
|
import 'package:manager_app/Components/resource_input_container.dart';
|
|
import 'package:manager_app/Components/multi_select_container.dart';
|
|
import 'package:manager_app/Components/single_select_container.dart';
|
|
import 'package:manager_app/Components/slider_input_container.dart';
|
|
import 'package:manager_app/Components/string_input_container.dart';
|
|
import 'package:manager_app/Screens/Configurations/Section/SubSection/Map/showNewOrUpdateGeoPoint.dart';
|
|
import 'package:html/parser.dart' show parse;
|
|
import 'package:manager_app/app_context.dart';
|
|
import 'package:manager_app/constants.dart';
|
|
import 'package:manager_api_new/api.dart';
|
|
import 'dart:convert';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
class MapConfig extends StatefulWidget {
|
|
final String? color;
|
|
final String? label;
|
|
final String initialValue;
|
|
final ValueChanged<String> onChanged;
|
|
const MapConfig({
|
|
Key? key,
|
|
this.color,
|
|
this.label,
|
|
required this.initialValue,
|
|
required this.onChanged,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
_MapConfigState createState() => _MapConfigState();
|
|
}
|
|
|
|
class _MapConfigState extends State<MapConfig> {
|
|
late MapDTO mapDTO;
|
|
late List<GeoPointDTO> pointsToShow;
|
|
List<String>? selectedCategories = [];
|
|
String mapType= "hybrid";
|
|
String mapTypeMapBox= "standard";
|
|
|
|
String filterSearch = '';
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
mapDTO = MapDTO.fromJson(json.decode(widget.initialValue))!;
|
|
pointsToShow = new List<GeoPointDTO>.from(mapDTO.points!);
|
|
mapDTO.points = pointsToShow;
|
|
pointsToShow.sort((a, b) => a.title!.firstWhere((t) => t.language == 'FR').value!.toLowerCase().compareTo(b.title!.firstWhere((t) => t.language == 'FR').value!.toLowerCase()));
|
|
|
|
selectedCategories = mapDTO.categories!.map((categorie) => categorie.label!.firstWhere((element) => element.language == 'FR').value!).toList();
|
|
|
|
pointsToShow.forEach((pts) {
|
|
if(pts.categorieId == null && pts.categorie != null && mapDTO.categories!.any((e) => e.order == pts.categorie!.order)) {
|
|
print("SET CATEGORIE ID FOR CAT");
|
|
print(pts.categorie);
|
|
var testCat = mapDTO.categories!.where((c) => c.label![0].value == pts.categorie!.label![0].value);
|
|
if(testCat.isNotEmpty) {
|
|
pts.categorieId = testCat.first.id;
|
|
pts.categorie!.id = testCat.first.id;
|
|
} else {
|
|
pts.categorie = null; // Categorie no more existing so we can reset cat
|
|
}
|
|
|
|
print(pts.categorieId);
|
|
}
|
|
});
|
|
|
|
print(pointsToShow);
|
|
|
|
if(mapDTO.mapType != null) {
|
|
switch(mapDTO.mapType!.value) {
|
|
case 0:
|
|
mapType = "none";
|
|
break;
|
|
case 1:
|
|
mapType = "normal";
|
|
break;
|
|
case 2:
|
|
mapType = "satellite";
|
|
break;
|
|
case 3:
|
|
mapType = "terrain";
|
|
break;
|
|
case 4:
|
|
mapType = "hybrid";
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(mapDTO.mapTypeMapbox != null) {
|
|
switch(mapDTO.mapTypeMapbox!.value) {
|
|
case 0:
|
|
mapTypeMapBox = "standard";
|
|
break;
|
|
case 1:
|
|
mapTypeMapBox = "streets";
|
|
break;
|
|
case 2:
|
|
mapTypeMapBox = "outdoors";
|
|
break;
|
|
case 3:
|
|
mapTypeMapBox = "light";
|
|
break;
|
|
case 4:
|
|
mapTypeMapBox = "dark";
|
|
break;
|
|
case 5:
|
|
mapTypeMapBox = "satellite";
|
|
break;
|
|
case 6:
|
|
mapTypeMapBox = "satellite_streets";
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*print("MAPDTO");
|
|
print(mapDTO);
|
|
print(mapDTO.mapType.toString());
|
|
if (mapDTO.mapType == null) {
|
|
mapDTO.mapType = MapTypeApp.hybrid;
|
|
}*/
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final appContext = Provider.of<AppContext>(context);
|
|
Size size = MediaQuery.of(context).size;
|
|
|
|
var mapProviderIn = "";
|
|
switch(mapDTO.mapProvider) {
|
|
case MapProvider.Google :
|
|
mapProviderIn = "Google";
|
|
break;
|
|
case MapProvider.MapBox :
|
|
mapProviderIn = "MapBox";
|
|
break;
|
|
default:
|
|
mapProviderIn = "Google";
|
|
break;
|
|
}
|
|
|
|
return
|
|
SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
Container(
|
|
height: size.height * 0.3,
|
|
width: double.infinity,
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
children: [
|
|
SingleSelectContainer(
|
|
label: "Service :",
|
|
color: Colors.black,
|
|
initialValue: mapProviderIn,
|
|
inputValues: map_providers,
|
|
onChanged: (String value) {
|
|
switch(value) {
|
|
case "Google":
|
|
mapDTO.mapProvider = MapProvider.Google;
|
|
break;
|
|
case "MapBox":
|
|
mapDTO.mapProvider = MapProvider.MapBox;
|
|
break;
|
|
}
|
|
widget.onChanged(jsonEncode(mapDTO).toString());
|
|
}
|
|
),
|
|
GeolocInputContainer(
|
|
label: "Point de centrage:",
|
|
initialValue: mapDTO.latitude != null && mapDTO.longitude != null ? LatLong(double.parse(mapDTO.latitude!), double.parse(mapDTO.longitude!)) : null,
|
|
color: kPrimaryColor,
|
|
onChanged: (LatLong? localisation) {
|
|
if(localisation != null) {
|
|
mapDTO.longitude = localisation.longitude.toString();
|
|
mapDTO.latitude = localisation.latitude.toString();
|
|
}
|
|
widget.onChanged(jsonEncode(mapDTO).toString());
|
|
},
|
|
isSmall: true
|
|
),
|
|
// Icon
|
|
ResourceInputContainer(
|
|
label: "Icône:",
|
|
initialValue: mapDTO.iconResourceId,
|
|
color: kPrimaryColor,
|
|
imageFit: BoxFit.contain,
|
|
onChanged: (ResourceDTO resource) {
|
|
if(resource.id == null) {
|
|
mapDTO.iconSource = null;
|
|
mapDTO.iconResourceId = null;
|
|
} else {
|
|
mapDTO.iconResourceId = resource.id;
|
|
mapDTO.iconSource = resource.url;
|
|
}
|
|
widget.onChanged(jsonEncode(mapDTO).toString());
|
|
},
|
|
isSmall: true
|
|
),
|
|
]
|
|
),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
children: [
|
|
if(mapDTO.mapProvider == MapProvider.Google)
|
|
// Map Type
|
|
DropDownInputContainer(
|
|
label: "Type:",
|
|
values: map_types,
|
|
initialValue: mapType,
|
|
onChange: (String? value) {
|
|
mapDTO.mapType = MapTypeApp.fromJson(value);
|
|
widget.onChanged(jsonEncode(mapDTO).toString());
|
|
},
|
|
),
|
|
if(mapDTO.mapProvider == MapProvider.MapBox)
|
|
DropDownInputContainer(
|
|
label: "Type:",
|
|
values: map_types_mapBox,
|
|
initialValue: mapTypeMapBox,
|
|
onChange: (String? value) {
|
|
mapDTO.mapTypeMapbox = MapTypeMapBox.fromJson(value);
|
|
widget.onChanged(jsonEncode(mapDTO).toString());
|
|
},
|
|
),
|
|
// Zoom
|
|
SliderInputContainer(
|
|
label: "Zoom:",
|
|
initialValue: mapDTO.zoom != null ? mapDTO.zoom!.toDouble() : 18,
|
|
color: kPrimaryColor,
|
|
min: 0,
|
|
max: 30,
|
|
onChanged: (double value) {
|
|
mapDTO.zoom = value.toInt();
|
|
widget.onChanged(jsonEncode(mapDTO).toString());
|
|
},
|
|
),
|
|
Container(
|
|
height: 70,
|
|
child: CategoryInputContainer(
|
|
label: "Catégories :",
|
|
initialValue: mapDTO.categories != null ? mapDTO.categories! : [],
|
|
color: kPrimaryColor,
|
|
onChanged: (List<CategorieDTO>? value) {
|
|
if(value != null) {
|
|
//print("COUCOU CategoryInputContainerCategoryInputContainerCategoryInputContainer");
|
|
//print(value);
|
|
mapDTO.categories = value;
|
|
|
|
//update point's category
|
|
if(mapDTO.points != null) {
|
|
mapDTO.points!.forEach((p) {
|
|
// Check if category still exist - Delete
|
|
if(p.categorieId != null && !mapDTO.categories!.map((c) => c.id).any((e) => e != null && e == p.categorieId))
|
|
{
|
|
print("DELETE CAT REF");
|
|
print(p.categorieId);
|
|
print(p.categorie);
|
|
// delete cat ref from point
|
|
p.categorieId = null;
|
|
p.categorie = null;
|
|
}
|
|
// update point category - Update
|
|
if(p.categorieId != null && mapDTO.categories!.map((c) => c.id).any((e) => e != null && e == p.categorieId))
|
|
{
|
|
var categorie = mapDTO.categories!.firstWhere((c) => c.id == p.categorieId);
|
|
p.categorie = categorie;
|
|
print("UPDATE CAT REF");
|
|
}
|
|
|
|
print(p);
|
|
if(p.categorieId == null && p.categorie != null && p.categorie!.label != null)
|
|
{
|
|
// need to update with label
|
|
var categorie = mapDTO.categories!.firstWhere((c) => c.label![0].value == p.categorie!.label![0].value);
|
|
//p.categorie = categorie;
|
|
p.categorieId = categorie.id;
|
|
}
|
|
});
|
|
}
|
|
/*print("mapDTO.points");
|
|
print(mapDTO.points);*/
|
|
widget.onChanged(jsonEncode(mapDTO).toString());
|
|
}
|
|
},
|
|
),
|
|
)
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(25),
|
|
border: Border.all(width: 1.5, color: kSecond)
|
|
),
|
|
child: Stack(
|
|
children: [
|
|
Container(
|
|
constraints: BoxConstraints(minHeight: 100),
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(top: 95, left: 10, right: 10, bottom: 10),
|
|
child: GridView.builder(
|
|
shrinkWrap: true,
|
|
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 8),
|
|
itemCount: pointsToShow.length,
|
|
itemBuilder: (BuildContext context, int index) {
|
|
return
|
|
Container(
|
|
decoration: boxDecoration(pointsToShow[index], appContext),
|
|
padding: const EdgeInsets.all(5),
|
|
margin: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
|
child: getElement(index, pointsToShow[index], size, appContext),
|
|
);
|
|
}
|
|
),
|
|
),
|
|
),
|
|
Positioned(
|
|
top: 10,
|
|
left: 10,
|
|
child: Text(
|
|
"Points géographiques",
|
|
style: TextStyle(fontSize: 15),
|
|
),
|
|
),
|
|
Positioned(
|
|
top: 10,
|
|
left: 175,
|
|
child: MultiSelectContainer(
|
|
label: null,
|
|
color: kSecond,
|
|
width: size.width * 0.45,
|
|
initialValue: selectedCategories!,
|
|
isMultiple: true,
|
|
isHTMLLabel : true,
|
|
values: mapDTO.categories!.map((categorie) => categorie.label!.firstWhere((element) => element.language == 'FR').value!).toList(),
|
|
onChanged: (value) {
|
|
var tempOutput = new List<String>.from(value);
|
|
setState(() {
|
|
selectedCategories = tempOutput;
|
|
if(selectedCategories == null || selectedCategories!.length == 0) {
|
|
pointsToShow = mapDTO.points!.where((point) => point.categorie == null).toList();
|
|
} else {
|
|
pointsToShow = mapDTO.points!.where((point) => tempOutput.any((tps) => point.categorie == null || point.categorie?.label?.firstWhere((lab) => lab.language == 'FR').value == tps)).toList();
|
|
}
|
|
});
|
|
},
|
|
)
|
|
),
|
|
Positioned(
|
|
top: 0,
|
|
right: 150,
|
|
child: Container(
|
|
height: size.height*0.1,
|
|
constraints: BoxConstraints(minHeight: 85),
|
|
child: StringInputContainer(
|
|
label: "Recherche:",
|
|
isSmall: true,
|
|
fontSize: 15,
|
|
fontSizeText: 15,
|
|
onChanged: (String value) {
|
|
setState(() {
|
|
filterSearch = value;
|
|
filterPoints();
|
|
});
|
|
},
|
|
),
|
|
),
|
|
),
|
|
Positioned(
|
|
top: 10,
|
|
right: 10,
|
|
child: InkWell(
|
|
onTap: () {
|
|
showNewOrUpdateGeoPoint(
|
|
mapDTO,
|
|
null,
|
|
(GeoPointDTO geoPoint) {
|
|
setState(() {
|
|
mapDTO.points!.add(geoPoint);
|
|
mapDTO.points!.sort((a, b) => a.title!.firstWhere((t) => t.language == 'FR').value!.toLowerCase().compareTo(b.title!.firstWhere((t) => t.language == 'FR').value!.toLowerCase()));
|
|
|
|
if(selectedCategories == null || selectedCategories!.length == 0) {
|
|
pointsToShow = mapDTO.points!.where((point) => point.categorie == null).toList();
|
|
} else {
|
|
pointsToShow = mapDTO.points!.where((point) => selectedCategories!.any((tps) => point.categorie == null || point.categorie?.label?.firstWhere((lab) => lab.language == 'FR').value == tps)).toList();
|
|
}
|
|
|
|
widget.onChanged(jsonEncode(mapDTO).toString());
|
|
});
|
|
},
|
|
appContext,
|
|
context);
|
|
},
|
|
child: Container(
|
|
height: MediaQuery.of(context).size.width * 0.04,
|
|
width: MediaQuery.of(context).size.width * 0.04,
|
|
child: Icon(
|
|
Icons.add,
|
|
color: kTextLightColor,
|
|
size: 30.0,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: kSuccess,
|
|
shape: BoxShape.rectangle,
|
|
borderRadius: BorderRadius.circular(20.0),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: kSecond,
|
|
spreadRadius: 0.5,
|
|
blurRadius: 5,
|
|
offset: Offset(0, 1.5), // changes position of shadow
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
)
|
|
]),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
getElement(int index, GeoPointDTO? point, Size size, AppContext appContext) {
|
|
return Container(
|
|
width: double.infinity,
|
|
height: double.infinity,
|
|
child: Stack(
|
|
children: [
|
|
Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: HtmlWidget(
|
|
point != null ? point.title == null ? "" : point.title![0].value! : "",
|
|
//textAlign: TextAlign.left,
|
|
customStylesBuilder: (element) {
|
|
return {'text-align': 'center'};
|
|
},
|
|
textStyle: TextStyle(fontSize: 20)
|
|
),
|
|
),
|
|
),
|
|
Positioned(
|
|
top: 0,
|
|
right: 0,
|
|
child: Icon(
|
|
getSectionIcon(SectionType.Map),
|
|
color: kSecond,
|
|
size: 18.0,
|
|
),
|
|
),
|
|
Positioned(
|
|
bottom: 0,
|
|
left: 0,
|
|
child: InkWell(
|
|
onTap: () {
|
|
showNewOrUpdateGeoPoint(
|
|
mapDTO,
|
|
mapDTO.points![index],
|
|
(GeoPointDTO geoPoint) {
|
|
setState(() {
|
|
mapDTO.points![index] = geoPoint;
|
|
mapDTO.points!.sort((a, b) => a.title!.firstWhere((t) => t.language == 'FR').value!.toLowerCase().compareTo(b.title!.firstWhere((t) => t.language == 'FR').value!.toLowerCase()));
|
|
widget.onChanged(jsonEncode(mapDTO).toString());
|
|
});
|
|
},
|
|
appContext,
|
|
context);
|
|
},
|
|
child: Icon(
|
|
Icons.edit,
|
|
color: kPrimaryColor,
|
|
size: 20.0,
|
|
)
|
|
),
|
|
),
|
|
Positioned(
|
|
bottom: 0,
|
|
right: 0,
|
|
child: InkWell(
|
|
onTap: () {
|
|
setState(() {
|
|
var pointToRemove = pointsToShow[index];
|
|
mapDTO.points = mapDTO.points!.where((p) => p.longitude != pointToRemove.longitude || p.latitude != p.latitude).toList();
|
|
|
|
pointsToShow.removeAt(index);
|
|
});
|
|
|
|
widget.onChanged(jsonEncode(mapDTO).toString());
|
|
},
|
|
child: Icon(
|
|
Icons.delete,
|
|
color: kError,
|
|
size: 20.0,
|
|
)
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void filterPoints() {
|
|
pointsToShow = filterSearch.isEmpty ? mapDTO.points! : mapDTO.points!.where((GeoPointDTO pointGeo) => removeDiacritics(pointGeo.title!.firstWhere((t) => t.language == "FR").value!.toUpperCase()).contains(removeDiacritics(filterSearch.toUpperCase()))).toList();
|
|
}
|
|
}
|
|
|
|
|
|
boxDecoration(GeoPointDTO geoPointDTO, appContext) {
|
|
return BoxDecoration(
|
|
color: kBackgroundColor,
|
|
shape: BoxShape.rectangle,
|
|
border: Border.all(width: 1.5, color: kSecond),
|
|
borderRadius: BorderRadius.circular(10.0),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: kSecond,
|
|
spreadRadius: 0.5,
|
|
blurRadius: 5,
|
|
offset: Offset(0, 1.5), // changes position of shadow
|
|
),
|
|
],
|
|
);
|
|
} |