From 5592989b44f4537e837306dad5b02418b0ff2e75 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Mon, 2 Jan 2023 11:25:34 +0300 Subject: [PATCH] Added Demo Marathon Module --- assets/json/demo_questions_marathon | 522 ++++++++++++++++++ assets/json/demo_upcoming_marathon | 46 ++ assets/langs/ar-SA.json | 4 +- assets/langs/en-US.json | 4 +- lib/api/marathon/demo_marathon_repo.dart | 27 + lib/api/marathon/marathon_api_client.dart | 3 +- lib/app_state/app_state.dart | 6 + lib/classes/consts.dart | 4 +- lib/generated/codegen_loader.g.dart | 11 +- lib/generated/locale_keys.g.dart | 2 + lib/ui/landing/dashboard_screen.dart | 6 +- lib/ui/marathon/marathon_intro_screen.dart | 14 +- lib/ui/marathon/marathon_provider.dart | 77 ++- lib/ui/marathon/marathon_screen.dart | 239 +++++--- .../countdown_timer_detail_screen.dart | 13 +- lib/ui/marathon/widgets/marathon_banner.dart | 22 +- .../widgets/marathon_details_card.dart | 110 ++-- lib/ui/marathon/widgets/marathon_footer.dart | 14 +- .../widgets/marathon_progress_container.dart | 41 +- pubspec.yaml | 1 + 20 files changed, 980 insertions(+), 186 deletions(-) create mode 100644 assets/json/demo_questions_marathon create mode 100644 assets/json/demo_upcoming_marathon create mode 100644 lib/api/marathon/demo_marathon_repo.dart diff --git a/assets/json/demo_questions_marathon b/assets/json/demo_questions_marathon new file mode 100644 index 0000000..7ec04fd --- /dev/null +++ b/assets/json/demo_questions_marathon @@ -0,0 +1,522 @@ +[ + { + "id": "b8f10b10-221c-495d-b99b-6a8094892549", + "titleEn": "How many time Uruguay won FIFA World Cups?", + "titleAr": "How many time Uruguay won FIFA World Cups?", + "marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "questionTypeId": 1, + "questionTime": 10, + "nextQuestGap": 5, + "gapType": 0, + "gapText": null, + "gapImage": "Questions/51b598b6-c837-45be-8734-1374978bd426_congratulations-gif.gif", + "questOptionsLimit": 0, + "remainingParticipantCount": 1, + "questionOptions": [ + { + "id": "772e6062-543c-4ddc-e516-08dae8b36b35", + "titleEn": "1", + "titleAr": "1", + "questionId": "b8f10b10-221c-495d-b99b-6a8094892549", + "sequence": 1, + "image": "null", + "isCorrectOption": false + }, + { + "id": "ea3c673e-78c7-41dd-e517-08dae8b36b35", + "titleEn": "2", + "titleAr": "2", + "questionId": "b8f10b10-221c-495d-b99b-6a8094892549", + "sequence": 2, + "image": "null", + "isCorrectOption": true + }, + { + "id": "7adbdfec-ef77-417e-e518-08dae8b36b35", + "titleEn": "3", + "titleAr": "3", + "questionId": "b8f10b10-221c-495d-b99b-6a8094892549", + "sequence": 3, + "image": "null", + "isCorrectOption": false + }, + { + "id": "895eab85-e321-4d3e-e519-08dae8b36b35", + "titleEn": "4", + "titleAr": "4", + "questionId": "b8f10b10-221c-495d-b99b-6a8094892549", + "sequence": 4, + "image": "null", + "isCorrectOption": false + } + ] + }, + { + "id": "0d60d55f-4067-48f9-9ace-b6309c6a7cf0", + "titleEn": "Who is the current FIFA World Cup Winner?", + "titleAr": "Who is the current FIFA World Cup Winner?", + "marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "questionTypeId": 1, + "questionTime": 10, + "nextQuestGap": 5, + "gapType": 0, + "gapText": null, + "gapImage": "Questions/24dddc50-7583-48b4-9fec-8a490d246191_great-thumbs.gif", + "questOptionsLimit": 0, + "remainingParticipantCount": 0, + "questionOptions": [ + { + "id": "dd0ba127-26ed-4308-e50e-08dae8b36b35", + "titleEn": "Brazil", + "titleAr": "Brazil", + "questionId": "0d60d55f-4067-48f9-9ace-b6309c6a7cf0", + "sequence": 1, + "image": "null", + "isCorrectOption": false + }, + { + "id": "4748df31-95f0-4fee-e50f-08dae8b36b35", + "titleEn": "Argentina", + "titleAr": "Argentina", + "questionId": "0d60d55f-4067-48f9-9ace-b6309c6a7cf0", + "sequence": 2, + "image": "null", + "isCorrectOption": true + }, + { + "id": "4079d32a-891b-4e83-e510-08dae8b36b35", + "titleEn": "Germany", + "titleAr": "Germany", + "questionId": "0d60d55f-4067-48f9-9ace-b6309c6a7cf0", + "sequence": 3, + "image": "null", + "isCorrectOption": false + }, + { + "id": "1c17cfcd-9f19-4020-e511-08dae8b36b35", + "titleEn": "France", + "titleAr": "France", + "questionId": "0d60d55f-4067-48f9-9ace-b6309c6a7cf0", + "sequence": 4, + "image": "null", + "isCorrectOption": false + } + ] + }, + { + "id": "489659b0-0400-4b64-8ce2-e6fe48db61db", + "titleEn": "How many times England won FIFA World Cups?", + "titleAr": "How many times England won FIFA World Cups?", + "marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "questionTypeId": 1, + "questionTime": 10, + "nextQuestGap": 5, + "gapType": 0, + "gapText": null, + "gapImage": "Questions/a9ffa364-231c-4877-824f-84febac51086_thumbs-up-simon-cowell.gif", + "questOptionsLimit": 0, + "remainingParticipantCount": 0, + "questionOptions": [ + { + "id": "7f63cd45-ce2c-417f-e502-08dae8b36b35", + "titleEn": "1", + "titleAr": "1", + "questionId": "489659b0-0400-4b64-8ce2-e6fe48db61db", + "sequence": 1, + "image": "null", + "isCorrectOption": true + }, + { + "id": "34690bfa-0ffd-453f-e503-08dae8b36b35", + "titleEn": "2", + "titleAr": "2", + "questionId": "489659b0-0400-4b64-8ce2-e6fe48db61db", + "sequence": 2, + "image": "null", + "isCorrectOption": false + }, + { + "id": "4526efdd-ff6f-4340-e504-08dae8b36b35", + "titleEn": "3", + "titleAr": "3", + "questionId": "489659b0-0400-4b64-8ce2-e6fe48db61db", + "sequence": 3, + "image": "null", + "isCorrectOption": false + }, + { + "id": "65d06188-fa63-49fd-e505-08dae8b36b35", + "titleEn": "4", + "titleAr": "4", + "questionId": "489659b0-0400-4b64-8ce2-e6fe48db61db", + "sequence": 4, + "image": "null", + "isCorrectOption": false + } + ] + }, + { + "id": "253fc396-dab9-41ca-82bd-511f98c5dee8", + "titleEn": "How many time Germany won FIFA World Cups?", + "titleAr": "How many time Germany won FIFA World Cups?", + "marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "questionTypeId": 1, + "questionTime": 10, + "nextQuestGap": 5, + "gapType": 0, + "gapText": null, + "gapImage": "Questions/012d6493-3612-42c9-8f6f-84417d4736d4_good-job-well-done.gif", + "questOptionsLimit": 0, + "remainingParticipantCount": 0, + "questionOptions": [ + { + "id": "dce4999c-5629-45f4-e4f6-08dae8b36b35", + "titleEn": "1", + "titleAr": "null", + "questionId": 1, + "sequence": 1, + "image": "null", + "isCorrectOption": false + }, + { + "id": "00913ba1-5ccc-4d7c-e4f7-08dae8b36b35", + "titleEn": "2", + "titleAr": "2", + "questionId": "253fc396-dab9-41ca-82bd-511f98c5dee8", + "sequence": 2, + "image": "null", + "isCorrectOption": false + }, + { + "id": "9e5f5e89-608e-4fc9-e4f8-08dae8b36b35", + "titleEn": "3", + "titleAr": "3", + "questionId": "253fc396-dab9-41ca-82bd-511f98c5dee8", + "sequence": 3, + "image": "null", + "isCorrectOption": false + }, + { + "id": "a535cacf-ee4d-4895-e4f9-08dae8b36b35", + "titleEn": "4", + "titleAr": "4", + "questionId": "253fc396-dab9-41ca-82bd-511f98c5dee8", + "sequence": 4, + "image": "null", + "isCorrectOption": true + } + ] + }, + { + "id": "669c4fe2-a3e6-4e29-8c56-ae09efa9ba6c", + "titleEn": "How many times Portugal won FIFA World Cups?", + "titleAr": "How many times Portugal won FIFA World Cups?", + "marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "questionTypeId": 1, + "questionTime": 10, + "nextQuestGap": 5, + "gapType": 0, + "gapText": null, + "gapImage": "Questions/ca3f32a1-ed9f-45df-b2fb-3d1df78d5651_congrats-14.gif", + "questOptionsLimit": 0, + "remainingParticipantCount": 0, + "questionOptions": [ + { + "id": "597c308e-3f09-4a05-e506-08dae8b36b35", + "titleEn": "0", + "titleAr": "0", + "questionId": "669c4fe2-a3e6-4e29-8c56-ae09efa9ba6c", + "sequence": 1, + "image": "null", + "isCorrectOption": true + }, + { + "id": "2face927-7c8e-4945-e507-08dae8b36b35", + "titleEn": "1", + "titleAr": "1", + "questionId": "669c4fe2-a3e6-4e29-8c56-ae09efa9ba6c", + "sequence": 2, + "image": "null", + "isCorrectOption": false + }, + { + "id": "bde21640-798e-4750-e508-08dae8b36b35", + "titleEn": "2", + "titleAr": "2", + "questionId": "669c4fe2-a3e6-4e29-8c56-ae09efa9ba6c", + "sequence": 3, + "image": "null", + "isCorrectOption": false + }, + { + "id": "9312acac-f0c3-4ed4-e509-08dae8b36b35", + "titleEn": "3", + "titleAr": "3", + "questionId": "669c4fe2-a3e6-4e29-8c56-ae09efa9ba6c", + "sequence": 4, + "image": "null", + "isCorrectOption": false + } + ] + }, + { + "id": "f91774ce-14f0-4af0-9a77-e649bc013b44", + "titleEn": "How many times Spain won FIFA World Cups?", + "titleAr": "How many times Spain won FIFA World Cups?", + "marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "questionTypeId": 1, + "questionTime": 10, + "nextQuestGap": 5, + "gapType": 0, + "gapText": null, + "gapImage": "Questions/6484c5bc-09fd-4586-8036-67868afbe27b_good-job-well-done.gif", + "questOptionsLimit": 0, + "remainingParticipantCount": 0, + "questionOptions": [ + { + "id": "2f968964-ce91-4478-e512-08dae8b36b35", + "titleEn": "1", + "titleAr": "1", + "questionId": "f91774ce-14f0-4af0-9a77-e649bc013b44", + "sequence": 1, + "image": "null", + "isCorrectOption": true + }, + { + "id": "4fed9355-2c9f-458d-e513-08dae8b36b35", + "titleEn": "2", + "titleAr": "2", + "questionId": "f91774ce-14f0-4af0-9a77-e649bc013b44", + "sequence": 2, + "image": "null", + "isCorrectOption": false + }, + { + "id": "8f232a43-3792-4cd0-e514-08dae8b36b35", + "titleEn": "3", + "titleAr": "3", + "questionId": "f91774ce-14f0-4af0-9a77-e649bc013b44", + "sequence": 3, + "image": "null", + "isCorrectOption": false + }, + { + "id": "24478e43-bf4c-4852-e515-08dae8b36b35", + "titleEn": "4", + "titleAr": "4", + "questionId": "f91774ce-14f0-4af0-9a77-e649bc013b44", + "sequence": 4, + "image": "null", + "isCorrectOption": false + } + ] + }, + { + "id": "fd3a90e6-5b35-4035-bc1c-4483facaf6d3", + "titleEn": "How many times France won FIFA World Cups?", + "titleAr": "How many times France won FIFA World Cups?", + "marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "questionTypeId": 1, + "questionTime": 10, + "nextQuestGap": 5, + "gapType": 0, + "gapText": null, + "gapImage": "Questions/24dddc50-7583-48b4-9fec-8a490d246191_great-thumbs.gif", + "questOptionsLimit": 0, + "remainingParticipantCount": 0, + "questionOptions": [ + { + "id": "9d0743e0-9f3f-48d0-e4fa-08dae8b36b35", + "titleEn": "1", + "titleAr": "1", + "questionId": "fd3a90e6-5b35-4035-bc1c-4483facaf6d3", + "sequence": 1, + "image": "null", + "isCorrectOption": false + }, + { + "id": "a81eda99-d9ad-49e0-e4fb-08dae8b36b35", + "titleEn": "2", + "titleAr": "2", + "questionId": "fd3a90e6-5b35-4035-bc1c-4483facaf6d3", + "sequence": 2, + "image": "null", + "isCorrectOption": true + }, + { + "id": "7ca78891-890d-4023-e4fc-08dae8b36b35", + "titleEn": "3", + "titleAr": "3", + "questionId": "fd3a90e6-5b35-4035-bc1c-4483facaf6d3", + "sequence": 3, + "image": "null", + "isCorrectOption": false + }, + { + "id": "d1a98bd9-8afa-49c1-e4fd-08dae8b36b35", + "titleEn": "4", + "titleAr": "4", + "questionId": "fd3a90e6-5b35-4035-bc1c-4483facaf6d3", + "sequence": 4, + "image": "null", + "isCorrectOption": false + } + ] + }, + { + "id": "3a35855d-3ed7-4d45-8864-9135d71378de", + "titleEn": "How many time Argentina won FIFA World Cups?", + "titleAr": "How many time Argentina won FIFA World Cups?", + "marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "questionTypeId": 1, + "questionTime": 10, + "nextQuestGap": 5, + "gapType": 0, + "gapText": null, + "gapImage": "Questions/24dddc50-7583-48b4-9fec-8a490d246191_great-thumbs.gif", + "questOptionsLimit": 0, + "remainingParticipantCount": 0, + "questionOptions": [ + { + "id": "f0766816-837f-47e6-e51a-08dae8b36b35", + "titleEn": "1", + "titleAr": "1", + "questionId": "3a35855d-3ed7-4d45-8864-9135d71378de", + "sequence": 1, + "image": "null", + "isCorrectOption": false + }, + { + "id": "dc9c68de-afa4-4b63-e51b-08dae8b36b35", + "titleEn": "2", + "titleAr": "2", + "questionId": "3a35855d-3ed7-4d45-8864-9135d71378de", + "sequence": 2, + "image": "null", + "isCorrectOption": false + }, + { + "id": "52f2d024-8a29-4781-e51c-08dae8b36b35", + "titleEn": "3", + "titleAr": "3", + "questionId": "3a35855d-3ed7-4d45-8864-9135d71378de", + "sequence": 3, + "image": "null", + "isCorrectOption": true + }, + { + "id": "122636e4-5e98-499e-e51d-08dae8b36b35", + "titleEn": "4", + "titleAr": "4", + "questionId": "3a35855d-3ed7-4d45-8864-9135d71378de", + "sequence": 4, + "image": "null", + "isCorrectOption": false + } + ] + }, + { + "id": "6c9d809d-683b-4d77-b98e-62a0d083488a", + "titleEn": "How many times Brazil won FIFA World Cups?", + "titleAr": "How many times Brazil won FIFA World Cups?", + "marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "questionTypeId": 1, + "questionTime": 10, + "nextQuestGap": 5, + "gapType": 0, + "gapText": null, + "gapImage": "Questions/a9ffa364-231c-4877-824f-84febac51086_thumbs-up-simon-cowell.gif", + "questOptionsLimit": 0, + "remainingParticipantCount": 0, + "questionOptions": [ + { + "id": "4e94437a-b10d-46c6-e4fe-08dae8b36b35", + "titleEn": "2", + "titleAr": "2", + "questionId": "6c9d809d-683b-4d77-b98e-62a0d083488a", + "sequence": 1, + "image": "null", + "isCorrectOption": false + }, + { + "id": "6e0e8baa-c13e-45f1-e4ff-08dae8b36b35", + "titleEn": "3", + "titleAr": "3", + "questionId": "6c9d809d-683b-4d77-b98e-62a0d083488a", + "sequence": 2, + "image": "null", + "isCorrectOption": false + }, + { + "id": "3065d26a-9aa4-4626-e500-08dae8b36b35", + "titleEn": "4", + "titleAr": "4", + "questionId": "6c9d809d-683b-4d77-b98e-62a0d083488a", + "sequence": 3, + "image": "null", + "isCorrectOption": false + }, + { + "id": "6cc3ff60-02cc-4e59-e501-08dae8b36b35", + "titleEn": "5", + "titleAr": "5", + "questionId": "6c9d809d-683b-4d77-b98e-62a0d083488a", + "sequence": 4, + "image": "null", + "isCorrectOption": true + } + ] + }, + { + "id": "e8c8442e-f370-444d-bee9-f7f75d146e5c", + "titleEn": "How many times Italy won FIFA World Cups?", + "titleAr": "How many times Italy won FIFA World Cups?", + "marathonId": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "questionTypeId": 1, + "questionTime": 10, + "nextQuestGap": 5, + "gapType": 0, + "gapText": null, + "gapImage": "Questions/34f3c402-1244-4320-98c2-751cb2a347c5_congrats-1.gif", + "questOptionsLimit": 0, + "remainingParticipantCount": 0, + "questionOptions": [ + { + "id": "53d456b7-8f56-4c58-e50a-08dae8b36b35", + "titleEn": "1", + "titleAr": "1", + "questionId": "e8c8442e-f370-444d-bee9-f7f75d146e5c", + "sequence": 1, + "image": "null", + "isCorrectOption": false + }, + { + "id": "280df6d7-ca61-4d78-e50b-08dae8b36b35", + "titleEn": "2", + "titleAr": "2", + "questionId": "e8c8442e-f370-444d-bee9-f7f75d146e5c", + "sequence": 2, + "image": "null", + "isCorrectOption": false + }, + { + "id": "769939dc-4a46-4f4f-e50c-08dae8b36b35", + "titleEn": "3", + "titleAr": "3", + "questionId": "e8c8442e-f370-444d-bee9-f7f75d146e5c", + "sequence": 3, + "image": "null", + "isCorrectOption": false + }, + { + "id": "c389fae7-0019-4922-e50d-08dae8b36b35", + "titleEn": "4", + "titleAr": "4", + "questionId": "e8c8442e-f370-444d-bee9-f7f75d146e5c", + "sequence": 4, + "image": "null", + "isCorrectOption": true + } + ] + } +] \ No newline at end of file diff --git a/assets/json/demo_upcoming_marathon b/assets/json/demo_upcoming_marathon new file mode 100644 index 0000000..2fdabf0 --- /dev/null +++ b/assets/json/demo_upcoming_marathon @@ -0,0 +1,46 @@ +{ + "id": "979813be-eafa-4d3e-d27e-08dae8a08a3b", + "titleEn": "FIFA World Cup", + "titleAr": "undefined", + "descEn": "FIFA World Cup Description", + "descAr": "undefined", + "questionTime": 10, + "winDeciderTime": 30, + "winnersCount": 1, + "questGapTime": 5, + "startTime": "2022-12-28T10:44:41", + "endTime": null, + "marathoneStatusId": 4, + "scheduleTime": "2022-12-28T10:14:41", + "selectedLanguage": 0, + "projects": { + "id": "b1cd3fa3-bb27-422e-a4c1-08dac09254df", + "nameEn": "Cloud Solutions", + "nameAr": "333شركة حلول السحابة للاتصالات وتقنية المعلومات", + "projectCode": "CS" + }, + "sponsors": [ + { + "id": "3272b127-b388-4f09-425b-08dac2eb788e", + "nameEn": "Cloud Solutions", + "nameAr": "حل السحابة", + "image": "SponsorImage/b9aed4a8-42b2-45fc-b6f1-47ee0c7b4138_sponsor.jpeg", + "video": "SponsorVideo/9ab678ab-1b4c-4ea4-aaf2-32ce1353d3fe_sample-10s.mp4", + "logo": "SponsorLogo/eb029f0d-bce1-4a61-b0c0-abaa484912a0_sponsor.jpeg", + "videoDuration": null, + "sponsorPrizes": [ + { + "id": "e657a18c-6fb2-4099-07c8-08dae89efcd3", + "marathonPrizeEn": "SAR 500", + "marathonPrizeAr": "SAR 500" + } + ] + } + ], + "questions": null, + "isEmailSent": false, + "totalQuestions": 10, + "cancelReason": null, + "marathonBufferTime": 30, + "currentTime": "2022-12-28T08:03:24.3671803Z" +} diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index c7259fd..1cf1205 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -480,6 +480,7 @@ "gameTime": "وقت اللعب:", "joinMarathon": "انضم إلى ماراثون", "joinDemoMarathon": "انضم إلى الماراثون التجريبي", + "demo":"تجريبي", "minutes": "الدقائق", "seconds": "ثواني", "note": "ملحوظة:", @@ -518,5 +519,6 @@ "winners": "الفائزين!!!", "noUpcoming": "لا يوجد قادم", "fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية", - "noWinner": "حزين! لم يفز أحد اليوم." + "noWinner": "حزين! لم يفز أحد اليوم.", + "youCanPlayDemo": "لكن يمكنك لعب العرض" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index f1eac93..61aba9b 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -469,6 +469,7 @@ "gameTime": "Game Time:", "joinMarathon": "Join Marathon", "joinDemoMarathon": "Join Demo Marathon", + "demo":"Demo", "minutes": "Minutes", "seconds": "Seconds", "note": "Note:", @@ -518,5 +519,6 @@ "winners": "WINNERS!!!", "noUpcoming": "There is no upcoming", "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.", - "noWinner": "Sad! No one won today." + "noWinner": "Sad! No one won today.", + "youCanPlayDemo": "But you can play demo" } \ No newline at end of file diff --git a/lib/api/marathon/demo_marathon_repo.dart b/lib/api/marathon/demo_marathon_repo.dart new file mode 100644 index 0000000..b019e51 --- /dev/null +++ b/lib/api/marathon/demo_marathon_repo.dart @@ -0,0 +1,27 @@ +import 'dart:convert'; + +import 'package:flutter/services.dart'; +import 'package:logger/logger.dart' as L; +import 'package:mohem_flutter_app/models/marathon/marathon_model.dart'; +import 'package:mohem_flutter_app/models/marathon/question_model.dart'; + +class DemoMarathonRepo { + L.Logger logger = L.Logger(); + + Future getDemoMarathonDetails() async { + String response = await rootBundle.loadString('assets/json/demo_upcoming_marathon'); + var json = jsonDecode(response); + logger.i("json in getDemoMarathonDetails: $json"); + MarathonDetailModel marathonDetailModel = MarathonDetailModel.fromJson(json); + return marathonDetailModel; + } + + Future getDemoNextQuestion({required int currentQuestionNumber}) async { + String response = await rootBundle.loadString('assets/json/demo_questions_marathon'); + List json = jsonDecode(response); + logger.i("json in getDemoNextQuestion: $json"); + QuestionModel currentQuestion = QuestionModel.fromJson(json.elementAt(currentQuestionNumber)); + + return currentQuestion; + } +} diff --git a/lib/api/marathon/marathon_api_client.dart b/lib/api/marathon/marathon_api_client.dart index 5b1dfc8..ee3810f 100644 --- a/lib/api/marathon/marathon_api_client.dart +++ b/lib/api/marathon/marathon_api_client.dart @@ -14,10 +14,8 @@ import 'package:mohem_flutter_app/models/marathon/question_model.dart'; import 'package:mohem_flutter_app/models/marathon/winner_model.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:provider/provider.dart'; -import 'package:signalr_netcore/hub_connection.dart'; class MarathonApiClient { - late HubConnection hubConnection; L.Logger logger = L.Logger(); Future getMarathonToken() async { @@ -184,6 +182,7 @@ class MarathonApiClient { return null; } +// late HubConnection hubConnection; // Future buildHubConnection(BuildContext context, String prizeId) async { // HttpConnectionOptions httpOptions = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); // hubConnection = HubConnectionBuilder() diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index f6f5ae9..e43c774 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -64,6 +64,12 @@ class AppState { String? get getMarathonProjectId => _projectID; + bool _isDemoMarathon = false; + + set setIsDemoMarathon(bool value) => _isDemoMarathon = value; + + bool get getIsDemoMarathon => _isDemoMarathon; + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 3.8, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 56b0008..56ddde6 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -3,8 +3,8 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server - // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server - static String baseUrl = "https://hmgwebservices.com"; // Live server + static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server + // static String baseUrl = "https://hmgwebservices.com"; // Live server static String baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 27bae71..c33ec06 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -489,6 +489,7 @@ class CodegenLoader extends AssetLoader { "gameTime": "وقت اللعب:", "joinMarathon": "انضم إلى ماراثون", "joinDemoMarathon": "انضم إلى الماراثون التجريبي", + "demo":"تجريبي", "minutes": "الدقائق", "seconds": "ثواني", "note": "ملحوظة:", @@ -527,7 +528,8 @@ class CodegenLoader extends AssetLoader { "winners": "الفائزين!!!", "noUpcoming": "لا يوجد قادم", "fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية", - "noWinner": "حزين! لم يفز أحد اليوم." + "noWinner": "حزين! لم يفز أحد اليوم.", + "youCanPlayDemo": "لكن يمكنك لعب العرض" }; static const Map en_US = { "mohemm": "Mohemm", @@ -993,10 +995,11 @@ class CodegenLoader extends AssetLoader { "gameTime": "Game Time:", "joinMarathon": "Join Marathon", "joinDemoMarathon": "Join Demo Marathon", + "demo":"Demo", "minutes": "Minutes", "seconds": "Seconds", "note": "Note:", - "demoMarathonNoteP1": "You can play the demo Marathon to learn how it works. You can join the Marathon", + "demoMarathonNoteP1": "You can play the demo_questions_marathon.json Marathon to learn how it works. You can join the Marathon", "demoMarathonNoteP2": "5 Minutes", "demoMarathonNoteP3": "before the actual time.", "sponsoredBy": "Sponsored By:", @@ -1042,7 +1045,9 @@ class CodegenLoader extends AssetLoader { "winners": "WINNERS!!!", "noUpcoming": "There is no upcoming", "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.", - "noWinner": "Sad! No one won today." + "noWinner": "Sad! No one won today.", + "youCanPlayDemo": "But you can play demo" + }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 1114c23..e4a3bca 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -466,6 +466,7 @@ abstract class LocaleKeys { static const gameTime = 'gameTime'; static const joinMarathon = 'joinMarathon'; static const joinDemoMarathon = 'joinDemoMarathon'; + static const demo = 'demo'; static const minutes = 'minutes'; static const seconds = 'seconds'; static const note = 'note'; @@ -505,5 +506,6 @@ abstract class LocaleKeys { static const noUpcoming = 'noUpcoming'; static const fakeLocation = 'fakeLocation'; static const noWinner = 'noWinner'; + static const youCanPlayDemo = 'youCanPlayDemo'; } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index c64cfa6..6c782fc 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -32,8 +32,6 @@ import 'package:signalr_netcore/signalr_client.dart'; late HubConnection chatHubConnection; - - class DashboardScreen extends StatefulWidget { DashboardScreen({Key? key}) : super(key: key); @@ -435,9 +433,7 @@ class _DashboardScreenState extends State { mainAxisSize: MainAxisSize.min, children: [ ServicesWidget(), - context.watch().isLoading - ? const MarathonBannerShimmer().paddingAll(20) - : MarathonBanner(isMarathonUpcoming: context.watch().isUpComingMarathon).paddingOnly(left: 21, right: 21, bottom: 21, top: 8), + context.watch().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 8), ], ), ), diff --git a/lib/ui/marathon/marathon_intro_screen.dart b/lib/ui/marathon/marathon_intro_screen.dart index f47b47e..9d4f81d 100644 --- a/lib/ui/marathon/marathon_intro_screen.dart +++ b/lib/ui/marathon/marathon_intro_screen.dart @@ -23,12 +23,14 @@ class MarathonIntroScreen extends StatelessWidget { ListView( padding: const EdgeInsets.all(21), children: [ - MarathonDetailsCard(provider: provider), - 10.height, - MarathonTimerCard( - provider: provider, - timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch, - ), + MarathonDetailsCard(marathonDetailModel: provider.isUpComingMarathon ? provider.marathonDetailModel : provider.demoMarathonDetailModel), + 20.height, + provider.isUpComingMarathon + ? MarathonTimerCard( + provider: provider, + timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch, + ) + : const SizedBox(), ], ).expanded, 1.divider, diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index c1338eb..9781475 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:appinio_swiper/appinio_swiper.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/marathon/demo_marathon_repo.dart'; import 'package:mohem_flutter_app/api/marathon/marathon_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; @@ -16,11 +17,12 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; import 'package:video_player/video_player.dart'; class MarathonProvider extends ChangeNotifier { - //****************VARIABLES********** + //************************************************ VARIABLES ********************************************************** final AppinioSwiperController swiperController = AppinioSwiperController(); MarathonDetailModel marathonDetailModel = MarathonDetailModel(); + MarathonDetailModel demoMarathonDetailModel = MarathonDetailModel(); List cardContentList = []; QuestionModel currentQuestion = QuestionModel(); List answerStatusesList = []; @@ -53,6 +55,7 @@ class MarathonProvider extends ChangeNotifier { set isUpComingMarathon(bool value) { _isUpComingMarathon = value; + notifyListeners(); } @@ -65,6 +68,15 @@ class MarathonProvider extends ChangeNotifier { notifyListeners(); } + bool _canPlayDemo = true; + + bool get canPlayDemo => _canPlayDemo; + + set canPlayDemo(bool value) { + _canPlayDemo = value; + notifyListeners(); + } + bool _isButtonEnabled = false; bool get isButtonEnabled => _isButtonEnabled; @@ -138,7 +150,7 @@ class MarathonProvider extends ChangeNotifier { // 9c47d281-c5b5-4b5d-a90a-08dacb8cbdb6 // MarathonI - //****************TIMERS********** + //************************************************ TIMERS ********************************************************** int sponsorsSecondsCounter = 0; int totalSponsorVideoSeconds = 0; @@ -213,7 +225,7 @@ class MarathonProvider extends ChangeNotifier { updateCardStatusToAnswer(); scheduleMicrotask(() async { - if (isUserOutOfGame) { + if (AppState().getIsDemoMarathon || isUserOutOfGame) { await callNextQuestionApi(); } else { await callSubmitOptionApi().then((bool value) async { @@ -223,7 +235,7 @@ class MarathonProvider extends ChangeNotifier { } }); - if (currentQuestionNumber == marathonDetailModel.totalQuestions!) { + if (currentQuestionNumber == (AppState().getIsDemoMarathon ? demoMarathonDetailModel.totalQuestions! : marathonDetailModel.totalQuestions!)) { isGettingQualifiers = true; updateQuestionCardStatus(QuestionCardStatus.findingWinner); timer.cancel(); @@ -275,19 +287,26 @@ class MarathonProvider extends ChangeNotifier { ); } - //****************FUNCTIONS********* + //************************************************ FUNCTIONS ********************************************************** Future callSubmitOptionApi() async { return await MarathonApiClient().submitSelectedOption(marathonId: marathonDetailModel.id!, questionId: currentQuestion.id, selectedAnswerId: selectedOptionId); } Future callGetQualifiersApi() async { - totalQualifiers = await MarathonApiClient().getQualifiers(marathonId: marathonDetailModel.id!); + if (AppState().getIsDemoMarathon) { + totalQualifiers = isUserOutOfGame ? 0 : 1; + } else { + totalQualifiers = await MarathonApiClient().getQualifiers(marathonId: marathonDetailModel.id!); + } isGettingQualifiers = false; notifyListeners(); } Future callGetSelectedWinnersApi() async { + if (AppState().getIsDemoMarathon) { + return; + } selectedWinners = await MarathonApiClient().getSelectedWinner(marathonId: marathonDetailModel.id!); if (selectedWinners != null) { selectedWinners!.removeWhere((WinnerModel element) { @@ -304,10 +323,14 @@ class MarathonProvider extends ChangeNotifier { } Future callNextQuestionApi() async { - if (currentQuestionNumber < marathonDetailModel.totalQuestions!) { + if (currentQuestionNumber < (AppState().getIsDemoMarathon ? demoMarathonDetailModel.totalQuestions! : marathonDetailModel.totalQuestions!)) { if (currentQuestionNumber == 0) { - Utils.showLoading(AppRoutes.navigatorKey.currentContext!); - currentQuestion = (await MarathonApiClient().getNextQuestion(questionId: null, marathonId: marathonDetailModel.id!)); + if (!AppState().getIsDemoMarathon) { + Utils.showLoading(AppRoutes.navigatorKey.currentContext!); + } + currentQuestion = AppState().getIsDemoMarathon + ? await DemoMarathonRepo().getDemoNextQuestion(currentQuestionNumber: currentQuestionNumber) + : (await MarathonApiClient().getNextQuestion(questionId: null, marathonId: marathonDetailModel.id!)); gapTimeImage = currentQuestion.gapImage; gapTimeText = currentQuestion.gapText; gapTimeType = currentQuestion.gapType; @@ -318,7 +341,9 @@ class MarathonProvider extends ChangeNotifier { updateCardData(); Navigator.pushReplacementNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.marathonScreen); } else { - currentQuestion = (await MarathonApiClient().getNextQuestion(questionId: currentQuestion.id, marathonId: marathonDetailModel.id!)); + currentQuestion = AppState().getIsDemoMarathon + ? await DemoMarathonRepo().getDemoNextQuestion(currentQuestionNumber: currentQuestionNumber) + : (await MarathonApiClient().getNextQuestion(questionId: currentQuestion.id, marathonId: marathonDetailModel.id!)); } notifyListeners(); } @@ -340,12 +365,21 @@ class MarathonProvider extends ChangeNotifier { } void populateQuestionStatusesList() { - if (marathonDetailModel.totalQuestions != null) { - for (int i = 0; i < marathonDetailModel.totalQuestions!; i++) { + answerStatusesList.clear(); + if (demoMarathonDetailModel.totalQuestions != null) { + for (int i = 0; i < demoMarathonDetailModel.totalQuestions!; i++) { answerStatusesList.add(QuestionCardStatus.question); } notifyListeners(); } + if (isUpComingMarathon) { + if (marathonDetailModel.totalQuestions != null) { + for (int i = 0; i < marathonDetailModel.totalQuestions!; i++) { + answerStatusesList.add(QuestionCardStatus.question); + } + notifyListeners(); + } + } } void updateAnswerStatusesList(QuestionCardStatus status) { @@ -369,9 +403,11 @@ class MarathonProvider extends ChangeNotifier { } void updateQuestionCardStatus(QuestionCardStatus status) { - // if (status == QuestionCardStatus.wrongAnswer || status == QuestionCardStatus.skippedAnswer) { - // updateIsUserOutOfGame = true; - // } + if (status == QuestionCardStatus.wrongAnswer || status == QuestionCardStatus.skippedAnswer) { + if (AppState().getIsDemoMarathon) { + updateIsUserOutOfGame = true; + } + } questionCardStatus = status; notifyListeners(); } @@ -417,11 +453,13 @@ class MarathonProvider extends ChangeNotifier { isUserOutOfGame = false; isButtonEnabled = false; isUserWaiting = false; + canPlayDemo = true; totalCurrentQuestionTime = 0; sponsorsSecondsCounter = 0; totalSponsorVideoSeconds = 0; totalSecondsToWaitForWinner = 30; totalSecondsToWaitForMarathon = 30; + AppState().setIsDemoMarathon = false; currentGapTime = 0; currentQuestion = QuestionModel(); if (answerStatusesList.isNotEmpty) { @@ -452,15 +490,19 @@ class MarathonProvider extends ChangeNotifier { isLoading = true; notifyListeners(); isPrivilegedWithMarathon = checkIfPrivilegedForMarathon(); + demoMarathonDetailModel = await DemoMarathonRepo().getDemoMarathonDetails(); + if (isPrivilegedWithMarathon) { marathonDetailModel = await MarathonApiClient().getMarathonDetails(); updateTotalSecondsToWaitForMarathon = marathonDetailModel.marathonBufferTime ?? 30; if (marathonDetailModel.id == null) { isUpComingMarathon = false; isLoading = false; + populateQuestionStatusesList(); notifyListeners(); return; } + isUpComingMarathon = true; if (DateTime.parse(marathonDetailModel.startTime!).isAfter(DateTime.now())) { itsMarathonTime = false; } @@ -478,4 +520,9 @@ class MarathonProvider extends ChangeNotifier { Utils.confirmDialog(context, e.toString()); } } + + Future onJoinDemoMarathonPressed(BuildContext context) async { + AppState().setIsDemoMarathon = true; + await callNextQuestionApi(); + } } diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index f8bc969..9d76cf7 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -45,106 +45,179 @@ class MarathonScreen extends StatelessWidget { return Image.asset(MyLottieConsts.congratsGif, height: 200); } + Widget getDemoWinnerWidget(BuildContext context, {required MarathonProvider provider}) { + return provider.isUserOutOfGame + ? Column( + children: [ + Lottie.asset(MyLottieConsts.noWinnerLottie), + Center( + child: LocaleKeys.noWinner.tr().toText18(color: MyColors.grey3AColor, isCentered: true), + ), + ], + ) + : Stack( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 50, + child: Stack( + children: [ + Align( + alignment: Alignment.center, + child: SvgPicture.asset("assets/images/winner_ribbon.svg", height: 50), + ), + Align( + alignment: Alignment.center, + child: LocaleKeys.winner.tr().toText32(color: MyColors.white, isBold: true, isCentered: true).paddingOnly(top: 07), + ) + ], + ), + ), + 16.height, + Column( + children: [ + (AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22( + color: MyColors.grey3AColor, + isCentered: true, + ), + 8.height, + AppState().memberInformationList!.eMPLOYEENUMBER!.toText22(color: MyColors.grey57Color), + ], + ), + 60.height, + if (provider.demoMarathonDetailModel.sponsors != null && provider.demoMarathonDetailModel.sponsors!.isNotEmpty) ...[ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + "${LocaleKeys.sponsoredBy.tr()} ".toText14(color: MyColors.grey77Color), + (AppState().isArabic(context) ? provider.demoMarathonDetailModel.sponsors!.first.nameAr ?? "" : provider.demoMarathonDetailModel.sponsors!.first.nameEn ?? "").toText14( + color: MyColors.darkTextColor, + isBold: true, + ), + ], + ), + 5.height, + Image.network( + ApiConsts.marathonBaseUrlServices + provider.demoMarathonDetailModel.sponsors!.first.logo!, + height: 50, + width: 150, + fit: BoxFit.contain, + errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { + return Image.asset("assets/images/logos/main_mohemm_logo.png", height: 50, width: 150); + }, + ) + ], + ], + ), + Lottie.asset(MyLottieConsts.celebrate1Lottie), + ], + ); + } + Widget getWinnerWidget(BuildContext context, {required MarathonProvider provider}) { return Container( width: double.infinity, decoration: MyDecorations.shadowDecoration, padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), - child: provider.selectedWinners == null || (provider.selectedWinners!.isEmpty && !provider.iAmWinner) - ? Column( - children: [ - Lottie.asset(MyLottieConsts.noWinnerLottie), - Center( - child: LocaleKeys.noWinner.tr().toText18(color: MyColors.grey3AColor, isCentered: true), - ), - ], - ) - : Stack( - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, + child: (AppState().getIsDemoMarathon) + ? getDemoWinnerWidget(context, provider: provider) + : provider.selectedWinners == null || (provider.selectedWinners!.isEmpty && !provider.iAmWinner) + ? Column( children: [ - SizedBox( - height: 50, - child: Stack( - children: [ - Align( - alignment: Alignment.center, - child: SvgPicture.asset("assets/images/winner_ribbon.svg", height: 50), - ), - Align( - alignment: Alignment.center, - child: ((provider.selectedWinners!.length == 1 && !provider.iAmWinner) || (provider.selectedWinners!.isEmpty && provider.iAmWinner) - ? LocaleKeys.winner.tr() - : LocaleKeys.winners.tr()) - .toText32(color: MyColors.white, isBold: true, isCentered: true) - .paddingOnly(top: 07), - ) - ], - ), + Lottie.asset(MyLottieConsts.noWinnerLottie), + Center( + child: LocaleKeys.noWinner.tr().toText18(color: MyColors.grey3AColor, isCentered: true), ), - 16.height, - provider.iAmWinner - ? Column( + ], + ) + : Stack( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 50, + child: Stack( children: [ - (AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22( - color: MyColors.grey3AColor, - isCentered: true, + Align( + alignment: Alignment.center, + child: SvgPicture.asset("assets/images/winner_ribbon.svg", height: 50), ), - 8.height, - AppState().memberInformationList!.eMPLOYEENUMBER!.toText22(color: MyColors.grey57Color), + Align( + alignment: Alignment.center, + child: ((provider.selectedWinners!.length == 1 && !provider.iAmWinner) || (provider.selectedWinners!.isEmpty && provider.iAmWinner) + ? LocaleKeys.winner.tr() + : LocaleKeys.winners.tr()) + .toText32(color: MyColors.white, isBold: true, isCentered: true) + .paddingOnly(top: 07), + ) ], - ) - : const SizedBox(), - 36.height, - if (provider.selectedWinners != null) ...[ - ListView.separated( - shrinkWrap: true, - itemCount: provider.selectedWinners!.length, - separatorBuilder: (BuildContext context, int index) { - return const Divider(); - }, - itemBuilder: (BuildContext context, int index) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, + ), + ), + 16.height, + provider.iAmWinner + ? Column( + children: [ + (AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn)!.toText22( + color: MyColors.grey3AColor, + isCentered: true, + ), + 8.height, + AppState().memberInformationList!.eMPLOYEENUMBER!.toText22(color: MyColors.grey57Color), + ], + ) + : const SizedBox(), + 36.height, + if (provider.selectedWinners != null) ...[ + ListView.separated( + shrinkWrap: true, + itemCount: provider.selectedWinners!.length, + separatorBuilder: (BuildContext context, int index) { + return const Divider(); + }, + itemBuilder: (BuildContext context, int index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (AppState().isArabic(context) ? provider.selectedWinners![index].nameEn : provider.selectedWinners![index].nameEn)!.toText16( + color: MyColors.grey3AColor, + ), + provider.selectedWinners!.first.employeeId!.toText16(color: MyColors.grey57Color), + ], + ); + }, + ), + ], + 60.height, + if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...[ + Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - (AppState().isArabic(context) ? provider.selectedWinners![index].nameEn : provider.selectedWinners![index].nameEn)!.toText16( - color: MyColors.grey3AColor, + "${LocaleKeys.sponsoredBy.tr()} ".toText14(color: MyColors.grey77Color), + (AppState().isArabic(context) ? provider.marathonDetailModel.sponsors!.first.nameAr ?? "" : provider.marathonDetailModel.sponsors!.first.nameEn ?? "").toText14( + color: MyColors.darkTextColor, + isBold: true, ), - provider.selectedWinners!.first.employeeId!.toText16(color: MyColors.grey57Color), ], - ); - }, - ), - ], - 60.height, - if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...[ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - "${LocaleKeys.sponsoredBy.tr()} ".toText14(color: MyColors.grey77Color), - (AppState().isArabic(context) ? provider.marathonDetailModel.sponsors!.first.nameAr ?? "" : provider.marathonDetailModel.sponsors!.first.nameEn ?? "").toText14( - color: MyColors.darkTextColor, - isBold: true, ), + 5.height, + Image.network( + ApiConsts.marathonBaseUrlServices + provider.marathonDetailModel.sponsors!.first.logo!, + height: 50, + width: 150, + fit: BoxFit.contain, + errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { + return Image.asset("assets/images/logos/main_mohemm_logo.png", height: 50, width: 150); + }, + ) ], - ), - 5.height, - Image.network( - ApiConsts.marathonBaseUrlServices + provider.marathonDetailModel.sponsors!.first.logo!, - height: 50, - width: 150, - fit: BoxFit.contain, - errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { - return Image.asset("assets/images/logos/main_mohemm_logo.png", height: 50, width: 150); - }, - ) - ], + ], + ), + Lottie.asset(MyLottieConsts.celebrate1Lottie), ], ), - Lottie.asset(MyLottieConsts.celebrate1Lottie), - ], - ), ); } diff --git a/lib/ui/marathon/widgets/countdown_timer_detail_screen.dart b/lib/ui/marathon/widgets/countdown_timer_detail_screen.dart index 8cc4f93..86b8b96 100644 --- a/lib/ui/marathon/widgets/countdown_timer_detail_screen.dart +++ b/lib/ui/marathon/widgets/countdown_timer_detail_screen.dart @@ -10,7 +10,6 @@ import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; -import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_banner.dart'; class CountdownTimerForDetailScreen extends StatelessWidget { final int timeToMarathon; @@ -122,6 +121,15 @@ class CountdownTimerForDetailScreen extends StatelessWidget { } Widget buildCountdownTimer(CurrentRemainingTime? time) { + if (provider.marathonDetailModel.startTime != null) { + int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes; + if (remainingTimeInMinutes <= 30) { + scheduleMicrotask(() { + provider.canPlayDemo = true; + }); + } + } + if (time == null) { if (!provider.itsMarathonTime) { scheduleMicrotask(() { @@ -193,8 +201,7 @@ class CountdownTimerForDetailScreen extends StatelessWidget { @override Widget build(BuildContext context) { return CountdownTimer( - endTime: dummyTime, - // endTime: timeToMarathon, + endTime: timeToMarathon, onEnd: null, widgetBuilder: (BuildContext context, CurrentRemainingTime? time) { return buildCountdownTimer(time); diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index ff374c3..1c4d6b8 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -18,14 +18,11 @@ import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer_main_screen.dart'; import 'package:provider/provider.dart'; - // It is used to pass a dummy time to test Marathon int dummyTime = DateTime.now().millisecondsSinceEpoch + 8690; class MarathonBanner extends StatelessWidget { - final bool isMarathonUpcoming; - - const MarathonBanner({Key? key, required this.isMarathonUpcoming}) : super(key: key); + const MarathonBanner({Key? key}) : super(key: key); Widget getUnPrivilegedMarathon(BuildContext context) { return Container( @@ -274,6 +271,16 @@ class MarathonBanner extends StatelessWidget { height: 32 / 22, ), ), + Text( + LocaleKeys.youCanPlayDemo.tr(), + style: TextStyle( + fontSize: isTablet ? 20 : 11, + fontStyle: FontStyle.italic, + fontWeight: FontWeight.w600, + color: MyColors.white.withOpacity(0.83), + letterSpacing: -0.4, + ), + ), ], ).paddingOnly( left: AppState().isArabic(context) ? 12 : 3, @@ -331,7 +338,9 @@ class MarathonBanner extends StatelessWidget { ).paddingOnly(top: 5), ], ), - ); + ).onPress(() { + Navigator.pushNamed(context, AppRoutes.marathonIntroScreen); + }); } @override @@ -340,7 +349,7 @@ class MarathonBanner extends StatelessWidget { return !provider.isPrivilegedWithMarathon ? getUnPrivilegedMarathon(context) - : provider.marathonDetailModel.startTime != null + : provider.isUpComingMarathon ? Container( decoration: MyDecorations.shadowDecoration, height: isTablet ? MediaQuery.of(context).size.height * 0.17 : MediaQuery.of(context).size.height * 0.11, @@ -432,7 +441,6 @@ class MarathonBanner extends StatelessWidget { isTablet ? 10.height : 3.height, CountdownTimerForMainScreen( timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch, - // timeToMarathon: dummyTime, provider: provider, ), ], diff --git a/lib/ui/marathon/widgets/marathon_details_card.dart b/lib/ui/marathon/widgets/marathon_details_card.dart index b888915..dda7ef8 100644 --- a/lib/ui/marathon/widgets/marathon_details_card.dart +++ b/lib/ui/marathon/widgets/marathon_details_card.dart @@ -6,72 +6,86 @@ import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/classes/decorations_helper.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/models/marathon/marathon_model.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; +import 'package:provider/provider.dart'; class MarathonDetailsCard extends StatelessWidget { - final MarathonProvider provider; + final MarathonDetailModel marathonDetailModel; - const MarathonDetailsCard({Key? key, required this.provider}) : super(key: key); + const MarathonDetailsCard({Key? key, required this.marathonDetailModel}) : super(key: key); @override Widget build(BuildContext context) { return Container( width: double.infinity, decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 14), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 14), child: Column( - mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.contestTopicAbout.tr().toText16(color: MyColors.grey77Color), - "${AppState().isArabic(context) ? provider.marathonDetailModel.titleAr : provider.marathonDetailModel.titleEn}".toText20(color: MyColors.textMixColor, isBold: true), - Row( - children: [ - Flexible( - child: "${AppState().isArabic(context) ? provider.marathonDetailModel.descAr : provider.marathonDetailModel.descEn}".toText14(color: MyColors.grey77Color), - ) - ], - ), - if (provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) ...[ - 5.height, - provider.marathonDetailModel.sponsors!.first.sponsorPrizes != null - ? Row( - children: [ - "${LocaleKeys.prize.tr()} ".toText16(color: MyColors.grey77Color, isBold: true), - "${AppState().isArabic(context) ? provider.marathonDetailModel.sponsors?.first.sponsorPrizes?.first.marathonPrizeAr : provider.marathonDetailModel.sponsors?.first.sponsorPrizes?.first.marathonPrizeAr}" - .toText16(color: MyColors.greenColor, isBold: true), - ], - ) - : const SizedBox(), - Row( - children: [ - "${LocaleKeys.sponsoredBy.tr()} ".toText16(color: MyColors.grey77Color), - "${AppState().isArabic(context) ? provider.marathonDetailModel.sponsors?.first.nameAr : provider.marathonDetailModel.sponsors?.first.nameEn}" - .toText16(color: MyColors.darkTextColor, isBold: true), - ], - ), - 10.height, - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.network( - ApiConsts.marathonBaseUrlServices + provider.marathonDetailModel.sponsors!.first.logo!, - height: 50, - width: 150, - fit: BoxFit.contain, - errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { - return Image.asset("assets/images/logos/main_mohemm_logo.png", height: 50, width: 150); - }, - ) + context.read().isUpComingMarathon + ? const SizedBox() + : Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + decoration: BoxDecoration(color: MyColors.yellowColorII, borderRadius: BorderRadius.circular(100)), + child: LocaleKeys.demo.tr().toText10(color: MyColors.white).paddingAll(4), + ), ], ), - ] + 7.height, + LocaleKeys.contestTopicAbout.tr().toText16(color: MyColors.grey77Color), + "${AppState().isArabic(context) ? marathonDetailModel.titleAr : marathonDetailModel.titleEn}".toText20(color: MyColors.textMixColor, isBold: true), + Row( + children: [ + Flexible( + child: "${AppState().isArabic(context) ? marathonDetailModel.descAr : marathonDetailModel.descEn}".toText14(color: MyColors.grey77Color), + ) ], ), + if (marathonDetailModel.sponsors != null && marathonDetailModel.sponsors!.isNotEmpty) ...[ + 5.height, + marathonDetailModel.sponsors!.first.sponsorPrizes != null + ? Row( + children: [ + "${LocaleKeys.prize.tr()} ".toText16(color: MyColors.grey77Color, isBold: true), + Row( + children: marathonDetailModel.sponsors!.first.sponsorPrizes! + .map( + (SponsorPrizes prizes) => + "${AppState().isArabic(context) ? prizes.marathonPrizeAr : prizes.marathonPrizeAr}".toText16(color: MyColors.greenColor, isBold: true).paddingOnly(right: 5), + ) + .toList(), + ), + ], + ) + : const SizedBox(), + Row( + children: [ + "${LocaleKeys.sponsoredBy.tr()} ".toText16(color: MyColors.grey77Color), + "${AppState().isArabic(context) ? marathonDetailModel.sponsors?.first.nameAr : marathonDetailModel.sponsors?.first.nameEn}".toText16(color: MyColors.darkTextColor, isBold: true), + ], + ), + 10.height, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.network( + ApiConsts.marathonBaseUrlServices + marathonDetailModel.sponsors!.first.logo!, + height: 50, + width: 150, + fit: BoxFit.contain, + errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { + return Image.asset("assets/images/logos/main_mohemm_logo.png", height: 50, width: 150); + }, + ) + ], + ), + ] ], ), ); diff --git a/lib/ui/marathon/widgets/marathon_footer.dart b/lib/ui/marathon/widgets/marathon_footer.dart index 4146cb3..2c82d94 100644 --- a/lib/ui/marathon/widgets/marathon_footer.dart +++ b/lib/ui/marathon/widgets/marathon_footer.dart @@ -41,9 +41,15 @@ class MarathonFooter extends StatelessWidget { @override Widget build(BuildContext context) { - return DefaultButton( - LocaleKeys.joinMarathon.tr(), - provider.isButtonEnabled ? () => provider.onJoinMarathonPressed(context) : null, - ).insideContainer; + return provider.isUpComingMarathon && !provider.canPlayDemo + ? DefaultButton( + LocaleKeys.joinMarathon.tr(), + provider.isButtonEnabled ? () => provider.onJoinMarathonPressed(context) : null, + ).insideContainer + : DefaultButton( + LocaleKeys.joinDemoMarathon.tr(), + () => provider.onJoinDemoMarathonPressed(context), + color: MyColors.yellowColorII, + ).insideContainer; } } diff --git a/lib/ui/marathon/widgets/marathon_progress_container.dart b/lib/ui/marathon/widgets/marathon_progress_container.dart index 20763b6..6a71b32 100644 --- a/lib/ui/marathon/widgets/marathon_progress_container.dart +++ b/lib/ui/marathon/widgets/marathon_progress_container.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/decorations_helper.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -14,24 +15,47 @@ class MarathonProgressContainer extends StatelessWidget { const MarathonProgressContainer({Key? key, required this.provider}) : super(key: key); + Widget getDemoMarathonerText() { + if (provider.isUserOutOfGame) { + return "0 ${LocaleKeys.marathoner.tr()}".toText14(); + } + return "1 ${LocaleKeys.marathoner.tr()}".toText14(); + } + @override Widget build(BuildContext context) { return Container( width: double.infinity, decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 13), + padding: EdgeInsets.fromLTRB(13, AppState().getIsDemoMarathon ? 5 : 18, 13, 18), child: Column( mainAxisSize: MainAxisSize.min, children: [ + AppState().getIsDemoMarathon + ? Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + decoration: BoxDecoration(color: MyColors.yellowColorII, borderRadius: BorderRadius.circular(100)), + child: LocaleKeys.demo.tr().toText10(color: MyColors.white).paddingAll(4), + ), + ], + ) + : const SizedBox(), + 5.height, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( decoration: BoxDecoration(color: MyColors.greenColor, borderRadius: BorderRadius.circular(5)), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8), - child: "${provider.currentQuestionNumber.toString()} / ${provider.marathonDetailModel.totalQuestions.toString()} ${LocaleKeys.question.tr()}".toText12(color: MyColors.white), + child: + "${provider.currentQuestionNumber.toString()} / ${AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.totalQuestions.toString() : provider.marathonDetailModel.totalQuestions.toString()} ${LocaleKeys.question.tr()}" + .toText12(color: MyColors.white), ), - "${provider.totalMarathoners} ${provider.totalMarathoners == 1 ? LocaleKeys.marathoner.tr() : LocaleKeys.marathoners.tr()}".toText14(), + AppState().getIsDemoMarathon + ? getDemoMarathonerText() + : "${provider.totalMarathoners} ${provider.totalMarathoners == 1 ? LocaleKeys.marathoner.tr() : LocaleKeys.marathoners.tr()}".toText14(), provider.questionCardStatus == QuestionCardStatus.question ? "00:${(provider.totalCurrentQuestionTime - provider.currentGapTime) < 10 ? "0${provider.totalCurrentQuestionTime - provider.currentGapTime}" : provider.totalCurrentQuestionTime - provider.currentGapTime}" .toText18(color: provider.totalCurrentQuestionTime - provider.currentGapTime < 5 ? MyColors.redColor : MyColors.black) @@ -39,14 +63,19 @@ class MarathonProgressContainer extends StatelessWidget { ], ), 12.height, - stepper(provider.currentQuestionNumber, provider.answerStatusesList, provider.marathonDetailModel.totalQuestions!, provider.isUserOutOfGame), + stepper( + provider.currentQuestionNumber, + provider.answerStatusesList, + AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.totalQuestions! : provider.marathonDetailModel.totalQuestions!, + provider.isUserOutOfGame, + ), 8.height, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - "${provider.currentQuestionNumber == 1 ? 0 : (((provider.currentQuestionNumber - 1) / provider.marathonDetailModel.totalQuestions!) * 100).toInt()}% ${LocaleKeys.completed.tr()}" + "${provider.currentQuestionNumber == 1 ? 0 : (((provider.currentQuestionNumber - 1) / (AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.totalQuestions! : provider.marathonDetailModel.totalQuestions!)) * 100).toInt()}% ${LocaleKeys.completed.tr()}" .toText14(), - provider.isUserOutOfGame ? LocaleKeys.youAreOutOfContest.tr().toText14(color: MyColors.redColor) : const SizedBox(), + provider.isUserOutOfGame ? LocaleKeys.youAreOutOfContest.tr().toText13(color: MyColors.redColor) : const SizedBox(), ], ), ], diff --git a/pubspec.yaml b/pubspec.yaml index d0758c5..95f6b3e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -138,6 +138,7 @@ flutter: - assets/icons/ - assets/lottie/ - assets/audio/ + - assets/json/ - assets/images/ - assets/images/worklist/ - assets/images/services_icons/