Update fix for parcours, event bloc call apis + update layout for game (tabs)
This commit is contained in:
parent
ded4620bf2
commit
e05e5234c8
@ -3,6 +3,10 @@ import 'package:manager_api_new/api.dart';
|
|||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'showNewOrUpdateProgrammeBlock.dart';
|
import 'showNewOrUpdateProgrammeBlock.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:manager_app/app_context.dart';
|
||||||
|
import 'package:manager_app/Models/managerContext.dart';
|
||||||
|
import 'package:manager_app/Components/message_notification.dart';
|
||||||
|
|
||||||
class EventConfig extends StatefulWidget {
|
class EventConfig extends StatefulWidget {
|
||||||
final SectionEventDTO initialValue;
|
final SectionEventDTO initialValue;
|
||||||
@ -25,6 +29,22 @@ class _EventConfigState extends State<EventConfig> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
eventDTO = widget.initialValue;
|
eventDTO = widget.initialValue;
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => _loadProgrammeBlocks());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadProgrammeBlocks() async {
|
||||||
|
if (eventDTO.id == null || !mounted) return;
|
||||||
|
final appContext = Provider.of<AppContext>(context, listen: false);
|
||||||
|
final api = (appContext.getContext() as ManagerAppContext).clientAPI!.sectionEventApi!;
|
||||||
|
try {
|
||||||
|
final blocks = await api.sectionEventGetAllProgrammeBlockFromSection(eventDTO.id!);
|
||||||
|
if (blocks == null || !mounted) return;
|
||||||
|
setState(() {
|
||||||
|
eventDTO.programme = blocks;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
// Silently keep initial value on error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -41,11 +61,11 @@ class _EventConfigState extends State<EventConfig> {
|
|||||||
title: Text("Date de début"),
|
title: Text("Date de début"),
|
||||||
subtitle: Text(eventDTO.startDate != null
|
subtitle: Text(eventDTO.startDate != null
|
||||||
? DateFormat('dd/MM/yyyy HH:mm')
|
? DateFormat('dd/MM/yyyy HH:mm')
|
||||||
.format(eventDTO.startDate!)
|
.format(eventDTO.startDate!.toLocal())
|
||||||
: "Non définie"),
|
: "Non définie"),
|
||||||
trailing: Icon(Icons.calendar_today),
|
trailing: Icon(Icons.calendar_today),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
DateTime initialDate = eventDTO.startDate ?? DateTime.now();
|
DateTime initialDate = eventDTO.startDate?.toLocal() ?? DateTime.now();
|
||||||
if (initialDate.isBefore(DateTime(2000))) {
|
if (initialDate.isBefore(DateTime(2000))) {
|
||||||
initialDate = DateTime.now();
|
initialDate = DateTime.now();
|
||||||
}
|
}
|
||||||
@ -71,7 +91,7 @@ class _EventConfigState extends State<EventConfig> {
|
|||||||
TimeOfDay? time = await showTimePicker(
|
TimeOfDay? time = await showTimePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialTime: TimeOfDay.fromDateTime(
|
initialTime: TimeOfDay.fromDateTime(
|
||||||
eventDTO.startDate ?? DateTime.now()),
|
eventDTO.startDate?.toLocal() ?? DateTime.now()),
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Theme(
|
return Theme(
|
||||||
data: Theme.of(context).copyWith(
|
data: Theme.of(context).copyWith(
|
||||||
@ -100,11 +120,11 @@ class _EventConfigState extends State<EventConfig> {
|
|||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text("Date de fin"),
|
title: Text("Date de fin"),
|
||||||
subtitle: Text(eventDTO.endDate != null
|
subtitle: Text(eventDTO.endDate != null
|
||||||
? DateFormat('dd/MM/yyyy HH:mm').format(eventDTO.endDate!)
|
? DateFormat('dd/MM/yyyy HH:mm').format(eventDTO.endDate!.toLocal())
|
||||||
: "Non définie"),
|
: "Non définie"),
|
||||||
trailing: Icon(Icons.calendar_today),
|
trailing: Icon(Icons.calendar_today),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
DateTime initialDate = eventDTO.endDate ??
|
DateTime initialDate = eventDTO.endDate?.toLocal() ??
|
||||||
DateTime.now().add(Duration(days: 1));
|
DateTime.now().add(Duration(days: 1));
|
||||||
if (initialDate.isBefore(DateTime(2000))) {
|
if (initialDate.isBefore(DateTime(2000))) {
|
||||||
initialDate = DateTime.now().add(Duration(days: 1));
|
initialDate = DateTime.now().add(Duration(days: 1));
|
||||||
@ -130,7 +150,7 @@ class _EventConfigState extends State<EventConfig> {
|
|||||||
if (picked != null) {
|
if (picked != null) {
|
||||||
TimeOfDay? time = await showTimePicker(
|
TimeOfDay? time = await showTimePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialTime: TimeOfDay.fromDateTime(eventDTO.endDate ??
|
initialTime: TimeOfDay.fromDateTime(eventDTO.endDate?.toLocal() ??
|
||||||
DateTime.now().add(Duration(days: 1))),
|
DateTime.now().add(Duration(days: 1))),
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Theme(
|
return Theme(
|
||||||
@ -171,17 +191,54 @@ class _EventConfigState extends State<EventConfig> {
|
|||||||
icon: Icon(Icons.add),
|
icon: Icon(Icons.add),
|
||||||
label: Text("Ajouter un bloc"),
|
label: Text("Ajouter un bloc"),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
final appContext =
|
||||||
|
Provider.of<AppContext>(context, listen: false);
|
||||||
showNewOrUpdateProgrammeBlock(
|
showNewOrUpdateProgrammeBlock(
|
||||||
context,
|
context,
|
||||||
null,
|
null,
|
||||||
(newBlock) {
|
(newBlock) async {
|
||||||
|
try {
|
||||||
|
// The API expects ProgrammeBlockDTO, while eventDTO.programme is List<ProgrammeBlock>
|
||||||
|
// Usually they are structural equivalents in these generated APIs, but let's be safe.
|
||||||
|
final programmeBlockDTO =
|
||||||
|
ProgrammeBlockDTO.fromJson(newBlock.toJson());
|
||||||
|
if (programmeBlockDTO == null) return;
|
||||||
|
|
||||||
|
final createdBlockDTO =
|
||||||
|
await (appContext.getContext() as ManagerAppContext)
|
||||||
|
.clientAPI!
|
||||||
|
.sectionEventApi!
|
||||||
|
.sectionEventCreateProgrammeBlock(
|
||||||
|
eventDTO.id!, programmeBlockDTO);
|
||||||
|
|
||||||
|
if (createdBlockDTO != null) {
|
||||||
|
// Convert back if necessary
|
||||||
|
final createdBlock =
|
||||||
|
ProgrammeBlock.fromJson(createdBlockDTO.toJson());
|
||||||
|
if (createdBlock != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
eventDTO.programme = [
|
eventDTO.programme = [
|
||||||
...(eventDTO.programme ?? []),
|
...(eventDTO.programme ?? []),
|
||||||
newBlock
|
createdBlock
|
||||||
];
|
];
|
||||||
widget.onChanged(eventDTO);
|
widget.onChanged(eventDTO);
|
||||||
});
|
});
|
||||||
|
showNotification(
|
||||||
|
kSuccess,
|
||||||
|
kWhite,
|
||||||
|
'Bloc de programme créé avec succès',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(
|
||||||
|
kError,
|
||||||
|
kWhite,
|
||||||
|
'Erreur lors de la création du bloc',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -219,25 +276,89 @@ class _EventConfigState extends State<EventConfig> {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit, color: kPrimaryColor),
|
icon: Icon(Icons.edit, color: kPrimaryColor),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
final appContext = Provider.of<AppContext>(
|
||||||
|
context,
|
||||||
|
listen: false);
|
||||||
showNewOrUpdateProgrammeBlock(
|
showNewOrUpdateProgrammeBlock(
|
||||||
context,
|
context,
|
||||||
block,
|
block,
|
||||||
(updatedBlock) {
|
(updatedBlock) async {
|
||||||
|
try {
|
||||||
|
final programmeBlockDTO =
|
||||||
|
ProgrammeBlockDTO.fromJson(
|
||||||
|
updatedBlock.toJson());
|
||||||
|
if (programmeBlockDTO == null) return;
|
||||||
|
|
||||||
|
final resultDTO =
|
||||||
|
await (appContext.getContext()
|
||||||
|
as ManagerAppContext)
|
||||||
|
.clientAPI!
|
||||||
|
.sectionEventApi!
|
||||||
|
.sectionEventUpdateProgrammeBlock(
|
||||||
|
programmeBlockDTO);
|
||||||
|
|
||||||
|
if (resultDTO != null) {
|
||||||
|
final result = ProgrammeBlock.fromJson(
|
||||||
|
resultDTO.toJson());
|
||||||
|
if (result != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
eventDTO.programme![index] = updatedBlock;
|
eventDTO.programme![index] = result;
|
||||||
widget.onChanged(eventDTO);
|
widget.onChanged(eventDTO);
|
||||||
});
|
});
|
||||||
|
showNotification(
|
||||||
|
kSuccess,
|
||||||
|
kWhite,
|
||||||
|
'Bloc mis à jour avec succès',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(
|
||||||
|
kError,
|
||||||
|
kWhite,
|
||||||
|
'Erreur lors de la mise à jour du bloc',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete, color: kError),
|
icon: Icon(Icons.delete, color: kError),
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
|
final appContext = Provider.of<AppContext>(
|
||||||
|
context,
|
||||||
|
listen: false);
|
||||||
|
try {
|
||||||
|
if (block.id != null) {
|
||||||
|
await (appContext.getContext()
|
||||||
|
as ManagerAppContext)
|
||||||
|
.clientAPI!
|
||||||
|
.sectionEventApi!
|
||||||
|
.sectionEventDeleteProgrammeBlock(
|
||||||
|
block.id!);
|
||||||
|
}
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
eventDTO.programme!.removeAt(index);
|
eventDTO.programme!.removeAt(index);
|
||||||
widget.onChanged(eventDTO);
|
widget.onChanged(eventDTO);
|
||||||
});
|
});
|
||||||
|
showNotification(
|
||||||
|
kSuccess,
|
||||||
|
kWhite,
|
||||||
|
'Bloc supprimé avec succès',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(
|
||||||
|
kError,
|
||||||
|
kWhite,
|
||||||
|
'Erreur lors de la suppression du bloc',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_app/Components/message_notification.dart';
|
|
||||||
import 'package:manager_app/Components/multi_string_input_and_resource_container.dart';
|
import 'package:manager_app/Components/multi_string_input_and_resource_container.dart';
|
||||||
import 'package:manager_app/Components/number_input_container.dart';
|
import 'package:manager_app/Components/number_input_container.dart';
|
||||||
import 'package:manager_app/Components/resource_input_container.dart';
|
import 'package:manager_app/Components/resource_input_container.dart';
|
||||||
@ -32,45 +32,75 @@ class _GameConfigState extends State<GameConfig> {
|
|||||||
gameDTO = widget.initialValue;
|
gameDTO = widget.initialValue;
|
||||||
gameDTO.rows = gameDTO.rows ?? 3;
|
gameDTO.rows = gameDTO.rows ?? 3;
|
||||||
gameDTO.cols = gameDTO.cols ?? 3;
|
gameDTO.cols = gameDTO.cols ?? 3;
|
||||||
gameDTO.gameType = gameDTO.gameType ?? GameTypes.number0;
|
gameDTO.gameType = gameDTO.gameType ?? GameTypes.Puzzle;
|
||||||
|
gameDTO.messageDebut = gameDTO.messageDebut ?? [];
|
||||||
|
gameDTO.messageFin = gameDTO.messageFin ?? [];
|
||||||
|
gameDTO.guidedPaths = gameDTO.guidedPaths ?? [];
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(GameConfig oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (widget.initialValue.id != oldWidget.initialValue.id) {
|
||||||
|
setState(() {
|
||||||
|
gameDTO = widget.initialValue;
|
||||||
|
gameDTO.rows = gameDTO.rows ?? 3;
|
||||||
|
gameDTO.cols = gameDTO.cols ?? 3;
|
||||||
|
gameDTO.gameType = gameDTO.gameType ?? GameTypes.Puzzle;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
int initialIndex = gameDTO.gameType?.value ?? 0;
|
||||||
|
|
||||||
|
return DefaultTabController(
|
||||||
|
key: ValueKey("${gameDTO.id}_$initialIndex"),
|
||||||
|
length: 3,
|
||||||
|
initialIndex: initialIndex,
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
final TabController controller = DefaultTabController.of(context);
|
||||||
|
|
||||||
|
// Attach listener to sync gameType when tab changes
|
||||||
|
controller.addListener(() {
|
||||||
|
if (!controller.indexIsChanging) {
|
||||||
|
GameTypes newType = GameTypes.values[controller.index];
|
||||||
|
if (gameDTO.gameType != newType) {
|
||||||
|
setState(() {
|
||||||
|
gameDTO.gameType = newType;
|
||||||
|
});
|
||||||
|
widget.onChanged(gameDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
TabBar(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
labelColor: kPrimaryColor,
|
||||||
child: Row(
|
unselectedLabelColor: Colors.grey,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
indicatorColor: kPrimaryColor,
|
||||||
children: [
|
tabs: [
|
||||||
Text("Type de Jeu : ",
|
Tab(icon: Icon(Icons.extension), text: "Puzzle"),
|
||||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18)),
|
Tab(icon: Icon(Icons.grid_on), text: "Puzzle Glissant"),
|
||||||
DropdownButton<GameTypes>(
|
Tab(icon: Icon(Icons.door_front_door), text: "Escape Game"),
|
||||||
value: gameDTO.gameType,
|
|
||||||
items: [
|
|
||||||
DropdownMenuItem(
|
|
||||||
value: GameTypes.number0, child: Text("Puzzle")),
|
|
||||||
DropdownMenuItem(
|
|
||||||
value: GameTypes.number1, child: Text("Puzzle Glissant")),
|
|
||||||
DropdownMenuItem(
|
|
||||||
value: GameTypes.number2, child: Text("Escape Game")),
|
|
||||||
],
|
|
||||||
onChanged: (val) {
|
|
||||||
setState(() {
|
|
||||||
gameDTO.gameType = val;
|
|
||||||
widget.onChanged(gameDTO);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
if (gameDTO.gameType == GameTypes.number2) ...[
|
|
||||||
// Escape Mode: Parcours Config
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ParcoursConfig(
|
child: Container(
|
||||||
|
height: 500,
|
||||||
|
child: TabBarView(
|
||||||
|
children: [
|
||||||
|
_buildPuzzleConfig(),
|
||||||
|
_buildPuzzleConfig(),
|
||||||
|
ParcoursConfig(
|
||||||
initialValue: gameDTO.guidedPaths ?? [],
|
initialValue: gameDTO.guidedPaths ?? [],
|
||||||
parentId: gameDTO.id!,
|
parentId: gameDTO.id!,
|
||||||
isEvent: false,
|
isEvent: false,
|
||||||
@ -82,17 +112,29 @@ class _GameConfigState extends State<GameConfig> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
] else ...[
|
),
|
||||||
// Regular Puzzle Mode
|
),
|
||||||
Column(
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPuzzleConfig() {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 16.0),
|
||||||
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
ResourceInputContainer(
|
ResourceInputContainer(
|
||||||
label: "Image du puzzle :",
|
label: "Image du puzzle :",
|
||||||
initialValue: gameDTO.puzzleImageId ?? '',
|
initialValue: gameDTO.puzzleImageId ?? '',
|
||||||
|
color: kPrimaryColor,
|
||||||
onChanged: (ResourceDTO resourceDTO) {
|
onChanged: (ResourceDTO resourceDTO) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (resourceDTO.id == null) {
|
if (resourceDTO.id == null) {
|
||||||
@ -106,8 +148,7 @@ class _GameConfigState extends State<GameConfig> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Container(
|
Flexible(
|
||||||
height: 100,
|
|
||||||
child: MultiStringInputAndResourceContainer(
|
child: MultiStringInputAndResourceContainer(
|
||||||
label: "Message départ :",
|
label: "Message départ :",
|
||||||
modalLabel: "Message départ",
|
modalLabel: "Message départ",
|
||||||
@ -131,8 +172,7 @@ class _GameConfigState extends State<GameConfig> {
|
|||||||
isTitle: false,
|
isTitle: false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Flexible(
|
||||||
height: 100,
|
|
||||||
child: MultiStringInputAndResourceContainer(
|
child: MultiStringInputAndResourceContainer(
|
||||||
label: "Message fin :",
|
label: "Message fin :",
|
||||||
modalLabel: "Message fin",
|
modalLabel: "Message fin",
|
||||||
@ -158,55 +198,38 @@ class _GameConfigState extends State<GameConfig> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
NumberInputContainer(
|
||||||
height: 100,
|
label: "Lignes :",
|
||||||
child: NumberInputContainer(
|
|
||||||
label: "Nombre de lignes :",
|
|
||||||
initialValue: gameDTO.rows ?? 3,
|
initialValue: gameDTO.rows ?? 3,
|
||||||
|
color: kPrimaryColor,
|
||||||
isSmall: true,
|
isSmall: true,
|
||||||
maxLength: 2,
|
onChanged: (String value) {
|
||||||
onChanged: (value) {
|
|
||||||
try {
|
|
||||||
gameDTO.rows = int.parse(value);
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
gameDTO.rows = int.tryParse(value) ?? 3;
|
||||||
widget.onChanged(gameDTO);
|
widget.onChanged(gameDTO);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
|
||||||
showNotification(Colors.orange, kWhite,
|
|
||||||
'Cela doit être un chiffre', context, null);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
NumberInputContainer(
|
||||||
Container(
|
label: "Colonnes :",
|
||||||
height: 100,
|
|
||||||
child: NumberInputContainer(
|
|
||||||
label: "Nombre de colonnes :",
|
|
||||||
initialValue: gameDTO.cols ?? 3,
|
initialValue: gameDTO.cols ?? 3,
|
||||||
|
color: kPrimaryColor,
|
||||||
isSmall: true,
|
isSmall: true,
|
||||||
maxLength: 2,
|
onChanged: (String value) {
|
||||||
onChanged: (value) {
|
|
||||||
try {
|
|
||||||
gameDTO.cols = int.parse(value);
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
gameDTO.cols = int.tryParse(value) ?? 3;
|
||||||
widget.onChanged(gameDTO);
|
widget.onChanged(gameDTO);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
|
||||||
showNotification(Colors.orange, kWhite,
|
|
||||||
'Cela doit être un chiffre', context, null);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_app/Components/geometry_input_container.dart';
|
import 'package:manager_app/Components/geometry_input_container.dart';
|
||||||
import 'package:manager_app/Components/dropDown_input_container_categories.dart';
|
import 'package:manager_app/Components/dropDown_input_container_categories.dart';
|
||||||
@ -13,9 +14,9 @@ import 'package:manager_api_new/api.dart';
|
|||||||
void showNewOrUpdateGeoPoint(MapDTO mapDTO, GeoPointDTO? inputGeoPointDTO,
|
void showNewOrUpdateGeoPoint(MapDTO mapDTO, GeoPointDTO? inputGeoPointDTO,
|
||||||
Function getResult, AppContext appContext, BuildContext context) {
|
Function getResult, AppContext appContext, BuildContext context) {
|
||||||
GeoPointDTO geoPointDTO = GeoPointDTO();
|
GeoPointDTO geoPointDTO = GeoPointDTO();
|
||||||
|
|
||||||
if (inputGeoPointDTO != null) {
|
if (inputGeoPointDTO != null) {
|
||||||
geoPointDTO = inputGeoPointDTO;
|
geoPointDTO =
|
||||||
|
GeoPointDTO.fromJson(jsonDecode(jsonEncode(inputGeoPointDTO)))!;
|
||||||
} else {
|
} else {
|
||||||
geoPointDTO.title = <TranslationDTO>[];
|
geoPointDTO.title = <TranslationDTO>[];
|
||||||
geoPointDTO.description = <TranslationDTO>[];
|
geoPointDTO.description = <TranslationDTO>[];
|
||||||
|
|||||||
@ -2,6 +2,10 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:manager_api_new/api.dart';
|
import 'package:manager_api_new/api.dart';
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
import 'package:manager_app/Screens/Configurations/Section/SubSection/Parcours/showNewOrUpdateGuidedPath.dart';
|
import 'package:manager_app/Screens/Configurations/Section/SubSection/Parcours/showNewOrUpdateGuidedPath.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:manager_app/app_context.dart';
|
||||||
|
import 'package:manager_app/Models/managerContext.dart';
|
||||||
|
import 'package:manager_app/Components/message_notification.dart';
|
||||||
|
|
||||||
class ParcoursConfig extends StatefulWidget {
|
class ParcoursConfig extends StatefulWidget {
|
||||||
final List<GuidedPathDTO> initialValue;
|
final List<GuidedPathDTO> initialValue;
|
||||||
@ -31,6 +35,24 @@ class _ParcoursConfigState extends State<ParcoursConfig> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
paths = List.from(widget.initialValue);
|
paths = List.from(widget.initialValue);
|
||||||
paths.sort((a, b) => (a.order ?? 0).compareTo(b.order ?? 0));
|
paths.sort((a, b) => (a.order ?? 0).compareTo(b.order ?? 0));
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => _loadFromApi());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadFromApi() async {
|
||||||
|
final appContext = Provider.of<AppContext>(context, listen: false);
|
||||||
|
final api = (appContext.getContext() as ManagerAppContext).clientAPI!.sectionMapApi!;
|
||||||
|
try {
|
||||||
|
// Backend already includes steps + quiz questions via .Include()
|
||||||
|
final fetchedPaths = await api.sectionMapGetAllGuidedPathFromSection(widget.parentId);
|
||||||
|
if (fetchedPaths == null || !mounted) return;
|
||||||
|
|
||||||
|
fetchedPaths.sort((a, b) => (a.order ?? 0).compareTo(b.order ?? 0));
|
||||||
|
setState(() {
|
||||||
|
paths = fetchedPaths;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
// Silently keep initial value on error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -48,18 +70,48 @@ class _ParcoursConfigState extends State<ParcoursConfig> {
|
|||||||
icon: Icon(Icons.add),
|
icon: Icon(Icons.add),
|
||||||
label: Text("Ajouter un parcours"),
|
label: Text("Ajouter un parcours"),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
final appContext =
|
||||||
|
Provider.of<AppContext>(context, listen: false);
|
||||||
showNewOrUpdateGuidedPath(
|
showNewOrUpdateGuidedPath(
|
||||||
context,
|
context,
|
||||||
null,
|
null,
|
||||||
widget.parentId,
|
widget.parentId,
|
||||||
widget.isEvent,
|
widget.isEvent,
|
||||||
widget.isEscapeMode,
|
widget.isEscapeMode,
|
||||||
(newPath) {
|
(newPath) async {
|
||||||
setState(() {
|
try {
|
||||||
newPath.order = paths.length;
|
newPath.order = paths.length;
|
||||||
paths.add(newPath);
|
newPath.instanceId = (appContext.getContext() as ManagerAppContext).instanceId;
|
||||||
|
if (widget.isEscapeMode) {
|
||||||
|
newPath.sectionGameId = widget.parentId;
|
||||||
|
} else if (widget.isEvent) {
|
||||||
|
newPath.sectionEventId = widget.parentId;
|
||||||
|
} else {
|
||||||
|
newPath.sectionMapId = widget.parentId;
|
||||||
|
}
|
||||||
|
final createdPath =
|
||||||
|
await (appContext.getContext() as ManagerAppContext)
|
||||||
|
.clientAPI!
|
||||||
|
.sectionMapApi!
|
||||||
|
.sectionMapCreateGuidedPath(
|
||||||
|
widget.parentId, newPath);
|
||||||
|
|
||||||
|
if (createdPath != null) {
|
||||||
|
setState(() {
|
||||||
|
paths.add(createdPath);
|
||||||
widget.onChanged(paths);
|
widget.onChanged(paths);
|
||||||
});
|
});
|
||||||
|
showNotification(kSuccess, kWhite,
|
||||||
|
'Parcours créé avec succès', context, null);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(
|
||||||
|
kError,
|
||||||
|
kWhite,
|
||||||
|
'Erreur lors de la création du parcours',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -77,16 +129,35 @@ class _ParcoursConfigState extends State<ParcoursConfig> {
|
|||||||
: ReorderableListView.builder(
|
: ReorderableListView.builder(
|
||||||
buildDefaultDragHandles: false,
|
buildDefaultDragHandles: false,
|
||||||
itemCount: paths.length,
|
itemCount: paths.length,
|
||||||
onReorder: (oldIndex, newIndex) {
|
onReorder: (oldIndex, newIndex) async {
|
||||||
setState(() {
|
|
||||||
if (newIndex > oldIndex) newIndex -= 1;
|
if (newIndex > oldIndex) newIndex -= 1;
|
||||||
final item = paths.removeAt(oldIndex);
|
final item = paths.removeAt(oldIndex);
|
||||||
paths.insert(newIndex, item);
|
paths.insert(newIndex, item);
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
paths[i].order = i;
|
paths[i].order = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setState(() {});
|
||||||
widget.onChanged(paths);
|
widget.onChanged(paths);
|
||||||
});
|
|
||||||
|
final appContext =
|
||||||
|
Provider.of<AppContext>(context, listen: false);
|
||||||
|
final api = (appContext.getContext() as ManagerAppContext)
|
||||||
|
.clientAPI!
|
||||||
|
.sectionMapApi!;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Update all affected paths orders
|
||||||
|
await Future.wait(
|
||||||
|
paths.map((p) => api.sectionMapUpdateGuidedPath(p)));
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(
|
||||||
|
kError,
|
||||||
|
kWhite,
|
||||||
|
'Erreur lors de la mise à jour de l\'ordre',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final path = paths[index];
|
final path = paths[index];
|
||||||
@ -112,24 +183,64 @@ class _ParcoursConfigState extends State<ParcoursConfig> {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit, color: kPrimaryColor),
|
icon: Icon(Icons.edit, color: kPrimaryColor),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
final appContext = Provider.of<AppContext>(
|
||||||
|
context,
|
||||||
|
listen: false);
|
||||||
showNewOrUpdateGuidedPath(
|
showNewOrUpdateGuidedPath(
|
||||||
context,
|
context,
|
||||||
path,
|
path,
|
||||||
widget.parentId,
|
widget.parentId,
|
||||||
widget.isEvent,
|
widget.isEvent,
|
||||||
widget.isEscapeMode,
|
widget.isEscapeMode,
|
||||||
(updatedPath) {
|
(updatedPath) async {
|
||||||
|
try {
|
||||||
|
final result =
|
||||||
|
await (appContext.getContext()
|
||||||
|
as ManagerAppContext)
|
||||||
|
.clientAPI!
|
||||||
|
.sectionMapApi!
|
||||||
|
.sectionMapUpdateGuidedPath(
|
||||||
|
updatedPath);
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
paths[index] = updatedPath;
|
paths[index] = result;
|
||||||
widget.onChanged(paths);
|
widget.onChanged(paths);
|
||||||
});
|
});
|
||||||
|
showNotification(
|
||||||
|
kSuccess,
|
||||||
|
kWhite,
|
||||||
|
'Parcours mis à jour avec succès',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(
|
||||||
|
kError,
|
||||||
|
kWhite,
|
||||||
|
'Erreur lors de la mise à jour du parcours',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete, color: kError),
|
icon: Icon(Icons.delete, color: kError),
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
|
final appContext = Provider.of<AppContext>(
|
||||||
|
context,
|
||||||
|
listen: false);
|
||||||
|
try {
|
||||||
|
if (path.id != null) {
|
||||||
|
await (appContext.getContext()
|
||||||
|
as ManagerAppContext)
|
||||||
|
.clientAPI!
|
||||||
|
.sectionMapApi!
|
||||||
|
.sectionMapDeleteGuidedPath(path.id!);
|
||||||
|
}
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
paths.removeAt(index);
|
paths.removeAt(index);
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
@ -137,6 +248,20 @@ class _ParcoursConfigState extends State<ParcoursConfig> {
|
|||||||
}
|
}
|
||||||
widget.onChanged(paths);
|
widget.onChanged(paths);
|
||||||
});
|
});
|
||||||
|
showNotification(
|
||||||
|
kSuccess,
|
||||||
|
kWhite,
|
||||||
|
'Parcours supprimé avec succès',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(
|
||||||
|
kError,
|
||||||
|
kWhite,
|
||||||
|
'Erreur lors de la suppression du parcours',
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ReorderableDragStartListener(
|
ReorderableDragStartListener(
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_api_new/api.dart';
|
import 'package:manager_api_new/api.dart';
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
@ -15,7 +16,7 @@ void showNewOrUpdateGuidedPath(
|
|||||||
Function(GuidedPathDTO) onSave,
|
Function(GuidedPathDTO) onSave,
|
||||||
) {
|
) {
|
||||||
GuidedPathDTO workingPath = path != null
|
GuidedPathDTO workingPath = path != null
|
||||||
? GuidedPathDTO.fromJson(path.toJson())!
|
? GuidedPathDTO.fromJson(jsonDecode(jsonEncode(path)))!
|
||||||
: GuidedPathDTO(
|
: GuidedPathDTO(
|
||||||
title: [],
|
title: [],
|
||||||
description: [],
|
description: [],
|
||||||
@ -193,8 +194,10 @@ void showNewOrUpdateGuidedPath(
|
|||||||
"Étape $index"
|
"Étape $index"
|
||||||
: "Étape $index",
|
: "Étape $index",
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: isEscapeMode
|
||||||
"${step.quizQuestions?.length ?? 0} question(s)"),
|
? Text(
|
||||||
|
"${step.quizQuestions?.length ?? 0} question(s)")
|
||||||
|
: null,
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@ -254,6 +257,16 @@ void showNewOrUpdateGuidedPath(
|
|||||||
child: RoundedButton(
|
child: RoundedButton(
|
||||||
text: "Sauvegarder",
|
text: "Sauvegarder",
|
||||||
press: () {
|
press: () {
|
||||||
|
// Initialise les booleans null → false
|
||||||
|
workingPath.isLinear ??= false;
|
||||||
|
workingPath.requireSuccessToAdvance ??= false;
|
||||||
|
workingPath.hideNextStepsUntilComplete ??= false;
|
||||||
|
// Initialise les booleans nuls dans chaque étape
|
||||||
|
for (final s in workingPath.steps ?? []) {
|
||||||
|
s.isHiddenInitially ??= false;
|
||||||
|
s.isStepTimer ??= false;
|
||||||
|
s.isStepLocked ??= false;
|
||||||
|
}
|
||||||
onSave(workingPath);
|
onSave(workingPath);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_api_new/api.dart';
|
import 'package:manager_api_new/api.dart';
|
||||||
import 'package:manager_app/Components/confirmation_dialog.dart';
|
import 'package:manager_app/Components/confirmation_dialog.dart';
|
||||||
@ -14,8 +15,9 @@ void showNewOrUpdateGuidedStep(
|
|||||||
bool isEscapeMode,
|
bool isEscapeMode,
|
||||||
Function(GuidedStepDTO) onSave,
|
Function(GuidedStepDTO) onSave,
|
||||||
) {
|
) {
|
||||||
|
// Use jsonEncode/jsonDecode for a robust deep copy that handles nested DTOs correctly
|
||||||
GuidedStepDTO workingStep = step != null
|
GuidedStepDTO workingStep = step != null
|
||||||
? GuidedStepDTO.fromJson(step.toJson())!
|
? GuidedStepDTO.fromJson(jsonDecode(jsonEncode(step)))!
|
||||||
: GuidedStepDTO(
|
: GuidedStepDTO(
|
||||||
title: [],
|
title: [],
|
||||||
description: [],
|
description: [],
|
||||||
@ -23,17 +25,6 @@ void showNewOrUpdateGuidedStep(
|
|||||||
order: 0,
|
order: 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Convert EventAddressDTOGeometry to GeometryDTO via JSON for the geometry picker
|
|
||||||
GeometryDTO? _toGeometryDTO(EventAddressDTOGeometry? geo) {
|
|
||||||
if (geo == null) return null;
|
|
||||||
return GeometryDTO.fromJson(geo.toJson());
|
|
||||||
}
|
|
||||||
|
|
||||||
EventAddressDTOGeometry? _toEventGeometry(GeometryDTO? geo) {
|
|
||||||
if (geo == null) return null;
|
|
||||||
return EventAddressDTOGeometry.fromJson(geo.toJson());
|
|
||||||
}
|
|
||||||
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
@ -100,16 +91,14 @@ void showNewOrUpdateGuidedStep(
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
Divider(height: 24),
|
Divider(height: 24),
|
||||||
// Géométrie — conversion JSON entre les deux types GeoDTO
|
// Géométrie — Directement avec GeometryDTO
|
||||||
GeometryInputContainer(
|
GeometryInputContainer(
|
||||||
label: "Emplacement de l'étape :",
|
label: "Emplacement de l'étape :",
|
||||||
initialGeometry:
|
initialGeometry: workingStep.geometry,
|
||||||
_toGeometryDTO(workingStep.geometry),
|
|
||||||
initialColor: null,
|
initialColor: null,
|
||||||
onSave: (geometry, color) {
|
onSave: (geometry, color) {
|
||||||
setState(() {
|
setState(() {
|
||||||
workingStep.geometry =
|
workingStep.geometry = geometry;
|
||||||
_toEventGeometry(geometry);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -244,6 +233,11 @@ void showNewOrUpdateGuidedStep(
|
|||||||
child: RoundedButton(
|
child: RoundedButton(
|
||||||
text: "Sauvegarder",
|
text: "Sauvegarder",
|
||||||
press: () {
|
press: () {
|
||||||
|
// Initialise les booleans null → false
|
||||||
|
// pour éviter l'erreur backend "Error converting null to Boolean"
|
||||||
|
workingStep.isHiddenInitially ??= false;
|
||||||
|
workingStep.isStepTimer ??= false;
|
||||||
|
workingStep.isStepLocked ??= false;
|
||||||
onSave(workingStep);
|
onSave(workingStep);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_api_new/api.dart';
|
import 'package:manager_api_new/api.dart';
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
@ -34,30 +35,24 @@ void showNewOrUpdateQuizQuestion(
|
|||||||
bool isEscapeMode,
|
bool isEscapeMode,
|
||||||
Function(QuizQuestion) onSave,
|
Function(QuizQuestion) onSave,
|
||||||
) {
|
) {
|
||||||
// QuizQuestion.label is List<TranslationAndResourceDTO> — convert for display
|
// Use JSON cloning for a robust deep copy
|
||||||
|
QuizQuestion? clonedQuestion = question != null
|
||||||
|
? QuizQuestion.fromJson(jsonDecode(jsonEncode(question)))
|
||||||
|
: null;
|
||||||
|
|
||||||
List<TranslationDTO> workingLabel = _toTranslationList(
|
List<TranslationDTO> workingLabel = _toTranslationList(
|
||||||
question != null && question.label.isNotEmpty
|
clonedQuestion != null && clonedQuestion.label.isNotEmpty
|
||||||
? question.label
|
? clonedQuestion.label
|
||||||
: [TranslationAndResourceDTO(language: 'FR', value: '')]);
|
: [TranslationAndResourceDTO(language: 'FR', value: '')]);
|
||||||
|
|
||||||
List<ResponseDTO> workingResponses =
|
List<ResponseDTO> workingResponses = clonedQuestion?.responses ?? [];
|
||||||
question != null && question.responses.isNotEmpty
|
|
||||||
? question.responses
|
|
||||||
.map((r) => ResponseDTO.fromJson(r.toJson())!)
|
|
||||||
.toList()
|
|
||||||
: [];
|
|
||||||
|
|
||||||
QuizQuestion workingQuestion = QuizQuestion(
|
QuizQuestion workingQuestion = clonedQuestion ??
|
||||||
id: question?.id ?? 0,
|
QuizQuestion(
|
||||||
label: _fromTranslationList(workingLabel), // kept in sync below
|
id: 0,
|
||||||
|
label: _fromTranslationList(workingLabel),
|
||||||
responses: workingResponses,
|
responses: workingResponses,
|
||||||
validationQuestionType:
|
validationQuestionType: QuestionType.number0,
|
||||||
question?.validationQuestionType ?? QuestionType.number0,
|
|
||||||
puzzleImageId: question?.puzzleImageId,
|
|
||||||
puzzleImage: question?.puzzleImage,
|
|
||||||
puzzleRows: question?.puzzleRows,
|
|
||||||
puzzleCols: question?.puzzleCols,
|
|
||||||
isSlidingPuzzle: question?.isSlidingPuzzle,
|
|
||||||
order: question?.order ?? 0,
|
order: question?.order ?? 0,
|
||||||
guidedStepId: question?.guidedStepId ?? stepId,
|
guidedStepId: question?.guidedStepId ?? stepId,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -35,9 +35,14 @@ class Client {
|
|||||||
SectionQuizApi? _sectionQuizApi;
|
SectionQuizApi? _sectionQuizApi;
|
||||||
SectionQuizApi? get sectionQuizApi => _sectionQuizApi;
|
SectionQuizApi? get sectionQuizApi => _sectionQuizApi;
|
||||||
|
|
||||||
|
SectionAgendaApi? _sectionAgendaApi;
|
||||||
|
SectionAgendaApi? get sectionAgendaApi => _sectionAgendaApi;
|
||||||
|
|
||||||
|
SectionEventApi? _sectionEventApi;
|
||||||
|
SectionEventApi? get sectionEventApi => _sectionEventApi;
|
||||||
|
|
||||||
Client(String path) {
|
Client(String path) {
|
||||||
_apiClient = ApiClient(
|
_apiClient = ApiClient(basePath: path);
|
||||||
basePath: path);
|
|
||||||
//basePath: "https://192.168.31.140");
|
//basePath: "https://192.168.31.140");
|
||||||
//basePath: "https://localhost:44339");
|
//basePath: "https://localhost:44339");
|
||||||
_apiClient!.addDefaultHeader("Access-Control_Allow_Origin", "*");
|
_apiClient!.addDefaultHeader("Access-Control_Allow_Origin", "*");
|
||||||
@ -51,5 +56,7 @@ class Client {
|
|||||||
_deviceApi = DeviceApi(_apiClient);
|
_deviceApi = DeviceApi(_apiClient);
|
||||||
_sectionMapApi = SectionMapApi(_apiClient);
|
_sectionMapApi = SectionMapApi(_apiClient);
|
||||||
_sectionQuizApi = SectionQuizApi(_apiClient);
|
_sectionQuizApi = SectionQuizApi(_apiClient);
|
||||||
|
_sectionAgendaApi = SectionAgendaApi(_apiClient);
|
||||||
|
_sectionEventApi = SectionEventApi(_apiClient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -23,15 +23,15 @@ class GameTypes {
|
|||||||
|
|
||||||
int toJson() => value;
|
int toJson() => value;
|
||||||
|
|
||||||
static const number0 = GameTypes._(0);
|
static const Puzzle = GameTypes._(0);
|
||||||
static const number1 = GameTypes._(1);
|
static const SlidingPuzzle = GameTypes._(1);
|
||||||
static const number2 = GameTypes._(2);
|
static const Escape = GameTypes._(2);
|
||||||
|
|
||||||
/// List of all possible values in this [enum][GameTypes].
|
/// List of all possible values in this [enum][GameTypes].
|
||||||
static const values = <GameTypes>[
|
static const values = <GameTypes>[
|
||||||
number0,
|
Puzzle,
|
||||||
number1,
|
SlidingPuzzle,
|
||||||
number2,
|
Escape,
|
||||||
];
|
];
|
||||||
|
|
||||||
static GameTypes? fromJson(dynamic value) =>
|
static GameTypes? fromJson(dynamic value) =>
|
||||||
@ -74,18 +74,33 @@ class GameTypesTypeTransformer {
|
|||||||
/// and users are still using an old app with the old code.
|
/// and users are still using an old app with the old code.
|
||||||
GameTypes? decode(dynamic data, {bool allowNull = true}) {
|
GameTypes? decode(dynamic data, {bool allowNull = true}) {
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
switch (data) {
|
if (data.runtimeType == String) {
|
||||||
case 0:
|
switch (data.toString()) {
|
||||||
return GameTypes.number0;
|
case r'Puzzle':
|
||||||
case 1:
|
return GameTypes.Puzzle;
|
||||||
return GameTypes.number1;
|
case r'SlidingPuzzle':
|
||||||
case 2:
|
return GameTypes.SlidingPuzzle;
|
||||||
return GameTypes.number2;
|
case r'Escape':
|
||||||
|
return GameTypes.Escape;
|
||||||
default:
|
default:
|
||||||
if (!allowNull) {
|
if (!allowNull) {
|
||||||
throw ArgumentError('Unknown enum value to decode: $data');
|
throw ArgumentError('Unknown enum value to decode: $data');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (data is int) {
|
||||||
|
switch (data) {
|
||||||
|
case 0:
|
||||||
|
return GameTypes.Puzzle;
|
||||||
|
case 1:
|
||||||
|
return GameTypes.SlidingPuzzle;
|
||||||
|
case 2:
|
||||||
|
return GameTypes.Escape;
|
||||||
|
default:
|
||||||
|
if (!allowNull) {
|
||||||
|
throw ArgumentError('Unknown enum value to decode: $data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user