From f43d23fe44829560d50fb979f3349fde23577e75 Mon Sep 17 00:00:00 2001 From: Fransolet Thomas Date: Thu, 2 Mar 2023 17:52:35 +0100 Subject: [PATCH] Add orientation logic for quizz (and tablet then) + clean code + update meterToBeacon + store beaconSection locally --- lib/Helpers/DatabaseHelper.dart | 251 +++++--- lib/Helpers/modelsHelper.dart | 12 + lib/Models/beaconSection.dart | 2 +- lib/Screens/Home/home.dart | 25 +- lib/Screens/Quizz/questions_list.dart | 435 ++++++------- lib/Screens/Quizz/quizz_page.dart | 844 ++++++++------------------ lib/Screens/Visit/visit.dart | 2 +- 7 files changed, 664 insertions(+), 907 deletions(-) diff --git a/lib/Helpers/DatabaseHelper.dart b/lib/Helpers/DatabaseHelper.dart index 7ae726b..c239ffe 100644 --- a/lib/Helpers/DatabaseHelper.dart +++ b/lib/Helpers/DatabaseHelper.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Models/articleRead.dart'; +import 'package:mymuseum_visitapp/Models/beaconSection.dart'; import 'package:mymuseum_visitapp/Models/resourceModel.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:path/path.dart'; @@ -12,47 +13,54 @@ enum DatabaseTableType { configurations, sections, resources, - articleRead + articleRead, + beaconSection } class DatabaseHelper { - static final _databaseName = "visit_database.db"; - static final _databaseVersion = 1; + static const _databaseName = "visit_database.db"; + static const _databaseVersion = 1; - static final mainTable = 'visitAppContext'; - static final columnLanguage = 'language'; + static const mainTable = 'visitAppContext'; + static const columnLanguage = 'language'; - static final columnLabel = 'label'; - static final columnId = 'id'; - static final columnInstanceId = 'instanceId'; - static final columnData = 'data'; - static final columnType = 'type'; - static final columnDateCreation = 'dateCreation'; - static final columnIsMobile = 'isMobile'; - static final columnIsTablet = 'isTablet'; - static final columnIsOffline = 'isOffline'; + static const columnLabel = 'label'; + static const columnId = 'id'; + static const columnInstanceId = 'instanceId'; + static const columnData = 'data'; + static const columnType = 'type'; + static const columnDateCreation = 'dateCreation'; + static const columnIsMobile = 'isMobile'; + static const columnIsTablet = 'isTablet'; + static const columnIsOffline = 'isOffline'; - static final configurationsTable = 'configurations'; - static final columnLanguages = 'languages'; - static final columnPrimaryColor = 'primaryColor'; - static final columnSecondaryColor = 'secondaryColor'; + static const configurationsTable = 'configurations'; + static const columnLanguages = 'languages'; + static const columnPrimaryColor = 'primaryColor'; + static const columnSecondaryColor = 'secondaryColor'; - static final sectionsTable = 'sections'; - static final columnTitle = 'title'; - static final columnDescription = 'description'; - static final columnImageId = 'imageId'; - static final columnImageSource = 'imageSource'; - static final columnConfigurationId = 'configurationId'; - static final columnIsSubSection = 'isSubSection'; - static final columnParentId = 'parentId'; - static final columnOrderOfElement = 'orderOfElement'; + static const sectionsTable = 'sections'; + static const columnTitle = 'title'; + static const columnDescription = 'description'; + static const columnImageId = 'imageId'; + static const columnImageSource = 'imageSource'; + static const columnConfigurationId = 'configurationId'; + static const columnIsSubSection = 'isSubSection'; + static const columnParentId = 'parentId'; + static const columnOrderOfElement = 'orderOfElement'; - static final resourcesTable = 'resources'; + static const resourcesTable = 'resources'; - static final columnSource = 'source'; + static const columnSource = 'source'; - static final articleReadTable = 'articleRead'; - static final columnLastTimeOpen = 'readTime'; + static const articleReadTable = 'articleRead'; + static const columnLastTimeOpen = 'readTime'; + + static const beaconSectionTable = 'beaconSection'; + static const columnMinorBeaconId = 'minorBeaconId'; + static const columnOrderInConfig = 'orderInConfig'; + static const columnSectionId = 'sectionId'; + static const columnSectionType = 'sectionType'; DatabaseHelper._privateConstructor(); static final DatabaseHelper instance = DatabaseHelper._privateConstructor(); @@ -69,66 +77,12 @@ class DatabaseHelper { // SQL code to create the database table Future _onCreate(Database db, int version) async { - await db.execute(''' - CREATE TABLE $mainTable ( - $columnId TEXT NOT NULL PRIMARY KEY, - $columnLanguage TEXT NOT NULL, - $columnInstanceId TEXT NOT NULL - ) - '''); - - await db.execute(''' - CREATE TABLE $configurationsTable ( - $columnId TEXT NOT NULL PRIMARY KEY, - $columnInstanceId TEXT NOT NULL, - $columnLabel TEXT NOT NULL, - $columnTitle TEXT NOT NULL, - $columnImageId TEXT, - $columnImageSource TEXT, - $columnLanguages TEXT NOT NULL, - $columnDateCreation TEXT NOT NULL, - $columnPrimaryColor TEXT, - $columnSecondaryColor TEXT, - $columnIsMobile BOOLEAN NOT NULL CHECK ($columnIsMobile IN (0,1)), - $columnIsTablet BOOLEAN NOT NULL CHECK ($columnIsTablet IN (0,1)), - $columnIsOffline BOOLEAN NOT NULL CHECK ($columnIsOffline IN (0,1)) - ) - '''); - - await db.execute(''' - CREATE TABLE $sectionsTable ( - $columnId TEXT NOT NULL PRIMARY KEY, - $columnInstanceId TEXT NOT NULL, - $columnLabel TEXT NOT NULL, - $columnTitle TEXT NOT NULL, - $columnDescription TEXT, - $columnImageId TEXT, - $columnImageSource TEXT, - $columnConfigurationId TEXT NOT NULL, - $columnIsSubSection BOOLEAN NOT NULL CHECK ($columnIsSubSection IN (0,1)), - $columnParentId TEXT, - $columnType INT NOT NULL, - $columnData TEXT NOT NULL, - $columnDateCreation TEXT NOT NULL, - $columnOrderOfElement TEXT NOT NULL - ) - '''); - - await db.execute(''' - CREATE TABLE $resourcesTable ( - $columnId TEXT NOT NULL PRIMARY KEY, - $columnData TEXT NOT NULL, - $columnSource TEXT NOT NULL, - $columnType INT NOT NULL - ) - '''); - - await db.execute(''' - CREATE TABLE $articleReadTable ( - $columnId TEXT NOT NULL PRIMARY KEY, - $columnLastTimeOpen INT NOT NULL - ) - '''); + await createTable(db, DatabaseTableType.main); + await createTable(db, DatabaseTableType.configurations); + await createTable(db, DatabaseTableType.sections); + await createTable(db, DatabaseTableType.resources); + await createTable(db, DatabaseTableType.articleRead); + await createTable(db, DatabaseTableType.beaconSection); } Future insert(DatabaseTableType type, Map info) async { @@ -141,6 +95,14 @@ class DatabaseHelper { } //var test = await instance.getData(type); + // Test if table exist + var isExistResult = await isExist(type); + if(!isExistResult) { + print("TABLE DOESNT EXIST"); + await createTable(db, type); + } + + var test = await DatabaseHelper.instance.queryWithColumnId(type, info[columnId].toString()); if((type == DatabaseTableType.main && test.isNotEmpty) || (type != DatabaseTableType.main && test.isNotEmpty)) { //test!.where((t) => info[columnId] == t.id).isNotEmpty @@ -181,6 +143,97 @@ class DatabaseHelper { ); } + Future createTable(Database db, DatabaseTableType type) async { + print("CREATE TABLE $type"); + switch(type) { + case DatabaseTableType.main : + db.execute(''' + CREATE TABLE $mainTable ( + $columnId TEXT NOT NULL PRIMARY KEY, + $columnLanguage TEXT NOT NULL, + $columnInstanceId TEXT NOT NULL + ) + '''); + break; + case DatabaseTableType.configurations : + db.execute(''' + CREATE TABLE $configurationsTable ( + $columnId TEXT NOT NULL PRIMARY KEY, + $columnInstanceId TEXT NOT NULL, + $columnLabel TEXT NOT NULL, + $columnTitle TEXT NOT NULL, + $columnImageId TEXT, + $columnImageSource TEXT, + $columnLanguages TEXT NOT NULL, + $columnDateCreation TEXT NOT NULL, + $columnPrimaryColor TEXT, + $columnSecondaryColor TEXT, + $columnIsMobile BOOLEAN NOT NULL CHECK ($columnIsMobile IN (0,1)), + $columnIsTablet BOOLEAN NOT NULL CHECK ($columnIsTablet IN (0,1)), + $columnIsOffline BOOLEAN NOT NULL CHECK ($columnIsOffline IN (0,1)) + ) + '''); + break; + case DatabaseTableType.sections : + db.execute(''' + CREATE TABLE $sectionsTable ( + $columnId TEXT NOT NULL PRIMARY KEY, + $columnInstanceId TEXT NOT NULL, + $columnLabel TEXT NOT NULL, + $columnTitle TEXT NOT NULL, + $columnDescription TEXT, + $columnImageId TEXT, + $columnImageSource TEXT, + $columnConfigurationId TEXT NOT NULL, + $columnIsSubSection BOOLEAN NOT NULL CHECK ($columnIsSubSection IN (0,1)), + $columnParentId TEXT, + $columnType INT NOT NULL, + $columnData TEXT NOT NULL, + $columnDateCreation TEXT NOT NULL, + $columnOrderOfElement TEXT NOT NULL + ) + '''); + break; + case DatabaseTableType.resources: + db.execute(''' + CREATE TABLE $resourcesTable ( + $columnId TEXT NOT NULL PRIMARY KEY, + $columnData TEXT NOT NULL, + $columnSource TEXT NOT NULL, + $columnType INT NOT NULL + ) + '''); + break; + case DatabaseTableType.articleRead: + db.execute(''' + CREATE TABLE $articleReadTable ( + $columnId TEXT NOT NULL PRIMARY KEY, + $columnLastTimeOpen INT NOT NULL + ) + '''); + break; + case DatabaseTableType.beaconSection: + db.execute(''' + CREATE TABLE $beaconSectionTable ( + $columnId TEXT NOT NULL PRIMARY KEY, + $columnMinorBeaconId INT NOT NULL, + $columnOrderInConfig INT NOT NULL, + $columnConfigurationId TEXT NOT NULL, + $columnSectionId TEXT NOT NULL, + $columnSectionType INT NOT NULL + ) + '''); + break; + } + } + + Future isExist(DatabaseTableType type) async { + Database db = await instance.database; + var nameOfTable = _getTableName(type); + var test = await db.rawQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='$nameOfTable'"); + return test.isNotEmpty; + } + Future>> queryAllRows(DatabaseTableType type) async { Database db = await instance.database; var res = await db.query(_getTableName(type), orderBy: "$columnId DESC"); @@ -249,6 +302,10 @@ class DatabaseHelper { dataToReturn.add(getArticleReadFromDB(element)); //print("DB - dataToReturn --- $test --> "); break; + case DatabaseTableType.beaconSection: + dataToReturn.add(getBeaconSectionFromDB(element)); + //print("DB - dataToReturn --- $test --> "); + break; } }); }).catchError((error) { @@ -269,6 +326,8 @@ class DatabaseHelper { return resourcesTable; case DatabaseTableType.articleRead: return articleReadTable; + case DatabaseTableType.beaconSection: + return beaconSectionTable; } } @@ -325,4 +384,14 @@ class DatabaseHelper { readTime: element["readTime"] ); } + + BeaconSection getBeaconSectionFromDB(dynamic element) { + return BeaconSection( + minorBeaconId: element["minorBeaconId"], + orderInConfig: element["orderInConfig"], + configurationId: element["configurationId"], + sectionId: element["sectionId"], + sectionType: SectionType.values[element["sectionType"]] + ); + } } \ No newline at end of file diff --git a/lib/Helpers/modelsHelper.dart b/lib/Helpers/modelsHelper.dart index 1281fe0..28e96b3 100644 --- a/lib/Helpers/modelsHelper.dart +++ b/lib/Helpers/modelsHelper.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:manager_api/api.dart'; +import 'package:mymuseum_visitapp/Models/beaconSection.dart'; class ModelsHelper { static Map configurationToMap(ConfigurationDTO configuration) { @@ -39,4 +40,15 @@ class ModelsHelper { 'orderOfElement': section.order, }; } + + static Map beaconSectionToMap(BeaconSection beaconSection) { + return { + 'Id': '${beaconSection.minorBeaconId}-${beaconSection.sectionId}', + 'minorBeaconId': beaconSection.minorBeaconId, + 'orderInConfig': beaconSection.orderInConfig, + 'configurationId': beaconSection.configurationId, + 'sectionId': beaconSection.sectionId, + 'sectionType': beaconSection.sectionType!.value, + }; + } } \ No newline at end of file diff --git a/lib/Models/beaconSection.dart b/lib/Models/beaconSection.dart index 65ac317..aac1daa 100644 --- a/lib/Models/beaconSection.dart +++ b/lib/Models/beaconSection.dart @@ -23,7 +23,7 @@ class BeaconSection { /*'rssi': rssi, 'accuracy': accuracy, 'proximityUUID': proximityUUID,*/ - 'found': found + //'found': found }; } diff --git a/lib/Screens/Home/home.dart b/lib/Screens/Home/home.dart index 1c45189..1e5fd49 100644 --- a/lib/Screens/Home/home.dart +++ b/lib/Screens/Home/home.dart @@ -8,6 +8,7 @@ import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; import 'package:mymuseum_visitapp/Components/Loading.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; +import 'package:mymuseum_visitapp/Helpers/modelsHelper.dart'; import 'package:mymuseum_visitapp/Helpers/networkCheck.dart'; import 'package:mymuseum_visitapp/Helpers/requirement_state_controller.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; @@ -128,7 +129,13 @@ class _HomePageState extends State with WidgetsBindingObserver { SnackBar(content: Text(TranslationHelper.getFromLocale("noInternet", appContext.getContext())), backgroundColor: kBlue2), ); - // TODO HANDLE BEACON IN LOCAL (CREATE TABLE) + // GET BEACONS FROM LOCAL + List beaconSections = List.from(await DatabaseHelper.instance.getData(DatabaseTableType.beaconSection)); + print("GOT beaconSection from LOCAL"); + print(beaconSections); + + visitAppContext.beaconSections = beaconSections; + //appContext.setContext(visitAppContext); return configurations; } @@ -138,9 +145,23 @@ class _HomePageState extends State with WidgetsBindingObserver { if(sections != null && sections.isNotEmpty) { List beaconSections = sections.map((e) => BeaconSection(minorBeaconId: e.beaconId, orderInConfig: e.order, configurationId: e.configurationId, sectionId: e.id, sectionType: e.type)).toList(); visitAppContext.beaconSections = beaconSections; + + try { + // Clear all before + await DatabaseHelper.instance.clearTable(DatabaseTableType.beaconSection); + // Store it locally for offline mode + for(var beaconSection in beaconSections) { + await DatabaseHelper.instance.insert(DatabaseTableType.beaconSection, ModelsHelper.beaconSectionToMap(beaconSection)); + } + print("STORE beaconSection DONE"); + } catch(e) { + print("Issue during beaconSection insertion"); + print(e); + } + print("Got some Beacons for you"); print(beaconSections); - appContext.setContext(visitAppContext); // STORE IT, TODO Store it locally + appContext.setContext(visitAppContext); } } diff --git a/lib/Screens/Quizz/questions_list.dart b/lib/Screens/Quizz/questions_list.dart index 230fb2b..1fae298 100644 --- a/lib/Screens/Quizz/questions_list.dart +++ b/lib/Screens/Quizz/questions_list.dart @@ -13,7 +13,8 @@ class QuestionsListWidget extends StatefulWidget { List? questionsSubDTO; bool isShowResponse = false; final Function onShowResponse; - QuestionsListWidget({Key? key, this.questionsSubDTO, required this.isShowResponse, required this.onShowResponse}) : super(key: key); + Orientation orientation; + QuestionsListWidget({Key? key, this.questionsSubDTO, required this.isShowResponse, required this.onShowResponse, required this.orientation}) : super(key: key); @override _QuestionsListWidget createState() => _QuestionsListWidget(); @@ -47,231 +48,235 @@ class _QuestionsListWidget extends State { //Size size = Size(sizeAll.width * 0.65, kIsWeb ? sizeAll.height * 0.5 : sizeAll.height * 0.32); final appContext = Provider.of(context); - return SizedBox( - height: widget.isShowResponse ? MediaQuery.of(context).size.height * 0.825 : MediaQuery.of(context).size.height, - width: double.infinity, - //color: Colors.orange, - child: Stack( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: widget.isShowResponse ? MainAxisAlignment.start : MainAxisAlignment.start, + /*return OrientationBuilder( + builder: (context, orientation) {*/ + return SizedBox( + height: widget.isShowResponse ? widget.orientation == Orientation.portrait ? MediaQuery.of(context).size.height * 0.825 : MediaQuery.of(context).size.height * 0.625 : MediaQuery.of(context).size.height, + width: double.infinity, + //color: Colors.orange, + child: Stack( children: [ - if(_questionsSubDTO.isNotEmpty) - CarouselSlider( - carouselController: sliderController, - options: CarouselOptions( - onPageChanged: (int index, CarouselPageChangedReason reason) { - setState(() { - currentIndex = index + 1; - }); - }, - height: widget.isShowResponse ? MediaQuery.of(context).size.height * 0.79 : MediaQuery.of(context).size.height * 0.85, - enlargeCenterPage: true, - scrollPhysics: const NeverScrollableScrollPhysics(), - reverse: false, - ), - items: _questionsSubDTO.map((i) { - return Builder( - builder: (BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 7.5, right: 7.5, bottom: 10.0, top: 8.0), - child: Container( - width: MediaQuery.of(context).size.width, - // height: widget.isShowResponse ? MediaQuery.of(context).size.height *0.55 : MediaQuery.of(context).size.height, - margin: const EdgeInsets.symmetric(horizontal: 1.5), - decoration: BoxDecoration( - //color: Colors.orange, //kBackgroundLight - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(20.0), - image: i.source_ != null ? DecorationImage( - fit: BoxFit.cover, - opacity: 0.35, - image: NetworkImage( - i.source_!, + Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: widget.isShowResponse ? MainAxisAlignment.start : MainAxisAlignment.start, + children: [ + if(_questionsSubDTO.isNotEmpty) + CarouselSlider( + carouselController: sliderController, + options: CarouselOptions( + onPageChanged: (int index, CarouselPageChangedReason reason) { + setState(() { + currentIndex = index + 1; + }); + }, + height: widget.isShowResponse ? widget.orientation == Orientation.portrait ? MediaQuery.of(context).size.height * 0.79 : MediaQuery.of(context).size.height * 0.6 : MediaQuery.of(context).size.height * 0.78, + enlargeCenterPage: true, + scrollPhysics: const NeverScrollableScrollPhysics(), + reverse: false, + ), + items: _questionsSubDTO.map((i) { + return Builder( + builder: (BuildContext context) { + return Padding( + padding: const EdgeInsets.only(left: 7.5, right: 7.5, bottom: 10.0, top: 8.0), + child: Container( + width: MediaQuery.of(context).size.width, + // height: widget.isShowResponse ? MediaQuery.of(context).size.height *0.55 : MediaQuery.of(context).size.height, + margin: const EdgeInsets.symmetric(horizontal: 1.5), + decoration: BoxDecoration( + //color: Colors.orange, //kBackgroundLight + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(20.0), + image: i.source_ != null ? DecorationImage( + fit: BoxFit.cover, + opacity: 0.35, + image: NetworkImage( + i.source_!, + ), + ): null, + boxShadow: const [ + BoxShadow( + color: kBackgroundSecondGrey, + spreadRadius: 0.5, + blurRadius: 5, + offset: Offset(0, 1.5), // changes position of shadow + ), + ], ), - ): null, - boxShadow: const [ - BoxShadow( - color: kBackgroundSecondGrey, - spreadRadius: 0.5, - blurRadius: 5, - offset: Offset(0, 1.5), // changes position of shadow - ), - ], - ), - child: Column( - //crossAxisAlignment: CrossAxisAlignment.center, - //mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Container( - //color: Colors.red, - //width: MediaQuery.of(context).size.width *0.65, - height: MediaQuery.of(context).size.height *0.25, - child: Stack( - children: [ - Center( - child: Container( - decoration: BoxDecoration( - color: kBackgroundLight, //kBackgroundLight - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(10.0), - boxShadow: const [ - BoxShadow( - color: kBackgroundSecondGrey, - spreadRadius: 0.3, - blurRadius: 4, - offset: Offset(0, 2), // changes position of shadow + child: Column( + //crossAxisAlignment: CrossAxisAlignment.center, + //mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Container( + //color: Colors.red, + //width: MediaQuery.of(context).size.width *0.65, + height: MediaQuery.of(context).size.height *0.25, + child: Stack( + children: [ + Center( + child: Container( + decoration: BoxDecoration( + color: kBackgroundLight, //kBackgroundLight + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(10.0), + boxShadow: const [ + BoxShadow( + color: kBackgroundSecondGrey, + spreadRadius: 0.3, + blurRadius: 4, + offset: Offset(0, 2), // changes position of shadow + ), + ], ), - ], - ), - width: MediaQuery.of(context).size.width *0.7, - height: MediaQuery.of(context).size.height *0.2, - child: Center( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(2.5), - child: Text(TranslationHelper.get(i.label, appContext.getContext() as VisitAppContext), textAlign: TextAlign.center, style: const TextStyle(fontSize: kDescriptionSize)), - ), - ), - ), - ) - ), - ] - ), - ), - /*SizedBox( - height: MediaQuery.of(context).size.height * 0.01, - ),*/ - Expanded( - child: Padding( - padding: const EdgeInsets.all(5.0), - child: SizedBox( - //height: MediaQuery.of(context).size.height * 0.75, - width: MediaQuery.of(context).size.width * 0.72, - //color: Colors.green, - child: Padding( - padding: const EdgeInsets.all(10.0), - child: GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 1, // TODO HERE IS TABLET - mainAxisExtent: widget.isShowResponse ? 70 : 75, // TODO depends on percentage - mainAxisSpacing: widget.isShowResponse ? 35 : 42.5, // TODO depends on percentage - crossAxisSpacing: widget.isShowResponse ? 0 : 0, // TODO depends on percentage - ), - itemCount: i.responsesSubDTO!.length, - itemBuilder: (BuildContext ctx, index) { - return InkWell( - onTap: () { - if(!widget.isShowResponse) { - setState(() { - i.chosen = index; - if(currentIndex == _questionsSubDTO.length && i.chosen == index) - { - widget.onShowResponse(); - //showResult = true; - //_controllerCenter!.play(); // TODO Maybe show only confetti on super score .. - } else { - sliderController!.nextPage(duration: const Duration(milliseconds: 650), curve: Curves.fastOutSlowIn); - } - }); - } - }, - child: Padding( - padding: const EdgeInsets.all(2.5), - child: Container( - alignment: Alignment.center, - child: Text(TranslationHelper.get(i.responsesSubDTO![index].label, appContext.getContext() as VisitAppContext), textAlign: TextAlign.center, style: TextStyle(fontSize: kDescriptionSize, color: i.chosen == index ? Colors.white : Colors.black)), - decoration: BoxDecoration( - color: !widget.isShowResponse ? i.chosen == index ? kTestSecondColor : kBackgroundLight : i.responsesSubDTO![index].isGood! ? kGreen : i.chosen == index ? kTextRed : kBackgroundLight, - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(10.0), - boxShadow: const [ - BoxShadow( - color: kBackgroundSecondGrey, - spreadRadius: 0.3, - blurRadius: 4, - offset: Offset(0, 2), // changes position of shadow - ), - ], + width: MediaQuery.of(context).size.width *0.7, + height: MediaQuery.of(context).size.height *0.2, + child: Center( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(2.5), + child: Text(TranslationHelper.get(i.label, appContext.getContext() as VisitAppContext), textAlign: TextAlign.center, style: const TextStyle(fontSize: kDescriptionSize)), + ), ), ), - ), - ); - }), + ) + ), + ] ), ), - ), - ), - ], - ) - ), + /*SizedBox( + height: MediaQuery.of(context).size.height * 0.01, + ),*/ + Expanded( + child: Padding( + padding: const EdgeInsets.all(5.0), + child: SizedBox( + //height: MediaQuery.of(context).size.height * 0.75, + width: MediaQuery.of(context).size.width * 0.72, + //color: Colors.green, + child: Padding( + padding: const EdgeInsets.all(10.0), + child: GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: widget.orientation == Orientation.portrait ? 1 : 2, // TODO HERE IS TABLET + mainAxisExtent: widget.isShowResponse ? widget.orientation == Orientation.portrait ? 70 : 50 : 65, // TODO depends on percentage + mainAxisSpacing: widget.isShowResponse ? widget.orientation == Orientation.portrait ? 35 : 10 : 42.5, // TODO depends on percentage + crossAxisSpacing: widget.isShowResponse ? 0 : 0, // TODO depends on percentage + ), + itemCount: i.responsesSubDTO!.length, + itemBuilder: (BuildContext ctx, index) { + return InkWell( + onTap: () { + if(!widget.isShowResponse) { + setState(() { + i.chosen = index; + if(currentIndex == _questionsSubDTO.length && i.chosen == index) + { + widget.onShowResponse(); + //showResult = true; + //_controllerCenter!.play(); // TODO Maybe show only confetti on super score .. + } else { + sliderController!.nextPage(duration: const Duration(milliseconds: 650), curve: Curves.fastOutSlowIn); + } + }); + } + }, + child: Padding( + padding: const EdgeInsets.all(2.5), + child: Container( + alignment: Alignment.center, + child: Text(TranslationHelper.get(i.responsesSubDTO![index].label, appContext.getContext() as VisitAppContext), textAlign: TextAlign.center, style: TextStyle(fontSize: kDescriptionSize, color: i.chosen == index ? Colors.white : Colors.black)), + decoration: BoxDecoration( + color: !widget.isShowResponse ? i.chosen == index ? kTestSecondColor : kBackgroundLight : i.responsesSubDTO![index].isGood! ? kGreen : i.chosen == index ? kTextRed : kBackgroundLight, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(10.0), + boxShadow: const [ + BoxShadow( + color: kBackgroundSecondGrey, + spreadRadius: 0.3, + blurRadius: 4, + offset: Offset(0, 2), // changes position of shadow + ), + ], + ), + ), + ), + ); + }), + ), + ), + ), + ), + ], + ) + ), + ); + }, ); - }, - ); - }).toList(), - ), - ], - ), - if(widget.questionsSubDTO!.isNotEmpty && _questionsSubDTO.length > 1 && currentIndex != _questionsSubDTO.length && _questionsSubDTO[currentIndex-1].chosen != null) - Positioned( - top: MediaQuery.of(context).size.height * 0.38, - right: -9, - child: InkWell( - onTap: () { - if( _questionsSubDTO.isNotEmpty && _questionsSubDTO[currentIndex-1].chosen != null) { - sliderController!.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); - } - }, - child: const Icon( - Icons.chevron_right, - size: 75, - color: kMainColor, - ), - ) - ), - if(_questionsSubDTO.length > 1 && currentIndex != 1) - Positioned( - top: MediaQuery.of(context).size.height * 0.38, - left: -9, - child: InkWell( - onTap: () { - if(currentIndex > 1) { - sliderController!.previousPage(duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); - } - }, - child: const Icon( - Icons.chevron_left, - size: 75, - color: kMainColor, - ), - ) - ), - if(_questionsSubDTO.isNotEmpty) - Positioned.fill( - child: Padding( - padding: EdgeInsets.only(bottom: widget.isShowResponse ? 0 : 0), - child: Align( - alignment: Alignment.bottomCenter, + }).toList(), + ), + ], + ), + if(widget.questionsSubDTO!.isNotEmpty && _questionsSubDTO.length > 1 && currentIndex != _questionsSubDTO.length && _questionsSubDTO[currentIndex-1].chosen != null) + Positioned( + top: widget.orientation == Orientation.portrait ? MediaQuery.of(context).size.height * 0.38 : MediaQuery.of(context).size.height * 0.325, + right: widget.orientation == Orientation.portrait ? -9 : 25, child: InkWell( - child: Text( - currentIndex.toString()+'/'+widget.questionsSubDTO!.length.toString(), - style: const TextStyle(fontSize: 30, fontWeight: FontWeight.w500), + onTap: () { + if( _questionsSubDTO.isNotEmpty && _questionsSubDTO[currentIndex-1].chosen != null) { + sliderController!.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); + } + }, + child: const Icon( + Icons.chevron_right, + size: 75, + color: kMainColor, ), ) ), - ), - ), - if(_questionsSubDTO.isEmpty) - const Center( - child: Text( - "Aucune question à afficher", - style: TextStyle(fontSize: kNoneInfoOrIncorrect), - textAlign: TextAlign.center - ), - ) - ] - ), - ); + if(_questionsSubDTO.length > 1 && currentIndex != 1) + Positioned( + top: widget.orientation == Orientation.portrait ? MediaQuery.of(context).size.height * 0.38 : MediaQuery.of(context).size.height * 0.325, + left: widget.orientation == Orientation.portrait ? -9 : 25, + child: InkWell( + onTap: () { + if(currentIndex > 1) { + sliderController!.previousPage(duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); + } + }, + child: const Icon( + Icons.chevron_left, + size: 75, + color: kMainColor, + ), + ) + ), + if(_questionsSubDTO.isNotEmpty) + Positioned.fill( + child: Padding( + padding: EdgeInsets.only(bottom: widget.isShowResponse ? 0 : 0), + child: Align( + alignment: Alignment.bottomCenter, + child: InkWell( + child: Text( + currentIndex.toString()+'/'+widget.questionsSubDTO!.length.toString(), + style: const TextStyle(fontSize: 30, fontWeight: FontWeight.w500), + ), + ) + ), + ), + ), + if(_questionsSubDTO.isEmpty) + const Center( + child: Text( + "Aucune question à afficher", + style: TextStyle(fontSize: kNoneInfoOrIncorrect), + textAlign: TextAlign.center + ), + ) + ] + ), + ); + /*} + )*/; } } \ No newline at end of file diff --git a/lib/Screens/Quizz/quizz_page.dart b/lib/Screens/Quizz/quizz_page.dart index 2e570ed..81bc7d8 100644 --- a/lib/Screens/Quizz/quizz_page.dart +++ b/lib/Screens/Quizz/quizz_page.dart @@ -3,7 +3,7 @@ import 'dart:developer'; import 'dart:typed_data'; import 'package:carousel_slider/carousel_slider.dart'; -import 'package:confetti/confetti.dart'; +//import 'package:confetti/confetti.dart'; import 'package:flutter/material.dart'; import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; @@ -15,9 +15,9 @@ import 'package:mymuseum_visitapp/Models/ResponseSubDTO.dart'; import 'package:mymuseum_visitapp/Models/articleRead.dart'; import 'package:mymuseum_visitapp/Models/resourceModel.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; -import 'package:mymuseum_visitapp/Screens/Quizz/drawPath.dart'; +//import 'package:mymuseum_visitapp/Screens/Quizz/drawPath.dart'; import 'package:mymuseum_visitapp/Screens/Quizz/questions_list.dart'; -import 'package:mymuseum_visitapp/Screens/Quizz/showResponses.dart'; +//import 'package:mymuseum_visitapp/Screens/Quizz/showResponses.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/client.dart'; import 'package:mymuseum_visitapp/constants.dart'; @@ -89,590 +89,141 @@ class _QuizzPageState extends State { title: sectionDTO != null ? TranslationHelper.get(sectionDTO!.title, visitAppContext!) : "", isHomeButton: false, ), - body: FutureBuilder( - future: getQuizz(appContext, appContext.clientAPI, widget.sectionId), // MAYBE MOVE THAT TO PARENT .. - builder: (context, AsyncSnapshot snapshot) { - if(quizzDTO != null && sectionDTO != null) { + body: OrientationBuilder( + builder: (context, orientation) { + return FutureBuilder( + future: getQuizz(appContext, appContext.clientAPI, widget.sectionId), // MAYBE MOVE THAT TO PARENT .. + builder: (context, AsyncSnapshot snapshot) { + if(quizzDTO != null && sectionDTO != null) { - if(showResult) { - var goodResponses = 0; - for (var question in _questionsSubDTO) { - if(question.chosen == question.responsesSubDTO!.indexWhere((response) => response.isGood!)) { - goodResponses +=1; - } - } - log("goodResponses =" + goodResponses.toString()); - QuizzDTOBadLevel levelToShow = QuizzDTOBadLevel(); - var test = goodResponses/quizzDTO!.questions!.length; + if(showResult) { + var goodResponses = 0; + for (var question in _questionsSubDTO) { + if(question.chosen == question.responsesSubDTO!.indexWhere((response) => response.isGood!)) { + goodResponses +=1; + } + } + log("goodResponses =" + goodResponses.toString()); + QuizzDTOBadLevel levelToShow = QuizzDTOBadLevel(); + var test = goodResponses/quizzDTO!.questions!.length; - if((0 == test || test < 0.25) && quizzDTO!.badLevel != null) { - levelToShow = quizzDTO!.badLevel!; - } - if((test>=0.25 && test < 0.5) && quizzDTO!.mediumLevel != null) { - levelToShow = quizzDTO!.mediumLevel!; - } - if((test>=0.5 && test < 0.75) && quizzDTO!.goodLevel != null) { - levelToShow = quizzDTO!.goodLevel!; - } - if((test>=0.75 && test <= 1) && quizzDTO!.greatLevel != null) { - levelToShow = quizzDTO!.greatLevel!; - } + if((0 == test || test < 0.25) && quizzDTO!.badLevel != null) { + levelToShow = quizzDTO!.badLevel!; + } + if((test>=0.25 && test < 0.5) && quizzDTO!.mediumLevel != null) { + levelToShow = quizzDTO!.mediumLevel!; + } + if((test>=0.5 && test < 0.75) && quizzDTO!.goodLevel != null) { + levelToShow = quizzDTO!.goodLevel!; + } + if((test>=0.75 && test <= 1) && quizzDTO!.greatLevel != null) { + levelToShow = quizzDTO!.greatLevel!; + } - return SizedBox( - width: double.infinity, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - /*Center( - child: SizedBox( - width: 5, - height: 5, - child: ConfettiWidget( - confettiController: _controllerCenter!, - blastDirectionality: BlastDirectionality.explosive, - shouldLoop: false, // start again as soon as the animation is finished - colors: const [ - kMainColor, - kSecondColor, - kConfigurationColor, - kTestSecondColor - //Colors.pink, - //Colors.orange, - //Colors.purple - ], // manually specify the colors to be used - createParticlePath: drawPath, // define a custom shape/path. - ), - ), - ),*/ - if (!showResponses && levelToShow.source_ != null) - Container( - //height: size.height * 0.2, - //width: size.width * 0.25, - constraints: BoxConstraints( - maxHeight: size.height * 0.25, - maxWidth: kIsWeb ? size.width * 0.20 : size.width * 0.85, - ), - alignment: Alignment.center, - decoration: BoxDecoration( - image: levelToShow.source_ != null ? DecorationImage( - fit: BoxFit.contain, - opacity: 0.85, - image: NetworkImage( - levelToShow.source_!, - ), - ): null, - borderRadius: const BorderRadius.all( Radius.circular(50.0)), - border: Border.all( - color: kBackgroundGrey, - width: 1.0, - ), - ), - child: Container( - //borderRadius: BorderRadius.all(Radius.circular(25.0)), - decoration: BoxDecoration( - color: const Color(0xff7c94b6), - image: DecorationImage( - image: NetworkImage( - levelToShow.source_!, - ), - fit: BoxFit.cover, - ), - borderRadius: const BorderRadius.all( Radius.circular(50.0)), - border: Border.all( - color: kBackgroundGrey, - width: 1.0, + return SizedBox( + width: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + /*Center( + child: SizedBox( + width: 5, + height: 5, + child: ConfettiWidget( + confettiController: _controllerCenter!, + blastDirectionality: BlastDirectionality.explosive, + shouldLoop: false, // start again as soon as the animation is finished + colors: const [ + kMainColor, + kSecondColor, + kConfigurationColor, + kTestSecondColor + //Colors.pink, + //Colors.orange, + //Colors.purple + ], // manually specify the colors to be used + createParticlePath: drawPath, // define a custom shape/path. ), ), - ), - ), - if(!showResponses) - // TEXT BOX WITH MAIN SCORE - Text('$goodResponses/${quizzDTO!.questions!.length}', textAlign: TextAlign.center, style: TextStyle(fontSize: kIsWeb ? (showResponses ? 60 : 100) : 75, color: kBackgroundSecondGrey)), - if(!showResponses) - // TEXT BOX WITH LEVEL TEXT RESULT - Padding( - padding: const EdgeInsets.only(bottom: 10), - child: Container( - width: MediaQuery.of(context).size.width *0.75, - height: kIsWeb ? (showResponses ? MediaQuery.of(context).size.height *0.10 : MediaQuery.of(context).size.height *0.20) : MediaQuery.of(context).size.height *0.25, - decoration: BoxDecoration( - color: kBackgroundLight, //kBackgroundLight - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(10.0), - boxShadow: const [ - BoxShadow( - color: kBackgroundSecondGrey, - spreadRadius: 0.3, - blurRadius: 4, - offset: Offset(0, 2), // changes position of shadow - ), + ),*/ + if (orientation == Orientation.portrait) + Column( + children: [ + if (!showResponses && levelToShow.source_ != null) + resultImage(size, levelToShow, orientation), + if(!showResponses) + // TEXT BOX WITH MAIN SCORE + Text('$goodResponses/${quizzDTO!.questions!.length}', textAlign: TextAlign.center, style: TextStyle(fontSize: kIsWeb ? (showResponses ? 60 : 100) : 75, color: kBackgroundSecondGrey)), ], ), - child: Center( - child: SizedBox( - width: double.infinity, - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(15.0), - child: Text(TranslationHelper.get(levelToShow.label, appContext.getContext() as VisitAppContext), textAlign: TextAlign.center, style: TextStyle(fontSize: kIsWeb ? kDescriptionSize : kDescriptionSize)), - ), - ), - ), + + if (orientation == Orientation.landscape) + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + if(!showResponses) + // TEXT BOX WITH MAIN SCORE + Text('$goodResponses/${quizzDTO!.questions!.length}', textAlign: TextAlign.center, style: TextStyle(fontSize: kIsWeb ? (showResponses ? 60 : 100) : 75, color: kBackgroundSecondGrey)), + if (!showResponses && levelToShow.source_ != null) + resultImage(size, levelToShow, orientation), + ], ), - ), - ), - if(showResponses) - QuestionsListWidget( - questionsSubDTO: _questionsSubDTO, - isShowResponse: true, - onShowResponse: () {} - ), - // RESPONSE BOX - //ShowReponsesWidget(questionsSubDTO: _questionsSubDTO), - // Buttons - Column( // TABLET IS ROW - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(4), - child: SizedBox( - height: kIsWeb ? 50 : 50, - width: size.width * 0.6, - child: RoundedButton( - text: "Recommencer", - color: kBackgroundSecondGrey, - textColor: kBackgroundLight, - icon: Icons.undo, - press: () { - setState(() { - showResult = false; - showResponses = false; - currentIndex = 1; - _questionsSubDTO = QuestionSubDTO().fromJSON(quizzDTO!.questions!); - }); - }, - fontSize: 18, - horizontal: 20, - vertical: 5 - ), - ), - ), + if(!showResponses) - Padding( - padding: const EdgeInsets.all(4.0), - child: SizedBox( - height: kIsWeb ? 50 : 50, - width: size.width * 0.6, - child: RoundedButton( - text: "Voir les réponses", - color: kBackgroundSecondGrey, - textColor: kBackgroundLight, - icon: Icons.assignment_turned_in, - press: () { - setState(() { - showResponses = true; - }); - }, - fontSize: 18, - horizontal: 20, - vertical: 5 - ), - ), - ) - ], - ), - ], - ), - ); + // TEXT BOX WITH LEVEL TEXT RESULT + resultText(size, levelToShow, appContext), + if(showResponses) + QuestionsListWidget( + questionsSubDTO: _questionsSubDTO, + isShowResponse: true, + onShowResponse: () {}, + orientation: orientation, + ), + // RESPONSE BOX + //ShowReponsesWidget(questionsSubDTO: _questionsSubDTO), - } else { - return QuestionsListWidget( - isShowResponse: false, - questionsSubDTO: _questionsSubDTO, - onShowResponse: () { - setState(() { - showResult = true; - }); - } - ); - /*return Stack( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - if(_questionsSubDTO.isNotEmpty) - CarouselSlider( - carouselController: sliderController, - options: CarouselOptions( - onPageChanged: (int index, CarouselPageChangedReason reason) { - setState(() { - currentIndex = index + 1; - }); - }, - height: MediaQuery.of(context).size.height * 0.85, - enlargeCenterPage: true, - scrollPhysics: const NeverScrollableScrollPhysics(), - reverse: false, - ), - items: _questionsSubDTO.map((i) { - return Builder( - builder: (BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 1.0, right: 1.0, bottom: 15.0), - child: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - margin: const EdgeInsets.symmetric(horizontal: 1.5), - decoration: BoxDecoration( - //color: Colors.orange, //kBackgroundLight - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(20.0), - image: i.source_ != null ? DecorationImage( - fit: BoxFit.cover, - opacity: 0.35, - image: NetworkImage( - i.source_!, - ), - ): null, - boxShadow: const [ - BoxShadow( - color: kBackgroundSecondGrey, - spreadRadius: 0.5, - blurRadius: 5, - offset: Offset(0, 1.5), // changes position of shadow - ), - ], - ), - child: Column( - //crossAxisAlignment: CrossAxisAlignment.center, - //mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - SizedBox( - //color: Colors.red, - //width: MediaQuery.of(context).size.width *0.65, - height: MediaQuery.of(context).size.height *0.25, - child: Stack( - children: [ - Center( - child: Container( - decoration: BoxDecoration( - color: kBackgroundLight, //kBackgroundLight - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(10.0), - boxShadow: const [ - BoxShadow( - color: kBackgroundSecondGrey, - spreadRadius: 0.3, - blurRadius: 4, - offset: Offset(0, 2), // changes position of shadow - ), - ], - ), - width: MediaQuery.of(context).size.width *0.7, - height: MediaQuery.of(context).size.height *0.2, - child: Center( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(2.5), - child: Text(TranslationHelper.get(i.label, appContext.getContext() as VisitAppContext), textAlign: TextAlign.center, style: const TextStyle(fontSize: kDescriptionSize)), - ), - ), - ), - ) - ), - ] - ), - ), - /*SizedBox( - height: MediaQuery.of(context).size.height * 0.01, - ),*/ - Expanded( - child: Padding( - padding: const EdgeInsets.all(5.0), - child: SizedBox( - //height: MediaQuery.of(context).size.height * 0.75, - width: MediaQuery.of(context).size.width * 0.72, - //color: Colors.green, - child: Padding( - padding: const EdgeInsets.all(10.0), - child: GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 1, // TODO HERE IS TABLET - mainAxisExtent: kIsWeb ? 75 : 75, // TODO depends on percentage - mainAxisSpacing: kIsWeb ? 75 : 42.5, // TODO depends on percentage - crossAxisSpacing: kIsWeb ? 75 : 0, // TODO depends on percentage - ), - itemCount: i.responsesSubDTO!.length, - itemBuilder: (BuildContext ctx, index) { - return InkWell( - onTap: () { - print("COUCOU"); - setState(() { - i.chosen = index; - if(currentIndex == _questionsSubDTO.length && i.chosen == index) - { - showResult = true; - //_controllerCenter!.play(); // TODO Maybe show only confetti on super score .. - } else { - sliderController!.nextPage(duration: const Duration(milliseconds: 650), curve: Curves.fastOutSlowIn); - } - }); - }, - child: Padding( - padding: const EdgeInsets.all(2.5), - child: Container( - alignment: Alignment.center, - child: Text(TranslationHelper.get(i.responsesSubDTO![index].label, appContext.getContext() as VisitAppContext), textAlign: TextAlign.center, style: TextStyle(fontSize: kDescriptionSize, color: i.chosen == index ? Colors.white : Colors.black)), - decoration: BoxDecoration( - color: i.chosen == index ? kTestSecondColor : kBackgroundLight, - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(10.0), - boxShadow: const [ - BoxShadow( - color: kBackgroundSecondGrey, - spreadRadius: 0.3, - blurRadius: 4, - offset: Offset(0, 2), // changes position of shadow - ), - ], - ), - ), - ), - ); - }), - ), - ), - ), - ), - ], - ) - ), - ); - }, - ); - }).toList(), + if(orientation == Orientation.portrait) + // Buttons + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: resultButtons(size, orientation), + ), + if(orientation == Orientation.landscape) + // Buttons + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: resultButtons(size, orientation), ), ], ), - if(_questionsSubDTO.length > 1 && currentIndex != _questionsSubDTO.length && _questionsSubDTO[currentIndex-1].chosen != null && quizzDTO!.questions!.isNotEmpty) - Positioned( - top: MediaQuery.of(context).size.height * 0.35, - right: 60, - child: InkWell( - onTap: () { - if(_questionsSubDTO[currentIndex-1].chosen != null && quizzDTO!.questions!.isNotEmpty) { - sliderController!.nextPage(duration: Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); - /*Fluttertoast.showToast( - msg: "Vous n'avez pas répondu à cette question", - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - timeInSecForIosWeb: 1, - backgroundColor: kMainRed, - textColor: Colors.white, - fontSize: 35.0 - );*/ - } - }, - child: Icon( - Icons.chevron_right, - size: kIsWeb ? 100 : 150, - color: kMainColor, - ), - ) - ), - if(_questionsSubDTO.length > 1 && currentIndex != 1) - Positioned( - top: MediaQuery.of(context).size.height * 0.35, - left: 60, - child: InkWell( - onTap: () { - if(currentIndex > 1) { - sliderController!.previousPage(duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); - } - }, - child: Icon( - Icons.chevron_left, - size: kIsWeb ? 100 : 150, - color: kMainColor, - ), - ) - ), - if(_questionsSubDTO.isNotEmpty) - Padding( - padding: const EdgeInsets.only(bottom: 0), - child: Align( - alignment: Alignment.bottomCenter, - child: InkWell( - child: Text( - currentIndex.toString()+'/'+quizzDTO!.questions!.length.toString(), - style: const TextStyle(fontSize: 30, fontWeight: FontWeight.w500), - ), - ) - ), - ), - if(_questionsSubDTO.isEmpty) - const Center( - child: - Text("Aucune question à afficher", style: TextStyle(fontSize: kNoneInfoOrIncorrect), textAlign: TextAlign.center), - ) - ] - );*/ - } + ); - /*if(size.height > size.width) { - return Column( - children: [ - Text("TODO show QUESTION THEN COLUMN WITH ALL RESPONSE") - ], - ); - } else { - return Container( - height: size.height, - width: size.width, - child: Column( - children: [ - Text("TODO show QUESTION THEN GRID LIKE IN TABLET") - ], - ), - ); - }*/ - } else { - return const Loading(); - } + } else { + return QuestionsListWidget( + isShowResponse: false, + questionsSubDTO: _questionsSubDTO, + onShowResponse: () { + setState(() { + showResult = true; + }); + }, + orientation: orientation, + ); + } + } else { + return const Loading(); + } + } + ); } ), - //floatingActionButton: const ScannerBouton(isReplacement: true), ); } - /*Widget getImages(Size size, bool isContentTop) { - if(size.width > size.height) { - return SizedBox( - width: size.width *0.5, - height: size.height * 0.75, - child: Padding( - padding: isContentTop ? const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0): const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: kBlue2, - width: 0.5, - ), - color: Colors.white, - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(5.0), - boxShadow: const [kDefaultShadow], - ), - child: SliderImagesWidget( - resources: resourcesModel, - height: size.height * 0.29, - imagesDTO: quizzDTO!.images!, - ) - ) - ) - ); - } else { - return SizedBox( - width: size.width, - height: size.height * 0.3, - child: Padding( - padding: isContentTop ? const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0): const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: kBlue2, - width: 0.5, - ), - color: Colors.white, - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(5.0), - boxShadow: const [kDefaultShadow], - ), - child: SliderImagesWidget( - resources: resourcesModel, - height: size.height * 0.29, - imagesDTO: articleDTO!.images!, - ) - ) - ) - ); - } - } -*/ - - /*Widget getContent(Size size, AppContext appContext) { - if(size.width > size.height) { - return SingleChildScrollView( - child: Container( - width: size.width *0.5, - height: size.height * 0.76, - //color: Colors.blueAccent, - child: Padding( - padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0, bottom: 8.0), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: kBlue2, - width: 0.5, - ), - color: Colors.white, - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(5.0), - boxShadow: const [kDefaultShadow], - ), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - TranslationHelper.get(articleDTO!.content, appContext.getContext()), - textAlign: TextAlign.left, - style: const TextStyle(fontSize: kArticleContentSize) - ), - ), - ) - ) - ) - ), - ); - } else { - return Expanded( - child: Container( - width: size.width, - //height: size.height * 0.65, - //color: Colors.blueAccent, - child: Padding( - padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0, bottom: 8.0), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: kBlue2, - width: 0.5, - ), - color: Colors.white, - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(5.0), - boxShadow: const [kDefaultShadow], - ), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - TranslationHelper.get(articleDTO!.content, appContext.getContext()), - textAlign: TextAlign.left, - style: const TextStyle(fontSize: kArticleContentSize) - ), - ), - ) - ) - ) - ), - ); - } - }*/ - Future getQuizz(AppContext appContext, Client client, String sectionId) async { try { if(sectionDTO == null || quizzDTO == null) { @@ -715,35 +266,6 @@ class _QuizzPageState extends State { _questionsSubDTO = QuestionSubDTO().fromJSON(quizzDTO!.questions!); if(quizzDTO!.questions != null && quizzDTO!.questions!.isNotEmpty) { quizzDTO!.questions!.sort((a, b) => a.order!.compareTo(b.order!)); - /*var audioIdArticle = articleDTO!.audioIds!.where((audioId) => audioId.language == (appContext.getContext() as VisitAppContext).language); - if(audioIdArticle.isNotEmpty && audioIdArticle.first.value != null) { - if(isConfigOffline) - { - // OFFLINE - List> ressourceTest = await DatabaseHelper - .instance.queryWithColumnId( - DatabaseTableType.resources, audioIdArticle.first.value!); - if (ressourceTest.isNotEmpty) { - audioResourceModel = DatabaseHelper.instance.getResourceFromDB(ressourceTest.first); - Uint8List base64String = base64Decode(audioResourceModel!.data!); - audiobytes = base64String; - } else { - print("EMPTY resourcesModel - first"); - } - } - else - { - // ONLINE - ResourceModel? resourceAudioOnline = await ApiService.downloadAudio(client, audioIdArticle.first.value!); - if(resourceAudioOnline != null) { - audioResourceModel = resourceAudioOnline; - Uint8List base64String = base64Decode(resourceAudioOnline.data!); - audiobytes = base64String; - } else { - print("EMPTY resourcesModel online - audio"); - } - } - }*/ for (var question in quizzDTO!.questions!) { if(isConfigOffline) { @@ -780,4 +302,132 @@ class _QuizzPageState extends State { return null; } } + + resultImage(Size size, QuizzDTOBadLevel levelToShow, Orientation orientation) { + return Container( + //height: size.height * 0.2, + //width: size.width * 0.25, + constraints: BoxConstraints( + maxHeight: size.height * 0.25, + maxWidth: kIsWeb ? size.width * 0.20 : orientation == Orientation.portrait ? size.width * 0.85 : size.width * 0.4, + ), + alignment: Alignment.center, + decoration: BoxDecoration( + image: levelToShow.source_ != null ? DecorationImage( + fit: BoxFit.contain, + opacity: 0.85, + image: NetworkImage( + levelToShow.source_!, + ), + ): null, + borderRadius: const BorderRadius.all( Radius.circular(50.0)), + border: Border.all( + color: kBackgroundGrey, + width: 1.0, + ), + ), + child: Container( + //borderRadius: BorderRadius.all(Radius.circular(25.0)), + decoration: BoxDecoration( + color: const Color(0xff7c94b6), + image: DecorationImage( + image: NetworkImage( + levelToShow.source_!, + ), + fit: BoxFit.cover, + ), + borderRadius: const BorderRadius.all( Radius.circular(50.0)), + border: Border.all( + color: kBackgroundGrey, + width: 1.0, + ), + ), + ), + ); + } + + resultText(Size size, QuizzDTOBadLevel levelToShow, AppContext appContext) { + return Padding( + padding: const EdgeInsets.only(bottom: 10), + child: Container( + width: size.width *0.75, + height: kIsWeb ? (showResponses ? size.height *0.10 : size.height *0.20) : size.height *0.25, + decoration: BoxDecoration( + color: kBackgroundLight, //kBackgroundLight + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(10.0), + boxShadow: const [ + BoxShadow( + color: kBackgroundSecondGrey, + spreadRadius: 0.3, + blurRadius: 4, + offset: Offset(0, 2), // changes position of shadow + ), + ], + ), + child: Center( + child: SizedBox( + width: double.infinity, + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Text(TranslationHelper.get(levelToShow.label, appContext.getContext() as VisitAppContext), textAlign: TextAlign.center, style: TextStyle(fontSize: kIsWeb ? kDescriptionSize : kDescriptionSize)), + ), + ), + ), + ), + ), + ); + } + + resultButtons(Size size, Orientation orientation) { + return [ + Padding( + padding: const EdgeInsets.all(4), + child: SizedBox( + height: kIsWeb ? 50 : 50, + width: orientation == Orientation.portrait ? size.width * 0.6 : size.width * 0.3, + child: RoundedButton( + text: "Recommencer", + color: kBackgroundSecondGrey, + textColor: kBackgroundLight, + icon: Icons.undo, + press: () { + setState(() { + showResult = false; + showResponses = false; + currentIndex = 1; + _questionsSubDTO = QuestionSubDTO().fromJSON(quizzDTO!.questions!); + }); + }, + fontSize: 18, + horizontal: 20, + vertical: 5 + ), + ), + ), + if(!showResponses) + Padding( + padding: const EdgeInsets.all(4.0), + child: SizedBox( + height: kIsWeb ? 50 : 50, + width: orientation == Orientation.portrait ? size.width * 0.6 : size.width * 0.3, + child: RoundedButton( + text: "Voir les réponses", + color: kBackgroundSecondGrey, + textColor: kBackgroundLight, + icon: Icons.assignment_turned_in, + press: () { + setState(() { + showResponses = true; + }); + }, + fontSize: 18, + horizontal: 20, + vertical: 5 + ), + ), + ) + ]; + } } diff --git a/lib/Screens/Visit/visit.dart b/lib/Screens/Visit/visit.dart index fadba5d..fab8464 100644 --- a/lib/Screens/Visit/visit.dart +++ b/lib/Screens/Visit/visit.dart @@ -35,7 +35,7 @@ class _VisitPageState extends State with WidgetsBindingObserver { ConfigurationDTO? configuration; int timeBetweenBeaconPopUp = 20000; // 20 sec - int meterToBeacon = 15; // 15 meters + int meterToBeacon = 100; // 15 meters bool modeDebugBeacon = true; // Beacon specific