import 'dart:convert'; import 'dart:developer'; import 'dart:typed_data'; //import 'package:confetti/confetti.dart'; import 'package:flutter/material.dart'; import 'package:manager_api_new/api.dart'; import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; import 'package:mymuseum_visitapp/Components/Loading.dart'; import 'package:mymuseum_visitapp/Components/loading_common.dart'; import 'package:mymuseum_visitapp/Components/rounded_button.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; 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/questions_list.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'; import 'package:provider/provider.dart'; class QuizzPage extends StatefulWidget { const QuizzPage({Key? key, required this.visitAppContextIn, required this.sectionId}) : super(key: key); final String sectionId; final VisitAppContext visitAppContextIn; @override State createState() => _QuizzPageState(); } class _QuizzPageState extends State { SectionDTO? sectionDTO; List resourcesModel = []; ResourceModel? audioResourceModel; final GlobalKey _scaffoldKey = GlobalKey(); late Uint8List audiobytes; late VisitAppContext visitAppContext; QuizDTO? quizDTO; List _questionsSubDTO = []; //ConfettiController? _controllerCenter; int currentIndex = 1; bool showResult = false; bool showResponses = false; bool kIsWeb = false; bool isResultPage = false; @override void initState() { widget.visitAppContextIn.isContentCurrentlyShown = true; //_controllerCenter = ConfettiController(duration: const Duration(seconds: 10)); //_controllerCenter!.play(); super.initState(); } @override void dispose() { visitAppContext.isContentCurrentlyShown = false; currentIndex = 1; //_controllerCenter!.dispose(); if(quizDTO != null) { if(quizDTO!.questions != null) { _questionsSubDTO = QuestionSubDTO().fromJSON(quizDTO!.questions!); } } super.dispose(); } @override Widget build(BuildContext context) { final appContext = Provider.of(context); Size size = MediaQuery.of(context).size; visitAppContext = appContext.getContext(); return Scaffold( key: _scaffoldKey, appBar: CustomAppBar( title: sectionDTO != null ? TranslationHelper.get(sectionDTO!.title, visitAppContext) : "", isHomeButton: false, ), body: OrientationBuilder( builder: (context, orientation) { return FutureBuilder( future: getQuizz(appContext, visitAppContext.clientAPI, widget.sectionId), // MAYBE MOVE THAT TO PARENT .. builder: (context, AsyncSnapshot snapshot) { if(quizDTO != 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()); List levelToShow = []; var test = goodResponses/quizDTO!.questions!.length; if((0 == test || test < 0.25) && quizDTO!.badLevel != null) { levelToShow = quizDTO!.badLevel!; } if((test>=0.25 && test < 0.5) && quizDTO!.mediumLevel != null) { levelToShow = quizDTO!.mediumLevel!; } if((test>=0.5 && test < 0.75) && quizDTO!.goodLevel != null) { levelToShow = quizDTO!.goodLevel!; } if((test>=0.75 && test <= 1) && quizDTO!.greatLevel != null) { levelToShow = quizDTO!.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, kMainColor1 //Colors.pink, //Colors.orange, //Colors.purple ], // manually specify the colors to be used createParticlePath: drawPath, // define a custom shape/path. ), ), ),*/ if (orientation == Orientation.portrait) Column( children: [ if (!showResponses && levelToShow.firstWhere((label) => label.language == visitAppContext.language).resource?.url != null) // TODO SUPPORT OTHER THAN IMAGES resultImage(visitAppContext, size, levelToShow, orientation), if(!showResponses) // TEXT BOX WITH MAIN SCORE Text('$goodResponses/${quizDTO!.questions!.length}', textAlign: TextAlign.center, style: TextStyle(fontSize: kIsWeb ? (showResponses ? 60 : 100) : 75, color: kBackgroundSecondGrey)), ], ), if (orientation == Orientation.landscape) Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ if(!showResponses) // TEXT BOX WITH MAIN SCORE Text('$goodResponses/${quizDTO!.questions!.length}', textAlign: TextAlign.center, style: TextStyle(fontSize: kIsWeb ? (showResponses ? 60 : 100) : 75, color: kBackgroundSecondGrey)), if (!showResponses && levelToShow.firstWhere((label) => label.language == visitAppContext.language).resource?.url != null) resultImage(visitAppContext, size, levelToShow, orientation), ], ), if(!showResponses) // 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), if(orientation == Orientation.portrait && !showResponses) // Buttons Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: resultButtons(size, orientation, visitAppContext!), ), if(orientation == Orientation.landscape && !showResponses) // Buttons Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: resultButtons(size, orientation, visitAppContext!), ), ], ), ); } else { return QuestionsListWidget( isShowResponse: false, questionsSubDTO: _questionsSubDTO, onShowResponse: () { setState(() { showResult = true; }); }, orientation: orientation, ); } } else { return const LoadingCommon(); } } ); } ), floatingActionButton: showResponses ? FloatingActionButton( onPressed: () { setState(() { showResult = false; showResponses = false; currentIndex = 1; _questionsSubDTO = QuestionSubDTO().fromJSON(quizDTO!.questions!); }); }, backgroundColor: kBackgroundSecondGrey, child: const Icon(Icons.undo), ) : null, floatingActionButtonLocation: FloatingActionButtonLocation.miniEndFloat, ); } Future getQuizz(AppContext appContext, Client client, String sectionId) async { try { if(sectionDTO == null || quizDTO == null) { bool isConfigOffline = (appContext.getContext() as VisitAppContext).configuration!.isOffline!; if(isConfigOffline) { // OFFLINE List> sectionTest = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.sections, sectionId); if(sectionTest.isNotEmpty) { sectionDTO = DatabaseHelper.instance.getSectionFromDB(sectionTest.first); try { SectionRead sectionRead = SectionRead(id: sectionDTO!.id!, readTime: DateTime.now().millisecondsSinceEpoch); await DatabaseHelper.instance.insert(DatabaseTableType.articleRead, sectionRead.toMap()); visitAppContext.readSections.add(sectionRead); appContext.setContext(visitAppContext); } catch (e) { print("DATABASE ERROR SECTIONREAD"); print(e); } } else { print("EMPTY SECTION"); } } else { // ONLINE SectionDTO? sectionOnline = await client.sectionApi!.sectionGetDetail(sectionId); if(sectionOnline != null) { sectionDTO = sectionOnline; } else { print("EMPTY SECTION"); } } if(sectionDTO!.type == SectionType.Quiz) { quizDTO = QuizDTO.fromJson(jsonDecode(sectionDTO!.data!)); } if(quizDTO != null) { quizDTO!.questions!.sort((a, b) => a.order!.compareTo(b.order!)); _questionsSubDTO = QuestionSubDTO().fromJSON(quizDTO!.questions!); if(quizDTO!.questions != null && quizDTO!.questions!.isNotEmpty) { quizDTO!.questions!.sort((a, b) => a.order!.compareTo(b.order!)); for (var question in quizDTO!.questions!) { if(isConfigOffline) { // OFFLINE if(question.imageBackgroundResourceId != null) { List> ressourceQuizz = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, question.imageBackgroundResourceId!); if(ressourceQuizz.isNotEmpty) { resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(ressourceQuizz.first)); } else { print("EMPTY resourcesModel - second"); } } } else { // ONLINE if(question.imageBackgroundResourceId != null) { resourcesModel.add(ResourceModel(id: question.imageBackgroundResourceId, source: question.imageBackgroundResourceUrl, type: ResourceType.Image)); } } } } } setState(() { //print(sectionDTO!.title); }); } else { return null; // TODO return local list.. } } catch (e) { print(e); print("IN CATCH"); return null; } } resultImage(VisitAppContext visitAppContext, Size size, List 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.where((label) => label.language == visitAppContext.language).isNotEmpty ? DecorationImage( fit: BoxFit.contain, opacity: 0.85, image: NetworkImage( levelToShow.firstWhere((label) => label.language == visitAppContext.language).resource!.url!, ), ): 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.firstWhere((label) => label.language == visitAppContext.language).resource!.url!, // TODO REDUNDANCY here?? ), fit: BoxFit.cover, ), borderRadius: const BorderRadius.all( Radius.circular(50.0)), border: Border.all( color: kBackgroundGrey, width: 1.0, ), ), ), ); } resultText(Size size, List 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.getWithResource(levelToShow, appContext.getContext() as VisitAppContext), textAlign: TextAlign.center, style: TextStyle(fontSize: kIsWeb ? kDescriptionSize : kDescriptionSize)), ), ), ), ), ), ); } resultButtons(Size size, Orientation orientation, VisitAppContext visitAppContext) { return [ Padding( padding: const EdgeInsets.all(4), child: SizedBox( height: kIsWeb ? 50 : 40, width: orientation == Orientation.portrait ? size.width * 0.6 : size.width * 0.35, child: RoundedButton( text: TranslationHelper.getFromLocale("restart", visitAppContext), color: kBackgroundSecondGrey, textColor: kBackgroundLight, icon: Icons.undo, press: () { setState(() { showResult = false; showResponses = false; currentIndex = 1; _questionsSubDTO = QuestionSubDTO().fromJSON(quizDTO!.questions!); }); }, fontSize: 18, horizontal: 20, vertical: 5 ), ), ), Padding( padding: const EdgeInsets.all(4.0), child: SizedBox( height: kIsWeb ? 50 : 40, width: orientation == Orientation.portrait ? size.width * 0.6 : size.width * 0.35, child: RoundedButton( text: TranslationHelper.getFromLocale("responses", visitAppContext), color: kBackgroundSecondGrey, textColor: kBackgroundLight, icon: Icons.assignment_turned_in, press: () { setState(() { showResponses = true; }); }, fontSize: 18, horizontal: 20, vertical: 5 ), ), ) ]; } }