diff --git a/assets/images/congrats.gif b/assets/images/congrats.gif new file mode 100644 index 0000000..32818b2 Binary files /dev/null and b/assets/images/congrats.gif differ diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 65f81ea..d51e724 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -505,7 +505,12 @@ "favorite": "مفضلتي", "searchfromchat": "البحث من الدردشة", "yourAnswerCorrect": "إجابتك صحيحة", - "youMissedTheQuestion": "فاتك !! أنت خارج اللعبة. لكن يمكنك المتابعة.", - "wrongAnswer": "إجابة خاطئة! أنت خارج اللعبة. لكن يمكنك المتابعة." - + "youMissedTheQuestion": "نفد منك الوقت. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", + "wrongAnswer": "إجابتك غير صحيحة. أنت خارج اللعبة. لكن يمكنك الاستمرار وكمشاهد.", + "oops": "أوه!!!", + "winner": "الفائز", + "youWantToLeaveMarathon": "هل أنت متأكد أنك تريد العودة؟ سوف تخرج من المسابقة.", + "ourSponsor": "راعينا:", + "startingIn": "يبدأ في", + "youAreOutOfContest": "أنت خارج المسابقة." } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 647a956..97e8c5c 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -502,10 +502,16 @@ "codeExpire": "The verification code has been expired", "allQuestionsCorrect": "You have answered all questions correct", "typeheretoreply": "Type here to reply", - "favorite" : "My Favorites", + "favorite": "My Favorites", "searchfromchat": "Search from chat", "yourAnswerCorrect": "Your answer is correct", - "youMissedTheQuestion": "You Missed !! You are out of the game. But you can follow up.", - "wrongAnswer": "Wrong Answer! You are out of the game. But you can follow up." + "youMissedTheQuestion": "You ran out of time. You are out of the game. But you can continue and as a viewer.", + "wrongAnswer": "Your answer is Incorrect. You are out of the game. But you can continue and as a viewer.", + "oops": "Ooopsss!!!!", + "winner": "WINNER", + "youWantToLeaveMarathon": "Are you sure you want to go back? You will be out of the contest.", + "ourSponsor": "Our Sponsor:", + "startingIn": "Starting in", + "youAreOutOfContest": "You are out of the contest." } \ No newline at end of file diff --git a/assets/lottie/marathon_waiting.json b/assets/lottie/marathon_waiting.json new file mode 100644 index 0000000..83e4756 --- /dev/null +++ b/assets/lottie/marathon_waiting.json @@ -0,0 +1 @@ +{"nm":"Loading_003","mn":"","layers":[{"ty":0,"nm":"2","mn":"","sr":1,"st":0,"op":600.000024438501,"ip":0,"hd":false,"cl":"","ln":"","ddd":0,"bm":0,"tt":0,"hasMask":false,"td":0,"ao":0,"ks":{"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[250,250,0],"ix":2},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10}},"ef":[],"w":500,"h":500,"refId":"comp_0","ind":0},{"ty":0,"nm":"1","mn":"","sr":1,"st":0,"op":600.000024438501,"ip":0,"hd":false,"cl":"","ln":"","ddd":0,"bm":0,"tt":0,"hasMask":false,"td":0,"ao":0,"ks":{"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[250,250,0],"ix":2},"sa":{"a":0,"k":0},"o":{"a":0,"k":60,"ix":11},"r":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-31],"t":4},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-31],"t":207.000008431283}],"ix":10}},"ef":[],"w":500,"h":500,"refId":"comp_1","ind":1}],"ddd":0,"h":500,"w":500,"meta":{"a":"","k":"","d":"","g":"@lottiefiles/toolkit-js 0.17.4","tc":"#ffffff"},"v":"5.2.1","fr":29.9700012207031,"op":202.000008227629,"ip":9.00000036657752,"assets":[{"nm":"","mn":"","layers":[{"ty":4,"nm":"Layer 3 Outlines 3","mn":"","sr":1,"st":5.00000020365417,"op":605.000024642155,"ip":-19.0000007738859,"hd":false,"cl":"","ln":"","ddd":0,"bm":0,"tt":0,"hasMask":false,"td":1,"ao":0,"ks":{"a":{"a":0,"k":[186.018,192.618,0],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[97.292,100.917,100],"t":4},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[104.224,99.892,100],"t":108},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[97.292,100.917,100],"t":209.000008512745}],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[252.209,249.449,0],"ix":2},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[310.866],"t":4},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-49],"t":209.000008512745}],"ix":10}},"ef":[],"shapes":[{"ty":"gr","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":1,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[51.471,-19.6],[51.29,75.368],[-11.48,42.136],[-85.813,28.535],[-16.737,-1.394],[-18.031,-37.988],[22.567,-60.623]],"o":[[-20.195,7.689],[-24.566,-36.096],[23.791,-87.319],[15.938,-5.3],[41.874,3.489],[28.123,59.252],[-20.321,54.592]],"v":[[18.613,169.26],[-146.062,126.343],[-172.423,1.333],[1.405,-192.793],[62.244,-200.318],[155.78,-124.529],[159.191,64.737]]},"ix":2}},{"ty":"gr","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":2,"cix":2,"np":0,"it":[{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"fl","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.098,0.1137,0.1451],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100.261,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[184.153,201.962],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":0},{"ty":4,"nm":"Layer 5 Outlines 3","mn":"","sr":1,"st":5.00000020365417,"op":605.000024642155,"ip":-19.0000007738859,"hd":false,"cl":"","ln":"","ddd":0,"bm":0,"tt":2,"hasMask":false,"td":0,"ao":0,"ks":{"a":{"a":0,"k":[216.251,216.449,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[252.209,249.449,0],"ix":2},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10}},"ef":[],"shapes":[{"ty":"gr","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":1,"cix":2,"np":2,"it":[{"ty":"gr","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":1,"cix":2,"np":1,"it":[{"ty":"sh","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 4","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[119.432,0],[0,-119.541],[-119.432,0],[0,119.542]],"o":[[-119.432,0],[0,119.542],[119.432,0],[0,-119.541]],"v":[[0,-216.449],[-216.25,0],[0,216.449],[216.251,0]]},"ix":2}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gf","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Graphic - G-Fill","nm":"Gradient Fill 1","e":{"a":0,"k":[65.201,-74.966],"ix":6},"g":{"p":3,"k":{"a":0,"k":[0,0.16862745098039217,0.7215686274509804,0.6588235294117647,0.455,0.13725490196078433,0.615686274509804,0.5607843137254902,0.999,0.11372549019607843,0.5725490196078431,0.6666666666666666],"ix":9}},"t":1,"a":{"a":0,"k":0},"s":{"a":0,"k":[-130.068,76.804],"ix":5},"r":1,"o":{"a":0,"k":100,"ix":10}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[216.251,216.449],"ix":2},"r":{"a":0,"k":-149.651,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":1}],"id":"comp_0","fr":30},{"nm":"","mn":"","layers":[{"ty":4,"nm":"Layer 3 Outlines 3","mn":"","sr":1,"st":5.00000020365417,"op":605.000024642155,"ip":-19.0000007738859,"hd":false,"cl":"","ln":"","ddd":0,"bm":0,"tt":0,"hasMask":false,"td":1,"ao":0,"ks":{"a":{"a":0,"k":[186.018,192.618,0],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[97.292,100.917,100],"t":4},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[104.224,99.892,100],"t":108},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[97.292,100.917,100],"t":209.000008512745}],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[252.209,249.449,0],"ix":2},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-49],"t":4},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[310.866],"t":209.000008512745}],"ix":10}},"ef":[],"shapes":[{"ty":"gr","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":1,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[51.471,-19.6],[51.29,75.368],[-11.48,42.136],[-85.813,28.535],[-16.737,-1.394],[-18.031,-37.988],[22.567,-60.623]],"o":[[-20.195,7.689],[-24.566,-36.096],[23.791,-87.319],[15.938,-5.3],[41.874,3.489],[28.123,59.252],[-20.321,54.592]],"v":[[18.613,169.26],[-146.062,126.343],[-172.423,1.333],[1.405,-192.793],[62.244,-200.318],[155.78,-124.529],[159.191,64.737]]},"ix":2}},{"ty":"gr","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":2,"cix":2,"np":0,"it":[{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"fl","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.098,0.1137,0.1451],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100.261,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[184.153,201.962],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":0},{"ty":4,"nm":"Layer 5 Outlines 3","mn":"","sr":1,"st":5.00000020365417,"op":605.000024642155,"ip":-19.0000007738859,"hd":false,"cl":"","ln":"","ddd":0,"bm":0,"tt":2,"hasMask":false,"td":0,"ao":0,"ks":{"a":{"a":0,"k":[216.251,216.449,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[252.209,249.449,0],"ix":2},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10}},"ef":[],"shapes":[{"ty":"gr","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":1,"cix":2,"np":2,"it":[{"ty":"gr","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":1,"cix":2,"np":1,"it":[{"ty":"sh","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 4","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[119.432,0],[0,-119.541],[-119.432,0],[0,119.542]],"o":[[-119.432,0],[0,119.542],[119.432,0],[0,-119.541]],"v":[[0,-216.449],[-216.25,0],[0,216.449],[216.251,0]]},"ix":2}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gf","bm":0,"cl":"","ln":"","hd":false,"mn":"ADBE Vector Graphic - G-Fill","nm":"Gradient Fill 1","e":{"a":0,"k":[65.201,-74.966],"ix":6},"g":{"p":3,"k":{"a":0,"k":[0,0.07058823529411765,0.3411764705882353,0.396078431372549,0.424,0.07058823529411765,0.3411764705882353,0.396078431372549,1,0.07058823529411765,0.3411764705882353,0.396078431372549],"ix":9}},"t":1,"a":{"a":0,"k":0},"s":{"a":0,"k":[-130.068,76.804],"ix":5},"r":1,"o":{"a":0,"k":100,"ix":10}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[216.251,216.449],"ix":2},"r":{"a":0,"k":-149.651,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":1}],"id":"comp_1","fr":30}]} \ No newline at end of file diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index 3eab65b..e30af91 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -65,13 +65,10 @@ class DashboardApiClient { }, url, postParams); } - Future> getAccrualBalances(String effectiveDate, {String? empID}) async { + Future> getAccrualBalances(String effectiveDate) async { String url = "${ApiConsts.erpRest}GET_ACCRUAL_BALANCES"; Map postParams = {"P_EFFECTIVE_DATE": effectiveDate}; postParams.addAll(AppState().postParamsJson); - if (empID!.isNotEmpty) { - postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; - } return await ApiClient().postJsonForObject((json) { GenericResponseModel responseData = GenericResponseModel.fromJson(json); return responseData.getAccrualBalancesList ?? []; diff --git a/lib/api/leave_balance_api_client.dart b/lib/api/leave_balance_api_client.dart index bb3f129..cd577ba 100644 --- a/lib/api/leave_balance_api_client.dart +++ b/lib/api/leave_balance_api_client.dart @@ -17,33 +17,27 @@ class LeaveBalanceApiClient { factory LeaveBalanceApiClient() => _instance; - Future> getAbsenceTransactions(int pSelectedResopID, {String? empID}) async { + Future> getAbsenceTransactions(int pSelectedResopID) async { String url = "${ApiConsts.erpRest}GET_ABSENCE_TRANSACTIONS"; Map postParams = {"P_PAGE_LIMIT": 50, "P_PAGE_NUM": 1, "P_MENU_TYPE": "E", "P_SELECTED_RESP_ID": pSelectedResopID}; postParams.addAll(AppState().postParamsJson); - if (empID!.isNotEmpty) { - postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; - } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.getAbsenceTransactionList ?? []; }, url, postParams); } - Future> getAbsenceAttendanceTypes({String? empID}) async { + Future> getAbsenceAttendanceTypes() async { String url = "${ApiConsts.erpRest}GET_ABSENCE_ATTENDANCE_TYPES"; Map postParams = {}; postParams.addAll(AppState().postParamsJson); - if (empID!.isNotEmpty) { - postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; - } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.getAbsenceAttendanceTypesList ?? []; }, url, postParams); } - Future calculateAbsenceDuration(int pAbsenceAttendanceTypeID, String pDateStart, String pDateEnd, int pSelectedResopID, {String? empID}) async { + Future calculateAbsenceDuration(int pAbsenceAttendanceTypeID, String pDateStart, String pDateEnd, int pSelectedResopID) async { String url = "${ApiConsts.erpRest}CALCULATE_ABSENCE_DURATION"; Map postParams = { "P_ABSENCE_ATTENDANCE_TYPE_ID": pAbsenceAttendanceTypeID, @@ -55,22 +49,16 @@ class LeaveBalanceApiClient { "P_TIME_START": null, }; postParams.addAll(AppState().postParamsJson); - if (empID!.isNotEmpty) { - postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; - } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.calculateAbsenceDuration!; }, url, postParams); } - Future> getAbsenceDffStructure(String pDescFlexContextCode, String pFunctionName, int pSelectedResopID, {String? empID}) async { + Future> getAbsenceDffStructure(String pDescFlexContextCode, String pFunctionName, int pSelectedResopID) async { String url = "${ApiConsts.erpRest}GET_ABSENCE_DFF_STRUCTURE"; Map postParams = {"P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, "P_FUNCTION_NAME": pFunctionName, "P_MENU_TYPE": "E", "P_SELECTED_RESP_ID": pSelectedResopID}; postParams.addAll(AppState().postParamsJson); - if (empID!.isNotEmpty) { - postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; - } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.getAbsenceDffStructureList ?? []; @@ -79,7 +67,7 @@ class LeaveBalanceApiClient { Future validateAbsenceTransaction( String pDescFlexContextCode, String pFunctionName, int pAbsenceAttendanceTypeID, String pReplacementUserName, String pDateStart, String pDateEnd, int pSelectedResopID, Map data, - {String comments = "", String? empID}) async { + {String comments = ""}) async { String url = "${ApiConsts.erpRest}VALIDATE_ABSENCE_TRANSACTION"; Map postParams = { "P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, @@ -98,9 +86,6 @@ class LeaveBalanceApiClient { }; postParams.addAll(data); postParams.addAll(AppState().postParamsJson); - if (empID!.isNotEmpty) { - postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; - } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData; @@ -109,7 +94,7 @@ class LeaveBalanceApiClient { Future submitAbsenceTransaction( String pDescFlexContextCode, String pFunctionName, int pAbsenceAttendanceTypeID, String pReplacementUserName, String pDateStart, String pDateEnd, int pSelectedResopID, Map data, - {String comments = "", String? empID}) async { + {String comments = ""}) async { String url = "${ApiConsts.erpRest}SUBMIT_ABSENCE_TRANSACTION"; Map postParams = { "P_DESC_FLEX_CONTEXT_CODE": pDescFlexContextCode, @@ -128,9 +113,6 @@ class LeaveBalanceApiClient { }; postParams.addAll(data); postParams.addAll(AppState().postParamsJson); - if (empID!.isNotEmpty) { - postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; - } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.sumbitAbsenceTransactionList!; @@ -147,7 +129,7 @@ class LeaveBalanceApiClient { }, url, postParams); } - Future startAbsenceApprovalProcess(int pTransactionID, String comments, int pSelectedResopID, {String? empID}) async { + Future startAbsenceApprovalProcess(int pTransactionID, String comments, int pSelectedResopID) async { String url = "${ApiConsts.erpRest}START_ABSENCE_APPROVAL_PROCESS"; Map postParams = { "P_TRANSACTION_ID": pTransactionID, @@ -156,9 +138,6 @@ class LeaveBalanceApiClient { "P_MENU_TYPE": "E", }; postParams.addAll(AppState().postParamsJson); - if (empID!.isNotEmpty) { - postParams['P_SELECTED_EMPLOYEE_NUMBER'] = empID; - } return await ApiClient().postJsonForObject((json) { GenericResponseModel? responseData = GenericResponseModel.fromJson(json); return responseData.startAbsenceApprovalProccess!; diff --git a/lib/api/marathon/marathon_api_client.dart b/lib/api/marathon/marathon_api_client.dart index 1ec117d..132ec30 100644 --- a/lib/api/marathon/marathon_api_client.dart +++ b/lib/api/marathon/marathon_api_client.dart @@ -1,22 +1,19 @@ import 'dart:convert'; -import 'package:flutter/material.dart'; import 'package:http/http.dart'; import 'package:logger/logger.dart' as L; -import 'package:logging/logging.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_generic_model.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_model.dart'; import 'package:mohem_flutter_app/models/marathon/question_model.dart'; -import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; -import 'package:provider/provider.dart'; -import 'package:signalr_netcore/http_connection_options.dart'; import 'package:signalr_netcore/hub_connection.dart'; -import 'package:signalr_netcore/hub_connection_builder.dart'; class MarathonApiClient { + late HubConnection hubConnection; + L.Logger logger = L.Logger(); + Future getMarathonToken() async { String employeeUserName = AppState().getUserName ?? ""; String employeeSession = AppState().postParamsObject?.pSessionId.toString() ?? ""; @@ -55,11 +52,9 @@ class MarathonApiClient { AppState().setMarathonProjectId = marathonModel.data[0]["id"] ?? ""; return marathonModel.data[0]["id"] ?? ""; } else { - //TODO : DO ERROR HANDLING HERE return ""; } } else { - //TODO : DO ERROR HANDLING HERE return ""; } } @@ -70,9 +65,14 @@ class MarathonApiClient { Response response = await ApiClient().getJsonForResponse(ApiConsts.marathonUpcomingUrl + payrollString, token: AppState().getMarathonToken ?? await getMarathonToken()); var json = jsonDecode(response.body); + logger.i("json in getMarathonDetails: $json"); MarathonGenericModel marathonGenericModel = MarathonGenericModel.fromJson(json); + if (marathonGenericModel.data == null) { + return MarathonDetailModel(); + } + MarathonDetailModel marathonDetailModel = MarathonDetailModel.fromJson(marathonGenericModel.data); AppState().setMarathonProjectId = marathonDetailModel.id!; @@ -80,99 +80,165 @@ class MarathonApiClient { return marathonDetailModel; } - late HubConnection hubConnection; - L.Logger logger = L.Logger(); + Future joinMarathonAsParticipant() async { + Map jsonObject = { + "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER ?? "", + "employeeName": AppState().memberInformationList!.eMPLOYEENAME ?? "", + "marathonId": AppState().getMarathonProjectId!, + }; - Future buildHubConnection(BuildContext context) async { - HttpConnectionOptions httpOptions = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); - hubConnection = HubConnectionBuilder() - .withUrl( - ApiConsts.marathonHubConnectionUrl + "?employeeNumber=${AppState().memberInformationList!.eMPLOYEENUMBER ?? ""}&employeeName=${AppState().memberInformationList!.eMPLOYEENAME ?? ""}", - options: httpOptions, - ) - .withAutomaticReconnect( - retryDelays: [2000, 5000, 10000, 20000], - ) - .configureLogging( - Logger("Logging"), - ) - .build(); - hubConnection.onclose( - ({Exception? error}) { - logger.i("onclose"); - }, - ); - hubConnection.onreconnecting( - ({Exception? error}) { - logger.i("onreconnecting"); - }, - ); - hubConnection.onreconnected( - ({String? connectionId}) { - logger.i("onreconnected"); - }, - ); - if (hubConnection.state != HubConnectionState.Connected) { - await hubConnection.start(); - logger.i("Started HubConnection"); - - await hubConnection.invoke( - "AddParticipant", - args: [ - { - "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER ?? "", - "employeeName": AppState().memberInformationList!.eMPLOYEENAME ?? "", - "marathonId": AppState().getMarathonProjectId, - } - ], - ).catchError((e) { - logger.i("Error in AddParticipant: $e"); - }); - - context.read().addItemToList(ApiConsts.dummyQuestion); - - await hubConnection.invoke( - "SendQuestionToParticipant", - args: [ - { - "marathonId": "${AppState().getMarathonProjectId}", - } - ], - ).catchError((e) { - logger.i("Error in SendQuestionToParticipant: $e"); - }); - - try { - hubConnection.on("OnSendQuestionToParticipant", (List? arguments) { - onSendQuestionToParticipant(arguments, context); - }); - } catch (e, s) { - logger.i("Error in OnSendQuestionToParticipant"); - } + Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonJoinParticipantUrl, jsonObject, token: AppState().getMarathonToken ?? await getMarathonToken()); + + var json = jsonDecode(response.body); + + MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json); + + if (marathonModel.statusCode == 208) { + // means participant is already in the marathon i.e already joined + return true; + } - try { - hubConnection.on("OnParticipantJoin", (List? arguments) { - onParticipantJoin(arguments, context); - }); - } catch (e, s) { - logger.i("Error in OnParticipantJoin"); + if (marathonModel.statusCode == 200) { + if (marathonModel.data != null && marathonModel.isSuccessful == true) { + logger.i("joinMarathonAsParticipant: ${marathonModel.data}"); + return true; + } else { + return false; } + } else { + return false; } } - Future onSendQuestionToParticipant(List? arguments, BuildContext context) async { - logger.i("onSendQuestionToParticipant arguments: $arguments"); + Future getNextQuestion({required String? questionId, required String marathonId}) async { + Map jsonObject = { + "questionId": questionId, + "marathonId": marathonId, + }; - if (arguments != null) { - Map data = arguments.first! as Map; - var json = data["data"]; - QuestionModel newQuestion = QuestionModel.fromJson(json); - context.read().onNewQuestionReceived(newQuestion); + Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonNextQuestionUrl, jsonObject, token: AppState().getMarathonToken ?? await getMarathonToken()); + + var json = jsonDecode(response.body); + + var data = json["data"]; + + if (data != null) { + QuestionModel newQuestion = QuestionModel.fromJson(data); + return newQuestion; + } else { + return null; } } - Future onParticipantJoin(List? arguments, BuildContext context) async { - logger.i("OnParticipantJoin arguments: $arguments"); - context.watch().totalMarathoners++; + Future submitSelectedOption({required String? selectedAnswerId}) async { + Map jsonObject = {"selectedOptionId": selectedAnswerId}; + + Response response = await ApiClient().postJsonForResponse(ApiConsts.marathonSubmitAnswerUrl, jsonObject, token: AppState().getMarathonToken ?? await getMarathonToken()); + + var json = jsonDecode(response.body); + logger.i("json: $json"); + + MarathonGenericModel marathonModel = MarathonGenericModel.fromJson(json); + + if (marathonModel.isSuccessful == null) { + return false; + } + + return marathonModel.isSuccessful!; } + +// Future buildHubConnection(BuildContext context, String prizeId) async { +// HttpConnectionOptions httpOptions = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); +// hubConnection = HubConnectionBuilder() +// .withUrl( +// ApiConsts.marathonHubConnectionUrl + "?employeeNumber=${AppState().memberInformationList!.eMPLOYEENUMBER ?? ""}&employeeName=${AppState().memberInformationList!.eMPLOYEENAME ?? ""}", +// options: httpOptions, +// ) +// .withAutomaticReconnect( +// retryDelays: [2000, 5000, 10000, 20000], +// ) +// .configureLogging( +// Logger("Logging"), +// ) +// .build(); +// hubConnection.onclose( +// ({Exception? error}) { +// logger.i("onclose"); +// }, +// ); +// hubConnection.onreconnecting( +// ({Exception? error}) { +// logger.i("onreconnecting"); +// }, +// ); +// hubConnection.onreconnected( +// ({String? connectionId}) { +// logger.i("onreconnected"); +// }, +// ); +// if (hubConnection.state != HubConnectionState.Connected) { +// await hubConnection.start(); +// logger.i("Started HubConnection"); +// +// await hubConnection.invoke( +// "AddParticipant", +// args: [ +// { +// "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER ?? "", +// "employeeName": AppState().memberInformationList!.eMPLOYEENAME ?? "", +// "marathonId": AppState().getMarathonProjectId, +// "prizeId": "8577B2E8-5DD7-43F0-10DD-08DACB0AC064", +// } +// ], +// ).catchError((e) { +// logger.i("Error in AddParticipant: $e"); +// }); +// +// context.read().addItemToList(ApiConsts.dummyQuestion); +// +// await hubConnection.invoke( +// "SendQuestionToParticipant", +// args: [ +// { +// "marathonId": "${AppState().getMarathonProjectId}", +// } +// ], +// ).catchError((e) { +// Utils.confirmDialog(context, e.toString()); +// logger.i("Error in SendQuestionToParticipant: $e"); +// }); +// +// try { +// hubConnection.on("OnSendQuestionToParticipant", (List? arguments) { +// onSendQuestionToParticipant(arguments, context); +// }); +// } catch (e, s) { +// logger.i("Error in OnSendQuestionToParticipant"); +// } +// +// try { +// hubConnection.on("OnParticipantJoin", (List? arguments) { +// onParticipantJoin(arguments, context); +// }); +// } catch (e, s) { +// logger.i("Error in OnParticipantJoin"); +// } +// } +// } +// +// Future onSendQuestionToParticipant(List? arguments, BuildContext context) async { +// logger.i("onSendQuestionToParticipant arguments: $arguments"); +// +// if (arguments != null) { +// Map data = arguments.first! as Map; +// var json = data["data"]; +// QuestionModel newQuestion = QuestionModel.fromJson(json); +// AppRoutes.navigatorKey.currentContext!.read().onNewQuestionReceived(newQuestion); +// } +// } +// +// Future onParticipantJoin(List? arguments, BuildContext context) async { +// logger.i("OnParticipantJoin arguments: $arguments"); +// context.watch().totalMarathoners++; +// } } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 45bfcf9..1230c8b 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -2,7 +2,7 @@ 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://uat.hmgwebservices.com"; // UAT 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 @@ -23,19 +23,23 @@ class ApiConsts { static String chatSingleUserHistoryUrl = chatServerBaseApiUrl + "UserChatHistory/"; static String chatMediaImageUploadUrl = chatServerBaseApiUrl + "shared/"; static String chatFavUser = chatServerBaseApiUrl + "FavUser/"; - static String chatUserImages = chatServerBaseUrl + "empservice/api/employee/"; + static String chatUserImages = chatServerBaseUrl + "empservice/api/employee/"; + //Brain Marathon Constants - static String marathonBaseUrl = "https://marathoon.com/service/"; - static String marathonParticipantLoginUrl = marathonBaseUrl + "api/auth/participantlogin"; - static String marathonProjectGetUrl = marathonBaseUrl + "api/Project/Project_Get"; - static String marathonUpcomingUrl = marathonBaseUrl + "api/marathon/upcoming/"; - static String marathonHubConnectionUrl = marathonBaseUrl + "MarathonBroadCast"; + static String marathonBaseUrl = "https://marathoon.com/service/api/"; + static String marathonParticipantLoginUrl = marathonBaseUrl + "auth/participantlogin"; + static String marathonProjectGetUrl = marathonBaseUrl + "Project/Project_Get"; + static String marathonUpcomingUrl = marathonBaseUrl + "marathon/upcoming/"; + static String marathonJoinParticipantUrl = marathonBaseUrl + "participant/participant_join"; + static String marathonNextQuestionUrl = marathonBaseUrl + "question/next"; + static String marathonSubmitAnswerUrl = marathonBaseUrl + "question/submit"; + static String marathonQualifiersUrl = marathonBaseUrl + "winner/getWinner/"; + static String marathonSelectedWinner = marathonBaseUrl + "winner/getSelectedWinner/"; //DummyCards for the UI static CardContent dummyQuestion = const CardContent(); - } class SharedPrefsConsts { diff --git a/lib/classes/lottie_consts.dart b/lib/classes/lottie_consts.dart index 24dc423..7846f6c 100644 --- a/lib/classes/lottie_consts.dart +++ b/lib/classes/lottie_consts.dart @@ -4,6 +4,7 @@ class MyLottieConsts { static const String celebrate2Lottie = "assets/lottie/celebrate2.json"; static const String winnerLottie = "assets/lottie/winner3.json"; static const String allQuestions = "assets/lottie/all_questions.json"; + static const String marathonWaiting = "assets/lottie/marathon_waiting.json"; static const String wrongAnswerGif = "assets/images/wrong_answer.gif"; - + static const String congratsGif = "assets/images/congrats.gif"; } diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 7cf8a35..d1b6b08 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -9,7 +9,6 @@ import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart'; import 'package:mohem_flutter_app/ui/landing/itg/survey_screen.dart'; -import 'package:mohem_flutter_app/ui/landing/today_attendance_screen.dart'; import 'package:mohem_flutter_app/ui/landing/today_attendance_screen2.dart'; import 'package:mohem_flutter_app/ui/leave_balance/add_leave_balance_screen.dart'; import 'package:mohem_flutter_app/ui/leave_balance/leave_balance_screen.dart'; @@ -21,6 +20,8 @@ import 'package:mohem_flutter_app/ui/login/verify_last_login_screen.dart'; import 'package:mohem_flutter_app/ui/login/verify_login_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_intro_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_screen.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_sponsor_video_screen.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_waiting_screen.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_winner_selection.dart'; import 'package:mohem_flutter_app/ui/marathon/winner_screen.dart'; import 'package:mohem_flutter_app/ui/misc/request_submit_screen.dart'; @@ -73,6 +74,8 @@ import 'package:mohem_flutter_app/ui/work_list/worklist_detail_screen.dart'; import 'package:mohem_flutter_app/ui/work_list/worklist_settings.dart'; class AppRoutes { + static GlobalKey navigatorKey = GlobalKey(); + static const String splash = "/splash"; static const String registerSelection = "/registerSelection"; static const String loginVerifyAccount = "/loginVerifyAccount"; @@ -185,6 +188,8 @@ class AppRoutes { static const String marathonScreen = "/marathonScreen"; static const String marathonWinnerSelection = "/marathonWinnerSelection"; static const String marathonWinnerScreen = "/marathonWinnerScreen"; + static const String marathonSponsorVideoScreen = "/marathonSponsorVideoScreen"; + static const String marathonWaitingScreen = "/marathonWaitingScreen"; static final Map routes = { login: (BuildContext context) => LoginScreen(), @@ -293,5 +298,7 @@ class AppRoutes { marathonScreen: (BuildContext context) => MarathonScreen(), marathonWinnerSelection: (BuildContext context) => MarathonWinnerSelection(), marathonWinnerScreen: (BuildContext context) => WinnerScreen(), + marathonSponsorVideoScreen: (BuildContext context) => const SponsorVideoScreen(), + marathonWaitingScreen: (BuildContext context) => const MarathonWaitingScreen(), }; } diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 3546f6b..3261149 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -118,8 +118,9 @@ extension EmailValidator on String { style: TextStyle(color: color ?? MyColors.darkTextColor, fontSize: 17, letterSpacing: -0.68, fontWeight: isBold ? FontWeight.bold : FontWeight.w600), ); - Widget toText18({Color? color, bool isBold = false}) => Text( + Widget toText18({Color? color, bool isBold = false, bool isCentered = false}) => Text( this, + textAlign: isCentered ? TextAlign.center : null, style: TextStyle(fontSize: 18, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -1.08), ); diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 9b9d1c3..c862385 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -493,5 +493,11 @@ abstract class LocaleKeys { static const yourAnswerCorrect = 'yourAnswerCorrect'; static const youMissedTheQuestion = 'youMissedTheQuestion'; static const wrongAnswer = 'wrongAnswer'; + static const oops = 'oops'; + static const winner = 'winner'; + static const youWantToLeaveMarathon = 'youWantToLeaveMarathon'; + static const ourSponsor = 'ourSponsor'; + static const startingIn = 'startingIn'; + static const youAreOutOfContest = 'youAreOutOfContest'; } diff --git a/lib/main.dart b/lib/main.dart index 4d686b8..4709be1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,11 +3,11 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:logger/logger.dart'; -import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/generated/codegen_loader.g.dart'; import 'package:mohem_flutter_app/models/post_params_model.dart'; +import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/provider/eit_provider_model.dart'; import 'package:mohem_flutter_app/theme/app_theme.dart'; @@ -92,6 +92,7 @@ class MyApp extends StatelessWidget { MonthYearPickerLocalizations.delegate, ); return MaterialApp( + navigatorKey: AppRoutes.navigatorKey, builder: (BuildContext context, Widget? child) { return MediaQuery( data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), @@ -249,3 +250,4 @@ class MyApp extends StatelessWidget { // }); // } // } + diff --git a/lib/models/marathon/marathon_model.dart b/lib/models/marathon/marathon_model.dart index b32530c..6fd1f5c 100644 --- a/lib/models/marathon/marathon_model.dart +++ b/lib/models/marathon/marathon_model.dart @@ -126,10 +126,10 @@ class Projects { class Sponsors { String? id; String? nameEn; - Null? nameAr; + String? nameAr; String? image; - Null? video; - Null? logo; + String? video; + String? logo; List? sponsorPrizes; Sponsors( @@ -186,7 +186,7 @@ class SponsorPrizes { } Map toJson() { - Map data = new Map(); + Map data = {}; data['id'] = id; data['marathonPrizeEn'] = marathonPrizeEn; data['marathonPrizeAr'] = marathonPrizeAr; diff --git a/lib/models/marathon/question_model.dart b/lib/models/marathon/question_model.dart index 0bb42cd..4501947 100644 --- a/lib/models/marathon/question_model.dart +++ b/lib/models/marathon/question_model.dart @@ -14,6 +14,7 @@ class QuestionModel { String? gapText; String? gapImage; int? questOptionsLimit; + int? remainingParticipantCount; List? questionOptions; QuestionModel({ @@ -28,6 +29,7 @@ class QuestionModel { String? gapText, String? gapImage, int? questOptionsLimit, + int? remainingParticipantCount, List? questionOptions, }); @@ -43,6 +45,7 @@ class QuestionModel { gapText = json['gapText']; gapImage = json['gapImage']; questOptionsLimit = json['questOptionsLimit']; + remainingParticipantCount = json['remainingParticipantCount']; if (json['questionOptions'] != null) { questionOptions = []; json['questionOptions'].forEach((v) { @@ -64,6 +67,7 @@ class QuestionModel { data['gapText'] = gapText; data['gapImage'] = gapImage; data['questOptionsLimit'] = questOptionsLimit; + data['remainingParticipantCount'] = remainingParticipantCount; if (questionOptions != null) { data['questionOptions'] = questionOptions!.map((v) => v.toJson()).toList(); } diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index f06a405..4e6988b 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -6,7 +6,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:mohem_flutter_app/api/dashboard_api_client.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/utils.dart'; @@ -322,9 +321,11 @@ class _DashboardScreenState extends State { ), ], ).paddingOnly(left: 21, right: 21, top: 7), - context.watch().isLoading ? MarathonBannerShimmer().paddingAll(20) : MarathonBanner().paddingAll(20), + context.watch().isLoading + ? const MarathonBannerShimmer().paddingAll(20) + : MarathonBanner(isMarathonUpcoming: context.watch().isUpComingMarathon).paddingAll(20), ServicesWidget(), - // 8.height, + 8.height, Container( width: double.infinity, padding: const EdgeInsets.only(top: 31), diff --git a/lib/ui/leave_balance/add_leave_balance_screen.dart b/lib/ui/leave_balance/add_leave_balance_screen.dart index 4b4d73f..1a4958e 100644 --- a/lib/ui/leave_balance/add_leave_balance_screen.dart +++ b/lib/ui/leave_balance/add_leave_balance_screen.dart @@ -4,7 +4,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/leave_balance_api_client.dart'; -import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/date_uitl.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; @@ -25,8 +24,7 @@ import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; class AddLeaveBalanceScreen extends StatefulWidget { - final String selectedEmp; - AddLeaveBalanceScreen({this.selectedEmp ='',Key? key}) : super(key: key); + AddLeaveBalanceScreen({Key? key}) : super(key: key); @override _AddLeaveBalanceScreenState createState() { @@ -45,8 +43,6 @@ class _AddLeaveBalanceScreenState extends State { String comment = ""; ReplacementList? selectedReplacementEmployee; - dynamic dynamicParams; - String selectedEmp =""; DateTime selectedDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day); @override @@ -58,7 +54,7 @@ class _AddLeaveBalanceScreenState extends State { void getAbsenceAttendanceTypes() async { try { Utils.showLoading(context); - absenceList = await LeaveBalanceApiClient().getAbsenceAttendanceTypes(empID: selectedEmp); + absenceList = await LeaveBalanceApiClient().getAbsenceAttendanceTypes(); Utils.hideLoading(context); setState(() {}); } catch (ex) { @@ -71,7 +67,7 @@ class _AddLeaveBalanceScreenState extends State { try { Utils.showLoading(context); getabsenceDffStructureList.clear(); - getabsenceDffStructureList = await LeaveBalanceApiClient().getAbsenceDffStructure(selectedAbsenceType!.dESCFLEXCONTEXTCODE!, "HR_LOA_SS", -999, empID: selectedEmp); + getabsenceDffStructureList = await LeaveBalanceApiClient().getAbsenceDffStructure(selectedAbsenceType!.dESCFLEXCONTEXTCODE!, "HR_LOA_SS", -999); Utils.hideLoading(context); setState(() {}); } catch (ex) { @@ -84,7 +80,7 @@ class _AddLeaveBalanceScreenState extends State { try { Utils.showLoading(context); CalculateAbsenceDuration duration = await LeaveBalanceApiClient() - .calculateAbsenceDuration(selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, Utils.getMonthNamedFormat(startDateTime!), Utils.getMonthNamedFormat(endDateTime!), -999, empID: selectedEmp); + .calculateAbsenceDuration(selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, Utils.getMonthNamedFormat(startDateTime!), Utils.getMonthNamedFormat(endDateTime!), -999); totalDays = duration.pABSENCEDAYS?.toInt(); Utils.hideLoading(context); @@ -113,17 +109,16 @@ class _AddLeaveBalanceScreenState extends State { } } } - await LeaveBalanceApiClient() - .validateAbsenceTransaction( - selectedAbsenceType!.dESCFLEXCONTEXTCODE!, - "HR_LOA_SS", - selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, - selectedReplacementEmployee != null ? selectedReplacementEmployee!.userName! : "", - DateUtil.getFormattedDate(startDateTime!, "MM/dd/yyyy"), - DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), - -999, - dffDataMap, - comments: comment,empID: selectedEmp ); + await LeaveBalanceApiClient().validateAbsenceTransaction( + selectedAbsenceType!.dESCFLEXCONTEXTCODE!, + "HR_LOA_SS", + selectedAbsenceType!.aBSENCEATTENDANCETYPEID!, + selectedReplacementEmployee != null ? selectedReplacementEmployee!.userName! : "", + DateUtil.getFormattedDate(startDateTime!, "MM/dd/yyyy"), + DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), + -999, + dffDataMap, + comments: comment); SumbitAbsenceTransactionList submit = await LeaveBalanceApiClient().submitAbsenceTransaction( selectedAbsenceType!.dESCFLEXCONTEXTCODE!, @@ -134,8 +129,7 @@ class _AddLeaveBalanceScreenState extends State { DateUtil.getFormattedDate(endDateTime!, "MM/dd/yyyy"), -999, dffDataMap, - comments: comment, - empID: selectedEmp); + comments: comment); Utils.hideLoading(context); @@ -158,18 +152,6 @@ class _AddLeaveBalanceScreenState extends State { @override Widget build(BuildContext context) { - if (dynamicParams == null) { - dynamicParams = ModalRoute - .of(context)! - .settings - .arguments; - if (dynamicParams.isNotEmpty) { - AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; - selectedEmp =dynamicParams; - getAbsenceAttendanceTypes(); - - } - } return Scaffold( backgroundColor: Colors.white, appBar: AppBarWidget( diff --git a/lib/ui/leave_balance/leave_balance_screen.dart b/lib/ui/leave_balance/leave_balance_screen.dart index 1218914..548ca99 100644 --- a/lib/ui/leave_balance/leave_balance_screen.dart +++ b/lib/ui/leave_balance/leave_balance_screen.dart @@ -1,7 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/leave_balance_api_client.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/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; @@ -9,14 +8,12 @@ import 'package:mohem_flutter_app/extensions/int_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/leave_balance/get_absence_transaction_list_model.dart'; -import 'package:mohem_flutter_app/ui/my_attendance/services_menu_list_screen.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/balances_dashboard_widget.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; class LeaveBalance extends StatefulWidget { - final String selectedEmp; - LeaveBalance({this.selectedEmp ='', Key? key}) : super(key: key); + LeaveBalance({Key? key}) : super(key: key); @override _LeaveBalanceState createState() { @@ -28,13 +25,12 @@ class _LeaveBalanceState extends State { List? absenceTransList; DateTime accrualDateTime = DateTime.now(); - dynamic dynamicParams; - String selectedEmp =""; + @override void initState() { super.initState(); - + getAbsenceTransactions(); } @override @@ -43,9 +39,9 @@ class _LeaveBalanceState extends State { } void getAbsenceTransactions() async { - try { + try { Utils.showLoading(context); - absenceTransList = await LeaveBalanceApiClient().getAbsenceTransactions(-999, empID: selectedEmp); + absenceTransList = await LeaveBalanceApiClient().getAbsenceTransactions(-999); Utils.hideLoading(context); setState(() {}); } catch (ex) { @@ -56,19 +52,6 @@ class _LeaveBalanceState extends State { @override Widget build(BuildContext context) { - if (dynamicParams == null) { - dynamicParams = ModalRoute - .of(context)! - .settings - .arguments; - if (dynamicParams.isNotEmpty) { - AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; - selectedEmp =dynamicParams; - getAbsenceTransactions(); - // setState(() {}); - - } - } return Scaffold( backgroundColor: Colors.white, appBar: AppBarWidget( @@ -79,7 +62,7 @@ class _LeaveBalanceState extends State { physics: const BouncingScrollPhysics(), padding: const EdgeInsets.all(21), children: [ - BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true,), + BalancesDashboardWidget(LocaleKeys.currentLeaveBalance.tr(), true), 12.height, absenceTransList == null ? const SizedBox() @@ -128,7 +111,7 @@ class _LeaveBalanceState extends State { ), child: const Icon(Icons.add, color: Colors.white, size: 30), ).onPress(() { - Navigator.pushNamed(context, AppRoutes.addLeaveBalance, arguments: selectedEmp ??''); + Navigator.pushNamed(context, AppRoutes.addLeaveBalance); }), ); } diff --git a/lib/ui/marathon/marathon_intro_screen.dart b/lib/ui/marathon/marathon_intro_screen.dart index d85a82f..f47b47e 100644 --- a/lib/ui/marathon/marathon_intro_screen.dart +++ b/lib/ui/marathon/marathon_intro_screen.dart @@ -1,21 +1,13 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:lottie/lottie.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/date_uitl.dart'; -import 'package:mohem_flutter_app/classes/decorations_helper.dart'; -import 'package:mohem_flutter_app/classes/lottie_consts.dart'; -import 'package:mohem_flutter_app/classes/utils.dart'; -import 'package:mohem_flutter_app/config/routes.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/ui/marathon/marathon_provider.dart'; -import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_details_card.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_footer.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_timer_card.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; -import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:provider/provider.dart'; class MarathonIntroScreen extends StatelessWidget { @@ -33,7 +25,10 @@ class MarathonIntroScreen extends StatelessWidget { children: [ MarathonDetailsCard(provider: provider), 10.height, - MarathonTimerCard(provider: provider, timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch,), + MarathonTimerCard( + provider: provider, + timeToMarathon: DateTime.parse(provider.marathonDetailModel.startTime!).millisecondsSinceEpoch, + ), ], ).expanded, 1.divider, @@ -43,180 +38,3 @@ class MarathonIntroScreen extends StatelessWidget { ); } } - -class MarathonDetailsCard extends StatelessWidget { - final MarathonProvider provider; - - const MarathonDetailsCard({Key? key, required this.provider}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - width: double.infinity, - decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.symmetric(vertical: 18, 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.itsMarathonTime && provider.marathonDetailModel.sponsors != null) ...[ - 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( - provider.marathonDetailModel.sponsors!.first.image!, - height: 40, - width: 150, - fit: BoxFit.fill, - errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { - return const Center(); - }, - ) - ], - ), - ] - ], - ), - ], - ), - ); - } -} - -class MarathonTimerCard extends StatelessWidget { - final int timeToMarathon; - final MarathonProvider provider; - - const MarathonTimerCard({ - Key? key, - required this.provider, - required this.timeToMarathon, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - width: double.infinity, - decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 14), - child: Column( - children: [ - Row( - children: [ - "${LocaleKeys.gameDate.tr()} ".toText16(color: MyColors.grey77Color), - DateUtil.getMonthDayYearDateFormatted(DateTime.parse(provider.marathonDetailModel.startTime!)).toText16(color: MyColors.darkTextColor, isBold: true), - ], - ), - Row( - children: [ - "${LocaleKeys.gameTime.tr()} ".toText16(color: MyColors.grey77Color), - DateUtil.formatDateToTimeLang(DateTime.parse(provider.marathonDetailModel.startTime!), AppState().isArabic(context)).toText16(color: MyColors.darkTextColor, isBold: true), - ], - ), - Lottie.asset(MyLottieConsts.hourGlassLottie, height: 200), - BuildCountdownTimer(timeToMarathon: timeToMarathon, provider: provider, screenFlag: 1), - ], - ), - ); - } -} - -class MarathonFooter extends StatelessWidget { - final MarathonProvider provider; - - const MarathonFooter({ - Key? key, - required this.provider, - }) : super(key: key); - - Widget buildNoteForDemo() { - return RichText( - text: TextSpan( - children: [ - TextSpan( - text: LocaleKeys.note.tr(), - style: const TextStyle(color: MyColors.darkTextColor, fontSize: 17, letterSpacing: -0.64, fontWeight: FontWeight.bold), - ), - TextSpan( - text: " " + LocaleKeys.demoMarathonNoteP1.tr(), - style: const TextStyle(color: MyColors.grey77Color, fontSize: 17, letterSpacing: -0.64, fontWeight: FontWeight.w500), - ), - TextSpan( - text: " " + LocaleKeys.demoMarathonNoteP2.tr(), - style: const TextStyle(color: MyColors.darkTextColor, fontSize: 17, fontWeight: FontWeight.bold), - ), - TextSpan( - text: " " + LocaleKeys.demoMarathonNoteP3.tr(), - style: const TextStyle(color: MyColors.grey77Color, fontSize: 17, letterSpacing: -0.64, fontWeight: FontWeight.w500), - ) - ], - ), - ).paddingOnly(right: 21, left: 21, top: 11, bottom: 0); - } - - @override - Widget build(BuildContext context) { - return !provider.itsMarathonTime - ? DefaultButton( - LocaleKeys.joinMarathon.tr(), - () async { - Utils.showLoading(context); - try { - provider.resetValues(); - await provider.connectSignalrAndJoinMarathon(context); - } catch (e, s) { - Utils.confirmDialog(context, e.toString()); - print(s); - } - Utils.hideLoading(context); - Navigator.pushNamed(context, AppRoutes.marathonScreen); - }, - ).insideContainer - : Container( - color: Colors.white, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - buildNoteForDemo(), - DefaultButton( - LocaleKeys.joinDemoMarathon.tr(), - () { - provider.connectSignalrAndJoinMarathon(context); - }, - color: MyColors.yellowColorII, - ).insideContainer, - ], - ), - ); - } -} diff --git a/lib/ui/marathon/marathon_provider.dart b/lib/ui/marathon/marathon_provider.dart index b629b36..1cf8efd 100644 --- a/lib/ui/marathon/marathon_provider.dart +++ b/lib/ui/marathon/marathon_provider.dart @@ -2,62 +2,46 @@ import 'dart:async'; import 'package:appinio_swiper/appinio_swiper.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/marathon/marathon_api_client.dart'; +import 'package:mohem_flutter_app/classes/utils.dart'; +import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/models/marathon/marathon_model.dart'; import 'package:mohem_flutter_app/models/marathon/question_model.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; +import 'package:video_player/video_player.dart'; class MarathonProvider extends ChangeNotifier { + //****************VARIABLES********** + final AppinioSwiperController swiperController = AppinioSwiperController(); MarathonDetailModel marathonDetailModel = MarathonDetailModel(); List cardContentList = []; QuestionModel currentQuestion = QuestionModel(); - + List answerStatusesList = []; QuestionCardStatus questionCardStatus = QuestionCardStatus.question; int? selectedOptionIndex; - int currentQuestionTime = 0; - - void onNewQuestionReceived(QuestionModel newQuestion) { - if (currentQuestionNumber > 0) { - swipeCardLeft(); - } - selectedOptionIndex = null; - currentQuestionNumber++; - currentQuestion = newQuestion; - cardContentList.add(const CardContent()); - currentQuestionTime = newQuestion.questionTime!; - questionCardStatus = QuestionCardStatus.question; - notifyListeners(); - } + String? selectedOptionId; + int totalQualifiers = 0; - void addItemToList(CardContent value) { - cardContentList.add(value); - notifyListeners(); - } + bool _isLoading = false; - void updateCurrentQuestionOptionStatus(QuestionsOptionStatus status, int index) { - for (int i = 0; i < currentQuestion.questionOptions!.length; i++) { - currentQuestion.questionOptions![i].optionStatus = QuestionsOptionStatus.unSelected; - } - currentQuestion.questionOptions![index].optionStatus = status; - selectedOptionIndex = index; - notifyListeners(); - } + bool get isLoading => _isLoading; - void updateQuestionCardStatus(QuestionCardStatus status) { - questionCardStatus = status; + set isLoading(bool value) { + _isLoading = value; notifyListeners(); } - bool _isLoading = false; + bool _isUpComingMarathon = true; - bool get isLoading => _isLoading; + bool get isUpComingMarathon => _isUpComingMarathon; - set isLoading(bool value) { - _isLoading = value; + set isUpComingMarathon(bool value) { + _isUpComingMarathon = value; notifyListeners(); } @@ -79,6 +63,13 @@ class MarathonProvider extends ChangeNotifier { notifyListeners(); } + bool isUserOutOfGame = false; + + set updateIsUserOutOfGame(bool value) { + isUserOutOfGame = value; + notifyListeners(); + } + int _currentQuestionNumber = 0; int get currentQuestionNumber => _currentQuestionNumber; @@ -88,7 +79,7 @@ class MarathonProvider extends ChangeNotifier { notifyListeners(); } - int _totalMarathoners = 23; + int _totalMarathoners = 0; int get totalMarathoners => _totalMarathoners; @@ -97,8 +88,202 @@ class MarathonProvider extends ChangeNotifier { notifyListeners(); } - void swipeCardLeft() { - swiperController.swipeLeft(); + //****************SPONSOR VIDEO PLAYER********** + + late VideoPlayerController videoController; + + Future initializeVideoPlayer() async { + // videoController = VideoPlayerController.network(marathonDetailModel.sponsors!.first.video!)..initialize(); + videoController = VideoPlayerController.network("http://clips.vorwaerts-gmbh.de/VfE_html5.mp4"); + await videoController.initialize(); + await videoController.play(); + await videoController.setVolume(1.0); + await videoController.setLooping(false); + totalSponsorVideoSeconds = videoController.value.duration.inSeconds; + notifyListeners(); + } + + void disposeVideoPlayer() { + videoController.dispose(); + notifyListeners(); + } + + //****************TIMERS********** + + int totalSponsorVideoSeconds = 0; + Timer timerForSponsorVideo = Timer.periodic(const Duration(seconds: 1), (Timer timer) {}); + + void startTimerForSponsorVideo() { + const Duration oneSec = Duration(seconds: 1); + timerForSponsorVideo = Timer.periodic( + oneSec, + (Timer timer) async { + if (totalSponsorVideoSeconds == 0) { + timer.cancel(); + notifyListeners(); + return; + } else { + totalSponsorVideoSeconds--; + } + + notifyListeners(); + }, + ); + } + + int totalSecondsToWaitForMarathon = 20; + Timer timerToWaitForMarathon = Timer.periodic(const Duration(seconds: 1), (Timer timer) {}); + + void startTimerToMarathon(BuildContext context) { + const Duration oneSec = Duration(seconds: 1); + timerToWaitForMarathon = Timer.periodic( + oneSec, + (Timer timer) async { + if (totalSecondsToWaitForMarathon == 0) { + } else { + totalSecondsToWaitForMarathon--; + } + notifyListeners(); + }, + ); + } + + int totalCurrentQuestionTime = 0; + int currentGapTime = 0; + Timer timerForQuestion = Timer.periodic(const Duration(seconds: 1), (Timer timer) {}); + + void startTimerForQuestion() { + const Duration oneSec = Duration(seconds: 1); + timerForQuestion = Timer.periodic( + oneSec, + (Timer timer) async { + // This 2 is just to show the color of answer tile for 2 seconds and then update card status + if (totalCurrentQuestionTime - currentGapTime == currentQuestion.questionTime! - 2) { + getCorrectAnswerAndUpdateAnswerColor(); + } + + if (totalCurrentQuestionTime == currentGapTime) { + updateCardStatusToAnswer(); + + await callSubmitOptionApi().then((bool value) async { + if (value) { + await callNextQuestionApi(); + } + }); + } + + if (totalCurrentQuestionTime == 0) { + updateCardData(); + if (currentQuestionNumber == marathonDetailModel.totalQuestions! - 1) { + updateQuestionCardStatus(QuestionCardStatus.findingWinner); + timer.cancel(); + cancelTimer(); + notifyListeners(); + } + return; + } else { + totalCurrentQuestionTime--; + } + + notifyListeners(); + }, + ); + } + + int totalSecondsToWaitForWinner = 30; + Timer timerForWinnerSelection = Timer.periodic(const Duration(seconds: 1), (Timer timer) {}); + + void startTimerForWinnerSelection() { + const Duration oneSec = Duration(seconds: 1); + timerForWinnerSelection = Timer.periodic( + oneSec, + (Timer timer) async { + if (totalSecondsToWaitForWinner == 0) { + timer.cancel(); + updateQuestionCardStatus(QuestionCardStatus.winnerFound); + return; + } else { + totalSecondsToWaitForWinner--; + } + + notifyListeners(); + }, + ); + } + + //****************FUNCTIONS********* + + Future callSubmitOptionApi() async { + return await MarathonApiClient().submitSelectedOption(selectedAnswerId: selectedOptionId); + } + + // TODO: here I need to add a logic where I should call this function for Api but for the 1st question it should behave differently + // TODO: Verify the callings!!! + Future callNextQuestionApi() async { + if (currentQuestionNumber < marathonDetailModel.totalQuestions!) { + if (currentQuestionNumber == 0) { + currentQuestion = (await MarathonApiClient().getNextQuestion(questionId: null, marathonId: marathonDetailModel.id!))!; + if (Utils.isLoading) { + Utils.hideLoading(AppRoutes.navigatorKey.currentContext!); + } + startTimerForQuestion(); + updateCardData(); + + Navigator.pushReplacementNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.marathonScreen); + } else { + currentQuestion = (await MarathonApiClient().getNextQuestion(questionId: currentQuestion.id, marathonId: marathonDetailModel.id!))!; + } + notifyListeners(); + } + } + + void updateCardData() { + if (currentQuestionNumber > 0) { + print("swiped it away!!"); + swipeCardLeft(); + } + selectedOptionIndex = null; + currentQuestionNumber++; + cardContentList.add(const CardContent()); + totalCurrentQuestionTime = currentQuestion.questionTime! + currentQuestion.nextQuestGap!; + currentGapTime = currentQuestion.nextQuestGap!; + totalMarathoners = currentQuestion.remainingParticipantCount!; + questionCardStatus = QuestionCardStatus.question; + } + + void populateQuestionStatusesList() { + if (marathonDetailModel.totalQuestions != null) { + for (int i = 0; i < marathonDetailModel.totalQuestions! - 1; i++) { + answerStatusesList.add(QuestionCardStatus.question); + } + notifyListeners(); + } + } + + void updateAnswerStatusesList(QuestionCardStatus status) { + answerStatusesList[currentQuestionNumber - 1] = status; + notifyListeners(); + } + + void addItemToList(CardContent value) { + cardContentList.add(value); + notifyListeners(); + } + + void updateCurrentQuestionOptionStatus(QuestionsOptionStatus status, int index) { + for (int i = 0; i < currentQuestion.questionOptions!.length; i++) { + currentQuestion.questionOptions![i].optionStatus = QuestionsOptionStatus.unSelected; + } + currentQuestion.questionOptions![index].optionStatus = status; + selectedOptionIndex = index; + notifyListeners(); + } + + void updateQuestionCardStatus(QuestionCardStatus status) { + if (status == QuestionCardStatus.wrongAnswer || status == QuestionCardStatus.skippedAnswer) { + updateIsUserOutOfGame = true; + } + questionCardStatus = status; notifyListeners(); } @@ -120,59 +305,36 @@ class MarathonProvider extends ChangeNotifier { if (selectedOptionIndex != null) { if (currentQuestion.questionOptions![selectedOptionIndex!].isCorrectOption!) { updateQuestionCardStatus(QuestionCardStatus.correctAnswer); + updateAnswerStatusesList(QuestionCardStatus.correctAnswer); } else { updateQuestionCardStatus(QuestionCardStatus.wrongAnswer); + updateAnswerStatusesList(QuestionCardStatus.wrongAnswer); } } else { updateQuestionCardStatus(QuestionCardStatus.skippedAnswer); + updateAnswerStatusesList(QuestionCardStatus.skippedAnswer); } } - Timer timerU = Timer.periodic(const Duration(seconds: 1), (Timer timer) {}); - - void startTimer(BuildContext context) { - const Duration oneSec = Duration(seconds: 1); - timerU = Timer.periodic( - oneSec, - (Timer timer) async { - if (currentQuestionTime == 2) { - getCorrectAnswerAndUpdateAnswerColor(); - } - if (currentQuestionTime == 0) { - updateCardStatusToAnswer(); - // if (currentQuestionNumber == 9) { - // timer.cancel(); - // cancelTimer(); - // isMarathonCompleted = true; - // await Future.delayed(const Duration(seconds: 2)).whenComplete( - // () => Navigator.pushReplacementNamed(context, AppRoutes.marathonWinnerSelection), - // ); - // - // resetValues(); - // - // return; - // } - // timer.cancel(); - } else { - currentQuestionTime--; - } - notifyListeners(); - }, - ); + void swipeCardLeft() { + swiperController.swipeLeft(); + notifyListeners(); } - void resetValues() { + void resetValues() async { _currentQuestionNumber = 0; cardContentList.clear(); - timerU.cancel(); + timerForWinnerSelection.cancel(); + timerForQuestion.cancel(); _isMarathonCompleted = false; - currentQuestionTime = 0; + totalCurrentQuestionTime = 0; currentQuestion = QuestionModel(); + notifyListeners(); } void cancelTimer() { - timerU.cancel(); + timerForQuestion.cancel(); notifyListeners(); } @@ -181,12 +343,51 @@ class MarathonProvider extends ChangeNotifier { notifyListeners(); await MarathonApiClient().getMarathonToken().whenComplete(() async { marathonDetailModel = await MarathonApiClient().getMarathonDetails(); + if (marathonDetailModel.id == null) { + isUpComingMarathon = false; + notifyListeners(); + return; + } + populateQuestionStatusesList(); isLoading = false; notifyListeners(); }); } - Future connectSignalrAndJoinMarathon(BuildContext context) async { - await MarathonApiClient().buildHubConnection(context); + Future buildConnectionWithSignalR(BuildContext context) async { + Utils.showLoading(context); + try { + resetValues(); + // await MarathonApiClient().buildHubConnection(context, marathonDetailModel.sponsors!.first.sponsorPrizes!.first.id!); + } catch (e) { + if (kDebugMode) { + print("error in buildConnectionWithSignalR: ${e.toString()}"); + } + Utils.hideLoading(context); + Utils.confirmDialog(context, e.toString()); + } + } + + Future onJoinMarathonPressed(BuildContext context) async { + //TODO: here we need to put a check to make sure we should not display sponsor when remaining time to marathon is less than 30 seconds plus video duration e.g. 30 seconds + video duration time + // if (marathonDetailModel.sponsors!.first.video != null && marathonDetailModel.sponsors!.first.video != "") { + if (false) { + await initializeVideoPlayer().then((_) { + startTimerForSponsorVideo(); + Navigator.pushNamed(context, AppRoutes.marathonSponsorVideoScreen); + }); + } else { + try { + Utils.showLoading(context); + bool isJoined = await MarathonApiClient().joinMarathonAsParticipant(); + if (isJoined) { + print("joined"); + callNextQuestionApi(); + } + } catch (e, s) { + Utils.hideLoading(context); + Utils.confirmDialog(context, e.toString()); + } + } } } diff --git a/lib/ui/marathon/marathon_screen.dart b/lib/ui/marathon/marathon_screen.dart index 79d61fe..e14f8c9 100644 --- a/lib/ui/marathon/marathon_screen.dart +++ b/lib/ui/marathon/marathon_screen.dart @@ -2,16 +2,22 @@ import 'dart:async'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:lottie/lottie.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/classes/lottie_consts.dart'; +import 'package:mohem_flutter_app/classes/utils.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/question_model.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/custom_status_widget.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_progress_container.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_qualifiers_container.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/question_card_builder.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; @@ -20,46 +26,164 @@ import 'package:provider/provider.dart'; class MarathonScreen extends StatelessWidget { const MarathonScreen({Key? key}) : super(key: key); + Widget getSuccessWidget({required int? gapType, required String? gapImage, required String? gapText}) { + if (gapType == 1) { + if (gapText == null) { + return Image.asset(MyLottieConsts.congratsGif, height: 200); + } + return gapText.toText18(color: MyColors.darkTextColor, isCentered: true); + } + if (gapType == 2) { + if (gapImage == null) { + return Image.asset(MyLottieConsts.congratsGif, height: 200); + } + return Image.network(gapImage, height: 200); + } + return Image.asset(MyLottieConsts.congratsGif, height: 200); + } + + Widget getWinnerWidget(BuildContext context, {required MarathonProvider provider}) { + return Container( + width: double.infinity, + decoration: MyDecorations.shadowDecoration, + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 200, + child: Stack( + children: [ + Lottie.asset(MyLottieConsts.celebrate1Lottie, height: 200), + Lottie.asset(MyLottieConsts.celebrate2Lottie, height: 200), + ], + ), + ), + 26.height, + 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).paddingOnly(top: 07), + ) + ], + ), + ), + 12.height, + "Muhammad Shrouff".toText22(color: MyColors.grey3AColor), + "837436".toText22(color: MyColors.grey57Color), + 80.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( + provider.marathonDetailModel.sponsors!.first.image!, + height: 40, + width: 150, + fit: BoxFit.fill, + errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { + return const Center(); + }, + ) + ], + ], + ), + ); + } + + Widget getNameContainer(BuildContext context) { + return Container( + height: 50, + padding: const EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + color: MyColors.greenColor, + borderRadius: BorderRadius.circular(15), + boxShadow: [BoxShadow(color: const Color(0xff000000).withOpacity(.05), blurRadius: 26, offset: const Offset(0, -3))], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr!) + .toText17(isBold: true, color: MyColors.white), + AppState().memberInformationList!.eMPLOYEENUMBER!.toText17(isBold: true, color: MyColors.white), + ], + ), + ).paddingOnly(left: 20, right: 20, top: 12, bottom: 20); + } + @override Widget build(BuildContext context) { MarathonProvider provider = context.watch(); return WillPopScope( child: Scaffold( - appBar: AppBarWidget(context, title: LocaleKeys.brainMarathon.tr()), + appBar: AppBarWidget( + context, + title: LocaleKeys.brainMarathon.tr(), + onHomeTapped: () { + Utils.confirmDialog(context, LocaleKeys.youWantToLeaveMarathon.tr()); + }, + onBackTapped: () { + Utils.confirmDialog(context, LocaleKeys.youWantToLeaveMarathon.tr()); + }, + ), body: SingleChildScrollView( child: Column( children: [ 20.height, - MarathonProgressContainer(provider: provider).paddingOnly(left: 21, right: 21), + if (provider.questionCardStatus == QuestionCardStatus.findingWinner) ...[ + QualifiersContainer(provider: provider).paddingOnly(left: 21, right: 21), + ] else if (provider.questionCardStatus == QuestionCardStatus.winnerFound) + ...[] + else ...[ + MarathonProgressContainer(provider: provider).paddingOnly(left: 21, right: 21), + ], + if (provider.questionCardStatus == QuestionCardStatus.findingWinner) ...[ + getNameContainer(context), + ], QuestionCardBuilder( onQuestion: (BuildContext context) => QuestionCard(provider: provider), onCompleted: (BuildContext context) => CustomStatusWidget( asset: Lottie.asset(MyLottieConsts.allQuestions, height: 200), title: LocaleKeys.congrats.tr().toText22(color: MyColors.greenColor), - subTitle: LocaleKeys.allQuestionsCorrect.toText18(color: MyColors.darkTextColor), + subTitle: LocaleKeys.allQuestionsCorrect.toText18(color: MyColors.darkTextColor, isCentered: true), ), onCorrectAnswer: (BuildContext context) => CustomStatusWidget( - asset: Lottie.asset(MyLottieConsts.allQuestions, height: 200), + asset: getSuccessWidget(gapType: provider.currentQuestion.gapType, gapImage: provider.currentQuestion.gapImage, gapText: provider.currentQuestion.gapText), title: LocaleKeys.congrats.tr().toText22(color: MyColors.greenColor), - subTitle: LocaleKeys.yourAnswerCorrect.toText18(color: MyColors.darkTextColor), + subTitle: LocaleKeys.yourAnswerCorrect.toText18(color: MyColors.darkTextColor, isCentered: true), ), - onWinner: (BuildContext context) => QuestionCard(provider: provider), + onWinner: (BuildContext context) => getWinnerWidget(context, provider: provider), onWrongAnswer: (BuildContext context) => CustomStatusWidget( asset: Image.asset(MyLottieConsts.wrongAnswerGif, height: 200), - title: const Text(""), - subTitle: LocaleKeys.wrongAnswer.tr().toText18(color: MyColors.darkTextColor), + title: LocaleKeys.oops.tr().toText22(color: MyColors.redColor), + subTitle: LocaleKeys.wrongAnswer.tr().toText18(color: MyColors.darkTextColor, isCentered: true), ), onSkippedAnswer: (BuildContext context) => CustomStatusWidget( asset: Image.asset(MyLottieConsts.wrongAnswerGif, height: 200), - title: const Text(""), - subTitle: LocaleKeys.youMissedTheQuestion.tr().toText18(color: MyColors.darkTextColor), + title: LocaleKeys.oops.tr().toText22(color: MyColors.redColor), + subTitle: LocaleKeys.youMissedTheQuestion.tr().toText18(color: MyColors.darkTextColor, isCentered: true), ), - questionCardStatus: provider.questionCardStatus, onFindingWinner: (BuildContext context) => CustomStatusWidget( asset: Lottie.asset(MyLottieConsts.winnerLottie, height: 168), title: LocaleKeys.fingersCrossed.tr().toText22(color: MyColors.greenColor), - subTitle: LocaleKeys.winnerSelectedRandomly.tr().toText18(color: MyColors.darkTextColor), + subTitle: LocaleKeys.winnerSelectedRandomly.tr().toText18(color: MyColors.darkTextColor, isCentered: true), ), + questionCardStatus: provider.questionCardStatus, ).paddingOnly(top: 12, left: 21, right: 21), ], ), @@ -72,127 +196,3 @@ class MarathonScreen extends StatelessWidget { ); } } - -class MarathonProgressContainer extends StatefulWidget { - final MarathonProvider provider; - - const MarathonProgressContainer({Key? key, required this.provider}) : super(key: key); - - @override - State createState() => _MarathonProgressContainerState(); -} - -class _MarathonProgressContainerState extends State { - @override - void initState() { - scheduleMicrotask(() { - widget.provider.startTimer(context); - }); - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Container( - width: double.infinity, - decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 13), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - decoration: BoxDecoration(color: MyColors.greenColor, borderRadius: BorderRadius.circular(5)), - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8), - child: "${widget.provider.currentQuestionNumber.toString()} / ${widget.provider.marathonDetailModel.totalQuestions.toString()} ${LocaleKeys.question.tr()}" - .toText12(color: MyColors.white), - ), - "${widget.provider.totalMarathoners} ${LocaleKeys.marathoners.tr()}".toText14(), - "00:${widget.provider.currentQuestionTime < 10 ? "0${widget.provider.currentQuestionTime}" : widget.provider.currentQuestionTime}" - .toText18(color: widget.provider.currentQuestionTime < 5 ? MyColors.redColor : MyColors.black), - ], - ), - 12.height, - stepper(widget.provider.currentQuestionNumber), - 8.height, - Row( - children: [ - "${((widget.provider.currentQuestionNumber / widget.provider.marathonDetailModel.totalQuestions!) * 100).toInt()}% ${LocaleKeys.completed.tr()}".toText14(), - ], - ), - ], - ), - ); - } - - Widget stepper(int value) { - return SizedBox( - width: double.infinity, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - for (int i = 0; i < 10; i++) - if (value <= i) roundContainer(MyColors.lightGreyDeColor, i != 0) else roundContainer(MyColors.greenColor, i != 0) - ], - ), - ); - } - - Widget roundContainer(Color color, bool isNeedLeftBorder) { - if (isNeedLeftBorder) { - return Row( - children: [ - Divider(thickness: 6, color: color).expanded, - Container( - width: 10, - height: 10, - decoration: BoxDecoration(shape: BoxShape.circle, color: color), - ), - ], - ).expanded; - } - - return Container( - width: 10, - height: 10, - decoration: BoxDecoration(shape: BoxShape.circle, color: color), - ); - } -} - -// InkWell( -// onTap: () { -// Navigator.pushReplacementNamed( -// context, -// AppRoutes.marathonWinnerSelection, -// ); -// }, -// child: CustomStatusWidget( -// asset: Lottie.asset( -// MyLottieConsts.allQuestions, -// height: 200, -// ), -// title: Text( -// LocaleKeys.congrats.tr(), -// style: const TextStyle( -// height: 23 / 24, -// color: MyColors.greenColor, -// fontSize: 27, -// letterSpacing: -1, -// fontWeight: FontWeight.w600, -// ), -// ), -// subTitle: Text( -// LocaleKeys.allQuestionsCorrect.tr(), -// textAlign: TextAlign.center, -// style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, letterSpacing: -1.08), -// ), -// ).paddingOnly(top: 12, left: 21, right: 21), -// ) diff --git a/lib/ui/marathon/marathon_sponsor_video_screen.dart b/lib/ui/marathon/marathon_sponsor_video_screen.dart new file mode 100644 index 0000000..c81f59b --- /dev/null +++ b/lib/ui/marathon/marathon_sponsor_video_screen.dart @@ -0,0 +1,91 @@ +import 'dart:async'; +import 'dart:ui' as ui; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/config/routes.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/ui/marathon/marathon_provider.dart'; +import 'package:provider/provider.dart'; +import 'package:video_player/video_player.dart'; + +class SponsorVideoScreen extends StatelessWidget { + const SponsorVideoScreen({Key? key}) : super(key: key); + + Future onSponsorVideoClosed(BuildContext context) async { + Navigator.pop(context); + } + + @override + Widget build(BuildContext context) { + MarathonProvider provider = context.watch(); + return WillPopScope( + onWillPop: () { + provider.videoController.dispose(); + return Future.value(true); + }, + child: Scaffold( + backgroundColor: MyColors.black, + body: SafeArea( + child: Stack( + children: [ + Align( + child: provider.videoController.value.isInitialized + ? AspectRatio( + aspectRatio: provider.videoController.value.aspectRatio, + child: VideoPlayer(provider.videoController), + ) + : Container(color: Colors.white), + ), + Align( + alignment: Alignment.topRight, + child: Container( + decoration: BoxDecoration( + color: MyColors.white, + shape: provider.totalSponsorVideoSeconds == 0 ? BoxShape.circle : BoxShape.rectangle, + borderRadius: provider.totalSponsorVideoSeconds == 0 ? null : BorderRadius.circular(15), + ), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8), + child: provider.totalSponsorVideoSeconds == 0 + ? InkWell( + onTap: () { + Navigator.pop(context); + provider.videoController.dispose(); + provider.buildConnectionWithSignalR(AppRoutes.navigatorKey.currentState!.overlay!.context); + }, + child: const Icon(Icons.close, size: 12), + ) + : Directionality( + textDirection: ui.TextDirection.ltr, + child: ("${LocaleKeys.ourSponsor.tr()} ${provider.totalSponsorVideoSeconds < 10 ? "0" : ""}${provider.totalSponsorVideoSeconds}").toText12(color: MyColors.darkTextColor), + ), + ), + ).paddingOnly(top: 20, right: 18), + Align( + alignment: Alignment.topLeft, + child: InkWell( + onTap: () { + Navigator.pop(context); + provider.videoController.dispose(); + provider.buildConnectionWithSignalR(AppRoutes.navigatorKey.currentState!.overlay!.context); + }, + child: Container( + decoration: BoxDecoration(color: MyColors.white, borderRadius: BorderRadius.circular(15)), + padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 6), + child: Directionality( + textDirection: ui.TextDirection.ltr, + child: LocaleKeys.skip.tr().toText11(color: MyColors.darkTextColor), + ), + ), + ), + ).paddingOnly(top: 20, left: 18), + ], + ), + ), + ), + ); + } +} diff --git a/lib/ui/marathon/marathon_waiting_screen.dart b/lib/ui/marathon/marathon_waiting_screen.dart new file mode 100644 index 0000000..27f0c08 --- /dev/null +++ b/lib/ui/marathon/marathon_waiting_screen.dart @@ -0,0 +1,62 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:lottie/lottie.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/decorations_helper.dart'; +import 'package:mohem_flutter_app/classes/lottie_consts.dart'; +import 'package:mohem_flutter_app/classes/utils.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/ui/marathon/marathon_provider.dart'; +import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:provider/provider.dart'; + +class MarathonWaitingScreen extends StatelessWidget { + const MarathonWaitingScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + MarathonProvider provider = context.watch(); + return Scaffold( + appBar: AppBarWidget( + context, + title: LocaleKeys.brainMarathon.tr(), + onHomeTapped: () { + Utils.confirmDialog(context, LocaleKeys.youWantToLeaveMarathon.tr()); + }, + onBackTapped: () { + Utils.confirmDialog(context, LocaleKeys.youWantToLeaveMarathon.tr()); + }, + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: double.infinity, + margin: const EdgeInsets.all(21), + decoration: MyDecorations.shadowDecoration, + child: Stack( + children: [ + Align( + child: Lottie.asset(MyLottieConsts.marathonWaiting, height: 200), + ), + Align( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LocaleKeys.startingIn.tr().toText16(), + "00:${provider.totalSecondsToWaitForMarathon < 10 ? "0${provider.totalSecondsToWaitForMarathon}" : provider.totalSecondsToWaitForMarathon}" + .toText18(color: provider.totalSecondsToWaitForMarathon < 5 ? MyColors.redColor : MyColors.black), + ], + ), + ), + ], + ), + ).expanded, + ], + ), + ); + } +} diff --git a/lib/ui/marathon/marathon_winner_selection.dart b/lib/ui/marathon/marathon_winner_selection.dart index 1f56801..ed49f04 100644 --- a/lib/ui/marathon/marathon_winner_selection.dart +++ b/lib/ui/marathon/marathon_winner_selection.dart @@ -1,10 +1,7 @@ -import 'dart:async'; - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:lottie/lottie.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; -import 'package:mohem_flutter_app/classes/decorations_helper.dart'; import 'package:mohem_flutter_app/classes/lottie_consts.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -13,6 +10,7 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/widgets/custom_status_widget.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/marathon_qualifiers_container.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:provider/provider.dart'; @@ -28,7 +26,7 @@ class MarathonWinnerSelection extends StatelessWidget { child: Column( children: [ 20.height, - QualifiersContainer(provider: provider).paddingOnly(left: 21, right: 21), + QualifiersContainer(provider: provider,).paddingOnly(left: 21, right: 21), 12.height, InkWell( onTap: () { @@ -90,60 +88,3 @@ class MarathonWinnerSelection extends StatelessWidget { ); } } - -class QualifiersContainer extends StatefulWidget { - final MarathonProvider provider; - - const QualifiersContainer({Key? key, required this.provider}) : super(key: key); - - @override - State createState() => _QualifiersContainerState(); -} - -class _QualifiersContainerState extends State { - final int totalQuestions = 10; - - final int currentQuestion = 04; - - @override - void initState() { - scheduleMicrotask(() { - // widget.provider.startTimer(context); - }); - super.initState(); - } - - @override - void dispose() { - // widget.provider.cancelTimer(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Container( - width: double.infinity, - decoration: MyDecorations.shadowDecoration, - padding: const EdgeInsets.only(top: 14,left: 18,right: 14,bottom: 18), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocaleKeys.winnerSelection.tr().toText21(color: MyColors.grey3AColor), - // "00:${widget.provider.start < 10 ? "0${widget.provider.start}" : widget.provider.start}".toText18(color: MyColors.redColor), - ], - ), - 10.height, - Row( - children: [ - "18".toText30(color: MyColors.greenColor, isBold: true),2.width, - LocaleKeys.qualifiers.tr().toText16(color: MyColors.greenColor), - ], - ), - ], - ), - ); - } -} diff --git a/lib/ui/marathon/widgets/custom_status_widget.dart b/lib/ui/marathon/widgets/custom_status_widget.dart index 8287bb4..44b44aa 100644 --- a/lib/ui/marathon/widgets/custom_status_widget.dart +++ b/lib/ui/marathon/widgets/custom_status_widget.dart @@ -22,6 +22,7 @@ class CustomStatusWidget extends StatelessWidget { decoration: MyDecorations.shadowDecoration, padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), child: Column( + mainAxisAlignment: MainAxisAlignment.center, children: [ asset, 50.height, diff --git a/lib/ui/marathon/widgets/marathon_banner.dart b/lib/ui/marathon/widgets/marathon_banner.dart index e711319..d805362 100644 --- a/lib/ui/marathon/widgets/marathon_banner.dart +++ b/lib/ui/marathon/widgets/marathon_banner.dart @@ -16,7 +16,9 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer.dart'; import 'package:provider/provider.dart'; class MarathonBanner extends StatelessWidget { - const MarathonBanner({Key? key}) : super(key: key); + final bool isMarathonUpcoming; + + const MarathonBanner({Key? key, required this.isMarathonUpcoming}) : super(key: key); @override Widget build(BuildContext context) { @@ -76,7 +78,7 @@ class MarathonBanner extends StatelessWidget { height: double.infinity, ), ), - Expanded( + Expanded( flex: AppState().isArabic(context) ? 4 : 5, child: SizedBox( width: double.infinity, diff --git a/lib/ui/marathon/widgets/marathon_details_card.dart b/lib/ui/marathon/widgets/marathon_details_card.dart new file mode 100644 index 0000000..b74b78b --- /dev/null +++ b/lib/ui/marathon/widgets/marathon_details_card.dart @@ -0,0 +1,82 @@ + +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'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; + + + +class MarathonDetailsCard extends StatelessWidget { + final MarathonProvider provider; + + const MarathonDetailsCard({Key? key, required this.provider}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + decoration: MyDecorations.shadowDecoration, + padding: const EdgeInsets.symmetric(vertical: 18, 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.itsMarathonTime && provider.marathonDetailModel.sponsors != null) ...[ + 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( + provider.marathonDetailModel.sponsors!.first.image!, + height: 40, + width: 150, + fit: BoxFit.fill, + errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { + return const Center(); + }, + ) + ], + ), + ] + ], + ), + ], + ), + ); + } +} + diff --git a/lib/ui/marathon/widgets/marathon_footer.dart b/lib/ui/marathon/widgets/marathon_footer.dart new file mode 100644 index 0000000..b5083c0 --- /dev/null +++ b/lib/ui/marathon/widgets/marathon_footer.dart @@ -0,0 +1,66 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/classes/colors.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/ui/marathon/marathon_provider.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; + +class MarathonFooter extends StatelessWidget { + final MarathonProvider provider; + + const MarathonFooter({ + Key? key, + required this.provider, + }) : super(key: key); + + Widget buildNoteForDemo() { + return RichText( + text: TextSpan( + children: [ + TextSpan( + text: LocaleKeys.note.tr(), + style: const TextStyle(color: MyColors.darkTextColor, fontSize: 17, letterSpacing: -0.64, fontWeight: FontWeight.bold), + ), + TextSpan( + text: " " + LocaleKeys.demoMarathonNoteP1.tr(), + style: const TextStyle(color: MyColors.grey77Color, fontSize: 17, letterSpacing: -0.64, fontWeight: FontWeight.w500), + ), + TextSpan( + text: " " + LocaleKeys.demoMarathonNoteP2.tr(), + style: const TextStyle(color: MyColors.darkTextColor, fontSize: 17, fontWeight: FontWeight.bold), + ), + TextSpan( + text: " " + LocaleKeys.demoMarathonNoteP3.tr(), + style: const TextStyle(color: MyColors.grey77Color, fontSize: 17, letterSpacing: -0.64, fontWeight: FontWeight.w500), + ) + ], + ), + ).paddingOnly(right: 21, left: 21, top: 11, bottom: 0); + } + + @override + Widget build(BuildContext context) { + return DefaultButton( + LocaleKeys.joinMarathon.tr(), + !provider.itsMarathonTime ? () => provider.onJoinMarathonPressed(context) : null, + ).insideContainer; + } +} + +//Container( +// color: Colors.white, +// child: Column( +// mainAxisSize: MainAxisSize.min, +// children: [ +// buildNoteForDemo(), +// DefaultButton( +// LocaleKeys.joinDemoMarathon.tr(), +// () { +// provider.connectSignalrAndJoinMarathon(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 new file mode 100644 index 0000000..c0dae6c --- /dev/null +++ b/lib/ui/marathon/widgets/marathon_progress_container.dart @@ -0,0 +1,115 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.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'; +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/question_model.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; + +class MarathonProgressContainer extends StatelessWidget { + final MarathonProvider provider; + + const MarathonProgressContainer({Key? key, required this.provider}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + decoration: MyDecorations.shadowDecoration, + padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 13), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + 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), + ), + "${provider.totalMarathoners} ${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) + : const SizedBox(), + ], + ), + 12.height, + stepper(provider.currentQuestionNumber, provider.answerStatusesList, provider.marathonDetailModel.totalQuestions!, provider.isUserOutOfGame), + 8.height, + Row( + children: [ + "${((provider.currentQuestionNumber / provider.marathonDetailModel.totalQuestions!) * 100).toInt()}% ${LocaleKeys.completed.tr()}".toText14(), + ], + ), + ], + ), + ); + } + + Color getStepColor(QuestionCardStatus status, bool isOutOfGame) { + if (isOutOfGame) { + return MyColors.redColor; + } + switch (status) { + case QuestionCardStatus.question: + return MyColors.yellowColorII; + case QuestionCardStatus.wrongAnswer: + return MyColors.redColor; + case QuestionCardStatus.correctAnswer: + return MyColors.greenColor; + case QuestionCardStatus.skippedAnswer: + return MyColors.redColor; + case QuestionCardStatus.completed: + return MyColors.lightGreyDeColor; + case QuestionCardStatus.findingWinner: + return MyColors.lightGreyDeColor; + case QuestionCardStatus.winnerFound: + return MyColors.lightGreyDeColor; + } + } + + Widget stepper(int value, List statusesList, int totalQuestions, bool isOutOfGame) { + return SizedBox( + width: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + for (int i = 0; i < totalQuestions - 1; i++) + if (value <= i) + roundContainer(MyColors.lightGreyDeColor, i != 0) + else + roundContainer( + getStepColor(statusesList[i], isOutOfGame), + i != 0, + ) + ], + ), + ); + } + + Widget roundContainer(Color color, bool isNeedLeftBorder) { + if (isNeedLeftBorder) { + return Row( + children: [ + Divider(thickness: 6, color: color).expanded, + Container( + width: 10, + height: 10, + decoration: BoxDecoration(shape: BoxShape.circle, color: color), + ), + ], + ).expanded; + } + + return Container( + width: 10, + height: 10, + decoration: BoxDecoration(shape: BoxShape.circle, color: color), + ); + } +} diff --git a/lib/ui/marathon/widgets/marathon_qualifiers_container.dart b/lib/ui/marathon/widgets/marathon_qualifiers_container.dart new file mode 100644 index 0000000..0308027 --- /dev/null +++ b/lib/ui/marathon/widgets/marathon_qualifiers_container.dart @@ -0,0 +1,54 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.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'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; + +class QualifiersContainer extends StatefulWidget { + final MarathonProvider provider; + + const QualifiersContainer({Key? key, required this.provider}) : super(key: key); + + @override + State createState() => _QualifiersContainerState(); +} + +class _QualifiersContainerState extends State { + @override + void initState() { + widget.provider.startTimerForWinnerSelection(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + decoration: MyDecorations.shadowDecoration, + padding: const EdgeInsets.only(top: 14, left: 18, right: 14, bottom: 18), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + LocaleKeys.winnerSelection.tr().toText21(color: MyColors.grey3AColor), + "00:${widget.provider.totalSecondsToWaitForWinner < 10 ? "0${widget.provider.totalSecondsToWaitForWinner}" : widget.provider.totalSecondsToWaitForWinner}".toText18(color: MyColors.redColor), + ], + ), + 10.height, + Row( + children: [ + widget.provider.totalQualifiers.toString().toText30(color: MyColors.greenColor, isBold: true), + 2.width, + LocaleKeys.qualifiers.tr().toText16(color: MyColors.greenColor), + ], + ), + ], + ), + ); + } +} diff --git a/lib/ui/marathon/widgets/marathon_timer_card.dart b/lib/ui/marathon/widgets/marathon_timer_card.dart new file mode 100644 index 0000000..e831738 --- /dev/null +++ b/lib/ui/marathon/widgets/marathon_timer_card.dart @@ -0,0 +1,51 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:lottie/lottie.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/date_uitl.dart'; +import 'package:mohem_flutter_app/classes/decorations_helper.dart'; +import 'package:mohem_flutter_app/classes/lottie_consts.dart'; +import 'package:mohem_flutter_app/extensions/string_extensions.dart'; +import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; +import 'package:mohem_flutter_app/ui/marathon/widgets/countdown_timer.dart'; + + +class MarathonTimerCard extends StatelessWidget { + final int timeToMarathon; + final MarathonProvider provider; + + const MarathonTimerCard({ + Key? key, + required this.provider, + required this.timeToMarathon, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + decoration: MyDecorations.shadowDecoration, + padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 14), + child: Column( + children: [ + Row( + children: [ + "${LocaleKeys.gameDate.tr()} ".toText16(color: MyColors.grey77Color), + DateUtil.getMonthDayYearDateFormatted(DateTime.parse(provider.marathonDetailModel.startTime!)).toText16(color: MyColors.darkTextColor, isBold: true), + ], + ), + Row( + children: [ + "${LocaleKeys.gameTime.tr()} ".toText16(color: MyColors.grey77Color), + DateUtil.formatDateToTimeLang(DateTime.parse(provider.marathonDetailModel.startTime!), AppState().isArabic(context)).toText16(color: MyColors.darkTextColor, isBold: true), + ], + ), + Lottie.asset(MyLottieConsts.hourGlassLottie, height: 200), + BuildCountdownTimer(timeToMarathon: timeToMarathon, provider: provider, screenFlag: 1), + ], + ), + ); + } +} diff --git a/lib/ui/marathon/widgets/question_card.dart b/lib/ui/marathon/widgets/question_card.dart index af538f8..4009983 100644 --- a/lib/ui/marathon/widgets/question_card.dart +++ b/lib/ui/marathon/widgets/question_card.dart @@ -145,21 +145,32 @@ class AnswerTileForText extends StatelessWidget { const AnswerTileForText({Key? key, required this.index, required this.onAnswerTapped}) : super(key: key); + Color getAnswerTextColor(QuestionsOptionStatus status) { + switch (status) { + case QuestionsOptionStatus.correct: + return MyColors.white; + case QuestionsOptionStatus.wrong: + return MyColors.white; + case QuestionsOptionStatus.selected: + return MyColors.white; + case QuestionsOptionStatus.unSelected: + return MyColors.darkTextColor; + } + } + @override Widget build(BuildContext context) { MarathonProvider provider = context.watch(); return InkWell( onTap: () { - onAnswerTapped(); + provider.isUserOutOfGame ? null : onAnswerTapped() ; }, child: Container( alignment: Alignment.centerLeft, decoration: MyDecorations.getAnswersContainerColor(provider.currentQuestion.questionOptions![index].optionStatus!), child: Center( child: (AppState().isArabic(context) ? provider.currentQuestion.questionOptions![index].titleAr! : provider.currentQuestion.questionOptions![index].titleEn!) - .toText16( - color: provider.currentQuestion.questionOptions![index].optionStatus == QuestionsOptionStatus.unSelected ? MyColors.darkTextColor : MyColors.white, - ) + .toText16(color: provider.isUserOutOfGame ? MyColors.darkTextColor : getAnswerTextColor(provider.currentQuestion.questionOptions![index].optionStatus!)) .paddingOnly(top: 17, bottom: 17), ), ), diff --git a/lib/ui/misc/request_submit_screen.dart b/lib/ui/misc/request_submit_screen.dart index 51a2440..f05bacb 100644 --- a/lib/ui/misc/request_submit_screen.dart +++ b/lib/ui/misc/request_submit_screen.dart @@ -8,7 +8,6 @@ import 'package:mohem_flutter_app/api/leave_balance_api_client.dart'; import 'package:mohem_flutter_app/api/my_attendance_api_client.dart'; import 'package:mohem_flutter_app/api/profile_api_client.dart'; import 'package:mohem_flutter_app/api/termination_dff_api_client.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/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; @@ -50,13 +49,8 @@ class _RequestSubmitScreenState extends State { List approverList = []; List attachmentFiles = []; - - dynamic dynamicParams; - String selectedEmp =""; - List attachments = []; - @override void initState() { super.initState(); @@ -129,7 +123,6 @@ class _RequestSubmitScreenState extends State { params!.transactionId, comments.text, -999, - empID: selectedEmp ); } else if (params!.approvalFlag == 'eit') { await MyAttendanceApiClient().startEitApprovalProcess( @@ -164,17 +157,6 @@ class _RequestSubmitScreenState extends State { @override Widget build(BuildContext context) { - // if (dynamicParams == null) { - // dynamicParams = ModalRoute - // .of(context)! - // .settings - // .arguments; - // if (dynamicParams.isNotEmpty) { - // AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; - // selectedEmp =dynamicParams; - // submitRequest(); - // } - // } if (params == null) { params = ModalRoute.of(context)!.settings.arguments as RequestSubmitScreenParams; getApproverList(); diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart index e914c70..08d2be7 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart @@ -635,9 +635,7 @@ class _DynamicInputScreenState extends State { ).paddingOnly(bottom: 12), itemBuilder: (_) => >[ if (model.rEADONLY != "Y") - for (int i = 0; i < model.eSERVICESVS!.length; i++) PopupMenuItem( - padding: EdgeInsets.all(10), - child: Text(model.eSERVICESVS![i].vALUECOLUMNNAME!), value: i), + for (int i = 0; i < model.eSERVICESVS!.length; i++) PopupMenuItem(child: Text(model.eSERVICESVS![i].vALUECOLUMNNAME!), value: i), ], onSelected: (int popipIndex) async { ESERVICESDV eservicesdv = ESERVICESDV( diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart index a670cbb..5c4053c 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart @@ -102,8 +102,8 @@ class _DynamicListViewScreenState extends State { itemBuilder: (cxt, int parentIndex) => getEITTransactionList![parentIndex].collectionTransaction!.isEmpty ? const SizedBox() : GridView( - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 1.0 / 0.75), - padding: const EdgeInsets.only(left: 12,right: 21,top: 12), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 1.9 / 0.75), + padding: const EdgeInsets.all(12.0), shrinkWrap: true, primary: false, physics: const ScrollPhysics(), diff --git a/lib/ui/my_attendance/services_menu_list_screen.dart b/lib/ui/my_attendance/services_menu_list_screen.dart index 7a61029..cd76132 100644 --- a/lib/ui/my_attendance/services_menu_list_screen.dart +++ b/lib/ui/my_attendance/services_menu_list_screen.dart @@ -54,7 +54,7 @@ class ServicesMenuListScreen extends StatelessWidget { } return; } else if (servicesMenuData.list[index].requestType == "ABSENCE") { - Navigator.pushNamed(context, AppRoutes.leaveBalance, arguments: servicesMenuData?.selectedEmp ??''); + Navigator.pushNamed(context, AppRoutes.leaveBalance); return; } if (servicesMenuData.list[index].requestType == "EIT") { diff --git a/lib/ui/my_team/create_request.dart b/lib/ui/my_team/create_request.dart index 1637586..53205c9 100644 --- a/lib/ui/my_team/create_request.dart +++ b/lib/ui/my_team/create_request.dart @@ -69,7 +69,7 @@ class _CreateRequestState extends State { if (menu.menuEntry.menuEntryType == "FUNCTION") { if (menu.menuEntry.requestType == "EIT") { - Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(menu.menuEntry.prompt!, menu.menuEntry.functionName!, selectedEmp: getEmployeeSubordinates?.eMPLOYEENUMBER??'')); + Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(menu.menuEntry.prompt!, menu.menuEntry.functionName!)); } else {} } else { Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, arguments: ServicesMenuListScreenParams(menu.menuEntry.prompt!, menu.menuEntiesList, selectedEmp: getEmployeeSubordinates?.eMPLOYEENUMBER??'')); diff --git a/lib/widgets/app_bar_widget.dart b/lib/widgets/app_bar_widget.dart index 6f0d7fd..199074a 100644 --- a/lib/widgets/app_bar_widget.dart +++ b/lib/widgets/app_bar_widget.dart @@ -8,7 +8,14 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/widgets/circular_avatar.dart'; AppBar AppBarWidget(BuildContext context, - {required String title, bool showHomeButton = true, bool showNotificationButton = false, bool showMemberButton = false, String? image, List? actions}) { + {required String title, + bool showHomeButton = true, + bool showNotificationButton = false, + bool showMemberButton = false, + String? image, + List? actions, + void Function()? onHomeTapped, + void Function()? onBackTapped}) { return AppBar( leadingWidth: 0, // leading: GestureDetector( @@ -21,7 +28,9 @@ AppBar AppBarWidget(BuildContext context, children: [ GestureDetector( behavior: HitTestBehavior.opaque, - onTap: Feedback.wrapForTap(() => Navigator.maybePop(context), context), + onTap: Feedback.wrapForTap(() { + (onBackTapped == null ? Navigator.maybePop(context) : onBackTapped()); + }, context), child: const Icon(Icons.arrow_back_ios, color: MyColors.darkIconColor), ), 4.width, @@ -43,7 +52,7 @@ AppBar AppBarWidget(BuildContext context, if (showHomeButton) IconButton( onPressed: () { - Navigator.popUntil(context, ModalRoute.withName(AppRoutes.dashboard)); + onHomeTapped == null ? Navigator.popUntil(context, ModalRoute.withName(AppRoutes.dashboard)) : onHomeTapped(); }, icon: const Icon(Icons.home, color: MyColors.darkIconColor), ), diff --git a/lib/widgets/balances_dashboard_widget.dart b/lib/widgets/balances_dashboard_widget.dart index e640ff4..e546acf 100644 --- a/lib/widgets/balances_dashboard_widget.dart +++ b/lib/widgets/balances_dashboard_widget.dart @@ -45,8 +45,6 @@ class _BalancesDashboardWidgetState extends State { late DateTime accrualDateTime; GetAccrualBalancesList? leaveBalanceAccrual; List? ticketBalanceAccrualList; - dynamic dynamicParams; - String selectedEmp =""; @override void initState() { @@ -62,7 +60,7 @@ class _BalancesDashboardWidgetState extends State { void changeAccrualDate() async { try { Utils.showLoading(context); - List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime),empID: selectedEmp); + List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime)); if (accrualList.isNotEmpty) { if (widget.isLeaveBalance) { leaveBalanceAccrual = accrualList[0]; @@ -88,17 +86,6 @@ class _BalancesDashboardWidgetState extends State { @override Widget build(BuildContext context) { - if (dynamicParams == null) { - dynamicParams = ModalRoute - .of(context)! - .settings - .arguments; - if (dynamicParams.isNotEmpty) { - AppState().postParamsJson['P_SELECTED_EMPLOYEE_NUMBER'] = dynamicParams; - selectedEmp =dynamicParams; - changeAccrualDate(); - } - } if (leaveBalanceAccrual == null && widget.isLeaveBalance) { leaveBalanceAccrual = Provider.of(context, listen: false).leaveBalanceAccrual; chartModelList = [