From de3f89e038ed605648515cb33d0fbb1072494b2b Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Wed, 4 Mar 2026 17:15:02 +0100 Subject: [PATCH] Fix agenda + update visu map (main params) + update wip config detail view --- .../SubSection/Agenda/agenda_config.dart | 187 ++++++----- .../Section/SubSection/Game/game_config.dart | 40 ++- .../Section/SubSection/Map/map_config.dart | 293 +++++++++--------- .../Section/section_detail_screen.dart | 105 ++++--- .../configuration_detail_screen.dart | 293 +++++++----------- 5 files changed, 451 insertions(+), 467 deletions(-) diff --git a/lib/Screens/Configurations/Section/SubSection/Agenda/agenda_config.dart b/lib/Screens/Configurations/Section/SubSection/Agenda/agenda_config.dart index 2b50510..40d6ac4 100644 --- a/lib/Screens/Configurations/Section/SubSection/Agenda/agenda_config.dart +++ b/lib/Screens/Configurations/Section/SubSection/Agenda/agenda_config.dart @@ -35,7 +35,7 @@ class _AgendaConfigState extends State { @override Widget build(BuildContext context) { - //Size size = MediaQuery.of(context).size; + Size size = MediaQuery.of(context).size; var mapProviderIn = ""; switch (agendaDTO.agendaMapProvider) { @@ -52,73 +52,21 @@ class _AgendaConfigState extends State { return Column( children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - CheckInputContainer( - label: "En ligne :", - isChecked: agendaDTO.isOnlineAgenda ?? true, - onChanged: (value) { - setState(() { - agendaDTO.isOnlineAgenda = value; - widget.onChanged(agendaDTO); - }); - }, - ), - SingleSelectContainer( - label: "Service carte :", - color: Colors.black, - initialValue: mapProviderIn, - inputValues: ["Google", "MapBox"], - onChanged: (String value) { - setState(() { - switch (value) { - case "Google": - agendaDTO.agendaMapProvider = MapProvider.Google; - break; - case "MapBox": - agendaDTO.agendaMapProvider = MapProvider.MapBox; - break; - } - widget.onChanged(agendaDTO); - }); - }, - ), - if (agendaDTO.isOnlineAgenda == true) - MultiStringInputContainer( - label: "Fichiers json :", - resourceTypes: [ResourceType.Json, ResourceType.JsonUrl], - modalLabel: "JSON", - color: kPrimaryColor, - initialValue: agendaDTO.resourceIds ?? [], - isTitle: false, - onGetResult: (value) { - setState(() { - agendaDTO.resourceIds = value; - widget.onChanged(agendaDTO); - }); - }, - maxLines: 1, - ), - ], - ), - ), + _buildAgendaHeader(size, mapProviderIn), if (agendaDTO.isOnlineAgenda == false) ...[ - Divider(), + const Divider(height: 32), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Évènements Manuels", + const Text("Évènements Manuels", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), ElevatedButton.icon( - icon: Icon(Icons.add), - label: Text("Ajouter un évènement"), + icon: const Icon(Icons.add), + label: const Text("Ajouter un évènement"), onPressed: () { showNewOrUpdateEventAgenda( context, @@ -136,14 +84,22 @@ class _AgendaConfigState extends State { ); }, style: ElevatedButton.styleFrom( - backgroundColor: kSuccess, foregroundColor: kWhite), + backgroundColor: kSuccess, + foregroundColor: kWhite, + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), ), ], ), ), - Expanded( + Container( + height: 600, + padding: const EdgeInsets.symmetric(vertical: 8), child: (agendaDTO.events == null || agendaDTO.events!.isEmpty) - ? Center( + ? const Center( child: Text("Aucun évènement manuel", style: TextStyle(fontStyle: FontStyle.italic))) : ListView.builder( @@ -151,21 +107,38 @@ class _AgendaConfigState extends State { itemBuilder: (context, index) { final event = agendaDTO.events![index]; return Card( - margin: - EdgeInsets.symmetric(horizontal: 16, vertical: 4), + elevation: 2, + margin: const EdgeInsets.symmetric( + horizontal: 16, vertical: 6), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12)), child: ListTile( - title: Text(event.label - ?.firstWhere((t) => t.language == 'FR', - orElse: () => event.label![0]) - .value ?? - "Évènement $index"), - subtitle: - Text(event.address?.address ?? "Pas d'adresse"), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 8), + leading: CircleAvatar( + backgroundColor: kPrimaryColor.withOpacity(0.1), + child: + const Icon(Icons.event, color: kPrimaryColor), + ), + title: Text( + (event.label != null && event.label!.isNotEmpty) + ? (event.label!.firstWhere( + (t) => t.language == 'FR', + orElse: () => event.label![0])).value! + : "Évènement $index", + style: const TextStyle(fontWeight: FontWeight.bold), + ), + subtitle: Padding( + padding: const EdgeInsets.only(top: 4), + child: + Text(event.address?.address ?? "Pas d'adresse"), + ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( - icon: Icon(Icons.edit, color: kPrimaryColor), + icon: const Icon(Icons.edit, + color: kPrimaryColor), onPressed: () { showNewOrUpdateEventAgenda( context, @@ -181,7 +154,7 @@ class _AgendaConfigState extends State { }, ), IconButton( - icon: Icon(Icons.delete, color: kError), + icon: const Icon(Icons.delete, color: kError), onPressed: () { setState(() { agendaDTO.events!.removeAt(index); @@ -200,4 +173,74 @@ class _AgendaConfigState extends State { ], ); } + + Widget _buildAgendaHeader(Size size, String mapProviderIn) { + return Container( + padding: const EdgeInsets.all(16.0), + margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 2, + blurRadius: 5, + offset: const Offset(0, 3), + ), + ], + border: Border.all(color: kPrimaryColor.withOpacity(0.2)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + CheckInputContainer( + label: "En ligne :", + isChecked: agendaDTO.isOnlineAgenda ?? true, + onChanged: (value) { + setState(() { + agendaDTO.isOnlineAgenda = value; + widget.onChanged(agendaDTO); + }); + }, + ), + SingleSelectContainer( + label: "Service carte :", + color: Colors.black, + initialValue: mapProviderIn, + inputValues: const ["Google", "MapBox"], + onChanged: (String value) { + setState(() { + switch (value) { + case "Google": + agendaDTO.agendaMapProvider = MapProvider.Google; + break; + case "MapBox": + agendaDTO.agendaMapProvider = MapProvider.MapBox; + break; + } + widget.onChanged(agendaDTO); + }); + }, + ), + if (agendaDTO.isOnlineAgenda == true) + MultiStringInputContainer( + label: "Fichiers json :", + resourceTypes: const [ResourceType.Json, ResourceType.JsonUrl], + modalLabel: "JSON", + color: kPrimaryColor, + initialValue: agendaDTO.resourceIds ?? [], + isTitle: false, + onGetResult: (value) { + setState(() { + agendaDTO.resourceIds = value; + widget.onChanged(agendaDTO); + }); + }, + maxLines: 1, + ), + ], + ), + ); + } } diff --git a/lib/Screens/Configurations/Section/SubSection/Game/game_config.dart b/lib/Screens/Configurations/Section/SubSection/Game/game_config.dart index c48c4af..258f9a9 100644 --- a/lib/Screens/Configurations/Section/SubSection/Game/game_config.dart +++ b/lib/Screens/Configurations/Section/SubSection/Game/game_config.dart @@ -93,27 +93,25 @@ class _GameConfigState extends State { Tab(icon: Icon(Icons.door_front_door), text: "Escape Game"), ], ), - Expanded( - child: Container( - height: 500, - child: TabBarView( - children: [ - _buildPuzzleConfig(), - _buildPuzzleConfig(), - ParcoursConfig( - initialValue: gameDTO.guidedPaths ?? [], - parentId: gameDTO.id!, - isEvent: false, - isEscapeMode: true, - onChanged: (paths) { - setState(() { - gameDTO.guidedPaths = paths; - widget.onChanged(gameDTO); - }); - }, - ), - ], - ), + Container( + height: 650, + child: TabBarView( + children: [ + _buildPuzzleConfig(), + _buildPuzzleConfig(), + ParcoursConfig( + initialValue: gameDTO.guidedPaths ?? [], + parentId: gameDTO.id!, + isEvent: false, + isEscapeMode: true, + onChanged: (paths) { + setState(() { + gameDTO.guidedPaths = paths; + widget.onChanged(gameDTO); + }); + }, + ), + ], ), ), ], diff --git a/lib/Screens/Configurations/Section/SubSection/Map/map_config.dart b/lib/Screens/Configurations/Section/SubSection/Map/map_config.dart index becde10..7396dbf 100644 --- a/lib/Screens/Configurations/Section/SubSection/Map/map_config.dart +++ b/lib/Screens/Configurations/Section/SubSection/Map/map_config.dart @@ -130,6 +130,7 @@ class _MapConfigState extends State { child: Column( mainAxisSize: MainAxisSize.min, children: [ + _buildMapHeader(size, mapProviderIn), TabBar( labelColor: kPrimaryColor, unselectedLabelColor: Colors.grey, @@ -140,151 +141,13 @@ class _MapConfigState extends State { ], ), Container( - height: 500, // Reduced from 550 to 500 to avoid 8.5px overflow + height: 700, child: TabBarView( children: [ // Tab 1: Configuration & Points SingleChildScrollView( child: Column( children: [ - Container( - height: size.height * 0.25, - width: double.infinity, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - 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(mapDTO); - }), - GeolocInputContainer( - label: "Point de centrage:", - initialValue: - mapDTO.centerLatitude != null && - mapDTO.centerLongitude != null - ? LatLong( - double.parse( - mapDTO.centerLatitude!), - double.parse( - mapDTO.centerLongitude!)) - : null, - color: kPrimaryColor, - onChanged: (LatLong? localisation) { - if (localisation != null) { - mapDTO.centerLongitude = - localisation.longitude.toString(); - mapDTO.centerLatitude = - localisation.latitude.toString(); - } - widget.onChanged(mapDTO); - }, - isSmall: true), - 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(mapDTO); - }, - isSmall: true), - ]), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - if (mapDTO.mapProvider == MapProvider.Google) - DropDownInputContainer( - label: "Type:", - values: map_types, - initialValue: mapType, - onChange: (String? value) { - mapDTO.mapType = - MapTypeApp.fromJson(value); - widget.onChanged(mapDTO); - }, - ), - if (mapDTO.mapProvider == MapProvider.MapBox) - DropDownInputContainer( - label: "Type:", - values: map_types_mapBox, - initialValue: mapTypeMapBox, - onChange: (String? value) { - mapDTO.mapTypeMapbox = - MapTypeMapBox.fromJson(value); - widget.onChanged(mapDTO); - }, - ), - 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(mapDTO); - }, - ), - Container( - height: 70, - child: CategoryInputContainer( - label: "Catégories :", - initialValue: mapDTO.categories != null - ? mapDTO.categories! - : [], - color: kPrimaryColor, - onChanged: (List? value) { - if (value != null) { - mapDTO.categories = value; - if (mapDTO.points != null) { - mapDTO.points!.forEach((p) { - if (p.categorieId != null && - !mapDTO.categories! - .map((c) => c.id) - .any((e) => - e != null && - e == p.categorieId)) { - p.categorieId = null; - } - }); - } - widget.onChanged(mapDTO); - } - }, - ), - ) - ], - ), - ], - ), - ), FutureBuilder( future: getGeoPoints( (appContext.getContext() as ManagerAppContext) @@ -533,18 +396,12 @@ class _MapConfigState extends State { }, appContext, context); }, child: Container( - height: MediaQuery.of(context) - .size - .width * - 0.04, - width: MediaQuery.of(context) - .size - .width * - 0.04, + height: 40, + width: 40, child: Icon( Icons.add, color: kTextLightColor, - size: 30.0, + size: 25.0, ), decoration: BoxDecoration( color: kSuccess, @@ -727,6 +584,146 @@ class _MapConfigState extends State { ), ); } + + Widget _buildMapHeader(Size size, String mapProviderIn) { + return Container( + padding: const EdgeInsets.all(16.0), + margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 2, + blurRadius: 5, + offset: Offset(0, 3), + ), + ], + border: Border.all(color: kPrimaryColor.withOpacity(0.2)), + ), + 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(mapDTO); + }), + GeolocInputContainer( + label: "Point de centrage :", + initialValue: mapDTO.centerLatitude != null && + mapDTO.centerLongitude != null + ? LatLong(double.parse(mapDTO.centerLatitude!), + double.parse(mapDTO.centerLongitude!)) + : null, + color: kPrimaryColor, + onChanged: (LatLong? localisation) { + if (localisation != null) { + mapDTO.centerLongitude = + localisation.longitude.toString(); + mapDTO.centerLatitude = localisation.latitude.toString(); + } + widget.onChanged(mapDTO); + }, + isSmall: true), + 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(mapDTO); + }, + isSmall: true), + ], + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + if (mapDTO.mapProvider == MapProvider.Google) + DropDownInputContainer( + label: "Type :", + values: map_types, + initialValue: mapType, + onChange: (String? value) { + mapDTO.mapType = MapTypeApp.fromJson(value); + widget.onChanged(mapDTO); + }, + ), + if (mapDTO.mapProvider == MapProvider.MapBox) + DropDownInputContainer( + label: "Type :", + values: map_types_mapBox, + initialValue: mapTypeMapBox, + onChange: (String? value) { + mapDTO.mapTypeMapbox = MapTypeMapBox.fromJson(value); + widget.onChanged(mapDTO); + }, + ), + 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(mapDTO); + }, + ), + Container( + height: 70, + child: CategoryInputContainer( + label: "Catégories :", + initialValue: + mapDTO.categories != null ? mapDTO.categories! : [], + color: kPrimaryColor, + onChanged: (List? value) { + if (value != null) { + mapDTO.categories = value; + if (mapDTO.points != null) { + mapDTO.points!.forEach((p) { + if (p.categorieId != null && + !mapDTO.categories!.map((c) => c.id).any( + (e) => e != null && e == p.categorieId)) { + p.categorieId = null; + } + }); + } + widget.onChanged(mapDTO); + } + }, + ), + ) + ], + ), + ], + ), + ); + } } boxDecoration(GeoPointDTO geoPointDTO, appContext) { diff --git a/lib/Screens/Configurations/Section/section_detail_screen.dart b/lib/Screens/Configurations/Section/section_detail_screen.dart index d5bf6b7..bf5bde7 100644 --- a/lib/Screens/Configurations/Section/section_detail_screen.dart +++ b/lib/Screens/Configurations/Section/section_detail_screen.dart @@ -51,7 +51,8 @@ class SectionDetailScreen extends StatefulWidget { class _SectionDetailScreenState extends State { late SectionDTO sectionDTO; - late Object sectionDetailDTO; + Object? sectionDetailDTO; + String? lastLoadedSectionId; @override Widget build(BuildContext context) { @@ -72,6 +73,14 @@ class _SectionDetailScreenState extends State { if (nullableSection != null) { sectionDTO = nullableSection; + + // Only initialize sectionDetailDTO if it's not already loaded for this section + if (sectionDetailDTO == null || + lastLoadedSectionId != widget.id) { + _initializeSectionDetail(rawSectionData); + lastLoadedSectionId = widget.id; + } + return Stack( children: [ bodySection( @@ -344,7 +353,6 @@ class _SectionDetailScreenState extends State { ), // FIELDS SECTION Container( //width: size.width * 0.8, - height: size.height * 0.5, child: Padding( padding: const EdgeInsets.all(10.0), child: getSpecificData(rawSectionDTO, appContext), @@ -439,7 +447,7 @@ class _SectionDetailScreenState extends State { var sectionResult = await (appContext.getContext() as ManagerAppContext) .clientAPI! .sectionApi! - .sectionUpdate(sectionDetailDTO); + .sectionUpdate(sectionDetailDTO!); SectionDTO? section = SectionDTO.fromJson(sectionResult); ManagerAppContext managerAppContext = appContext.getContext(); @@ -462,111 +470,88 @@ class _SectionDetailScreenState extends State { getSpecificData(Object? rawSectionData, AppContext appContext) { switch (sectionDTO.type) { case SectionType.Map: - MapDTO mapDTO = MapDTO.fromJson(rawSectionData)!; - sectionDetailDTO = mapDTO; return MapConfig( - initialValue: mapDTO, + initialValue: sectionDetailDTO as MapDTO, onChanged: (MapDTO changedMap) { sectionDetailDTO = changedMap; }, ); case SectionType.Slider: - SliderDTO sliderDTO = SliderDTO.fromJson(rawSectionData)!; - sectionDetailDTO = sliderDTO; return SliderConfig( - initialValue: sliderDTO, + initialValue: sectionDetailDTO as SliderDTO, onChanged: (SliderDTO changedSlider) { sectionDetailDTO = changedSlider; }, ); case SectionType.Video: - VideoDTO videoDTO = VideoDTO.fromJson(rawSectionData)!; - sectionDetailDTO = videoDTO; return VideoConfig( label: "Url de la vidéo:", - initialValue: videoDTO, + initialValue: sectionDetailDTO as VideoDTO, onChanged: (VideoDTO updatedWebDTO) { sectionDetailDTO = updatedWebDTO; }, ); case SectionType.Web: - WebDTO webDTO = WebDTO.fromJson(rawSectionData)!; - sectionDetailDTO = webDTO; return WebConfig( label: "Url du site web:", - initialValue: webDTO, + initialValue: sectionDetailDTO as WebDTO, onChanged: (WebDTO updatedWebDTO) { sectionDetailDTO = updatedWebDTO; }, ); case SectionType.Menu: - MenuDTO menuDTO = MenuDTO.fromJson(rawSectionData)!; - sectionDetailDTO = menuDTO; return MenuConfig( - initialValue: menuDTO, + initialValue: sectionDetailDTO as MenuDTO, onChanged: (String data) { //sectionDTO.data = data; }, ); case SectionType.Quiz: - QuizDTO quizDTO = QuizDTO.fromJson(rawSectionData)!; - sectionDetailDTO = quizDTO; return QuizzConfig( - initialValue: quizDTO, + initialValue: sectionDetailDTO as QuizDTO, onChanged: (QuizDTO updatedQuiz) { sectionDetailDTO = updatedQuiz; }, ); case SectionType.Article: - ArticleDTO articleDTO = ArticleDTO.fromJson(rawSectionData)!; - sectionDetailDTO = articleDTO; return ArticleConfig( - initialValue: articleDTO, + initialValue: sectionDetailDTO as ArticleDTO, onChanged: (ArticleDTO changedArticle) { sectionDetailDTO = changedArticle; }, ); case SectionType.Pdf: - PdfDTO pdfDTO = PdfDTO.fromJson(rawSectionData)!; - sectionDetailDTO = pdfDTO; return PDFConfig( - initialValue: pdfDTO, + initialValue: sectionDetailDTO as PdfDTO, onChanged: (PdfDTO changedPDF) { sectionDetailDTO = changedPDF; }, ); case SectionType.Game: - GameDTO gameDTO = GameDTO.fromJson(rawSectionData)!; - sectionDetailDTO = gameDTO; return GameConfig( - initialValue: gameDTO, + key: ValueKey(sectionDTO.id), + initialValue: sectionDetailDTO as GameDTO, onChanged: (GameDTO updatedGame) { sectionDetailDTO = updatedGame; }, ); case SectionType.Agenda: - AgendaDTO agendaDTO = AgendaDTO.fromJson(rawSectionData)!; - sectionDetailDTO = agendaDTO; return AgendaConfig( - initialValue: agendaDTO, + initialValue: sectionDetailDTO as AgendaDTO, onChanged: (AgendaDTO updatedAgenda) { sectionDetailDTO = updatedAgenda; }, ); case SectionType.Weather: - WeatherDTO weatherDTO = WeatherDTO.fromJson(rawSectionData)!; - sectionDetailDTO = weatherDTO; return WeatherConfig( - initialValue: weatherDTO, + initialValue: sectionDetailDTO as WeatherDTO, onChanged: (WeatherDTO updatedWeather) { sectionDetailDTO = updatedWeather; }, ); case SectionType.Event: - SectionEventDTO eventDTO = SectionEventDTO.fromJson(rawSectionData)!; - sectionDetailDTO = eventDTO; return EventConfig( - initialValue: eventDTO, + initialValue: sectionDetailDTO as SectionEventDTO, onChanged: (SectionEventDTO updatedEvent) { sectionDetailDTO = updatedEvent; }, @@ -574,6 +559,48 @@ class _SectionDetailScreenState extends State { } } + _initializeSectionDetail(Object? rawSectionData) { + if (rawSectionData == null) return; + switch (sectionDTO.type) { + case SectionType.Map: + sectionDetailDTO = MapDTO.fromJson(rawSectionData)!; + break; + case SectionType.Slider: + sectionDetailDTO = SliderDTO.fromJson(rawSectionData)!; + break; + case SectionType.Video: + sectionDetailDTO = VideoDTO.fromJson(rawSectionData)!; + break; + case SectionType.Web: + sectionDetailDTO = WebDTO.fromJson(rawSectionData)!; + break; + case SectionType.Menu: + sectionDetailDTO = MenuDTO.fromJson(rawSectionData)!; + break; + case SectionType.Quiz: + sectionDetailDTO = QuizDTO.fromJson(rawSectionData)!; + break; + case SectionType.Article: + sectionDetailDTO = ArticleDTO.fromJson(rawSectionData)!; + break; + case SectionType.Pdf: + sectionDetailDTO = PdfDTO.fromJson(rawSectionData)!; + break; + case SectionType.Game: + sectionDetailDTO = GameDTO.fromJson(rawSectionData)!; + break; + case SectionType.Agenda: + sectionDetailDTO = AgendaDTO.fromJson(rawSectionData)!; + break; + case SectionType.Weather: + sectionDetailDTO = WeatherDTO.fromJson(rawSectionData)!; + break; + case SectionType.Event: + sectionDetailDTO = SectionEventDTO.fromJson(rawSectionData)!; + break; + } + } + updateSectionDetail() { switch (sectionDTO.type) { case SectionType.Map: diff --git a/lib/Screens/Configurations/configuration_detail_screen.dart b/lib/Screens/Configurations/configuration_detail_screen.dart index 17e7311..2889d85 100644 --- a/lib/Screens/Configurations/configuration_detail_screen.dart +++ b/lib/Screens/Configurations/configuration_detail_screen.dart @@ -157,16 +157,107 @@ class _ConfigurationDetailScreenState extends State { mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, + LayoutBuilder( + builder: (context, constraints) { + final isWide = constraints.maxWidth > 700; + + final fields = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 70, + child: StringInputContainer( + label: "Identifiant :", + fontSize: 20, + fontSizeText: 20, + initialValue: configurationDTO.label, + onChanged: (value) { + configurationDTO.label = value; + }, + ), + ), + Wrap( + spacing: 24, + runSpacing: 8, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + MultiSelectDropdownLanguageContainer( + label: "Langues :", + initialValue: configurationDTO.languages != null ? configurationDTO.languages! : [], + values: languages, + isMultiple: true, + fontSize: 20, + isAtLeastOne: true, + onChanged: (value) { + var tempOutput = new List.from(value); + configurationDTO.languages = tempOutput; + }, + ), + CheckInputContainer( + icon: Icons.signal_wifi_off, + label: "Hors ligne :", + fontSize: 20, + isChecked: configurationDTO.isOffline, + onChanged: (value) { + configurationDTO.isOffline = value; + }, + ), + ], + ), + ], + ); + + final images = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ResourceInputContainer( + label: "Image fond d'écran :", + fontSize: 20, + initialValue: configurationDTO.imageId, + color: kPrimaryColor, + onChanged: (ResourceDTO resource) { + if (resource.id == null) { + configurationDTO.imageId = null; + configurationDTO.imageSource = null; + } else { + configurationDTO.imageId = resource.id; + configurationDTO.imageSource = resource.url; + } + }, + ), + ResourceInputContainer( + label: "Image loader :", + fontSize: 20, + initialValue: configurationDTO.loaderImageId, + color: kPrimaryColor, + onChanged: (ResourceDTO resource) { + if (resource.id == null) { + configurationDTO.loaderImageId = null; + configurationDTO.loaderImageUrl = null; + } else { + configurationDTO.loaderImageId = resource.id; + configurationDTO.loaderImageUrl = resource.url; + } + }, + ), + ], + ); + + if (isWide) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(flex: 3, child: fields), + SizedBox(width: 24), + Expanded(flex: 2, child: images), + ], + ); + } else { + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - height: 100, + height: 70, child: StringInputContainer( label: "Identifiant :", fontSize: 20, @@ -177,9 +268,10 @@ class _ConfigurationDetailScreenState extends State { }, ), ), + SizedBox(height: 8), MultiSelectDropdownLanguageContainer( label: "Langues :", - initialValue: configurationDTO.languages != null ? configurationDTO.languages!: [], + initialValue: configurationDTO.languages != null ? configurationDTO.languages! : [], values: languages, isMultiple: true, fontSize: 20, @@ -187,40 +279,9 @@ class _ConfigurationDetailScreenState extends State { onChanged: (value) { var tempOutput = new List.from(value); configurationDTO.languages = tempOutput; - //print(configurationDTO.languages); }, ), - ResourceInputContainer( - label: "Image loader :", - fontSize: 20, - initialValue: configurationDTO.loaderImageId, - color: kPrimaryColor, - onChanged: (ResourceDTO resource) { - if(resource.id == null) { - configurationDTO.loaderImageId = null; - configurationDTO.loaderImageUrl = null; - } else { - configurationDTO.loaderImageId = resource.id; - configurationDTO.loaderImageUrl = resource.url; - } - }, - ), - /*if(configurationDTO.isTablet!) - CheckInputContainer( - icon: Icons.image, - label: "Fond pour les images des sections :", - fontSize: 20, - isChecked: configurationDTO.isSectionImageBackground, - onChanged: (value) { - configurationDTO.isSectionImageBackground = value; - }, - ),*/ - ], - ), - Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + SizedBox(height: 8), CheckInputContainer( icon: Icons.signal_wifi_off, label: "Hors ligne :", @@ -230,154 +291,12 @@ class _ConfigurationDetailScreenState extends State { configurationDTO.isOffline = value; }, ), - /*CheckInputContainer( - icon: Icons.tablet, - label: "Tablette :", - fontSize: 20, - isChecked: configurationDTO.isTablet, - onChanged: (value) { - configurationDTO.isTablet = value; - save(configurationDTO, appContext); - }, - ),*/ - /*CheckInputContainer( - icon: Icons.phone_android, - label: "Mobile :", - fontSize: 20, - isChecked: configurationDTO.isMobile, - onChanged: (value) { - configurationDTO.isMobile = value; - save(configurationDTO, appContext); - }, - ),*/ - /*if(configurationDTO.isMobile != null && configurationDTO.isMobile!) - RoundedButton( - text: "Télécharger les QRCodes", - icon: Icons.qr_code, - color: Colors.grey, - textColor: Colors.white, - fontSize: 15, - press: () { - PDFHelper.downloadPDF(managerAppContext, sections!); - }, - ), - if(configurationDTO.isTablet!) - CheckInputContainer( - icon: Icons.date_range, - label: "Date :", - fontSize: 20, - isChecked: configurationDTO.isDate, - onChanged: (value) { - configurationDTO.isDate = value; - }, - ), - if(configurationDTO.isTablet!) - CheckInputContainer( - icon: Icons.watch_later_outlined, - label: "Heure :", - fontSize: 20, - isChecked: configurationDTO.isHour, - onChanged: (value) { - configurationDTO.isHour = value; - }, - ),*/ + SizedBox(height: 16), + images, ], - ), - Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - /*if(!configurationDTO.isMobile!) - ColorPickerInputContainer( - label: "Couleur fond d'écran :", - fontSize: 20, - color: configurationDTO.secondaryColor, - onChanged: (value) { - configurationDTO.secondaryColor = value; - }, - ),*/ - /*if(!configurationDTO.isMobile!) - ColorPickerInputContainer( - label: "Couleur principale :", - fontSize: 20, - color: configurationDTO.primaryColor, - onChanged: (value) { - configurationDTO.primaryColor = value; - }, - ), - if(configurationDTO.isMobile!) - Padding( - padding: const EdgeInsets.only(bottom: 15), - child: MultiStringInputContainer( - label: "Titre affiché:", - modalLabel: "Titre", - fontSize: 20, - isHTML: true, - color: kPrimaryColor, - initialValue: configurationDTO != null ? configurationDTO.title! : [], - onGetResult: (value) { - if (configurationDTO.title != value) { - configurationDTO.title = value; - } - }, - maxLines: 1, - isTitle: true, - ), - ),*/ - ResourceInputContainer( - label: "Image fond d'écran :", - fontSize: 20, - initialValue: configurationDTO.imageId, - color: kPrimaryColor, - onChanged: (ResourceDTO resource) { - if(resource.id == null) { - configurationDTO.imageId = null; - configurationDTO.imageSource = null; - } else { - configurationDTO.imageId = resource.id; - configurationDTO.imageSource = resource.url; - } - }, - ), - /*if(configurationDTO.isTablet!) - Container( - height: 100, - child: NumberInputContainer( - label: "Place des sections (%) :", - initialValue: configurationDTO.screenPercentageSectionsMainPage ?? 0, - isSmall: true, - maxLength: 3, - onChanged: (value) { - try { - configurationDTO.screenPercentageSectionsMainPage = int.parse(value); - } catch (e) { - print('Screen percentage value not a number'); - showNotification(Colors.orange, kWhite, 'Cela doit être un chiffre', context, null); - } - }, - ), - ), - if(configurationDTO.isTablet!) - Container( - height: 100, - child: NumberInputContainer( - label: "Pourcentage des arrondis (0-50) :", - initialValue: configurationDTO.roundedValue ?? 0, - isSmall: true, - maxLength: 2, - onChanged: (value) { - try { - configurationDTO.roundedValue = int.parse(value); - } catch (e) { - print('Rounded value not a number'); - showNotification(Colors.orange, kWhite, 'Cela doit être un chiffre', context, null); - } - }, - ), - ),*/ - ]) - ], - ), + ); + } + }, ), Padding( padding: const EdgeInsets.all(20.0),