From 205f1ec93366d9c7345f112eccab1e0efb3818a0 Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Sat, 9 May 2026 00:23:04 +0200 Subject: [PATCH] Misc --- lib/Components/fetch_section_icon.dart | 18 + lib/Components/message_notification.dart | 54 +-- .../multi_string_input_html_modal.dart | 6 +- ...nslation_input_and_resource_container.dart | 1 + .../translation_input_container.dart | 30 +- lib/Models/managerContext.dart | 2 + lib/Screens/Applications/web_app_screen.dart | 1 - .../SubSection/Event/event_config.dart | 6 + .../Menu/listView_card_subSection.dart | 80 +--- .../SubSection/Menu/showEditSubSection.dart | 293 ------------- .../Menu/sub_section_edit_screen.dart | 394 ++++++++++++++++++ .../Section/section_detail_screen.dart | 4 +- .../Configurations/configurations_screen.dart | 7 + lib/Screens/Main/main_screen.dart | 5 +- lib/Screens/Statistics/statistics_screen.dart | 1 + lib/api/openApiTest.dart | 2 +- lib/api/swagger.yaml | 8 +- lib/main.dart | 5 +- .../lib/model/application_instance_dto.dart | 18 +- manager_api_new/lib/model/day_stat_dto.dart | 175 ++++++++ manager_api_new/lib/model/game_stat_dto.dart | 158 +++++++ manager_api_new/lib/model/instance_dto.dart | 12 +- manager_api_new/lib/model/poi_stat_dto.dart | 169 ++++++++ manager_api_new/lib/model/quiz_stat_dto.dart | 186 +++++++++ .../lib/model/section_stat_dto.dart | 169 ++++++++ pubspec.lock | 36 +- pubspec.yaml | 1 + 27 files changed, 1379 insertions(+), 462 deletions(-) delete mode 100644 lib/Screens/Configurations/Section/SubSection/Menu/showEditSubSection.dart create mode 100644 lib/Screens/Configurations/Section/SubSection/Menu/sub_section_edit_screen.dart create mode 100644 manager_api_new/lib/model/day_stat_dto.dart create mode 100644 manager_api_new/lib/model/game_stat_dto.dart create mode 100644 manager_api_new/lib/model/poi_stat_dto.dart create mode 100644 manager_api_new/lib/model/quiz_stat_dto.dart create mode 100644 manager_api_new/lib/model/section_stat_dto.dart diff --git a/lib/Components/fetch_section_icon.dart b/lib/Components/fetch_section_icon.dart index 93d81d4..c97de7e 100644 --- a/lib/Components/fetch_section_icon.dart +++ b/lib/Components/fetch_section_icon.dart @@ -1,6 +1,24 @@ import 'package:flutter/material.dart'; import 'package:manager_api_new/api.dart'; +String getSectionTypeName(SectionType? type) { + switch (type) { + case SectionType.Map: return 'Map'; + case SectionType.Slider: return 'Slider'; + case SectionType.Video: return 'Vidéo'; + case SectionType.Web: return 'Web'; + case SectionType.Menu: return 'Menu'; + case SectionType.Quiz: return 'Quiz'; + case SectionType.Article: return 'Article'; + case SectionType.Pdf: return 'PDF'; + case SectionType.Game: return 'Jeu'; + case SectionType.Agenda: return 'Agenda'; + case SectionType.Weather: return 'Météo'; + case SectionType.Event: return 'Événement'; + default: return 'Section'; + } +} + IconData getSectionIcon(elementType) { switch(elementType) { case SectionType.Map: diff --git a/lib/Components/message_notification.dart b/lib/Components/message_notification.dart index efde63f..551dc80 100644 --- a/lib/Components/message_notification.dart +++ b/lib/Components/message_notification.dart @@ -1,38 +1,26 @@ -//import 'package:another_flushbar/flushbar.dart'; import 'package:flutter/material.dart'; +import 'package:toastification/toastification.dart'; +import 'package:manager_app/constants.dart'; -showNotification (Color backgroundColor, Color textColor, String text, BuildContext context, int? duration) async { +showNotification(Color backgroundColor, Color textColor, String text, BuildContext context, int? duration) { + final ToastificationType type; + if (backgroundColor == kSuccess) { + type = ToastificationType.success; + } else if (backgroundColor == kError) { + type = ToastificationType.error; + } else if (backgroundColor == Colors.orange) { + type = ToastificationType.warning; + } else { + type = ToastificationType.info; + } - /*await Flushbar( - message: text, - messageColor: textColor, - margin: EdgeInsets.all(8), - backgroundColor: backgroundColor, - borderRadius: BorderRadius.circular(8), - duration: duration == null ? Duration(milliseconds: 1500) : Duration(milliseconds: duration), - ).show(context);*/ - - final snackBar = SnackBar( - behavior: SnackBarBehavior.floating, - duration: duration == null ? Duration(milliseconds: 1500) : Duration(milliseconds: duration), - width: 450.0, // Width of the SnackBar. - backgroundColor: backgroundColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - padding: const EdgeInsets.symmetric( - horizontal: 10.0, // Inner padding for SnackBar content. - ), - content: Container( - height: 50.5, - child: Center( - child: Text( - text, - textAlign: TextAlign.center, - style: TextStyle(color: textColor), - ), - ), - ) + toastification.show( + context: context, + type: type, + style: ToastificationStyle.fillColored, + description: Text(text, softWrap: true), + alignment: Alignment.topRight, + autoCloseDuration: Duration(milliseconds: duration ?? 4000), + pauseOnHover: true, ); - ScaffoldMessenger.of(context).showSnackBar(snackBar); } diff --git a/lib/Components/multi_string_input_html_modal.dart b/lib/Components/multi_string_input_html_modal.dart index 5a347ce..88d6497 100644 --- a/lib/Components/multi_string_input_html_modal.dart +++ b/lib/Components/multi_string_input_html_modal.dart @@ -17,7 +17,7 @@ showMultiStringInputHTML (String label, String modalLabel, bool isTitle, List { @override Widget build(BuildContext context) { return Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Flexible( @@ -219,19 +220,22 @@ class _TranslationInputContainerState extends State { Builder(builder: (ctx) { final instance = ctx.watch().getContext()?.instanceDTO; if (instance?.isAssistant != true) return const SizedBox.shrink(); - return Center( - child: SizedBox( - width: 370, - height: 70, - child: _isTranslating - ? const Center(child: CircularProgressIndicator()) - : RoundedButton( - text: "Traduire via IA", - icon: Icons.auto_awesome, - color: kPrimaryColor, - press: _translateWithAI, - fontSize: 20, - ), + return Padding( + padding: const EdgeInsets.only(top: 8), + child: Center( + child: SizedBox( + width: 370, + height: 70, + child: _isTranslating + ? const Center(child: CircularProgressIndicator()) + : RoundedButton( + text: "Traduire via IA", + icon: Icons.auto_awesome, + color: kPrimaryColor, + press: _translateWithAI, + fontSize: 20, + ), + ), ), ); }), diff --git a/lib/Models/managerContext.dart b/lib/Models/managerContext.dart index 9d3289e..cb2ae54 100644 --- a/lib/Models/managerContext.dart +++ b/lib/Models/managerContext.dart @@ -14,6 +14,8 @@ class ManagerAppContext with ChangeNotifier{ Client? clientAPI; ConfigurationDTO? selectedConfiguration; SectionDTO? selectedSection; + SectionDTO? selectedSubSection; + Object? selectedSubSectionRawData; bool? isLoading = false; UserRole? role; Locale locale = const Locale('fr'); diff --git a/lib/Screens/Applications/web_app_screen.dart b/lib/Screens/Applications/web_app_screen.dart index 5ea72b9..5f660a4 100644 --- a/lib/Screens/Applications/web_app_screen.dart +++ b/lib/Screens/Applications/web_app_screen.dart @@ -54,7 +54,6 @@ class _WebInstanceLoaderState extends State { languages: ['fr'], layoutMainPage: LayoutMainPageType.MasonryGrid, isAssistant: false, - isStatistic: false, ); final created = await managerCtx.clientAPI!.applicationInstanceApi! diff --git a/lib/Screens/Configurations/Section/SubSection/Event/event_config.dart b/lib/Screens/Configurations/Section/SubSection/Event/event_config.dart index bc06f67..fd2072d 100644 --- a/lib/Screens/Configurations/Section/SubSection/Event/event_config.dart +++ b/lib/Screens/Configurations/Section/SubSection/Event/event_config.dart @@ -35,6 +35,12 @@ class _EventConfigState extends State { void initState() { super.initState(); eventDTO = widget.initialValue; + if (eventDTO.startDate != null && eventDTO.startDate!.toUtc().year < 1000) { + eventDTO.startDate = null; + } + if (eventDTO.endDate != null && eventDTO.endDate!.toUtc().year < 1000) { + eventDTO.endDate = null; + } WidgetsBinding.instance.addPostFrameCallback((_) { _loadProgrammeBlocks(); _loadGlobalAnnotations(); diff --git a/lib/Screens/Configurations/Section/SubSection/Menu/listView_card_subSection.dart b/lib/Screens/Configurations/Section/SubSection/Menu/listView_card_subSection.dart index 9f7774f..bd11157 100644 --- a/lib/Screens/Configurations/Section/SubSection/Menu/listView_card_subSection.dart +++ b/lib/Screens/Configurations/Section/SubSection/Menu/listView_card_subSection.dart @@ -5,7 +5,6 @@ import 'package:manager_app/l10n/app_localizations.dart'; import 'package:manager_app/Components/fetch_section_icon.dart'; import 'package:manager_app/Components/message_notification.dart'; import 'package:manager_app/Models/managerContext.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/Menu/showEditSubSection.dart'; import 'package:manager_app/app_context.dart'; import 'package:manager_app/constants.dart'; import 'package:manager_api_new/api.dart'; @@ -61,27 +60,10 @@ class _ListViewCardSubSection extends State { children: [ InkWell( onTap: () { - showEditSubSection( - widget.listItems[widget.index], - (Object value) async { - final l = AppLocalizations.of(context)!; - try { - var test = updateSectionDetail(widget.listItems[widget.index], value); - // update sub section - await (appContext.getContext() as ManagerAppContext).clientAPI!.sectionApi!.sectionUpdate(test); - showNotification(kSuccess, kWhite, l.subSectionUpdatedSuccess, context, null); - setState(() { - //widget.listItems[widget.index] = value; - widget.onChanged(widget.listItems); // For resfreh ui - }); - } catch(e) { - showNotification(kError, kWhite, l.subSectionUpdateError, context, null); - } - }, - widget.appContext, - context, - widget.rawData - ); + final ctx = appContext.getContext() as ManagerAppContext; + ctx.selectedSubSection = widget.listItems[widget.index]; + ctx.selectedSubSectionRawData = widget.rawData; + appContext.setContext(ctx); }, child: Padding( padding: const EdgeInsets.all(6.0), @@ -191,60 +173,6 @@ class _ListViewCardSubSection extends State { ); } - dynamic updateSectionDetail(SectionDTO sectionDTO, Object sectionDetailDTO) { - dynamic castedDetail; - - switch (sectionDTO.type) { - case SectionType.Map: - castedDetail = sectionDetailDTO is MapDTO ? sectionDetailDTO : MapDTO.fromJson(sectionDetailDTO)!; - break; - case SectionType.Slider: - castedDetail = sectionDetailDTO is SliderDTO ? sectionDetailDTO : SliderDTO.fromJson(sectionDetailDTO)!; - break; - case SectionType.Video: - castedDetail = sectionDetailDTO is VideoDTO ? sectionDetailDTO : VideoDTO.fromJson(sectionDetailDTO)!; - break; - case SectionType.Web: - castedDetail = sectionDetailDTO is WebDTO ? sectionDetailDTO : WebDTO.fromJson(sectionDetailDTO)!; - break; - case SectionType.Quiz: - castedDetail = sectionDetailDTO is QuizDTO ? sectionDetailDTO : QuizDTO.fromJson(sectionDetailDTO)!; - break; - case SectionType.Pdf: - castedDetail = sectionDetailDTO is PdfDTO ? sectionDetailDTO : PdfDTO.fromJson(sectionDetailDTO)!; - break; - case SectionType.Game: - castedDetail = sectionDetailDTO is GameDTO ? sectionDetailDTO : GameDTO.fromJson(sectionDetailDTO)!; - break; - case SectionType.Agenda: - castedDetail = sectionDetailDTO is AgendaDTO ? sectionDetailDTO : AgendaDTO.fromJson(sectionDetailDTO)!; - break; - case SectionType.Weather: - castedDetail = sectionDetailDTO is WeatherDTO ? sectionDetailDTO : WeatherDTO.fromJson(sectionDetailDTO)!; - break; - } - - // Mise à jour générique des champs communs - castedDetail.id = sectionDTO.id; - castedDetail.order = sectionDTO.order; - castedDetail.dateCreation = sectionDTO.dateCreation; - castedDetail.type = sectionDTO.type; - castedDetail.instanceId = sectionDTO.instanceId; - castedDetail.configurationId = sectionDTO.configurationId; - castedDetail.isSubSection = sectionDTO.isSubSection; - castedDetail.parentId = sectionDTO.parentId; - castedDetail.label = sectionDTO.label; - castedDetail.title = sectionDTO.title; - castedDetail.description = sectionDTO.description; - castedDetail.imageId = sectionDTO.imageId; - castedDetail.imageSource = sectionDTO.imageSource; - castedDetail.isBeacon = sectionDTO.isBeacon; - castedDetail.beaconId = sectionDTO.beaconId; - castedDetail.latitude = sectionDTO.latitude; - castedDetail.longitude = sectionDTO.longitude; - castedDetail.meterZoneGPS = sectionDTO.meterZoneGPS; - return castedDetail; - } } diff --git a/lib/Screens/Configurations/Section/SubSection/Menu/showEditSubSection.dart b/lib/Screens/Configurations/Section/SubSection/Menu/showEditSubSection.dart deleted file mode 100644 index 4fb99e4..0000000 --- a/lib/Screens/Configurations/Section/SubSection/Menu/showEditSubSection.dart +++ /dev/null @@ -1,293 +0,0 @@ -import 'package:manager_app/Components/resource_input_container.dart'; -import 'package:flutter/material.dart'; -import 'package:manager_app/Components/multi_string_input_container.dart'; -import 'package:manager_app/Components/rounded_button.dart'; -import 'package:manager_app/Components/string_input_container.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/Agenda/agenda_config.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/Article/article_config.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/Game/game_config.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/Map/map_config.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/PDF/PDF_config.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/Quizz/quizz_config.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/Slider/slider_config.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/Video/video_config.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/Weather/weather_config.dart'; -import 'package:manager_app/Screens/Configurations/Section/SubSection/WebOrVideo/web_config.dart'; -import 'package:manager_app/app_context.dart'; -import 'package:manager_app/constants.dart'; -import 'package:manager_app/l10n/app_localizations.dart'; -import 'package:manager_api_new/api.dart'; - -import 'menu_config.dart'; - -void showEditSubSection(SectionDTO subSectionDTO, Function getResult, AppContext appContext, BuildContext context, Object rawSubSectionData) { - Object updatedRawSubSectionData = rawSubSectionData; - - Size size = MediaQuery.of(context).size; - showDialog( - builder: (BuildContext context) => Dialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(20.0)) - ), - child: SizedBox( - width: MediaQuery.of(context).size.width * 0.85, - child: Padding( - padding: const EdgeInsets.fromLTRB(24, 20, 24, 24), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Flexible( - child: SingleChildScrollView( - child: Column( - children: [ - Text("Modifier sous section", style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)), - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - SizedBox( - height: 100, - child: StringInputContainer( - label: "Nom :", - initialValue: subSectionDTO.label, - onChanged: (String name) { - subSectionDTO.label = name; - }, - ), - ), - ResourceInputContainer( - label: "Image :", - initialValue: subSectionDTO.imageId, - color: kPrimaryColor, - onChanged: (ResourceDTO resource) { - if(resource.id == null) { - subSectionDTO.imageId = null; - subSectionDTO.imageSource = null; - } else { - subSectionDTO.imageId = resource.id; - subSectionDTO.imageSource = resource.url; - } - }, - isSmall: true, - ), - ], - ), - Container( - height: size.height * 0.1, - width: double.infinity, - constraints: BoxConstraints(minHeight: 50), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Container( - constraints: BoxConstraints(minHeight: 50, maxHeight: 80), - child: MultiStringInputContainer( - label: AppLocalizations.of(context)!.displayTitleLabel, - modalLabel: "Titre", - fontSize: 20, - isHTML: true, - color: kPrimaryColor, - initialValue: subSectionDTO.title != null ? subSectionDTO.title! : [], - onGetResult: (value) { - if (subSectionDTO.title != value) { - subSectionDTO.title = value; - } - }, - maxLines: 1, - isTitle: true - ), - ), - Container( - constraints: BoxConstraints(minHeight: 50, maxHeight: 80), - child: MultiStringInputContainer( - label: AppLocalizations.of(context)!.displayedDescriptionLabel, - modalLabel: "Description", - fontSize: 20, - isHTML: true, - color: kPrimaryColor, - initialValue: subSectionDTO.description != null ? subSectionDTO.description! : [], - isMandatory: false, - onGetResult: (value) { - if (subSectionDTO.description != value) { - subSectionDTO.description = value; - } - }, - maxLines: 1, - isTitle: false - ), - ), - ], - ) - ), - Container( - decoration: BoxDecoration( - color: kWhite, - borderRadius: BorderRadius.circular(20), - border: Border.all(width: 0.5, color: kSecond) - ), - child: Padding( - padding: const EdgeInsets.all(10.0), - child: getSpecificData( - subSectionDTO, - rawSubSectionData, - rawSubSectionData, - appContext, - (updatedData) { - updatedRawSubSectionData = updatedData; - }, context), - ), - ), - ], - ), - ], - ), - ), - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Align( - alignment: AlignmentDirectional.bottomEnd, - child: Container( - width: 175, - height: 70, - child: RoundedButton( - text: "Annuler", - icon: Icons.undo, - color: kSecond, - press: () { - Navigator.of(context).pop(); - }, - fontSize: 20, - ), - ), - ), - Align( - alignment: AlignmentDirectional.bottomEnd, - child: Container( - width: subSectionDTO != null ? 220: 150, - height: 70, - child: RoundedButton( - text: "Sauvegarder", - icon: Icons.check, - color: kPrimaryColor, - textColor: kWhite, - press: () { - getResult(updatedRawSubSectionData); - Navigator.of(context).pop(); - }, - fontSize: 20, - ), - ), - ), - ], - ), - ], - ), - ), - ), - ), context: context - ); -} - -getSpecificData(SectionDTO subSectionDTO, Object? rawSectionData, Object sectionDetailDTO, AppContext appContext, Function(Object) onChanged, [BuildContext? context]) { - switch(subSectionDTO.type) { - case SectionType.Map: - MapDTO mapDTO = MapDTO.fromJson(rawSectionData)!; - sectionDetailDTO = mapDTO; - return MapConfig( - initialValue: mapDTO, - onChanged: (MapDTO changedMap) { - onChanged(changedMap); - }, - ); - case SectionType.Slider: - SliderDTO sliderDTO = SliderDTO.fromJson(rawSectionData)!; - sectionDetailDTO = sliderDTO; - return SliderConfig( - initialValue: sliderDTO, - onChanged: (SliderDTO changedSlider) { - onChanged(changedSlider); - }, - ); - case SectionType.Video: - VideoDTO videoDTO = VideoDTO.fromJson(rawSectionData)!; - sectionDetailDTO = videoDTO; - return VideoConfig( - label: context != null ? AppLocalizations.of(context)!.videoUrlLabel : "Url de la vidéo:", - initialValue: videoDTO, - onChanged: (VideoDTO updatedWebDTO) { - onChanged(updatedWebDTO); - }, - ); - case SectionType.Web: - WebDTO webDTO = WebDTO.fromJson(rawSectionData)!; - sectionDetailDTO = webDTO; - return WebConfig( - label: "Url du site web:", - initialValue: webDTO, - onChanged: (WebDTO updatedWebDTO) { - onChanged(updatedWebDTO); - }, - ); - case SectionType.Quiz: - QuizDTO quizDTO = QuizDTO.fromJson(rawSectionData)!; - sectionDetailDTO = quizDTO; - return QuizzConfig( - initialValue: quizDTO, - onChanged: (QuizDTO updatedQuiz) { - onChanged(updatedQuiz); - }, - ); - case SectionType.Article: - ArticleDTO articleDTO = ArticleDTO.fromJson(rawSectionData)!; - sectionDetailDTO = articleDTO; - return ArticleConfig( - initialValue: articleDTO, - onChanged: (ArticleDTO changedArticle) - { - onChanged(changedArticle); - }, - ); - case SectionType.Pdf: - PdfDTO pdfDTO = PdfDTO.fromJson(rawSectionData)!; - sectionDetailDTO = pdfDTO; - return PDFConfig( - initialValue: pdfDTO, - onChanged: (PdfDTO changedPDF) { - onChanged(changedPDF); - }, - ); - case SectionType.Game: - GameDTO gameDTO = GameDTO.fromJson(rawSectionData)!; - sectionDetailDTO = gameDTO; - return GameConfig( - initialValue: gameDTO, - onChanged: (GameDTO updatedGame) { - onChanged(updatedGame); - }, - ); - case SectionType.Agenda: - AgendaDTO agendaDTO = AgendaDTO.fromJson(rawSectionData)!; - sectionDetailDTO = agendaDTO; - return AgendaConfig( - initialValue: agendaDTO, - onChanged: (AgendaDTO updatedAgenda) { - onChanged(updatedAgenda); - }, - ); - case SectionType.Weather: - WeatherDTO weatherDTO = WeatherDTO.fromJson(rawSectionData)!; - sectionDetailDTO = weatherDTO; - return WeatherConfig( - initialValue: weatherDTO, - onChanged: (WeatherDTO updatedWeather) { - onChanged(updatedWeather); - }, - ); - } -} diff --git a/lib/Screens/Configurations/Section/SubSection/Menu/sub_section_edit_screen.dart b/lib/Screens/Configurations/Section/SubSection/Menu/sub_section_edit_screen.dart new file mode 100644 index 0000000..e219cff --- /dev/null +++ b/lib/Screens/Configurations/Section/SubSection/Menu/sub_section_edit_screen.dart @@ -0,0 +1,394 @@ +import 'package:flutter/material.dart'; +import 'package:manager_app/Components/fetch_section_icon.dart'; +import 'package:manager_app/Components/message_notification.dart'; +import 'package:manager_app/Components/multi_string_input_container.dart'; +import 'package:manager_app/Components/resource_input_container.dart'; +import 'package:manager_app/Components/string_input_container.dart'; +import 'package:manager_app/Models/managerContext.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/Agenda/agenda_config.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/Article/article_config.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/Game/game_config.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/Map/map_config.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/PDF/PDF_config.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/Quizz/quizz_config.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/Slider/slider_config.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/Video/video_config.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/Event/event_config.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/Weather/weather_config.dart'; +import 'package:manager_app/Screens/Configurations/Section/SubSection/WebOrVideo/web_config.dart'; +import 'package:manager_app/app_context.dart'; +import 'package:manager_app/constants.dart'; +import 'package:manager_app/l10n/app_localizations.dart'; +import 'package:manager_api_new/api.dart'; +import 'package:provider/provider.dart'; + +class SubSectionEditScreen extends StatefulWidget { + final SectionDTO subSectionDTO; + final Object rawData; + + const SubSectionEditScreen({ + Key? key, + required this.subSectionDTO, + required this.rawData, + }) : super(key: key); + + @override + _SubSectionEditScreenState createState() => _SubSectionEditScreenState(); +} + +class _SubSectionEditScreenState extends State { + late SectionDTO subSectionDTO; + Object? sectionDetailDTO; + + @override + void initState() { + super.initState(); + subSectionDTO = widget.subSectionDTO; + _initializeDetailDTO(); + } + + void _initializeDetailDTO() { + final raw = widget.rawData; + switch (subSectionDTO.type) { + case SectionType.Map: + sectionDetailDTO = MapDTO.fromJson(raw)!; + break; + case SectionType.Slider: + sectionDetailDTO = SliderDTO.fromJson(raw)!; + break; + case SectionType.Video: + sectionDetailDTO = VideoDTO.fromJson(raw)!; + break; + case SectionType.Web: + sectionDetailDTO = WebDTO.fromJson(raw)!; + break; + case SectionType.Quiz: + sectionDetailDTO = QuizDTO.fromJson(raw)!; + break; + case SectionType.Article: + sectionDetailDTO = ArticleDTO.fromJson(raw)!; + break; + case SectionType.Pdf: + sectionDetailDTO = PdfDTO.fromJson(raw)!; + break; + case SectionType.Game: + sectionDetailDTO = GameDTO.fromJson(raw)!; + break; + case SectionType.Agenda: + sectionDetailDTO = AgendaDTO.fromJson(raw)!; + break; + case SectionType.Weather: + sectionDetailDTO = WeatherDTO.fromJson(raw)!; + break; + case SectionType.Event: + sectionDetailDTO = SectionEventDTO.fromJson(raw)!; + break; + default: + sectionDetailDTO = null; + } + } + + @override + Widget build(BuildContext context) { + final l = AppLocalizations.of(context)!; + return Column( + children: [ + _buildHeader(l), + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _cardIdentity(l), + if (sectionDetailDTO != null) ...[ + const SizedBox(height: 12), + _cardTypeConfig(), + ], + const SizedBox(height: 80), + ], + ), + ), + ), + _buildFooter(l), + ], + ); + } + + void _goBack() { + final appContext = Provider.of(context, listen: false); + final ctx = appContext.getContext() as ManagerAppContext; + ctx.selectedSubSection = null; + ctx.selectedSubSectionRawData = null; + appContext.setContext(ctx); + } + + Widget _buildHeader(AppLocalizations l) { + final typeName = getSectionTypeName(subSectionDTO.type); + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + color: kWhite, + border: Border(bottom: BorderSide(color: kSecond, width: 1)), + ), + child: Row( + children: [ + IconButton( + icon: const Icon(Icons.arrow_back, color: kPrimaryColor), + onPressed: _goBack, + ), + const SizedBox(width: 8), + Icon(getSectionIcon(subSectionDTO.type), color: kPrimaryColor, size: 22), + const SizedBox(width: 8), + Expanded( + child: Text( + subSectionDTO.label ?? '', + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600), + overflow: TextOverflow.ellipsis, + ), + ), + Chip( + label: Text(typeName.toUpperCase()), + backgroundColor: kPrimaryColor.withValues(alpha: 0.1), + labelStyle: const TextStyle( + color: kPrimaryColor, fontWeight: FontWeight.w600, fontSize: 11), + side: BorderSide.none, + visualDensity: VisualDensity.compact, + ), + ], + ), + ); + } + + Widget _cardIdentity(AppLocalizations l) { + return Card( + elevation: 0, + color: kWhite, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + l.identifierLabel.replaceAll(':', '').trim(), + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: kTitleTextColor), + ), + const SizedBox(height: 12), + StringInputContainer( + label: l.identifierLabel, + initialValue: subSectionDTO.label, + onChanged: (value) => subSectionDTO.label = value, + ), + const SizedBox(height: 12), + ResourceInputContainer( + label: l.imageLabel, + initialValue: subSectionDTO.imageId, + color: kPrimaryColor, + onChanged: (ResourceDTO resource) { + if (resource.id == null) { + subSectionDTO.imageId = null; + subSectionDTO.imageSource = null; + } else { + subSectionDTO.imageId = resource.id; + subSectionDTO.imageSource = resource.url; + } + }, + ), + const SizedBox(height: 12), + MultiStringInputContainer( + label: l.displayTitleLabel, + modalLabel: l.messageTitle, + color: kPrimaryColor, + initialValue: subSectionDTO.title ?? [], + onGetResult: (value) { + if (subSectionDTO.title != value) subSectionDTO.title = value; + }, + maxLines: 1, + isHTML: true, + isTitle: true, + ), + const SizedBox(height: 12), + MultiStringInputContainer( + label: l.displayedDescriptionLabel, + modalLabel: "Description", + color: kPrimaryColor, + initialValue: subSectionDTO.description ?? [], + isMandatory: false, + onGetResult: (value) { + if (subSectionDTO.description != value) { + subSectionDTO.description = value; + } + }, + maxLines: 1, + isHTML: true, + isTitle: false, + ), + ], + ), + ), + ); + } + + Widget _cardTypeConfig() { + final typeName = getSectionTypeName(subSectionDTO.type); + return Card( + elevation: 0, + color: kWhite, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Configuration $typeName", + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: kTitleTextColor), + ), + const SizedBox(height: 12), + _getSpecificConfig(), + ], + ), + ), + ); + } + + Widget _getSpecificConfig() { + final l = AppLocalizations.of(context)!; + switch (subSectionDTO.type) { + case SectionType.Map: + return MapConfig( + initialValue: sectionDetailDTO as MapDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + case SectionType.Slider: + return SliderConfig( + initialValue: sectionDetailDTO as SliderDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + case SectionType.Video: + return VideoConfig( + label: l.videoUrlLabel, + initialValue: sectionDetailDTO as VideoDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + case SectionType.Web: + return WebConfig( + label: l.webUrlLabel, + initialValue: sectionDetailDTO as WebDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + case SectionType.Quiz: + return QuizzConfig( + initialValue: sectionDetailDTO as QuizDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + case SectionType.Article: + return ArticleConfig( + initialValue: sectionDetailDTO as ArticleDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + case SectionType.Pdf: + return PDFConfig( + initialValue: sectionDetailDTO as PdfDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + case SectionType.Game: + return GameConfig( + initialValue: sectionDetailDTO as GameDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + case SectionType.Agenda: + return AgendaConfig( + initialValue: sectionDetailDTO as AgendaDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + case SectionType.Weather: + return WeatherConfig( + initialValue: sectionDetailDTO as WeatherDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + case SectionType.Event: + return EventConfig( + initialValue: sectionDetailDTO as SectionEventDTO, + onChanged: (v) => sectionDetailDTO = v, + ); + default: + return const SizedBox.shrink(); + } + } + + Widget _buildFooter(AppLocalizations l) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + decoration: const BoxDecoration( + color: kWhite, + boxShadow: [ + BoxShadow(color: kSecond, blurRadius: 8, offset: Offset(0, -2)) + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + OutlinedButton.icon( + icon: const Icon(Icons.undo, size: 16), + label: Text(l.cancel), + onPressed: _goBack, + ), + const SizedBox(width: 8), + ElevatedButton.icon( + icon: const Icon(Icons.done, size: 16, color: kWhite), + label: Text(l.save, style: const TextStyle(color: kWhite)), + style: ElevatedButton.styleFrom(backgroundColor: kPrimaryColor), + onPressed: _save, + ), + ], + ), + ); + } + + Future _save() async { + final appContext = Provider.of(context, listen: false); + final l = AppLocalizations.of(context)!; + try { + final detailToSave = _buildDetailDTOWithFields(); + await (appContext.getContext() as ManagerAppContext) + .clientAPI! + .sectionApi! + .sectionUpdate(detailToSave); + showNotification(kSuccess, kWhite, l.subSectionUpdatedSuccess, context, null); + if (mounted) _goBack(); + } catch (e) { + showNotification(kError, kWhite, l.subSectionUpdateError, context, null); + } + } + + dynamic _buildDetailDTOWithFields() { + dynamic detail = sectionDetailDTO; + detail.id = subSectionDTO.id; + detail.order = subSectionDTO.order; + detail.dateCreation = subSectionDTO.dateCreation; + detail.type = subSectionDTO.type; + detail.instanceId = subSectionDTO.instanceId; + detail.configurationId = subSectionDTO.configurationId; + detail.isSubSection = subSectionDTO.isSubSection; + detail.parentId = subSectionDTO.parentId; + detail.label = subSectionDTO.label; + detail.title = subSectionDTO.title; + detail.description = subSectionDTO.description; + detail.imageId = subSectionDTO.imageId; + detail.imageSource = subSectionDTO.imageSource; + detail.isBeacon = subSectionDTO.isBeacon; + detail.beaconId = subSectionDTO.beaconId; + detail.latitude = subSectionDTO.latitude; + detail.longitude = subSectionDTO.longitude; + detail.meterZoneGPS = subSectionDTO.meterZoneGPS; + return detail; + } +} diff --git a/lib/Screens/Configurations/Section/section_detail_screen.dart b/lib/Screens/Configurations/Section/section_detail_screen.dart index 871d75f..f7b7fc1 100644 --- a/lib/Screens/Configurations/Section/section_detail_screen.dart +++ b/lib/Screens/Configurations/Section/section_detail_screen.dart @@ -142,7 +142,7 @@ class _SectionDetailScreenState extends State { // ── Header ── Widget _buildHeader(AppContext appContext, AppLocalizations l) { - final typeName = sectionDTO.type?.toString().split('.').last ?? ''; + final typeName = getSectionTypeName(sectionDTO.type); return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( @@ -404,7 +404,7 @@ class _SectionDetailScreenState extends State { // ── Card Type Config ── Widget _cardTypeConfig(Object? rawSectionData, AppContext appContext) { - final typeName = sectionDTO.type?.toString().split('.').last ?? 'Section'; + final typeName = getSectionTypeName(sectionDTO.type); return Card( elevation: 0, color: kWhite, diff --git a/lib/Screens/Configurations/configurations_screen.dart b/lib/Screens/Configurations/configurations_screen.dart index 3c97abd..295f7e9 100644 --- a/lib/Screens/Configurations/configurations_screen.dart +++ b/lib/Screens/Configurations/configurations_screen.dart @@ -14,6 +14,7 @@ import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import 'Section/section_detail_screen.dart'; +import 'Section/SubSection/Menu/sub_section_edit_screen.dart'; class ConfigurationsScreen extends StatefulWidget { ConfigurationsScreen({Key? key}) : super(key: key); @@ -35,6 +36,12 @@ class _ConfigurationsScreenState extends State { final Size size = MediaQuery.of(context).size; final ManagerAppContext managerAppContext = appContext.getContext(); + if (managerAppContext.selectedSubSection != null) { + return SubSectionEditScreen( + subSectionDTO: managerAppContext.selectedSubSection!, + rawData: managerAppContext.selectedSubSectionRawData!, + ); + } if (managerAppContext.selectedSection != null) { return SectionDetailScreen(id: managerAppContext.selectedSection!.id!); } diff --git a/lib/Screens/Main/main_screen.dart b/lib/Screens/Main/main_screen.dart index 2a334c5..9b3742b 100644 --- a/lib/Screens/Main/main_screen.dart +++ b/lib/Screens/Main/main_screen.dart @@ -62,7 +62,7 @@ class _MainScreenState extends State { resources = MenuSection(name: "Ressources", type: "resources", menuId: 6, subMenu: []); menu.sections = [devices, configurations, resources]; - if (widget.instance.isStatistic == true) { + if (widget.instance.hasStats == true) { menu.sections!.add(MenuSection(name: "Statistiques", type: "statistics", menuId: 7, subMenu: [])); } @@ -143,7 +143,8 @@ class _MainScreenState extends State { name: instanceDetail?.name, pinCode: instanceDetail?.pinCode, isPushNotification: instanceDetail?.isPushNotification, - isStatistic: instanceDetail?.isStatistic, + hasStats: instanceDetail?.hasStats, + hasAdvancedStats: instanceDetail?.hasAdvancedStats, isMobile: instanceDetail?.isMobile, isTablet: instanceDetail?.isTablet, isWeb: instanceDetail?.isWeb, diff --git a/lib/Screens/Statistics/statistics_screen.dart b/lib/Screens/Statistics/statistics_screen.dart index dc926fc..665d8ac 100644 --- a/lib/Screens/Statistics/statistics_screen.dart +++ b/lib/Screens/Statistics/statistics_screen.dart @@ -28,6 +28,7 @@ class _StatisticsScreenState extends State { } void _load() { + if (_managerAppContext.instanceDTO?.hasStats != true) return; final days = _selectedDays; final appType = _selectedAppType; setState(() { diff --git a/lib/api/openApiTest.dart b/lib/api/openApiTest.dart index ddaa072..4b9e49a 100644 --- a/lib/api/openApiTest.dart +++ b/lib/api/openApiTest.dart @@ -1,4 +1,4 @@ -// Openapi Generator last run: : 2026-03-13T16:08:54.634997 +// Openapi Generator last run: : 2026-05-07T21:23:24.036284 import 'package:openapi_generator_annotations/openapi_generator_annotations.dart'; @Openapi( diff --git a/lib/api/swagger.yaml b/lib/api/swagger.yaml index b3262fa..cf45c52 100644 --- a/lib/api/swagger.yaml +++ b/lib/api/swagger.yaml @@ -6172,7 +6172,7 @@ "isAssistant": { "type": "boolean" }, - "isStatistic": { + "hasStats": { "type": "boolean" } } @@ -7937,9 +7937,6 @@ "isPushNotification": { "type": "boolean" }, - "isStatistic": { - "type": "boolean" - }, "isMobile": { "type": "boolean" }, @@ -7981,9 +7978,6 @@ "isPushNotification": { "type": "boolean" }, - "isStatistic": { - "type": "boolean" - }, "isMobile": { "type": "boolean" }, diff --git a/lib/main.dart b/lib/main.dart index 4131190..97f54ca 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,6 +21,7 @@ import 'app_context.dart'; import 'client.dart'; import 'constants.dart'; import 'package:flutter_web_plugins/url_strategy.dart'; +import 'package:toastification/toastification.dart'; import 'dart:html' as html; //import 'package:window_size/window_size.dart'; @@ -237,7 +238,8 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { final locale = Provider.of(context).getContext()?.locale ?? const Locale('fr'); - return MaterialApp.router( + return ToastificationWrapper( + child: MaterialApp.router( routerConfig: widget.router, key: mainKey, builder: (context, child) => ResponsiveBreakpoints.builder( @@ -289,6 +291,7 @@ class _MyAppState extends State { onUnknownRoute: (settings) => MaterialPageRoute( builder: (context) => Container(child: Center(child: Text("Not found"))), ),*/ + ), ); } } diff --git a/manager_api_new/lib/model/application_instance_dto.dart b/manager_api_new/lib/model/application_instance_dto.dart index 9e1de79..f703cc3 100644 --- a/manager_api_new/lib/model/application_instance_dto.dart +++ b/manager_api_new/lib/model/application_instance_dto.dart @@ -28,7 +28,7 @@ class ApplicationInstanceDTO { this.sectionEventId, this.sectionEventDTO, this.isAssistant, - this.isStatistic, + this.hasStats, }); String? id; @@ -73,7 +73,7 @@ class ApplicationInstanceDTO { bool? isAssistant; - bool? isStatistic; + bool? hasStats; @override bool operator ==(Object other) => @@ -94,7 +94,7 @@ class ApplicationInstanceDTO { other.sectionEventId == sectionEventId && other.sectionEventDTO == sectionEventDTO && other.isAssistant == isAssistant && - other.isStatistic == isStatistic; + other.hasStats == hasStats; @override int get hashCode => @@ -114,11 +114,11 @@ class ApplicationInstanceDTO { (sectionEventId == null ? 0 : sectionEventId!.hashCode) + (sectionEventDTO == null ? 0 : sectionEventDTO!.hashCode) + (isAssistant == null ? 0 : isAssistant!.hashCode) + - (isStatistic == null ? 0 : isStatistic!.hashCode); + (hasStats == null ? 0 : hasStats!.hashCode); @override String toString() => - 'ApplicationInstanceDTO[id=$id, instanceId=$instanceId, appType=$appType, configurations=$configurations, mainImageId=$mainImageId, mainImageUrl=$mainImageUrl, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor, layoutMainPage=$layoutMainPage, languages=$languages, sectionEventId=$sectionEventId, sectionEventDTO=$sectionEventDTO, isAssistant=$isAssistant, isStatistic=$isStatistic]'; + 'ApplicationInstanceDTO[id=$id, instanceId=$instanceId, appType=$appType, configurations=$configurations, mainImageId=$mainImageId, mainImageUrl=$mainImageUrl, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor, layoutMainPage=$layoutMainPage, languages=$languages, sectionEventId=$sectionEventId, sectionEventDTO=$sectionEventDTO, isAssistant=$isAssistant, hasStats=$hasStats]'; Map toJson() { final json = {}; @@ -197,10 +197,10 @@ class ApplicationInstanceDTO { } else { json[r'isAssistant'] = null; } - if (this.isStatistic != null) { - json[r'isStatistic'] = this.isStatistic; + if (this.hasStats != null) { + json[r'hasStats'] = this.hasStats; } else { - json[r'isStatistic'] = null; + json[r'hasStats'] = null; } return json; } @@ -246,7 +246,7 @@ class ApplicationInstanceDTO { sectionEventId: mapValueOfType(json, r'sectionEventId'), sectionEventDTO: SectionEventDTO.fromJson(json[r'sectionEventDTO']), isAssistant: mapValueOfType(json, r'isAssistant'), - isStatistic: mapValueOfType(json, r'isStatistic'), + hasStats: mapValueOfType(json, r'hasStats'), ); } return null; diff --git a/manager_api_new/lib/model/day_stat_dto.dart b/manager_api_new/lib/model/day_stat_dto.dart new file mode 100644 index 0000000..8a28c5a --- /dev/null +++ b/manager_api_new/lib/model/day_stat_dto.dart @@ -0,0 +1,175 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class DayStatDTO { + /// Returns a new [DayStatDTO] instance. + DayStatDTO({ + this.date, + this.total, + this.mobile, + this.tablet, + }); + + String? date; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? total; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? mobile; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? tablet; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is DayStatDTO && + other.date == date && + other.total == total && + other.mobile == mobile && + other.tablet == tablet; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (date == null ? 0 : date!.hashCode) + + (total == null ? 0 : total!.hashCode) + + (mobile == null ? 0 : mobile!.hashCode) + + (tablet == null ? 0 : tablet!.hashCode); + + @override + String toString() => + 'DayStatDTO[date=$date, total=$total, mobile=$mobile, tablet=$tablet]'; + + Map toJson() { + final json = {}; + if (this.date != null) { + json[r'date'] = this.date; + } else { + json[r'date'] = null; + } + if (this.total != null) { + json[r'total'] = this.total; + } else { + json[r'total'] = null; + } + if (this.mobile != null) { + json[r'mobile'] = this.mobile; + } else { + json[r'mobile'] = null; + } + if (this.tablet != null) { + json[r'tablet'] = this.tablet; + } else { + json[r'tablet'] = null; + } + return json; + } + + /// Returns a new [DayStatDTO] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static DayStatDTO? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), + 'Required key "DayStatDTO[$key]" is missing from JSON.'); + assert(json[key] != null, + 'Required key "DayStatDTO[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return DayStatDTO( + date: mapValueOfType(json, r'date'), + total: mapValueOfType(json, r'total'), + mobile: mapValueOfType(json, r'mobile'), + tablet: mapValueOfType(json, r'tablet'), + ); + } + return null; + } + + static List listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = DayStatDTO.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = DayStatDTO.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of DayStatDTO-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + // ignore: parameter_assignments + json = json.cast(); + for (final entry in json.entries) { + map[entry.key] = DayStatDTO.listFromJson( + entry.value, + growable: growable, + ); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/manager_api_new/lib/model/game_stat_dto.dart b/manager_api_new/lib/model/game_stat_dto.dart new file mode 100644 index 0000000..6f34cf8 --- /dev/null +++ b/manager_api_new/lib/model/game_stat_dto.dart @@ -0,0 +1,158 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class GameStatDTO { + /// Returns a new [GameStatDTO] instance. + GameStatDTO({ + this.gameType, + this.completions, + this.avgDurationSeconds, + }); + + String? gameType; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? completions; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? avgDurationSeconds; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is GameStatDTO && + other.gameType == gameType && + other.completions == completions && + other.avgDurationSeconds == avgDurationSeconds; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (gameType == null ? 0 : gameType!.hashCode) + + (completions == null ? 0 : completions!.hashCode) + + (avgDurationSeconds == null ? 0 : avgDurationSeconds!.hashCode); + + @override + String toString() => + 'GameStatDTO[gameType=$gameType, completions=$completions, avgDurationSeconds=$avgDurationSeconds]'; + + Map toJson() { + final json = {}; + if (this.gameType != null) { + json[r'gameType'] = this.gameType; + } else { + json[r'gameType'] = null; + } + if (this.completions != null) { + json[r'completions'] = this.completions; + } else { + json[r'completions'] = null; + } + if (this.avgDurationSeconds != null) { + json[r'avgDurationSeconds'] = this.avgDurationSeconds; + } else { + json[r'avgDurationSeconds'] = null; + } + return json; + } + + /// Returns a new [GameStatDTO] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static GameStatDTO? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), + 'Required key "GameStatDTO[$key]" is missing from JSON.'); + assert(json[key] != null, + 'Required key "GameStatDTO[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return GameStatDTO( + gameType: mapValueOfType(json, r'gameType'), + completions: mapValueOfType(json, r'completions'), + avgDurationSeconds: mapValueOfType(json, r'avgDurationSeconds'), + ); + } + return null; + } + + static List listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = GameStatDTO.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = GameStatDTO.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of GameStatDTO-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + // ignore: parameter_assignments + json = json.cast(); + for (final entry in json.entries) { + map[entry.key] = GameStatDTO.listFromJson( + entry.value, + growable: growable, + ); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/manager_api_new/lib/model/instance_dto.dart b/manager_api_new/lib/model/instance_dto.dart index 42cd418..6ce5230 100644 --- a/manager_api_new/lib/model/instance_dto.dart +++ b/manager_api_new/lib/model/instance_dto.dart @@ -18,7 +18,6 @@ class InstanceDTO { this.dateCreation, this.pinCode, this.isPushNotification, - this.isStatistic, this.isMobile, this.isTablet, this.isWeb, @@ -60,7 +59,6 @@ class InstanceDTO { /// source code must fall back to having a nullable type. /// Consider adding a "default:" property in the specification file to hide this note. /// - bool? isStatistic; /// /// Please note: This property should have been non-nullable! Since the specification file @@ -129,7 +127,6 @@ class InstanceDTO { other.dateCreation == dateCreation && other.pinCode == pinCode && other.isPushNotification == isPushNotification && - other.isStatistic == isStatistic && other.isMobile == isMobile && other.isTablet == isTablet && other.isWeb == isWeb && @@ -155,7 +152,6 @@ class InstanceDTO { (dateCreation == null ? 0 : dateCreation!.hashCode) + (pinCode == null ? 0 : pinCode!.hashCode) + (isPushNotification == null ? 0 : isPushNotification!.hashCode) + - (isStatistic == null ? 0 : isStatistic!.hashCode) + (isMobile == null ? 0 : isMobile!.hashCode) + (isTablet == null ? 0 : isTablet!.hashCode) + (isWeb == null ? 0 : isWeb!.hashCode) + @@ -169,7 +165,7 @@ class InstanceDTO { @override String toString() => - 'InstanceDTO[id=$id, name=$name, dateCreation=$dateCreation, pinCode=$pinCode, isPushNotification=$isPushNotification, isStatistic=$isStatistic, isMobile=$isMobile, isTablet=$isTablet, isWeb=$isWeb, isVR=$isVR, isAssistant=$isAssistant, subscriptionPlanId=$subscriptionPlanId, subscriptionPlan=$subscriptionPlan, aiRequestsThisMonth=$aiRequestsThisMonth, aiUsageMonthKey=$aiUsageMonthKey, applicationInstanceDTOs=$applicationInstanceDTOs]'; + 'InstanceDTO[id=$id, name=$name, dateCreation=$dateCreation, pinCode=$pinCode, isPushNotification=$isPushNotification, isMobile=$isMobile, isTablet=$isTablet, isWeb=$isWeb, isVR=$isVR, isAssistant=$isAssistant, subscriptionPlanId=$subscriptionPlanId, subscriptionPlan=$subscriptionPlan, aiRequestsThisMonth=$aiRequestsThisMonth, aiUsageMonthKey=$aiUsageMonthKey, applicationInstanceDTOs=$applicationInstanceDTOs]'; Map toJson() { final json = {}; @@ -198,11 +194,6 @@ class InstanceDTO { } else { json[r'isPushNotification'] = null; } - if (this.isStatistic != null) { - json[r'isStatistic'] = this.isStatistic; - } else { - json[r'isStatistic'] = null; - } if (this.isMobile != null) { json[r'isMobile'] = this.isMobile; } else { @@ -317,7 +308,6 @@ class InstanceDTO { dateCreation: mapDateTime(json, r'dateCreation', r''), pinCode: mapValueOfType(json, r'pinCode'), isPushNotification: mapValueOfType(json, r'isPushNotification'), - isStatistic: mapValueOfType(json, r'isStatistic'), isMobile: mapValueOfType(json, r'isMobile'), isTablet: mapValueOfType(json, r'isTablet'), isWeb: mapValueOfType(json, r'isWeb'), diff --git a/manager_api_new/lib/model/poi_stat_dto.dart b/manager_api_new/lib/model/poi_stat_dto.dart new file mode 100644 index 0000000..0747131 --- /dev/null +++ b/manager_api_new/lib/model/poi_stat_dto.dart @@ -0,0 +1,169 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class PoiStatDTO { + /// Returns a new [PoiStatDTO] instance. + PoiStatDTO({ + this.geoPointId, + this.title, + this.taps, + this.sectionId, + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? geoPointId; + + String? title; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? taps; + + String? sectionId; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is PoiStatDTO && + other.geoPointId == geoPointId && + other.title == title && + other.taps == taps && + other.sectionId == sectionId; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (geoPointId == null ? 0 : geoPointId!.hashCode) + + (title == null ? 0 : title!.hashCode) + + (taps == null ? 0 : taps!.hashCode) + + (sectionId == null ? 0 : sectionId!.hashCode); + + @override + String toString() => + 'PoiStatDTO[geoPointId=$geoPointId, title=$title, taps=$taps, sectionId=$sectionId]'; + + Map toJson() { + final json = {}; + if (this.geoPointId != null) { + json[r'geoPointId'] = this.geoPointId; + } else { + json[r'geoPointId'] = null; + } + if (this.title != null) { + json[r'title'] = this.title; + } else { + json[r'title'] = null; + } + if (this.taps != null) { + json[r'taps'] = this.taps; + } else { + json[r'taps'] = null; + } + if (this.sectionId != null) { + json[r'sectionId'] = this.sectionId; + } else { + json[r'sectionId'] = null; + } + return json; + } + + /// Returns a new [PoiStatDTO] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static PoiStatDTO? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), + 'Required key "PoiStatDTO[$key]" is missing from JSON.'); + assert(json[key] != null, + 'Required key "PoiStatDTO[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return PoiStatDTO( + geoPointId: mapValueOfType(json, r'geoPointId'), + title: mapValueOfType(json, r'title'), + taps: mapValueOfType(json, r'taps'), + sectionId: mapValueOfType(json, r'sectionId'), + ); + } + return null; + } + + static List listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = PoiStatDTO.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PoiStatDTO.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of PoiStatDTO-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + // ignore: parameter_assignments + json = json.cast(); + for (final entry in json.entries) { + map[entry.key] = PoiStatDTO.listFromJson( + entry.value, + growable: growable, + ); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/manager_api_new/lib/model/quiz_stat_dto.dart b/manager_api_new/lib/model/quiz_stat_dto.dart new file mode 100644 index 0000000..c5fbfd9 --- /dev/null +++ b/manager_api_new/lib/model/quiz_stat_dto.dart @@ -0,0 +1,186 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class QuizStatDTO { + /// Returns a new [QuizStatDTO] instance. + QuizStatDTO({ + this.sectionId, + this.sectionTitle, + this.avgScore, + this.totalQuestions, + this.completions, + }); + + String? sectionId; + + String? sectionTitle; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + double? avgScore; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? totalQuestions; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? completions; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is QuizStatDTO && + other.sectionId == sectionId && + other.sectionTitle == sectionTitle && + other.avgScore == avgScore && + other.totalQuestions == totalQuestions && + other.completions == completions; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (sectionId == null ? 0 : sectionId!.hashCode) + + (sectionTitle == null ? 0 : sectionTitle!.hashCode) + + (avgScore == null ? 0 : avgScore!.hashCode) + + (totalQuestions == null ? 0 : totalQuestions!.hashCode) + + (completions == null ? 0 : completions!.hashCode); + + @override + String toString() => + 'QuizStatDTO[sectionId=$sectionId, sectionTitle=$sectionTitle, avgScore=$avgScore, totalQuestions=$totalQuestions, completions=$completions]'; + + Map toJson() { + final json = {}; + if (this.sectionId != null) { + json[r'sectionId'] = this.sectionId; + } else { + json[r'sectionId'] = null; + } + if (this.sectionTitle != null) { + json[r'sectionTitle'] = this.sectionTitle; + } else { + json[r'sectionTitle'] = null; + } + if (this.avgScore != null) { + json[r'avgScore'] = this.avgScore; + } else { + json[r'avgScore'] = null; + } + if (this.totalQuestions != null) { + json[r'totalQuestions'] = this.totalQuestions; + } else { + json[r'totalQuestions'] = null; + } + if (this.completions != null) { + json[r'completions'] = this.completions; + } else { + json[r'completions'] = null; + } + return json; + } + + /// Returns a new [QuizStatDTO] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static QuizStatDTO? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), + 'Required key "QuizStatDTO[$key]" is missing from JSON.'); + assert(json[key] != null, + 'Required key "QuizStatDTO[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return QuizStatDTO( + sectionId: mapValueOfType(json, r'sectionId'), + sectionTitle: mapValueOfType(json, r'sectionTitle'), + avgScore: mapValueOfType(json, r'avgScore'), + totalQuestions: mapValueOfType(json, r'totalQuestions'), + completions: mapValueOfType(json, r'completions'), + ); + } + return null; + } + + static List listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = QuizStatDTO.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = QuizStatDTO.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of QuizStatDTO-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + // ignore: parameter_assignments + json = json.cast(); + for (final entry in json.entries) { + map[entry.key] = QuizStatDTO.listFromJson( + entry.value, + growable: growable, + ); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/manager_api_new/lib/model/section_stat_dto.dart b/manager_api_new/lib/model/section_stat_dto.dart new file mode 100644 index 0000000..76fe33e --- /dev/null +++ b/manager_api_new/lib/model/section_stat_dto.dart @@ -0,0 +1,169 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class SectionStatDTO { + /// Returns a new [SectionStatDTO] instance. + SectionStatDTO({ + this.sectionId, + this.sectionTitle, + this.views, + this.avgDurationSeconds, + }); + + String? sectionId; + + String? sectionTitle; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? views; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? avgDurationSeconds; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is SectionStatDTO && + other.sectionId == sectionId && + other.sectionTitle == sectionTitle && + other.views == views && + other.avgDurationSeconds == avgDurationSeconds; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (sectionId == null ? 0 : sectionId!.hashCode) + + (sectionTitle == null ? 0 : sectionTitle!.hashCode) + + (views == null ? 0 : views!.hashCode) + + (avgDurationSeconds == null ? 0 : avgDurationSeconds!.hashCode); + + @override + String toString() => + 'SectionStatDTO[sectionId=$sectionId, sectionTitle=$sectionTitle, views=$views, avgDurationSeconds=$avgDurationSeconds]'; + + Map toJson() { + final json = {}; + if (this.sectionId != null) { + json[r'sectionId'] = this.sectionId; + } else { + json[r'sectionId'] = null; + } + if (this.sectionTitle != null) { + json[r'sectionTitle'] = this.sectionTitle; + } else { + json[r'sectionTitle'] = null; + } + if (this.views != null) { + json[r'views'] = this.views; + } else { + json[r'views'] = null; + } + if (this.avgDurationSeconds != null) { + json[r'avgDurationSeconds'] = this.avgDurationSeconds; + } else { + json[r'avgDurationSeconds'] = null; + } + return json; + } + + /// Returns a new [SectionStatDTO] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static SectionStatDTO? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), + 'Required key "SectionStatDTO[$key]" is missing from JSON.'); + assert(json[key] != null, + 'Required key "SectionStatDTO[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return SectionStatDTO( + sectionId: mapValueOfType(json, r'sectionId'), + sectionTitle: mapValueOfType(json, r'sectionTitle'), + views: mapValueOfType(json, r'views'), + avgDurationSeconds: mapValueOfType(json, r'avgDurationSeconds'), + ); + } + return null; + } + + static List listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = SectionStatDTO.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = SectionStatDTO.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of SectionStatDTO-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + // ignore: parameter_assignments + json = json.cast(); + for (final entry in json.entries) { + map[entry.key] = SectionStatDTO.listFromJson( + entry.value, + growable: growable, + ); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/pubspec.lock b/pubspec.lock index 4231409..e76e1bf 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -813,6 +813,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + iconsax_flutter: + dependency: transitive + description: + name: iconsax_flutter + sha256: d14b4cec8586025ac15276bdd40f6eea308cb85748135965bb6255f14beb2564 + url: "https://pub.dev" + source: hosted + version: "1.0.1" image: dependency: transitive description: @@ -1164,6 +1172,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.1" + pausable_timer: + dependency: transitive + description: + name: pausable_timer + sha256: "6ef1a95441ec3439de6fb63f39a011b67e693198e7dae14e20675c3c00e86074" + url: "https://pub.dev" + source: hosted + version: "3.1.0+3" pdf: dependency: "direct main" description: @@ -1385,14 +1401,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" - sprintf: - dependency: transitive - description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.dev" - source: hosted - version: "7.0.0" sqflite: dependency: transitive description: @@ -1481,6 +1489,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + toastification: + dependency: "direct main" + description: + name: toastification + sha256: "4d97fbfa463dfe83691044cba9f37cb185a79bb9205cfecb655fa1f6be126a13" + url: "https://pub.dev" + source: hosted + version: "2.3.0" typed_data: dependency: transitive description: @@ -1565,10 +1581,10 @@ packages: dependency: transitive description: name: uuid - sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" + sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.5.3" vector_graphics: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 7c5460e..5c66abe 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -80,6 +80,7 @@ dependencies: firebase_storage: ^12.0.1 firebase_core: ^3.1.0 fl_chart: ^0.69.0 + toastification: ^2.3.0 #another_flushbar: ^1.12.30 dependency_overrides: