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: