Merge branch 'master_mohemm_flutter'

# Conflicts:
#	assets/langs/en-US.json
#	ios/Runner/Info.plist
#	lib/app_state/app_state.dart
#	pubspec.yaml
master
haroon amjad 3 days ago
commit e4d182912c

@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.3339 15.9992H13.3339V11.1992C13.3339 10.9365 13.3343 10.7929 13.34 10.6886L13.341 10.673L13.3565 10.6721C13.4609 10.6664 13.6045 10.6659 13.8672 10.6659H17.3339C18.8066 10.6659 20.0005 11.8598 20.0005 13.3326C20.0005 14.8053 18.8066 15.9992 17.3339 15.9992Z" fill="#2E3039"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.0684 2.33203H15.9316C13.1698 2.33202 11.005 2.33201 9.30102 2.53899C7.55973 2.75051 6.16606 3.19084 5.02088 4.16892C4.71548 4.42976 4.43104 4.71419 4.1702 5.0196C3.19212 6.16478 2.75179 7.55845 2.54027 9.29974C2.33329 11.0037 2.3333 13.1684 2.33331 15.9304V16.067C2.3333 18.829 2.33329 20.9937 2.54027 22.6977C2.75179 24.4389 3.19212 25.8326 4.1702 26.9778C4.43104 27.2832 4.71547 27.5676 5.02088 27.8285C6.16606 28.8066 7.55973 29.2469 9.30102 29.4584C11.005 29.6654 13.1697 29.6654 15.9316 29.6654H16.0683C18.8302 29.6654 20.995 29.6654 22.6989 29.4584C24.4402 29.2469 25.8339 28.8066 26.9791 27.8285C27.2845 27.5676 27.5689 27.2832 27.8298 26.9778C28.8078 25.8326 29.2482 24.4389 29.4597 22.6977C29.6667 20.9937 29.6667 18.829 29.6666 16.067V15.9304C29.6667 13.1684 29.6667 11.0037 29.4597 9.29974C29.2482 7.55845 28.8078 6.16478 27.8298 5.0196C27.5689 4.71419 27.2845 4.42976 26.9791 4.16892C25.8339 3.19084 24.4402 2.75051 22.6989 2.53899C20.995 2.33201 18.8303 2.33202 16.0684 2.33203ZM13.8672 7.99925L13.7592 7.99898C13.3835 7.99761 12.9217 7.99593 12.5098 8.12976C11.698 8.39355 11.0615 9.03003 10.7977 9.84187C10.6639 10.2538 10.6656 10.7156 10.6669 11.0913L10.6672 11.1992V23.9993C10.6672 24.7356 11.2642 25.3326 12.0005 25.3326C12.7369 25.3326 13.3339 24.7356 13.3339 23.9993V18.6659H17.3339C20.2794 18.6659 22.6672 16.2781 22.6672 13.3326C22.6672 10.3871 20.2794 7.99925 17.3339 7.99925H13.8672Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="19.5" height="19.5" viewBox="0 0 19.5 19.5">
<g id="graduation-cap" transform="translate(0)">
<path id="cap-top" d="M9.75,4.5L3.5,7.5L9.75,10.5L16,7.5L9.75,4.5Z" fill="#2e303a"/>
<path id="cap-body" d="M4.5,8.5V13.5C4.5,14.5,6.5,16.5,9.75,16.5C13,16.5,15,14.5,15,13.5V8.5L9.75,11.5L4.5,8.5Z" fill="#2e303a"/>
<path id="tassel" d="M16,8V12.5L16.5,13L17,12.5V8H16Z" fill="#2e303a"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 457 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.2 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.2 MiB

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32.774" height="32.788" viewBox="0 0 32.774 32.788">
<g id="park-tickets-couple" transform="translate(-0.205 0.001)">
<path id="Path_4724" data-name="Path 4724" d="M68.36,485.746a1.657,1.657,0,0,1-1.581,1.3.539.539,0,0,0-.206,1.025,1.656,1.656,0,0,1,.955,1.814l-.14.7a1.744,1.744,0,0,1-2.093,1.278c-.25-.06-.506-.106-.759-.156-.373-.073-.745-.15-1.118-.223-.493-.1-.985-.2-1.477-.3l-1.76-.353c-.655-.133-1.311-.263-1.967-.4-.7-.14-1.4-.279-2.1-.423-.719-.143-1.438-.289-2.153-.433l-2.133-.429-2.036-.409c-.622-.123-1.241-.25-1.863-.373-.539-.107-1.078-.216-1.614-.323l-1.291-.26-.888-.18c-.136-.027-.273-.057-.409-.083-.007,0-.013,0-.02,0a1.686,1.686,0,0,1-.12,1.062,1.705,1.705,0,0,1-1.87.958.5.5,0,0,0-.562.246l-.3.649a.5.5,0,0,0,.176.589c.033.027,24.018,11.084,24.058,11.094a.5.5,0,0,0,.562-.246l.3-.649a.5.5,0,0,0-.176-.589,1.7,1.7,0,0,1,1.388-3,.5.5,0,0,0,.562-.246l.3-.649a.5.5,0,0,0-.176-.589,1.7,1.7,0,0,1,1.388-3,.5.5,0,0,0,.562-.246l.3-.649a.5.5,0,0,0-.176-.589,1.7,1.7,0,0,1,1.388-3,.5.5,0,0,0,.562-.246l.329-.719a.41.41,0,0,0-.2-.546L68.416,485.5Z" transform="translate(-39.26 -469.349)" fill="#2bb8a6"/>
<path id="Path_4725" data-name="Path 4725" d="M.519,16.168c.04.02,25.932,5.214,25.975,5.214a.5.5,0,0,0,.489-.369l.14-.7a.5.5,0,0,0-.309-.532,1.7,1.7,0,0,1,.652-3.244.5.5,0,0,0,.489-.369l.1-.512.037-.19a.5.5,0,0,0-.309-.532,1.7,1.7,0,0,1,.652-3.244.5.5,0,0,0,.489-.369l.14-.7a.5.5,0,0,0-.309-.532,1.7,1.7,0,0,1,.652-3.244.5.5,0,0,0,.489-.369l.156-.775a.41.41,0,0,0-.323-.482S3.714,0,3.687,0a.412.412,0,0,0-.4.329L3.128,1.1a.5.5,0,0,0,.309.532A1.7,1.7,0,0,1,2.786,4.88.5.5,0,0,0,2.3,5.25l-.14.7a.5.5,0,0,0,.309.532,1.7,1.7,0,0,1-.652,3.244.5.5,0,0,0-.489.369l-.14.7a.5.5,0,0,0,.309.532A1.7,1.7,0,0,1,.842,14.57a.5.5,0,0,0-.489.369l-.14.7A.494.494,0,0,0,.519,16.168ZM22.7,7.639a.831.831,0,1,1,1.631.326l-1.1,5.464L22.555,16.8a.832.832,0,0,1-.815.669.9.9,0,0,1-.163-.017.833.833,0,0,1-.652-.978l.755-3.757ZM7.7,4.628a.831.831,0,0,1,1.631.326L8.948,6.84,8.519,8.98,8.173,10.7l-.616,3.081a.832.832,0,0,1-.815.669.9.9,0,0,1-.163-.017.4.4,0,0,1-.067-.017.829.829,0,0,1-.582-.962l.123-.622.323-1.611Z" fill="#125765"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="23.959" height="37.006" viewBox="0 0 23.959 37.006">
<g id="Layer_x0020_1" transform="translate(-300.998)">
<g id="_411123120" transform="translate(301)">
<g id="Group_8657" data-name="Group 8657" transform="translate(3.252)">
<path id="Path_13674" data-name="Path 13674" d="M612.691,6.612H619.8V1.691h-7.111ZM620.669,8.3h-8.823A.833.833,0,0,1,611,7.458V.845A.847.847,0,0,1,611.846,0h8.823a.861.861,0,0,1,.845.845V7.458A.847.847,0,0,1,620.669,8.3Z" transform="translate(-607.531)" fill="#2bb8a6"/>
<path id="Path_13675" data-name="Path 13675" d="M466.845,305h15.089a.833.833,0,0,1,.845.845,5.44,5.44,0,0,1-5.42,5.441h-5.918A5.478,5.478,0,0,1,466,305.845.847.847,0,0,1,466.845,305Z" transform="translate(-465.675 -298.388)" fill="#2bb8a6"/>
<path id="Path_13676" data-name="Path 13676" d="M527.845,0A.861.861,0,0,0,527,.845a.847.847,0,0,0,.846.845h12.444a.851.851,0,0,0,.867-.845A.865.865,0,0,0,540.289,0Z" transform="translate(-525.352)" fill="#2bb8a6"/>
<g id="Group_8656" data-name="Group 8656" transform="translate(0 33.863)">
<path id="Path_13677" data-name="Path 13677" d="M455.553,1562v.867a2.276,2.276,0,1,1-4.553,0V1562h4.553Z" transform="translate(-451 -1562)" fill="#2bb8a6"/>
<path id="Path_13678" data-name="Path 13678" d="M1050.553,1562v.867a2.276,2.276,0,0,1-4.553,0V1562h4.553Z" transform="translate(-1033.101 -1562)" fill="#2bb8a6"/>
</g>
</g>
<path id="Subtraction_59" data-name="Subtraction 59" d="M20570.063,22681.4h-16.975a.817.817,0,0,1-.238-.023,3.388,3.388,0,0,1-2.236-1.018,3.476,3.476,0,0,1-1.02-2.471v-19.4a3.557,3.557,0,0,1,1.02-2.475,3.457,3.457,0,0,1,1.906-.975,1.745,1.745,0,0,0-.193.8,6.288,6.288,0,0,0,6.289,6.285h5.92a6.288,6.288,0,0,0,6.285-6.285,1.692,1.692,0,0,0-.217-.8,3.472,3.472,0,0,1,2.949,3.449v19.4a3.476,3.476,0,0,1-1.02,2.471,3.383,3.383,0,0,1-2.236,1.018A.879.879,0,0,1,20570.063,22681.4Zm-10.756-7.187a2.114,2.114,0,1,0,1.494.619A2.1,2.1,0,0,0,20559.307,22674.211Zm4.027.732-.613.621.961.939-.961.943.613.621.963-.949v0l.973.949.609-.621-.961-.943.961-.939-.609-.621-.973.951Zm-4.025-6.031a2.112,2.112,0,0,0-.807,4.063,2.071,2.071,0,0,0,.809.164,2.113,2.113,0,0,0,0-4.227Zm3.543,1.406-.645.584,1.531,1.7,2.637-2.6-.609-.619-1.992,1.963Zm-3.539-6.709a2.158,2.158,0,0,0-.486.059,2.111,2.111,0,1,0,.969,4.109,2.123,2.123,0,0,0,1.57-2.545A2.1,2.1,0,0,0,20559.313,22663.609Zm3.539,1.266-.645.58,1.531,1.7,2.637-2.6-.609-.619-1.992,1.963Z" transform="translate(-20549.596 -22648.381)" fill="#125765"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@ -0,0 +1 @@
<?xml version="1.0" ?><svg id="Outline" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:#ffffff;}</style></defs><path style="fill: #FFF" class="cls-1" d="M376,170a11.34,11.34,0,0,0-16,.15L215.28,317.64l-64-65.22a11.34,11.34,0,0,0-16.18,15.88l72.16,73.58a11.35,11.35,0,0,0,16,.15,12,12,0,0,0,1.43-1.7l.4-.37,151-154A11.33,11.33,0,0,0,376,170Z"/><path style="fill: #FFF" class="cls-1" d="M256,58.65c-108.38,0-196.56,88.18-196.56,196.56S147.62,451.77,256,451.77,452.56,363.6,452.56,255.21,364.38,58.65,256,58.65Zm0,370.45c-95.88,0-173.88-78-173.88-173.89S160.12,81.33,256,81.33s173.88,78,173.88,173.88S351.88,429.1,256,429.1Z"/></svg>

After

Width:  |  Height:  |  Size: 665 B

@ -0,0 +1 @@
<?xml version="1.0" ?><svg data-name="Livello 1" id="Livello_1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"><title/><path style="fill: #fff;" d="M64,0a64,64,0,1,0,64,64A64.07,64.07,0,0,0,64,0Zm0,122a58,58,0,1,1,58-58A58.07,58.07,0,0,1,64,122Z"/><path style="fill: #fff;" d="M92.12,35.79a3,3,0,0,0-4.24,0L64,59.75l-23.87-24A3,3,0,0,0,35.88,40L59.76,64,35.88,88a3,3,0,0,0,4.25,4.24L64,68.25l23.88,24A3,3,0,0,0,92.13,88L68.24,64,92.13,40A3,3,0,0,0,92.12,35.79Z"/></svg>

After

Width:  |  Height:  |  Size: 479 B

@ -164,6 +164,7 @@
"quotationAnalysis": "تحليل الاقتباس", "quotationAnalysis": "تحليل الاقتباس",
"subject": "موضوعات", "subject": "موضوعات",
"description": "وصف", "description": "وصف",
"pleaseEnterDescription": "الرجاء إدخال الوصف",
"supplier": "المورد", "supplier": "المورد",
"site": "موقع", "site": "موقع",
"buyer": "مشتر", "buyer": "مشتر",
@ -258,6 +259,7 @@
"fullName": "الأسم الكامل", "fullName": "الأسم الكامل",
"remove": "حذف", "remove": "حذف",
"submit": "ارسال", "submit": "ارسال",
"submitAsAnonymous": "إرسال كمجهول",
"areYouSureYouWantToSubmit": "هل أنت متأكد أنك تريد أن تقدم؟", "areYouSureYouWantToSubmit": "هل أنت متأكد أنك تريد أن تقدم؟",
"comments": "تعليقات", "comments": "تعليقات",
"writeComment": "أكتب تعليقا", "writeComment": "أكتب تعليقا",
@ -639,5 +641,32 @@
"yearsUsed": "سنوات الاستخدام", "yearsUsed": "سنوات الاستخدام",
"faRequest": "طلب التخلص من FA", "faRequest": "طلب التخلص من FA",
"showMore": "عرض المزيد", "showMore": "عرض المزيد",
"buyerDetails": "تفاصيل المشتري" "ticketDetails": "تفاصيل التذكرة",
"currentTicketBalance": "رصيد التذكرة الحالي",
"ticketHistory": "تاريخ التذكرة",
"proceedBooking": "المتابعة للحجز",
"courses": "الدورات التدريبية",
"course": "دورة",
"status": "الحالة",
"deadline": "الموعد النهائي",
"overdue": "متأخر",
"noCoursesAvailable": "لا توجد دورات متاحة",
"pullToRefresh": "اسحب للتحديث",
"courseUrlNotAvailable": "رابط الدورة غير متوفر",
"buyerDetails": "تفاصيل المشتري",
"etqanOVR": "الإبلاغ عن حادثة",
"etqanRequest": "طلبات الحوادث",
"selectProject": "حدد المشروع",
"project": "مشروع",
"keen": "حريص",
"reportIncident": "الإبلاغ عن الحادث",
"myIncidents": "حوادثي",
"incidentDetails": "تفاصيل الحادث",
"ticketNumber": "رقم التذكرة",
"ticketId": "معرف التذكرة",
"pleaseSelectProject": "الرجاء اختيار مشروع",
"viewAttachment" : "عرض المرفق",
"parkingQr": "وقوف السيارات QR",
"startNow": "ابدأ الآن"
} }

@ -158,6 +158,7 @@
"subject": "Subject", "subject": "Subject",
"quotationAnalysis": "Quotation Analysis", "quotationAnalysis": "Quotation Analysis",
"description": "Description", "description": "Description",
"pleaseEnterDescription": "Please enter description",
"supplier": "Supplier", "supplier": "Supplier",
"site": "Site", "site": "Site",
"buyer": "Buyer", "buyer": "Buyer",
@ -256,6 +257,7 @@
"remove": "Remove", "remove": "Remove",
"Attendance": "Attendance", "Attendance": "Attendance",
"submit": "Submit", "submit": "Submit",
"submitAsAnonymous": "Submit as Anonymous",
"areYouSureYouWantToSubmit": "Are you sure you want to submit?", "areYouSureYouWantToSubmit": "Are you sure you want to submit?",
"comments": "Comments", "comments": "Comments",
"writeComment": "Write a comment", "writeComment": "Write a comment",
@ -639,5 +641,31 @@
"yearsUsed": "Years Used", "yearsUsed": "Years Used",
"faRequest": "FA Disposal Request", "faRequest": "FA Disposal Request",
"showMore": "Show More", "showMore": "Show More",
"buyerDetails": "Buyer Details" "ticketDetails": "Ticket Details",
"currentTicketBalance": "Current Ticket Balance",
"ticketHistory": "Ticket History",
"proceedBooking": "Proceed For Booking",
"courses": "Courses",
"course": "Course",
"status": "Status",
"deadline": "Deadline",
"overdue": "Overdue",
"noCoursesAvailable": "No Courses Available",
"pullToRefresh": "Pull to refresh",
"courseUrlNotAvailable": "Course URL not available",
"buyerDetails": "Buyer Details",
"etqanOVR": "Report An Incident",
"etqanRequest": "Incident Requests",
"selectProject": "Select Project",
"project": "Project",
"keen": "Keen",
"reportIncident": "Report Incident",
"myIncidents": "My Incidents",
"incidentDetails": "Incident Details",
"ticketNumber": "Ticket Number",
"ticketId": "Ticket ID",
"pleaseSelectProject": "Please select a project",
"viewAttachment" : "View Attachment",
"parkingQr": "Parking QR",
"startNow": "Start Now"
} }

@ -55,6 +55,8 @@
<string>This app requires photo library access to select image as document &amp; upload it.</string> <string>This app requires photo library access to select image as document &amp; upload it.</string>
<key>NSMicrophoneUsageDescription</key> <key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access to for call.</string> <string>This app requires microphone access to for call.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app requires speech recognition access to access voice command features.</string>
<key>UIBackgroundModes</key> <key>UIBackgroundModes</key>
<array> <array>
<string>fetch</string> <string>fetch</string>

@ -15,7 +15,10 @@ import 'package:mohem_flutter_app/models/dashboard/get_accural_ticket_balance_mo
import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart';
import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart'; import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart';
import 'package:mohem_flutter_app/models/dashboard/list_menu.dart'; import 'package:mohem_flutter_app/models/dashboard/list_menu.dart';
import 'package:mohem_flutter_app/models/dashboard/courses_response_model.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/models/get_employee_parking_details_model.dart';
import 'package:mohem_flutter_app/models/greetings/greeting_card_model.dart';
import 'package:mohem_flutter_app/models/itg/itg_main_response.dart'; import 'package:mohem_flutter_app/models/itg/itg_main_response.dart';
import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart';
import 'package:mohem_flutter_app/models/sso_auth_model.dart'; import 'package:mohem_flutter_app/models/sso_auth_model.dart';
@ -226,10 +229,11 @@ class DashboardApiClient {
} }
Future<dynamic> getBookingSSOFinalRedirection({required String token}) async { Future<dynamic> getBookingSSOFinalRedirection({required String token}) async {
token = // token =
"eyJhbGciOiJSUzI1NiIsImtpZCI6IjhjZTE2OWM0YjIwYjQ2ZWM5YTQyOTU3Y2ZhODUzNzQ1IiwidHlwIjoiSldUIn0.eyJ0ZW5hbnRfaWQiOiJhOWY0ZDFhMDU5NmQ0YWVhOGY4MzA5OTJlYzRiZGFjMSIsImVpZCI6IjExNzkzMCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3NpZCI6Ijk2MDI0OGM1NzA3YzQ3MmFhYTEzM2I1N2ZhODE1ZmVhIiwibGFuZ3VhZ2UiOiJVUyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI6IjExNzkzMEBobWcuY29tIiwiZXhwIjoxNzgyNDc1NzY5LCJpc3MiOiJodHRwczovL3Nzby11YXQuaG1nLmNvbSIsImF1ZCI6ImE5ZjRkMWEwNTk2ZDRhZWE4ZjgzMDk5MmVjNGJkYWMxIn0.rJcLVsG8D0XECyLERCTD2uqGeWyvp-OBVGE9uL2qKrX4etFUHgdFt_5kYF6edFTtGy-0PIZadHDmv7e-IOhVWHm5HVMClaukiXoRXR8cDN8XA1wfme3Kd-U5PXN-IRh49AyRTzLO0rYNPvH81ScosWGlsFSkOvA-0hJNa2adHdtvgNvB8wJshSU5p7sAmF8mjdDY6aInG19etu2iEuUDwHHA4ZY_ts4hboHo8fE392hFaYGonExoD7bpW5RMx5xKWeRCmWpG_PK8Aw_z1jGzdB9PANus4pteRGuln1J-kmo2lQC9pVrSyZATAKp1HfgfyZ_vUhaHEfM69cMWaCslJQ"; // "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhjZTE2OWM0YjIwYjQ2ZWM5YTQyOTU3Y2ZhODUzNzQ1IiwidHlwIjoiSldUIn0.eyJ0ZW5hbnRfaWQiOiJhOWY0ZDFhMDU5NmQ0YWVhOGY4MzA5OTJlYzRiZGFjMSIsImVpZCI6IjExNzkzMCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3NpZCI6Ijk2MDI0OGM1NzA3YzQ3MmFhYTEzM2I1N2ZhODE1ZmVhIiwibGFuZ3VhZ2UiOiJVUyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI6IjExNzkzMEBobWcuY29tIiwiZXhwIjoxNzgyNDc1NzY5LCJpc3MiOiJodHRwczovL3Nzby11YXQuaG1nLmNvbSIsImF1ZCI6ImE5ZjRkMWEwNTk2ZDRhZWE4ZjgzMDk5MmVjNGJkYWMxIn0.rJcLVsG8D0XECyLERCTD2uqGeWyvp-OBVGE9uL2qKrX4etFUHgdFt_5kYF6edFTtGy-0PIZadHDmv7e-IOhVWHm5HVMClaukiXoRXR8cDN8XA1wfme3Kd-U5PXN-IRh49AyRTzLO0rYNPvH81ScosWGlsFSkOvA-0hJNa2adHdtvgNvB8wJshSU5p7sAmF8mjdDY6aInG19etu2iEuUDwHHA4ZY_ts4hboHo8fE392hFaYGonExoD7bpW5RMx5xKWeRCmWpG_PK8Aw_z1jGzdB9PANus4pteRGuln1J-kmo2lQC9pVrSyZATAKp1HfgfyZ_vUhaHEfM69cMWaCslJQ";
// var request = http.MultipartRequest('POST', Uri.parse('https://ek.techmaster.in/SSO/HMG')); // // var request = http.MultipartRequest('POST', Uri.parse('https://ek.techmaster.in/SSO/HMG'));
var request = http.MultipartRequest('POST', Uri.parse('https://Paxes-release.techmaster.in/SSO/HMG')); var request = http.MultipartRequest('POST', Uri.parse('https://Paxes-release.techmaster.in/SSO/HMG')); // UAT
// var request = http.MultipartRequest('POST', Uri.parse('https://paxes.com/sso/hmg')); // Prod
request.fields.addAll({'JWTToken': token}); request.fields.addAll({'JWTToken': token});
// request.headers.addAll(headers); // request.headers.addAll(headers);
@ -414,4 +418,57 @@ class DashboardApiClient {
// postParams, // postParams,
// ); // );
// } // }
Future<GetEmployeeParking?> getEmployeeParkingQrCode() async {
String url = "${ApiConsts.erpRest}GET_Employee_Parking";
Map<String, dynamic> postParams = {};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject(
(json) {
GetEmployeeParking responseData = GetEmployeeParking.fromJson(json);
return responseData;
},
url,
postParams,
);
}
//Fetch All Courses Status
Future<CoursesResponseModel?> fetchAllCoursesStatus() async {
String url = "https://elearning.hmg.com/moodle_dev/api/Fetch_All_Courses_Status.php";
Map<String, String> headers = {
'x-api-key': 'bLi@mbXJeXTHd/)h&LFh%25+%25(Nbnaq6hBg%7d%5dyQbthY%7bv6ew6-5UT\$NASwucn%7d,_PSJpuwNCCen2%7djj%7b00HR2T-%5b,k7W%7d-0yepK?%258',
'Content-Type': 'application/x-www-form-urlencoded',
};
Map<String, dynamic> postParams = {
"username": AppState().memberInformationList?.eMPLOYEENUMBER ?? "",
};
return await ApiClient().postJsonForObject(
(json) {
CoursesResponseModel responseData = CoursesResponseModel.fromJson(json);
return responseData;
},
url,
postParams,
headers: headers,
isFormData: false,
);
}
Future<GetGreetingCardsModelResponse?> getGreetingCards() async {
String url = "${ApiConsts.erpRest}Get_GreetingCards";
Map<String, dynamic> postParams = {};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject(
(json) {
GetGreetingCardsModelResponse responseData = GetGreetingCardsModelResponse.fromJson(json);
return responseData;
},
url,
postParams,
);
}
} }

@ -0,0 +1,140 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:intl/intl.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/etqan_ovr/etqan_get_employee_incident_report.dart';
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_requests_model.dart';
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_getprojects_model.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_department_sections.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_project_departments.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_projects.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_section_topics.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_details.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_transactions.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_ticket_types.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_tickets_list.dart';
import 'package:mohem_flutter_app/models/mowadhafhi/get_transaction_attachment_model.dart';
class EtqanApiClient {
static final EtqanApiClient _instance = EtqanApiClient._internal();
EtqanApiClient._internal();
factory EtqanApiClient() => _instance;
Future<List<EtqanGetProjectsResponse>> getEtqanProjects() async {
String url = "${ApiConsts.cocRest}ETQAN_GetProjects";
Map<String, dynamic> postParams = <String, dynamic>{"P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject(
(json) {
List<EtqanGetProjectsResponse>? responseData = <EtqanGetProjectsResponse>[];
if (json["ETQAN_GetProjects_Response"] != null && json["ETQAN_GetProjects_Response"].isNotEmpty) {
json["ETQAN_GetProjects_Response"].forEach((element) {
responseData.add(EtqanGetProjectsResponse.fromJson(element));
});
}
return responseData;
},
url,
postParams,
);
}
Future<List<EtqanGetEmployeeOvrRequestsResponse>> getEmployeeEtqanRequests() async {
String url = "${ApiConsts.cocRest}ETQAN_GetEmployeeOVRRequests";
Map<String, dynamic> postParams = <String, dynamic>{
"ETQAN_EmployeeID": AppState().memberInformationList?.eMPLOYEENUMBER,
"P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER,
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject(
(json) {
List<EtqanGetEmployeeOvrRequestsResponse> responseData = <EtqanGetEmployeeOvrRequestsResponse>[];
if (json["ETQAN_GetEmployeeOVRRequests_Response"] != null && json["ETQAN_GetEmployeeOVRRequests_Response"].isNotEmpty) {
json["ETQAN_GetEmployeeOVRRequests_Response"].forEach((element) {
responseData.add(EtqanGetEmployeeOvrRequestsResponse.fromJson(element));
});
}
if (responseData.isNotEmpty) {
responseData.sort((EtqanGetEmployeeOvrRequestsResponse a, EtqanGetEmployeeOvrRequestsResponse b) {
if (a.createdDate == null && b.createdDate == null) return 0;
if (a.createdDate == null) return 1;
if (b.createdDate == null) return -1;
try {
// Parse dates in format "26-Feb-2026 12:54 PM" or "01-Mar-2026 02:45 PM"
DateFormat dateFormat = DateFormat("dd-MMM-yyyy hh:mm a", "en_US");
DateTime dateA = dateFormat.parse(a.createdDate!);
DateTime dateB = dateFormat.parse(b.createdDate!);
return dateB.compareTo(dateA); // Descending order (newest first)
} catch (e) {
return (b.createdDate ?? '').compareTo(a.createdDate ?? '');
}
});
}
return responseData;
},
url,
postParams,
);
}
Future<List<EtqanGetIncidentRequestResponse>> getEtqanIncidentRequests(String ticketNo) async {
String url = "${ApiConsts.cocRest}ETQAN_GetIncidentRequest";
Map<String, dynamic> postParams = <String, dynamic>{"ETQAN_TicketNumber": ticketNo, "P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject(
(json) {
List<EtqanGetIncidentRequestResponse> responseData = <EtqanGetIncidentRequestResponse>[];
if (json["ETQAN_GetIncidentRequest_Response"] != null && json["ETQAN_GetIncidentRequest_Response"].isNotEmpty) {
json["ETQAN_GetIncidentRequest_Response"].forEach((element) {
responseData.add(EtqanGetIncidentRequestResponse.fromJson(element));
});
}
return responseData;
},
url,
postParams,
);
}
Future<Map<String, dynamic>?> createRequest(String description, int? projectID, String? attachmentBase64, bool? isAnonymous) async {
String url = "${ApiConsts.cocRest}ETQAN_CreateIncident";
Map<String, dynamic> postParams = <String, dynamic>{
"P_SELECTED_EMPLOYEE_NUMBER": AppState().memberInformationList?.eMPLOYEENUMBER,
"P_USER_NAME": AppState().memberInformationList?.eMPLOYEENUMBER,
"ETQAN_Emp_EmployeeNumber": AppState().memberInformationList?.eMPLOYEENUMBER,
"ETQAN_Description": description,
"ETQAN_ProjectId": projectID,
"ETQAN_FileInfoBase64": attachmentBase64,
"ETQAN_IsAnonymous": isAnonymous ?? false,
};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject(
(json) {
if (json["ETQAN_CreateIncident_Response"] != null) {
var response = json["ETQAN_CreateIncident_Response"];
if (response["id"] != null && response["ticketNumber"] != null) {
return {"id": response["id"], "ticketNumber": response["ticketNumber"]};
}
return null;
}
return null;
// "ETQAN_CreateIncident_Response": {
// "id": "00adabe4-4a32-4b35-1f00-08de4d152e7c",
// "ticketNumber": "OVR/OLY/2026/224"
// },
},
url,
postParams,
);
}
}

@ -90,7 +90,7 @@ class AppState {
String get getHuaweiPushToken => _huaweiPushToken; String get getHuaweiPushToken => _huaweiPushToken;
final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 33, versionID: 9.5, mobileType: Platform.isAndroid ? "android" : "ios"); final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 33, versionID: 9.6, mobileType: Platform.isAndroid ? "android" : "ios");
void setPostParamsInitConfig() { void setPostParamsInitConfig() {
isAuthenticated = false; isAuthenticated = false;

@ -4,14 +4,14 @@ class ApiConsts {
// static String baseUrl = "http://10.200.204.11"; // Local server // static String baseUrl = "http://10.200.204.11"; // Local server
// static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server
// static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver
// static String baseUrl = "http://10.201.204.101:2024"; // static String baseUrl = "http://10.201.204.101:2024";
// static String baseUrl = "https://webservices.hmg.com"; // PreProd // static String baseUrl = "https://webservices.hmg.com"; // PreProd
// static String baseUrl = "https://hmgwebservices.com"; // Live server // static String baseUrl = "https://hmgwebservices.com"; // Live server
static String baseUrl = "https://mohemm.hmg.com"; // New Live server // static String baseUrl = "https://mohemm.hmg.com"; // New Live server
// //
// static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver
// static String baseUrl = "http://10.20.200.111:1010/"; // static String baseUrl = "http://10.20.200.111:1010/";
// static String baseUrl = "https://webservices.hmg.com"; // PreProd // static String baseUrl = "https://webservices.hmg.com"; // PreProd
@ -27,7 +27,8 @@ class ApiConsts {
static String user = baseUrlServices + "api/User/"; static String user = baseUrlServices + "api/User/";
static String cocRest = baseUrlServices + "COCWS.svc/REST/"; static String cocRest = baseUrlServices + "COCWS.svc/REST/";
static String ssoAuthRedirection = "https://sso-uat.hmg.com/api/auth/connect"; static String ssoAuthRedirection = "https://sso-uat.hmg.com/api/auth/connect"; // UAT
// static String ssoAuthRedirection = "https://sso.hmg.com/api/auth/connect"; // Prod
//Chat //Chat
static String chatServerBaseUrl = "https://apiderichat.hmg.com/"; static String chatServerBaseUrl = "https://apiderichat.hmg.com/";

@ -135,8 +135,8 @@ class Utils {
} }
} }
static Future showErrorDialog({required BuildContext context, required VoidCallback onOkTapped, required String message}) async { static Future showErrorDialog({required BuildContext context, required VoidCallback onOkTapped, required String message, VoidCallback? onCloseTap}) async {
return showDialog(context: context, builder: (BuildContext context) => ConfirmDialog(message: message, onTap: onOkTapped)); return showDialog(context: context, builder: (BuildContext context) => ConfirmDialog(message: message, onTap: onOkTapped, onCloseTap: onCloseTap));
} }
static void confirmDialog(cxt, String message, {VoidCallback? onTap}) { static void confirmDialog(cxt, String message, {VoidCallback? onTap}) {

@ -10,6 +10,9 @@ import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart';
import 'package:mohem_flutter_app/ui/chat/group_chat_detaied_screen.dart'; import 'package:mohem_flutter_app/ui/chat/group_chat_detaied_screen.dart';
import 'package:mohem_flutter_app/ui/chat/group_members.dart'; import 'package:mohem_flutter_app/ui/chat/group_members.dart';
import 'package:mohem_flutter_app/ui/chat/manage_group.dart'; import 'package:mohem_flutter_app/ui/chat/manage_group.dart';
import 'package:mohem_flutter_app/ui/etqan_ovr/etqan_create_request.dart';
import 'package:mohem_flutter_app/ui/etqan_ovr/etqan_ovr_home.dart';
import 'package:mohem_flutter_app/ui/etqan_ovr/etqan_request_detailed.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
import 'package:mohem_flutter_app/ui/landing/itg/change_itg_ad_password_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/change_itg_ad_password_screen.dart';
import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart'; import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart';
@ -40,6 +43,7 @@ import 'package:mohem_flutter_app/ui/my_team/profile_details.dart';
import 'package:mohem_flutter_app/ui/my_team/subordinate_leave.dart'; import 'package:mohem_flutter_app/ui/my_team/subordinate_leave.dart';
import 'package:mohem_flutter_app/ui/my_team/team_members.dart'; import 'package:mohem_flutter_app/ui/my_team/team_members.dart';
import 'package:mohem_flutter_app/ui/my_team/view_attendance.dart'; import 'package:mohem_flutter_app/ui/my_team/view_attendance.dart';
import 'package:mohem_flutter_app/ui/parking_qr/parking_qr.dart';
import 'package:mohem_flutter_app/ui/payslip/monthly_pay_slip_screen.dart'; import 'package:mohem_flutter_app/ui/payslip/monthly_pay_slip_screen.dart';
import 'package:mohem_flutter_app/ui/performance/performance_appraisal_screen.dart'; import 'package:mohem_flutter_app/ui/performance/performance_appraisal_screen.dart';
import 'package:mohem_flutter_app/ui/profile/add_update_family_member.dart'; import 'package:mohem_flutter_app/ui/profile/add_update_family_member.dart';
@ -54,6 +58,7 @@ import 'package:mohem_flutter_app/ui/profile/profile_screen.dart';
import 'package:mohem_flutter_app/ui/screens/announcements/announcement_details.dart'; import 'package:mohem_flutter_app/ui/screens/announcements/announcement_details.dart';
import 'package:mohem_flutter_app/ui/screens/announcements/announcements.dart'; import 'package:mohem_flutter_app/ui/screens/announcements/announcements.dart';
import 'package:mohem_flutter_app/ui/screens/child_education/child_education_assistance.dart'; import 'package:mohem_flutter_app/ui/screens/child_education/child_education_assistance.dart';
import 'package:mohem_flutter_app/ui/screens/courses/courses_screen.dart';
// import 'package:mohem_flutter_app/ui/my_attendance/work_from_home_screen.dart'; // import 'package:mohem_flutter_app/ui/my_attendance/work_from_home_screen.dart';
import 'package:mohem_flutter_app/ui/screens/eit/add_eit.dart'; import 'package:mohem_flutter_app/ui/screens/eit/add_eit.dart';
import 'package:mohem_flutter_app/ui/screens/event_activity/event_activity.dart'; import 'package:mohem_flutter_app/ui/screens/event_activity/event_activity.dart';
@ -166,6 +171,9 @@ class AppRoutes {
static const String offersAndDiscounts = "/offersAndDiscounts"; static const String offersAndDiscounts = "/offersAndDiscounts";
static const String offersAndDiscountsDetails = "/offersAndDiscountsDetails"; static const String offersAndDiscountsDetails = "/offersAndDiscountsDetails";
// Courses
static const String courses = "/courses";
//Pay slip //Pay slip
static const String monthlyPaySlip = "/monthlyPaySlip"; static const String monthlyPaySlip = "/monthlyPaySlip";
@ -211,6 +219,13 @@ class AppRoutes {
static const String activityScreen = "/activityScreen"; static const String activityScreen = "/activityScreen";
static const String etqanOvr = "/etqanOvr";
static const String etqanCreateRequest = "/etqanCreateRequest";
static const String etqanGetIncidientRequest = "/etqanGetIncidientRequest";
//Parking QR
static const String parkingQr = "/parkingQrScreen";
static final Map<String, WidgetBuilder> routes = { static final Map<String, WidgetBuilder> routes = {
login: (BuildContext context) => LoginScreen(), login: (BuildContext context) => LoginScreen(),
verifyLogin: (BuildContext context) => VerifyLoginScreen(), verifyLogin: (BuildContext context) => VerifyLoginScreen(),
@ -291,6 +306,9 @@ class AppRoutes {
offersAndDiscounts: (BuildContext context) => OffersAndDiscountsHome(), offersAndDiscounts: (BuildContext context) => OffersAndDiscountsHome(),
offersAndDiscountsDetails: (BuildContext context) => OffersAndDiscountsDetails(), offersAndDiscountsDetails: (BuildContext context) => OffersAndDiscountsDetails(),
// Courses
courses: (BuildContext context) => const CoursesScreen(),
//pay slip //pay slip
monthlyPaySlip: (BuildContext context) => MonthlyPaySlipScreen(), monthlyPaySlip: (BuildContext context) => MonthlyPaySlipScreen(),
performanceEvaluation: (BuildContext context) => PerformanceAppraisal(), performanceEvaluation: (BuildContext context) => PerformanceAppraisal(),
@ -328,6 +346,16 @@ class AppRoutes {
unsafeDeviceScreen: (BuildContext context) => const UnsafeDeviceScreen(), unsafeDeviceScreen: (BuildContext context) => const UnsafeDeviceScreen(),
appUpdateScreen: (BuildContext context) => const AppUpdateScreen(), appUpdateScreen: (BuildContext context) => const AppUpdateScreen(),
childEducation: (BuildContext context) => ChildEducationAssistance(), childEducation: (BuildContext context) => ChildEducationAssistance(),
activityScreen:(BuildContext context) => const EventActivityScreen() activityScreen:(BuildContext context) => const EventActivityScreen(),
//ETQAN OVR
etqanOvr: (BuildContext context) => EtqanOvrHome(),
etqanCreateRequest: (BuildContext context) => EtqanOvrCreateRequest(),
etqanGetIncidientRequest: (BuildContext context) => EtqanOvrRequestDetailed(),
activityScreen:(BuildContext context) => const EventActivityScreen(),
//Parking QR
parkingQr: (BuildContext context) => const ParkingQrScreen(),
}; };
} }

@ -180,6 +180,7 @@ class CodegenLoader extends AssetLoader{
"quotationAnalysis": "تحليل الاقتباس", "quotationAnalysis": "تحليل الاقتباس",
"subject": "موضوعات", "subject": "موضوعات",
"description": "وصف", "description": "وصف",
"pleaseEnterDescription": "الرجاء إدخال الوصف",
"supplier": "المورد", "supplier": "المورد",
"site": "موقع", "site": "موقع",
"buyer": "مشتر", "buyer": "مشتر",
@ -274,6 +275,7 @@ class CodegenLoader extends AssetLoader{
"fullName": "الأسم الكامل", "fullName": "الأسم الكامل",
"remove": "حذف", "remove": "حذف",
"submit": "ارسال", "submit": "ارسال",
"submitAsAnonymous": "إرسال كمجهول",
"areYouSureYouWantToSubmit": "هل أنت متأكد أنك تريد أن تقدم؟", "areYouSureYouWantToSubmit": "هل أنت متأكد أنك تريد أن تقدم؟",
"comments": "تعليقات", "comments": "تعليقات",
"writeComment": "أكتب تعليقا", "writeComment": "أكتب تعليقا",
@ -655,7 +657,33 @@ class CodegenLoader extends AssetLoader{
"yearsUsed": "سنوات الاستخدام", "yearsUsed": "سنوات الاستخدام",
"faRequest": "طلب التخلص من FA", "faRequest": "طلب التخلص من FA",
"showMore": "عرض المزيد", "showMore": "عرض المزيد",
"buyerDetails": "تفاصيل المشتري" "ticketDetails": "تفاصيل التذكرة",
"currentTicketBalance": "رصيد التذكرة الحالي",
"ticketHistory": "تاريخ التذكرة",
"proceedBooking": "المتابعة للحجز",
"courses": "الدورات التدريبية",
"course": "دورة",
"status": "الحالة",
"deadline": "الموعد النهائي",
"overdue": "متأخر",
"noCoursesAvailable": "لا توجد دورات متاحة",
"pullToRefresh": "اسحب للتحديث",
"courseUrlNotAvailable": "رابط الدورة غير متوفر",
"buyerDetails": "تفاصيل المشتري",
"etqanOVR": "الإبلاغ عن حادثة",
"etqanRequest": "طلبات الحوادث",
"selectProject": "حدد المشروع",
"project": "مشروع",
"keen": "حريص",
"reportIncident": "الإبلاغ عن الحادث",
"myIncidents": "حوادثي",
"incidentDetails": "تفاصيل الحادث",
"ticketNumber": "رقم التذكرة",
"ticketId": "معرف التذكرة",
"pleaseSelectProject": "الرجاء اختيار مشروع",
"viewAttachment": "عرض المرفق",
"parkingQr": "وقوف السيارات QR",
"startNow": "ابدأ الآن"
}; };
static const Map<String,dynamic> _en_US = { static const Map<String,dynamic> _en_US = {
"mohemm": "Mohemm", "mohemm": "Mohemm",
@ -817,6 +845,7 @@ static const Map<String,dynamic> _en_US = {
"subject": "Subject", "subject": "Subject",
"quotationAnalysis": "Quotation Analysis", "quotationAnalysis": "Quotation Analysis",
"description": "Description", "description": "Description",
"pleaseEnterDescription": "Please enter description",
"supplier": "Supplier", "supplier": "Supplier",
"site": "Site", "site": "Site",
"buyer": "Buyer", "buyer": "Buyer",
@ -915,6 +944,7 @@ static const Map<String,dynamic> _en_US = {
"remove": "Remove", "remove": "Remove",
"Attendance": "Attendance", "Attendance": "Attendance",
"submit": "Submit", "submit": "Submit",
"submitAsAnonymous": "Submit as Anonymous",
"areYouSureYouWantToSubmit": "Are you sure you want to submit?", "areYouSureYouWantToSubmit": "Are you sure you want to submit?",
"comments": "Comments", "comments": "Comments",
"writeComment": "Write a comment", "writeComment": "Write a comment",
@ -1298,7 +1328,33 @@ static const Map<String,dynamic> _en_US = {
"yearsUsed": "Years Used", "yearsUsed": "Years Used",
"faRequest": "FA Disposal Request", "faRequest": "FA Disposal Request",
"showMore": "Show More", "showMore": "Show More",
"buyerDetails": "Buyer Details" "ticketDetails": "Ticket Details",
"currentTicketBalance": "Current Ticket Balance",
"ticketHistory": "Ticket History",
"proceedBooking": "Proceed For Booking",
"courses": "Courses",
"course": "Course",
"status": "Status",
"deadline": "Deadline",
"overdue": "Overdue",
"noCoursesAvailable": "No Courses Available",
"pullToRefresh": "Pull to refresh",
"courseUrlNotAvailable": "Course URL not available",
"buyerDetails": "Buyer Details",
"etqanOVR": "Report An Incident",
"etqanRequest": "Incident Requests",
"selectProject": "Select Project",
"project": "Project",
"keen": "Keen",
"reportIncident": "Report Incident",
"myIncidents": "My Incidents",
"incidentDetails": "Incident Details",
"ticketNumber": "Ticket Number",
"ticketId": "Ticket ID",
"pleaseSelectProject": "Please select a project",
"viewAttachment": "View Attachment",
"parkingQr": "Parking QR",
"startNow": "Start Now"
}; };
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": _ar_SA, "en_US": _en_US}; static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": _ar_SA, "en_US": _en_US};
} }

@ -167,6 +167,7 @@ abstract class LocaleKeys {
static const quotationAnalysis = 'quotationAnalysis'; static const quotationAnalysis = 'quotationAnalysis';
static const subject = 'subject'; static const subject = 'subject';
static const description = 'description'; static const description = 'description';
static const pleaseEnterDescription = 'pleaseEnterDescription';
static const supplier = 'supplier'; static const supplier = 'supplier';
static const site = 'site'; static const site = 'site';
static const buyer = 'buyer'; static const buyer = 'buyer';
@ -261,6 +262,7 @@ abstract class LocaleKeys {
static const fullName = 'fullName'; static const fullName = 'fullName';
static const remove = 'remove'; static const remove = 'remove';
static const submit = 'submit'; static const submit = 'submit';
static const submitAsAnonymous = 'submitAsAnonymous';
static const areYouSureYouWantToSubmit = 'areYouSureYouWantToSubmit'; static const areYouSureYouWantToSubmit = 'areYouSureYouWantToSubmit';
static const comments = 'comments'; static const comments = 'comments';
static const writeComment = 'writeComment'; static const writeComment = 'writeComment';
@ -627,6 +629,32 @@ abstract class LocaleKeys {
static const yearsUsed = 'yearsUsed'; static const yearsUsed = 'yearsUsed';
static const faRequest = 'faRequest'; static const faRequest = 'faRequest';
static const showMore = 'showMore'; static const showMore = 'showMore';
static const ticketDetails = 'ticketDetails';
static const currentTicketBalance = 'currentTicketBalance';
static const ticketHistory = 'ticketHistory';
static const proceedBooking = 'proceedBooking';
static const courses = 'courses';
static const course = 'course';
static const status = 'status';
static const deadline = 'deadline';
static const overdue = 'overdue';
static const noCoursesAvailable = 'noCoursesAvailable';
static const pullToRefresh = 'pullToRefresh';
static const courseUrlNotAvailable = 'courseUrlNotAvailable';
static const buyerDetails = 'buyerDetails'; static const buyerDetails = 'buyerDetails';
static const etqanOVR = 'etqanOVR';
static const etqanRequest = 'etqanRequest';
static const selectProject = 'selectProject';
static const project = 'project';
static const keen = 'keen';
static const reportIncident = 'reportIncident';
static const myIncidents = 'myIncidents';
static const incidentDetails = 'incidentDetails';
static const ticketNumber = 'ticketNumber';
static const ticketId = 'ticketId';
static const pleaseSelectProject = 'pleaseSelectProject';
static const viewAttachment = 'viewAttachment';
static const parkingQr = 'parkingQr';
static const startNow = 'startNow';
} }

@ -12,6 +12,7 @@ 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/chat_provider_model.dart';
import 'package:mohem_flutter_app/provider/dashboard_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/provider/eit_provider_model.dart';
import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart';
import 'package:mohem_flutter_app/theme/app_theme.dart'; import 'package:mohem_flutter_app/theme/app_theme.dart';
import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart'; import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart';
import 'package:month_year_picker/month_year_picker.dart'; import 'package:month_year_picker/month_year_picker.dart';
@ -53,6 +54,7 @@ Future<void> main() async {
ChangeNotifierProvider<EITProviderModel>(create: (_) => EITProviderModel()), ChangeNotifierProvider<EITProviderModel>(create: (_) => EITProviderModel()),
ChangeNotifierProvider<ChatProviderModel>(create: (_) => ChatProviderModel()), ChangeNotifierProvider<ChatProviderModel>(create: (_) => ChatProviderModel()),
ChangeNotifierProvider<MarathonProvider>(create: (_) => MarathonProvider()), ChangeNotifierProvider<MarathonProvider>(create: (_) => MarathonProvider()),
ChangeNotifierProvider<EtqanOvrProviderModel>(create: (_) => EtqanOvrProviderModel()),
// ChangeNotifierProvider<ChatCallProvider>( // ChangeNotifierProvider<ChatCallProvider>(
// create: (_) => ChatCallProvider(), // create: (_) => ChatCallProvider(),
// ), // ),

@ -0,0 +1,94 @@
class CoursesResponseModel {
bool? success;
int? status;
String? username;
List<CourseStatus>? coursesStatus;
int? totalCourses;
CoursesResponseModel({
this.success,
this.status,
this.username,
this.coursesStatus,
this.totalCourses,
});
CoursesResponseModel.fromJson(Map<String, dynamic> json) {
success = json['success'];
status = json['status'];
username = json['username'];
if (json['courses_status'] != null) {
coursesStatus = <CourseStatus>[];
json['courses_status'].forEach((v) {
coursesStatus!.add(CourseStatus.fromJson(v));
});
}
totalCourses = json['total_courses'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = <String, dynamic>{};
data['success'] = success;
data['status'] = status;
data['username'] = username;
if (coursesStatus != null) {
data['courses_status'] = coursesStatus!.map((v) => v.toJson()).toList();
}
data['total_courses'] = totalCourses;
return data;
}
}
class CourseStatus {
String? cId;
String? cFullname;
String? cNameAr;
String? cShortname;
String? cStatus;
String? cIsMohemmAffective;
String? cStartdate;
String? cEnddate;
String? cUrl;
String? token;
CourseStatus({
this.cId,
this.cFullname,
this.cNameAr,
this.cShortname,
this.cStatus,
this.cIsMohemmAffective,
this.cStartdate,
this.cEnddate,
this.cUrl,
this.token
});
CourseStatus.fromJson(Map<String, dynamic> json) {
cId = json['c_id'];
cFullname = json['c_fullname'];
cNameAr = json['c_name_ar'];
cShortname = json['c_shortname'];
cStatus = json['c_status'];
cIsMohemmAffective = json['c_is_mohemm_affective'];
cStartdate = json['c_startdate'];
cEnddate = json['c_enddate'];
cUrl = json['c_url'];
token =json['c_token'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = <String, dynamic>{};
data['c_id'] = cId;
data['c_fullname'] = cFullname;
data['c_name_ar'] = cNameAr;
data['c_shortname'] = cShortname;
data['c_status'] = cStatus;
data['c_is_mohemm_affective'] = cIsMohemmAffective;
data['c_startdate'] = cStartdate;
data['c_enddate'] = cEnddate;
data['c_url'] = cUrl;
data['c_token'] = token;
return data;
}
}

@ -0,0 +1,57 @@
import 'dart:convert';
class EtqanGetEmployeeIncidentRequestModel {
List<EtqanGetIncidentRequestResponse>? etqanGetIncidentRequestResponse;
EtqanGetEmployeeIncidentRequestModel({
this.etqanGetIncidentRequestResponse,
});
factory EtqanGetEmployeeIncidentRequestModel.fromRawJson(String str) => EtqanGetEmployeeIncidentRequestModel.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory EtqanGetEmployeeIncidentRequestModel.fromJson(Map<String, dynamic> json) => EtqanGetEmployeeIncidentRequestModel(
etqanGetIncidentRequestResponse: json["ETQAN_GetIncidentRequest_Response"] == null ? [] : List<EtqanGetIncidentRequestResponse>.from(json["ETQAN_GetIncidentRequest_Response"]!.map((x) => EtqanGetIncidentRequestResponse.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"ETQAN_GetIncidentRequest_Response": etqanGetIncidentRequestResponse == null ? [] : List<dynamic>.from(etqanGetIncidentRequestResponse!.map((x) => x.toJson())),
};
}
class EtqanGetIncidentRequestResponse {
String? key;
String? keyAr;
String? value;
String? valueAr;
List<String>? subValues;
EtqanGetIncidentRequestResponse({
this.key,
this.keyAr,
this.value,
this.valueAr,
this.subValues,
});
factory EtqanGetIncidentRequestResponse.fromRawJson(String str) => EtqanGetIncidentRequestResponse.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory EtqanGetIncidentRequestResponse.fromJson(Map<String, dynamic> json) => EtqanGetIncidentRequestResponse(
key: json["key"],
keyAr: json["keyAr"],
value: json["value"],
valueAr: json["valueAr"],
subValues: json["subValues"] == null ? [] : List<String>.from(json["subValues"]!.map((x) => x)),
);
Map<String, dynamic> toJson() => {
"key": key,
"keyAr": keyAr,
"value": value,
"valueAr": valueAr,
"subValues": subValues == null ? [] : List<dynamic>.from(subValues!.map((x) => x)),
};
}

@ -0,0 +1,65 @@
import 'dart:convert';
class EtqanGetEmployeeRequestsModel {
List<EtqanGetEmployeeOvrRequestsResponse>? etqanGetEmployeeOvrRequestsResponse;
EtqanGetEmployeeRequestsModel({
this.etqanGetEmployeeOvrRequestsResponse,
});
factory EtqanGetEmployeeRequestsModel.fromRawJson(String str) => EtqanGetEmployeeRequestsModel.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory EtqanGetEmployeeRequestsModel.fromJson(Map<String, dynamic> json) => EtqanGetEmployeeRequestsModel(
etqanGetEmployeeOvrRequestsResponse: json["ETQAN_GetEmployeeOVRRequests_Response"] == null ? [] : List<EtqanGetEmployeeOvrRequestsResponse>.from(json["ETQAN_GetEmployeeOVRRequests_Response"]!.map((x) => EtqanGetEmployeeOvrRequestsResponse.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"ETQAN_GetEmployeeOVRRequests_Response": etqanGetEmployeeOvrRequestsResponse == null ? [] : List<dynamic>.from(etqanGetEmployeeOvrRequestsResponse!.map((x) => x.toJson())),
};
}
class EtqanGetEmployeeOvrRequestsResponse {
String? createdDate;
String? description;
String? id;
bool? isAnonymous;
String? status;
String? statusAr;
String? ticketNumber;
EtqanGetEmployeeOvrRequestsResponse({
this.createdDate,
this.description,
this.id,
this.isAnonymous,
this.status,
this.statusAr,
this.ticketNumber,
});
factory EtqanGetEmployeeOvrRequestsResponse.fromRawJson(String str) => EtqanGetEmployeeOvrRequestsResponse.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory EtqanGetEmployeeOvrRequestsResponse.fromJson(Map<String, dynamic> json) => EtqanGetEmployeeOvrRequestsResponse(
createdDate: json["createdDate"],
description: json["description"],
id: json["id"],
isAnonymous: json["isAnonymous"],
status: json["status"],
statusAr: json["statusAr"],
ticketNumber: json["ticketNumber"],
);
Map<String, dynamic> toJson() => {
"createdDate": createdDate,
"description": description,
"id": id,
"isAnonymous": isAnonymous,
"status": status,
"statusAr": statusAr,
"ticketNumber": ticketNumber,
};
}

@ -0,0 +1,53 @@
import 'dart:convert';
class EtqanGetProjectsModel {
List<EtqanGetProjectsResponse>? etqanGetProjectsResponse;
EtqanGetProjectsModel({
this.etqanGetProjectsResponse,
});
factory EtqanGetProjectsModel.fromRawJson(String str) => EtqanGetProjectsModel.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory EtqanGetProjectsModel.fromJson(Map<String, dynamic> json) => EtqanGetProjectsModel(
etqanGetProjectsResponse: json["ETQAN_GetProjects_Response"] == null ? [] : List<EtqanGetProjectsResponse>.from(json["ETQAN_GetProjects_Response"]!.map((x) => EtqanGetProjectsResponse.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"ETQAN_GetProjects_Response": etqanGetProjectsResponse == null ? [] : List<dynamic>.from(etqanGetProjectsResponse!.map((x) => x.toJson())),
};
}
class EtqanGetProjectsResponse {
String? projectAr;
String? projectCode;
String? projectEn;
int? projectId;
EtqanGetProjectsResponse({
this.projectAr,
this.projectCode,
this.projectEn,
this.projectId,
});
factory EtqanGetProjectsResponse.fromRawJson(String str) => EtqanGetProjectsResponse.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory EtqanGetProjectsResponse.fromJson(Map<String, dynamic> json) => EtqanGetProjectsResponse(
projectAr: json["projectAr"],
projectCode: json["projectCode"],
projectEn: json["projectEn"],
projectId: json["projectId"],
);
Map<String, dynamic> toJson() => {
"projectAr": projectAr,
"projectCode": projectCode,
"projectEn": projectEn,
"projectId": projectId,
};
}

@ -0,0 +1,61 @@
import 'dart:convert';
class GetEmployeeParking {
GetEmployeeParkingClass? getEmployeeParking;
GetEmployeeParking({
this.getEmployeeParking,
});
factory GetEmployeeParking.fromRawJson(String str) => GetEmployeeParking.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory GetEmployeeParking.fromJson(Map<String, dynamic> json) => GetEmployeeParking(
getEmployeeParking: json["GET_Employee_Parking"] == null ? null : GetEmployeeParkingClass.fromJson(json["GET_Employee_Parking"]),
);
Map<String, dynamic> toJson() => {
"GET_Employee_Parking": getEmployeeParking?.toJson(),
};
}
class GetEmployeeParkingClass {
DateTime? createdAt;
String? employeeCode;
String? isNewQrCode;
String? qrCode;
String? qrCodeImageBase64;
bool? success;
GetEmployeeParkingClass({
this.createdAt,
this.employeeCode,
this.isNewQrCode,
this.qrCode,
this.qrCodeImageBase64,
this.success,
});
factory GetEmployeeParkingClass.fromRawJson(String str) => GetEmployeeParkingClass.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory GetEmployeeParkingClass.fromJson(Map<String, dynamic> json) => GetEmployeeParkingClass(
createdAt: json["createdAt"] == null ? null : DateTime.parse(json["createdAt"]),
employeeCode: json["employeeCode"],
isNewQrCode: json["isNewQRCode"],
qrCode: json["qrCode"],
qrCodeImageBase64: json["qrCodeImageBase64"],
success: json["success"],
);
Map<String, dynamic> toJson() => {
"createdAt": createdAt?.toIso8601String(),
"employeeCode": employeeCode,
"isNewQRCode": isNewQrCode,
"qrCode": qrCode,
"qrCodeImageBase64": qrCodeImageBase64,
"success": success,
};
}

@ -0,0 +1,142 @@
import 'dart:convert';
class GetGreetingCardsModelResponse {
List<GetGreetingCardsModelResponseElement>? getGreetingCardsModelResponse;
GetGreetingCardsModelResponse({
this.getGreetingCardsModelResponse,
});
factory GetGreetingCardsModelResponse.fromRawJson(String str) => GetGreetingCardsModelResponse.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory GetGreetingCardsModelResponse.fromJson(Map<String, dynamic> json) => GetGreetingCardsModelResponse(
getGreetingCardsModelResponse: json["Get_GreetingCardsModel_Response"] == null ? [] : List<GetGreetingCardsModelResponseElement>.from(json["Get_GreetingCardsModel_Response"]!.map((x) => GetGreetingCardsModelResponseElement.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"Get_GreetingCardsModel_Response": getGreetingCardsModelResponse == null ? [] : List<dynamic>.from(getGreetingCardsModelResponse!.map((x) => x.toJson())),
};
}
class GetGreetingCardsModelResponseElement {
String? backgroundImageUrlAr;
String? backgroundImageUrlEn;
String? buttonBgColor;
String? buttonText;
String? buttonTextN;
int? cardType;
int? categoryId;
String? categoryNameAr;
String? categoryNameEn;
int? channel;
String? createdOn;
String? descriptionAr;
String? descriptionEn;
String? endDate;
bool? hasButton;
int? id;
bool? isActive;
int? moduleId;
String? moduleName;
String? moduleNameN;
String? startDate;
String? textColor;
String? titleAr;
String? titleEn;
String? urlAr;
String? urlEn;
GetGreetingCardsModelResponseElement({
this.backgroundImageUrlAr,
this.backgroundImageUrlEn,
this.buttonBgColor,
this.buttonText,
this.buttonTextN,
this.cardType,
this.categoryId,
this.categoryNameAr,
this.categoryNameEn,
this.channel,
this.createdOn,
this.descriptionAr,
this.descriptionEn,
this.endDate,
this.hasButton,
this.id,
this.isActive,
this.moduleId,
this.moduleName,
this.moduleNameN,
this.startDate,
this.textColor,
this.titleAr,
this.titleEn,
this.urlAr,
this.urlEn,
});
factory GetGreetingCardsModelResponseElement.fromRawJson(String str) => GetGreetingCardsModelResponseElement.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory GetGreetingCardsModelResponseElement.fromJson(Map<String, dynamic> json) => GetGreetingCardsModelResponseElement(
backgroundImageUrlAr: json["BackgroundImageUrlAr"],
backgroundImageUrlEn: json["BackgroundImageUrlEn"],
buttonBgColor: json["ButtonBgColor"],
buttonText: json["ButtonText"],
buttonTextN: json["ButtonTextN"],
cardType: json["CardType"],
categoryId: json["CategoryID"],
categoryNameAr: json["CategoryNameAr"],
categoryNameEn: json["CategoryNameEn"],
channel: json["Channel"],
createdOn: json["CreatedOn"],
descriptionAr: json["DescriptionAr"],
descriptionEn: json["DescriptionEn"],
endDate: json["EndDate"],
hasButton: json["HasButton"],
id: json["ID"],
isActive: json["IsActive"],
moduleId: json["ModuleID"],
moduleName: json["ModuleName"],
moduleNameN: json["ModuleNameN"],
startDate: json["StartDate"],
textColor: json["TextColor"],
titleAr: json["TitleAr"],
titleEn: json["TitleEn"],
urlAr: json["UrlAr"],
urlEn: json["UrlEn"],
);
Map<String, dynamic> toJson() => {
"BackgroundImageUrlAr": backgroundImageUrlAr,
"BackgroundImageUrlEn": backgroundImageUrlEn,
"ButtonBgColor": buttonBgColor,
"ButtonText": buttonText,
"ButtonTextN": buttonTextN,
"CardType": cardType,
"CategoryID": categoryId,
"CategoryNameAr": categoryNameAr,
"CategoryNameEn": categoryNameEn,
"Channel": channel,
"CreatedOn": createdOn,
"DescriptionAr": descriptionAr,
"DescriptionEn": descriptionEn,
"EndDate": endDate,
"HasButton": hasButton,
"ID": id,
"IsActive": isActive,
"ModuleID": moduleId,
"ModuleName": moduleName,
"ModuleNameN": moduleNameN,
"StartDate": startDate,
"TextColor": textColor,
"TitleAr": titleAr,
"TitleEn": titleEn,
"UrlAr": urlAr,
"UrlEn": urlEn,
};
}

@ -136,10 +136,21 @@ class ActionButtonsColl {
late String btnTextEn; late String btnTextEn;
late String btnTextAr; late String btnTextAr;
late String actionValue; late String actionValue;
late dynamic iconOrImage; dynamic iconOrImage;
String? actionType;
late int orderNo; late int orderNo;
String? url;
ActionButtonsColl({required this.actionButtonId, required this.btnTextEn, required this.btnTextAr, required this.actionValue, required this.iconOrImage, required this.orderNo}); ActionButtonsColl({
required this.actionButtonId,
required this.btnTextEn,
required this.btnTextAr,
required this.actionValue,
this.iconOrImage,
this.actionType,
required this.orderNo,
this.url,
});
ActionButtonsColl.fromJson(Map<String, dynamic> json) { ActionButtonsColl.fromJson(Map<String, dynamic> json) {
actionButtonId = json['actionButtonId']; actionButtonId = json['actionButtonId'];
@ -147,7 +158,9 @@ class ActionButtonsColl {
btnTextAr = json['btnTextAr']; btnTextAr = json['btnTextAr'];
actionValue = json['actionValue']; actionValue = json['actionValue'];
iconOrImage = json['iconOrImage']; iconOrImage = json['iconOrImage'];
actionType = json['actionType'];
orderNo = json['orderNo']; orderNo = json['orderNo'];
url = json['url'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -157,7 +170,9 @@ class ActionButtonsColl {
data['btnTextAr'] = this.btnTextAr; data['btnTextAr'] = this.btnTextAr;
data['actionValue'] = this.actionValue; data['actionValue'] = this.actionValue;
data['iconOrImage'] = this.iconOrImage; data['iconOrImage'] = this.iconOrImage;
data['actionType'] = this.actionType;
data['orderNo'] = this.orderNo; data['orderNo'] = this.orderNo;
data['url'] = this.url;
return data; return data;
} }
} }

@ -19,8 +19,10 @@ import 'package:mohem_flutter_app/models/dashboard/list_menu.dart';
import 'package:mohem_flutter_app/models/dashboard/menu_entries.dart'; import 'package:mohem_flutter_app/models/dashboard/menu_entries.dart';
import 'package:mohem_flutter_app/models/dashboard/menus.dart'; import 'package:mohem_flutter_app/models/dashboard/menus.dart';
import 'package:mohem_flutter_app/models/dashboard/mohemm_itg_pending_task_responseitem.dart'; import 'package:mohem_flutter_app/models/dashboard/mohemm_itg_pending_task_responseitem.dart';
import 'package:mohem_flutter_app/models/dashboard/courses_response_model.dart';
import 'package:mohem_flutter_app/models/eit/get_eit_transaction_model.dart'; import 'package:mohem_flutter_app/models/eit/get_eit_transaction_model.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/models/greetings/greeting_card_model.dart';
import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart';
import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart';
import 'package:mohem_flutter_app/models/sso_auth_model.dart'; import 'package:mohem_flutter_app/models/sso_auth_model.dart';
@ -67,6 +69,15 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
bool isOffersLoading = true; bool isOffersLoading = true;
List<OffersListModel> getOffersList = []; List<OffersListModel> getOffersList = [];
//Courses
bool isCoursesLoading = true;
CoursesResponseModel? coursesResponse;
List<CourseStatus> coursesList = [];
bool isGreetingCardsLoading = true;
bool isDisplayEidGreetings = false;
List<GetGreetingCardsModelResponseElement>? greetingCardsList;
//Attendance Tracking API's & Methods //Attendance Tracking API's & Methods
Future<bool> fetchAttendanceTracking(context) async { Future<bool> fetchAttendanceTracking(context) async {
try { try {
@ -115,12 +126,18 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
getMenuEntriesList = null; getMenuEntriesList = null;
isOffersLoading = true; isOffersLoading = true;
getOffersList = []; getOffersList = [];
isGreetingCardsLoading = true;
isDisplayEidGreetings = false;
drawerMenuItemList = [ drawerMenuItemList = [
DrawerMenuItem("assets/images/drawer/my_profile.svg", LocaleKeys.myProfile.tr(), AppRoutes.profile), DrawerMenuItem("assets/images/drawer/my_profile.svg", LocaleKeys.myProfile.tr(), AppRoutes.profile),
DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation), DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation),
DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi), DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi),
// DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.etqanOVR.tr(), AppRoutes.etqanOvr),
DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.keen.tr(), AppRoutes.etqanOvr),
// DrawerMenuItem("assets/images/drawer/car_parking_icon.svg", LocaleKeys.parkingQr.tr(), AppRoutes.parkingQr),
DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions), DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions),
// DrawerMenuItem("assets/images/drawer/courses.svg", "courses".tr(), AppRoutes.courses),
// DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen), // DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen),
DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword), DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword),
]; ];
@ -306,6 +323,28 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
} }
} }
void fetchGreetingCards() async {
isGreetingCardsLoading = true;
notifyListeners();
try {
GetGreetingCardsModelResponse? response = await DashboardApiClient().getGreetingCards();
greetingCardsList = response?.getGreetingCardsModelResponse ?? [];
if (greetingCardsList != null && greetingCardsList!.isNotEmpty) {
isDisplayEidGreetings = greetingCardsList!.any((card) => card.isActive == true);
} else {
isDisplayEidGreetings = false;
}
isGreetingCardsLoading = false;
notifyListeners();
} catch (ex) {
logger.wtf(ex);
isDisplayEidGreetings = false;
greetingCardsList = [];
isGreetingCardsLoading = false;
notifyListeners();
}
}
Future<void> fetchTicketBooking() async { Future<void> fetchTicketBooking() async {
try { try {
GenericResponseModel? genericResponseModel = await DashboardApiClient().getTicketBookingRedirection(); GenericResponseModel? genericResponseModel = await DashboardApiClient().getTicketBookingRedirection();
@ -326,8 +365,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
void fetchTicketBalance() async { void fetchTicketBalance() async {
try { try {
GenericResponseModel? ticketResponse = await DashboardApiClient().getTicketBalance(); GenericResponseModel? ticketResponse = await DashboardApiClient().getTicketBalance();
logger.d("Ticket Balance Response: ${ticketResponse?.toJson()}");
print(" ========= Ticket Balance Response ======= ");
} catch (ex) { } catch (ex) {
logger.wtf(ex); logger.wtf(ex);
isEventLoadingLoading = false; isEventLoadingLoading = false;
@ -340,8 +377,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
Future<SSOAuthModel?> fetchSSOAuthRedirection({String? clientID}) async { Future<SSOAuthModel?> fetchSSOAuthRedirection({String? clientID}) async {
try { try {
SSOAuthModel? ssoResponse = await DashboardApiClient().getBookingSSOAuthRedirection(clientID: clientID!); SSOAuthModel? ssoResponse = await DashboardApiClient().getBookingSSOAuthRedirection(clientID: clientID!);
logger.d("SSO Response: ${ssoResponse!.toJson()}"); if (ssoResponse!.status == "Success") {
if (ssoResponse.status == "Success") {
return ssoResponse; return ssoResponse;
} else { } else {
Utils.showToast(ssoResponse.message!.first ?? "Failed to fetch SSO Auth Token"); Utils.showToast(ssoResponse.message!.first ?? "Failed to fetch SSO Auth Token");
@ -361,18 +397,12 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
dynamic res = await DashboardApiClient().getBookingSSOFinalRedirection(token: token); dynamic res = await DashboardApiClient().getBookingSSOFinalRedirection(token: token);
logger.d("SSO URL: $res"); logger.d("SSO URL: $res");
return res; return res;
// if (ssoResponse.status == "Success") {
// return ssoResponse;
// } else {
// Utils.showToast(ssoResponse.message!.first ?? "Failed to fetch SSO Auth Token");
// return null;
// }
} catch (ex) { } catch (ex) {
logger.wtf(ex); logger.wtf(ex);
isEventLoadingLoading = false; isEventLoadingLoading = false;
notifyListeners(); notifyListeners();
Utils.handleException(ex, null, null); Utils.handleException(ex, null, null);
return null; // Ensure a return value in case of an exception return null;
} }
} }
@ -409,6 +439,30 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
return res; return res;
} }
//Courses API's & Methods
Future<void> fetchCourses(BuildContext context) async {
try {
isCoursesLoading = true;
notifyListeners();
coursesResponse = await DashboardApiClient().fetchAllCoursesStatus();
if (coursesResponse != null && coursesResponse!.success == true) {
coursesList = coursesResponse!.coursesStatus ?? [];
} else {
coursesList = [];
}
isCoursesLoading = false;
notifyListeners();
} catch (ex) {
isCoursesLoading = false;
coursesList = [];
notifyListeners();
Utils.handleException(ex, context, null);
}
}
void notify() { void notify() {
notifyListeners(); notifyListeners();
} }

@ -0,0 +1,262 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/etqan_ovr_api_client.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_employee_incident_report.dart';
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_requests_model.dart';
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_getprojects_model.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';
class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
// Home screen state
List<EtqanGetProjectsResponse>? getEtqanProjectsList;
List<EtqanGetEmployeeOvrRequestsResponse>? getEtqanEmployeeRequestsList;
List<EtqanGetIncidentRequestResponse>? getEtqanEmployeeIncidnetRequest;
bool isLoading = false;
String? _ticketId;
String? _currentStatus;
String? _currentStatusAr;
bool? _currentIsAnonymous;
// Speech to text state
final SpeechToText _speechToText = SpeechToText();
bool _speechEnabled = false;
bool _isListening = false;
String _currentLocaleId = '';
TextEditingController? _currentController;
String _baseText = ''; // Text that was there when we started listening
String _currentSessionText = ''; // Text captured in current listening session
// Getters for speech state
bool get speechEnabled => _speechEnabled;
bool get isListening => _isListening;
// Getter for ticketId
String get getTicketId => _ticketId ?? '';
String get getCurrentStatus => _currentStatus ?? '';
String get getCurrentStatusAr => _currentStatusAr ?? '';
bool get getCurrentIsAnonymous => _currentIsAnonymous ?? false;
// Setter for ticketId with status and isAnonymous
void setTicketId(String ticketId, {String? status, String? statusAr, bool? isAnonymous}) {
_ticketId = ticketId;
_currentStatus = status;
_currentStatusAr = statusAr;
_currentIsAnonymous = isAnonymous;
notifyListeners();
}
// Create request screen state
EtqanGetProjectsResponse? selectedProject;
String? selectedEmployeeNumber;
File? attachment;
String? attachmentBase64;
String description = '';
bool isAnonymous = false;
/// Initialize speech recognition - call this once when screen loads
Future<void> initSpeech() async {
_speechEnabled = await _speechToText.initialize(
onStatus: (String status) {
print('Speech status: $status, isListening: $_isListening');
// If user wants to keep listening but speech stopped, restart it
if ((status == 'done' || status == 'notListening') && _isListening && _currentController != null) {
// Save the finalized text before restarting
if (_currentSessionText.isNotEmpty) {
_baseText = _currentController!.text.trim();
_currentSessionText = '';
}
// Automatically restart listening after a brief pause
Future.delayed(const Duration(milliseconds: 300), () {
if (_isListening && _currentController != null) {
_startListeningInternal(_currentLocaleId, _currentController!);
}
});
}
},
);
notifyListeners();
}
/// Internal method to start listening
Future<void> _startListeningInternal(String localeId, TextEditingController controller) async {
if (!_speechEnabled) return;
await _speechToText.listen(
onResult: (SpeechRecognitionResult result) {
_currentSessionText = result.recognizedWords;
// Combine base text with current session text
String combinedText = _baseText.isEmpty
? _currentSessionText
: _baseText + (_baseText.endsWith(' ') ? '' : ' ') + _currentSessionText;
description = combinedText;
controller.text = combinedText;
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
notifyListeners();
},
localeId: localeId,
listenFor: const Duration(seconds: 60),
pauseFor: const Duration(seconds: 10),
listenOptions: SpeechListenOptions(
partialResults: true,
listenMode: ListenMode.confirmation,
cancelOnError: false,
),
);
}
/// Start listening for speech input
Future<void> startListening(String localeId, TextEditingController controller) async {
_isListening = true;
_currentLocaleId = localeId;
_currentController = controller;
_baseText = controller.text.trim(); // Save existing text
_currentSessionText = '';
notifyListeners();
await _startListeningInternal(localeId, controller);
}
/// Stop listening for speech input
Future<void> stopListening() async {
_isListening = false;
_currentLocaleId = '';
_currentController = null;
_baseText = '';
_currentSessionText = '';
await _speechToText.stop();
notifyListeners();
}
/// Toggle listening state
Future<void> toggleListening(String localeId, TextEditingController controller) async {
if (_isListening) {
await stopListening();
} else {
await startListening(localeId, controller);
}
}
// Fetch Etqan Projects
Future<void> fetchEtqanProjects(BuildContext context) async {
isLoading = true;
notifyListeners();
Utils.showLoading(context);
getEtqanProjectsList?.clear();
getEtqanProjectsList = await EtqanApiClient().getEtqanProjects();
Utils.hideLoading(context);
isLoading = false;
notifyListeners();
}
// Fetch Etqan Employee Requests
Future<void> fetchEtqanEmployeeRequests(BuildContext context) async {
isLoading = true;
notifyListeners();
Utils.showLoading(context);
getEtqanEmployeeRequestsList?.clear();
getEtqanEmployeeRequestsList = await EtqanApiClient().getEmployeeEtqanRequests();
Utils.hideLoading(context);
isLoading = false;
notifyListeners();
}
// Fetch Etqan Employee Incident Report
Future<void> fetchEtqanEmployeeIncidentRequests(BuildContext context, String ticketNo) async {
isLoading = true;
notifyListeners();
Utils.showLoading(context);
getEtqanEmployeeIncidnetRequest?.clear();
getEtqanEmployeeIncidnetRequest = await EtqanApiClient().getEtqanIncidentRequests(ticketNo);
Utils.hideLoading(context);
isLoading = false;
notifyListeners();
}
// Set selected project
void setSelectedProject(EtqanGetProjectsResponse? project) {
selectedProject = project;
notifyListeners();
}
// Set selected employee number
void setSelectedEmployeeNumber(String? employeeNumber) {
selectedEmployeeNumber = employeeNumber;
notifyListeners();
}
// Set attachment with base64
void setAttachment(File file, String base64) {
attachment = file;
attachmentBase64 = base64;
notifyListeners();
}
// Remove attachment
void removeAttachment() {
attachment = null;
attachmentBase64 = null;
notifyListeners();
}
// Set description
void setDescription(String value) {
description = value;
notifyListeners();
}
// Validate description
bool isDescriptionValid() {
return description.trim().isNotEmpty;
}
// Set isAnonymous
void setIsAnonymous(bool value) {
isAnonymous = value;
notifyListeners();
}
// Clear create request form
void clearCreateRequestForm() {
selectedProject = null;
selectedEmployeeNumber = null;
attachment = null;
attachmentBase64 = null;
description = '';
isAnonymous = false;
notifyListeners();
}
// Submit request
Future<Map<String, dynamic>?> submitRequest(BuildContext context) async {
try {
Utils.showLoading(context);
Map<String, dynamic>? response = await EtqanApiClient().createRequest(description, selectedProject?.projectId, attachmentBase64, isAnonymous);
Utils.hideLoading(context);
if (response != null) {
getEtqanEmployeeRequestsList = await EtqanApiClient().getEmployeeEtqanRequests();
notifyListeners();
return response;
}
return null;
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
return null;
}
}
@override
void dispose() {
if (_isListening) {
_speechToText.stop();
}
super.dispose();
}
}

@ -0,0 +1,355 @@
import 'dart:io';
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/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/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_getprojects_model.dart';
import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/bottom_sheet.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/image_picker.dart';
import 'package:provider/provider.dart';
class EtqanOvrCreateRequest extends StatefulWidget {
const EtqanOvrCreateRequest({Key? key}) : super(key: key);
@override
_EtqanOvrCreateRequestState createState() => _EtqanOvrCreateRequestState();
}
class _EtqanOvrCreateRequestState extends State<EtqanOvrCreateRequest> {
final TextEditingController _descriptionController = TextEditingController();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
var provider = context.read<EtqanOvrProviderModel>();
provider.initSpeech();
provider.fetchEtqanProjects(context);
provider.clearCreateRequestForm();
});
}
@override
void dispose() {
// Stop listening if active
context.read<EtqanOvrProviderModel>().stopListening();
_descriptionController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBarWidget(context, title: LocaleKeys.reportIncident.tr(), showHomeButton: false),
body: Consumer<EtqanOvrProviderModel>(
builder: (BuildContext context, EtqanOvrProviderModel provider, Widget? child) {
return Column(
children: <Widget>[
(ListView(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.all(21),
children: <Widget>[
_buildDropdownField(
label: LocaleKeys.project.tr(),
hint: LocaleKeys.selectProject.tr(),
value: _getProjectDisplayName(provider.selectedProject),
onTap: () => _showProjectSelectionSheet(context, provider),
isMandatory: true,
),
16.height,
// _buildDropdownField(
// label: 'Employee Number',
// hint: 'Write a message',
// value: provider.selectedEmployeeNumber,
// onTap: () {
// // TODO: Show employee selection dialog
// },
// ),
// 16.height,
_buildAttachmentSection(provider),
16.height,
_buildDescriptionField(provider),
8.height,
_buildAnonymousCheckbox(provider),
24.height,
],
)).expanded,
DefaultButton(LocaleKeys.submit.tr(), () async {
provider.setDescription(_descriptionController.text);
if (provider.selectedProject == null) {
Utils.showErrorDialog(
context: context,
message: LocaleKeys.pleaseSelectProject.tr(),
onOkTapped: () {
Navigator.of(context).pop();
},
);
return;
}
if (!provider.isDescriptionValid()) {
Utils.showErrorDialog(
context: context,
message: LocaleKeys.pleaseEnterDescription.tr(),
onOkTapped: () {
Navigator.of(context).pop();
},
);
return;
}
Map<String, dynamic>? ticketInfo = await provider.submitRequest(context);
if (ticketInfo != null) {
String ticketNumber = ticketInfo['ticketNumber'] ?? '';
String ticketId = ticketInfo['id'] ?? '';
String successMessage = '${LocaleKeys.requestCreatedSuccessfully.tr()}\n\n${LocaleKeys.ticketNumber.tr()}: $ticketNumber\n${LocaleKeys.ticketId.tr()}: $ticketId';
Utils.showErrorDialog(
context: context,
message: successMessage,
onOkTapped: () {
Navigator.popAndPushNamed(context, AppRoutes.etqanOvr);
},
onCloseTap: () {
Navigator.popAndPushNamed(context, AppRoutes.etqanOvr);
},
);
}
}).insideContainer,
],
);
},
),
);
}
String? _getProjectDisplayName(EtqanGetProjectsResponse? project) {
if (project == null) return null;
return AppState().isArabic(context) ? project.projectAr : project.projectEn;
}
void _showProjectSelectionSheet(BuildContext context, EtqanOvrProviderModel provider) {
if (provider.getEtqanProjectsList == null || provider.getEtqanProjectsList!.isEmpty) {
return;
}
showMyBottomSheet(
context,
callBackFunc: () {},
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text(LocaleKeys.selectProject.tr(), style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xff2B353E))),
),
const Divider(),
ListView.separated(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
itemCount: provider.getEtqanProjectsList!.length,
separatorBuilder: (BuildContext context, int index) => const Divider(height: 1),
itemBuilder: (BuildContext context, int index) {
EtqanGetProjectsResponse project = provider.getEtqanProjectsList![index];
bool isSelected = provider.selectedProject?.projectId == project.projectId;
return ListTile(
title: Text(
AppState().isArabic(context) ? (project.projectAr ?? '') : (project.projectEn ?? ''),
style: TextStyle(fontSize: 14, fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, color: isSelected ? MyColors.gradiantEndColor : const Color(0xff2B353E)),
),
trailing: isSelected ? const Icon(Icons.check, color: MyColors.gradiantEndColor) : null,
onTap: () {
provider.setSelectedProject(project);
Navigator.pop(context);
},
);
},
),
16.height,
],
),
);
}
Widget _buildDropdownField({required String label, required String hint, String? value, required VoidCallback onTap, bool isMandatory = false}) {
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(15),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(15), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)),
child: Row(
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Text(label, style: const TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.44)),
if (isMandatory) const Text(' *', style: TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Colors.red, letterSpacing: -0.44)),
],
),
const SizedBox(height: 4),
Text(value ?? hint, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: value != null ? const Color(0xff2B353E) : const Color(0xff575757), letterSpacing: -0.56)),
],
),
),
const Icon(Icons.keyboard_arrow_down, color: Color(0xff575757)),
],
),
),
);
}
Widget _buildAttachmentSection(EtqanOvrProviderModel provider) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(15), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(LocaleKeys.supportingDocument.tr(), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E))),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(LocaleKeys.attachments.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Color(0xff2B353E))),
if (provider.attachment == null)
InkWell(
onTap: () {
ImageOptions.showImageOptionsNew(context, true, (String base64, File file) {
provider.setAttachment(file, base64);
Navigator.of(context).pop();
});
},
borderRadius: BorderRadius.circular(8),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
decoration: BoxDecoration(color: MyColors.gradiantEndColor, borderRadius: BorderRadius.circular(8)),
child: Text(LocaleKeys.add.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Colors.white)),
),
),
],
),
if (provider.attachment != null) ...<Widget>[
const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: <Widget>[
const Icon(Icons.attach_file, size: 18, color: Color(0xff575757)),
const SizedBox(width: 8),
Expanded(child: Text(provider.attachment!.path.split('/').last, style: const TextStyle(fontSize: 12, color: Color(0xff575757)), overflow: TextOverflow.ellipsis)),
InkWell(
onTap: () {
provider.removeAttachment();
},
child: const Icon(Icons.close, size: 18, color: Colors.red),
),
],
),
),
],
],
),
);
}
Widget _buildDescriptionField(EtqanOvrProviderModel provider) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(15), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Text(LocaleKeys.description.tr(), style: const TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.44)),
const Text(' *', style: TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Colors.red, letterSpacing: -0.44)),
],
),
GestureDetector(
onTap:
provider.speechEnabled
? () {
String localeId = AppState().isArabic(context) ? 'ar_SA' : 'en_US';
provider.toggleListening(localeId, _descriptionController);
}
: null,
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(color: provider.isListening ? MyColors.gradiantEndColor.withOpacity(0.1) : Colors.transparent, borderRadius: BorderRadius.circular(20)),
child: Icon(
provider.isListening ? Icons.mic : Icons.mic_none,
color: provider.isListening ? MyColors.gradiantEndColor : (provider.speechEnabled ? MyColors.grey57Color : Colors.grey.shade300),
size: 24,
),
),
),
],
),
if (provider.isListening)
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: <Widget>[
Container(width: 8, height: 8, decoration: BoxDecoration(color: Colors.red, borderRadius: BorderRadius.circular(4))),
const SizedBox(width: 8),
const Text('Listening...', style: TextStyle(fontSize: 12, color: MyColors.gradiantEndColor, fontWeight: FontWeight.w500)),
],
),
),
TextField(
controller: _descriptionController,
maxLines: 4,
onChanged: (String value) => provider.setDescription(value),
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Color(0xff2B353E), letterSpacing: -0.44),
decoration: InputDecoration(
isDense: true,
hintText: LocaleKeys.writeAMessage.tr(),
hintStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Color(0xff575757), letterSpacing: -0.56),
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
),
),
],
),
);
}
Widget _buildAnonymousCheckbox(EtqanOvrProviderModel provider) {
return InkWell(
onTap: () {
provider.setIsAnonymous(!provider.isAnonymous);
},
child: Row(
children: <Widget>[
Checkbox(
value: provider.isAnonymous,
onChanged: (bool? value) {
if (value != null) {
provider.setIsAnonymous(value);
}
},
activeColor: MyColors.gradiantEndColor,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
),
Expanded(child: Text(LocaleKeys.submitAsAnonymous.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Color(0xff2B353E), letterSpacing: -0.44))),
],
),
);
}
}

@ -0,0 +1,165 @@
import 'package:easy_localization/easy_localization.dart' as lclize;
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.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/models/etqan_ovr/etqan_get_requests_model.dart';
import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart';
import 'package:mohem_flutter_app/classes/utils.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';
import 'package:intl/src/intl/text_direction.dart' as intl;
import 'package:sizer/sizer.dart';
class EtqanOvrHome extends StatefulWidget {
const EtqanOvrHome({Key? key}) : super(key: key);
@override
_EtqanOvrHomeState createState() => _EtqanOvrHomeState();
}
class _EtqanOvrHomeState extends State<EtqanOvrHome> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<EtqanOvrProviderModel>().fetchEtqanEmployeeRequests(context);
});
}
Color _getStatusColor(String status) {
String statusLower = status.toLowerCase();
if (statusLower.contains('open') || statusLower.contains('مفتوح')) {
return const Color(0xff2196F3); // Blue for open
} else if (statusLower.contains('progress') || statusLower.contains('قيد التنفيذ')) {
return const Color(0xffFF9800); // Orange for in progress
} else if (statusLower.contains('closed') || statusLower.contains('مغلق')) {
return const Color(0xff4CAF50); // Green for closed
}
return MyColors.grey70Color; // Default gray
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBarWidget(context, title: LocaleKeys.myIncidents.tr()),
body: Consumer<EtqanOvrProviderModel>(
builder: (BuildContext context, EtqanOvrProviderModel provider, Widget? child) {
return Column(
children: <Widget>[
(provider.getEtqanEmployeeRequestsList == null || provider.getEtqanEmployeeRequestsList!.isEmpty
? Utils.getNoDataWidget(context)
: ListView.separated(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.all(20),
itemBuilder: (BuildContext context, int index) {
EtqanGetEmployeeOvrRequestsResponse data = provider.getEtqanEmployeeRequestsList![index];
return InkWell(
onTap: () {
context.read<EtqanOvrProviderModel>().setTicketId(data.ticketNumber ?? '', status: data.status, statusAr: data.statusAr, isAnonymous: data.isAnonymous);
Navigator.pushNamed(context, AppRoutes.etqanGetIncidientRequest);
},
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15), border: Border.all(color: const Color(0xffefefef), width: 1)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: [
Expanded(
child: Wrap(
spacing: 8,
runSpacing: 8,
children: [
if (data.status != null && data.status!.isNotEmpty)
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: _getStatusColor(data.status ?? "").withOpacity(0.1),
borderRadius: BorderRadius.circular(6),
border: Border.all(color: _getStatusColor(data.status ?? "").withOpacity(0.3), width: 1),
),
child: (AppState().isArabic(context) ? (data.statusAr ?? "") : (data.status ?? "")).toText11(
color: _getStatusColor(data.status ?? ""),
isBold: true,
),
),
if (data.isAnonymous == true)
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: MyColors.grey70Color.withOpacity(0.15),
borderRadius: BorderRadius.circular(6),
border: Border.all(color: MyColors.grey70Color.withOpacity(0.3), width: 1),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.visibility_off, size: 12, color: MyColors.grey70Color),
const SizedBox(width: 4),
(AppState().isArabic(context) ? "مجهول" : "Anonymous").toText11(color: MyColors.grey70Color, isBold: true),
],
),
),
],
),
),
const SizedBox(width: 8),
],
),
8.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
(data.ticketNumber ?? "").toText14(isBold: true, color: MyColors.darkTextColor),
Directionality(textDirection: TextDirection.ltr, child: (data.createdDate!.split(" ").first ?? "").toText12(color: MyColors.grey70Color)),
],
),
8.height,
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [(data.description ?? "").toText12(color: MyColors.grey57Color).expanded]),
3.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
children: [
RotatedBox(
quarterTurns: AppState().isArabic(context) ? 2 : 0,
child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.grey70Color, width: 16, height: 16),
),
],
),
],
),
),
],
),
),
);
},
separatorBuilder: (BuildContext context, int index) => 12.height,
itemCount: provider.getEtqanEmployeeRequestsList!.length,
))
.expanded,
DefaultButton(LocaleKeys.reportIncident.tr(), () async {
await Navigator.pushNamed(context, AppRoutes.etqanCreateRequest);
// getOpenTickets();
}).insideContainer,
],
);
},
),
);
}
}

@ -0,0 +1,235 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
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/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/etqan_ovr/etqan_get_employee_incident_report.dart';
import 'package:mohem_flutter_app/provider/etqan_ovr_provider.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:provider/provider.dart';
import 'package:open_filex/open_filex.dart';
import 'package:path_provider/path_provider.dart';
class EtqanOvrRequestDetailed extends StatefulWidget {
const EtqanOvrRequestDetailed({Key? key}) : super(key: key);
@override
_EtqanOvrRequestDetailedState createState() => _EtqanOvrRequestDetailedState();
}
class _EtqanOvrRequestDetailedState extends State<EtqanOvrRequestDetailed> {
List<String> get fieldOrder => ['Status', 'Project', 'Created', 'Is Anonymous', 'Occurrence Time', 'OVR Reference No', 'Involved Employee Number', 'Description'];
List<String> get hiddenFields => ['OVR Id'];
Color _getStatusColor(String status) {
String statusLower = status.toLowerCase();
if (statusLower.contains('open') || statusLower.contains('مفتوح')) {
return const Color(0xff2196F3); // Blue for open
} else if (statusLower.contains('progress') || statusLower.contains('قيد التنفيذ')) {
return const Color(0xffFF9800); // Orange for in progress
} else if (statusLower.contains('closed') || statusLower.contains('مغلق')) {
return const Color(0xff4CAF50); // Green for closed
}
return MyColors.grey70Color; // Default gray
}
Future<void> _viewAttachment(BuildContext context, String base64Data) async {
try {
Uint8List bytes = base64.decode(base64Data);
String dir = (await getApplicationDocumentsDirectory()).path;
String ext = 'pdf';
if (base64Data.startsWith('/9j/')) {
ext = 'jpg';
} else if (base64Data.startsWith('iVBORw0KGgo')) {
ext = 'png';
}
File file = File("$dir/${DateTime.now().millisecondsSinceEpoch}.$ext");
await file.writeAsBytes(bytes);
OpenFilex.open(file.path);
} catch (e) {
Utils.showToast("Cannot open attachment.");
}
}
List<EtqanGetIncidentRequestResponse> _getOrderedList(List<EtqanGetIncidentRequestResponse> list, EtqanOvrProviderModel provider) {
List<EtqanGetIncidentRequestResponse> orderedList = [];
List<EtqanGetIncidentRequestResponse> filteredList = list.where((EtqanGetIncidentRequestResponse item) => !hiddenFields.any((f) => f.toLowerCase() == item.key?.toLowerCase())).toList();
for (String fieldName in fieldOrder) {
// Check if this is Status or Is Anonymous - inject from provider
if (fieldName.toLowerCase() == 'status' && provider.getCurrentStatus.isNotEmpty) {
orderedList.add(EtqanGetIncidentRequestResponse(
key: 'Status',
keyAr: 'الحالة',
value: provider.getCurrentStatus,
valueAr: provider.getCurrentStatusAr.isNotEmpty ? provider.getCurrentStatusAr : provider.getCurrentStatus,
));
} else if (fieldName.toLowerCase() == 'is anonymous') {
orderedList.add(EtqanGetIncidentRequestResponse(
key: 'Is Anonymous',
keyAr: 'مجهول',
value: provider.getCurrentIsAnonymous.toString(),
valueAr: provider.getCurrentIsAnonymous.toString(),
));
} else {
// Regular field from API
var item = filteredList.firstWhere((e) => e.key?.toLowerCase() == fieldName.toLowerCase(), orElse: () => EtqanGetIncidentRequestResponse());
if (item.key != null) {
orderedList.add(item);
}
}
}
for (var item in filteredList) {
if (!fieldOrder.any((f) => f.toLowerCase() == item.key?.toLowerCase())) {
orderedList.add(item);
}
}
return orderedList;
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
EtqanOvrProviderModel provider = context.read<EtqanOvrProviderModel>();
provider.fetchEtqanEmployeeIncidentRequests(context, provider.getTicketId);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBarWidget(context, title: LocaleKeys.incidentDetails.tr()),
body: Consumer<EtqanOvrProviderModel>(
builder: (BuildContext context, EtqanOvrProviderModel provider, Widget? child) {
if (provider.getEtqanEmployeeIncidnetRequest == null || provider.getEtqanEmployeeIncidnetRequest!.isEmpty) {
return Utils.getNoDataWidget(context);
}
List<EtqanGetIncidentRequestResponse> orderedList = _getOrderedList(provider.getEtqanEmployeeIncidnetRequest!, provider);
return SingleChildScrollView(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.all(16),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
border: Border.all(color: const Color(0xffefefef), width: 1),
boxShadow: <BoxShadow>[BoxShadow(color: Colors.black.withValues(alpha: 0.05), blurRadius: 10, offset: const Offset(0, 2))],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children:
orderedList.asMap().entries.map((MapEntry<int, EtqanGetIncidentRequestResponse> entry) {
int index = entry.key;
EtqanGetIncidentRequestResponse data = entry.value;
bool isLast = index == orderedList.length - 1;
bool isAttachment = data.key?.toLowerCase() == 'attachment';
bool isStatus = data.key?.toLowerCase() == 'status';
bool isAnonymous = data.key?.toLowerCase() == 'is anonymous';
String displayKey = context.locale.languageCode == "ar" ? (data.keyAr ?? data.key ?? "") : (data.key ?? "");
String displayValue = context.locale.languageCode == "ar" ? (data.valueAr ?? data.value ?? "") : (data.value ?? "");
bool hasSubValues = data.subValues != null && data.subValues!.isNotEmpty;
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(flex: 2, child: displayKey.toText12(isBold: true, color: MyColors.grey57Color)),
8.width,
Expanded(
flex: 3,
child: isStatus
? displayValue.toText14(
color: _getStatusColor(displayValue),
isBold: true,
)
: isAnonymous
? (displayValue.toLowerCase() == 'true' || displayValue.toLowerCase() == 'yes' || displayValue == '1'
? (context.locale.languageCode == "ar" ? "نعم" : "Yes")
: (context.locale.languageCode == "ar" ? "لا" : "No")
).toText14(color: MyColors.darkTextColor)
: isAttachment && hasSubValues
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: data.subValues!.asMap().entries.map((entry) {
int subIndex = entry.key;
String base64Data = entry.value;
return Padding(
padding: EdgeInsets.only(bottom: subIndex < data.subValues!.length - 1 ? 8.0 : 0),
child: GestureDetector(
onTap: () => _viewAttachment(context, base64Data),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: context.locale.languageCode == "ar" ? MainAxisAlignment.end : MainAxisAlignment.start,
children: [
Text(
data.subValues!.length > 1 ? '${LocaleKeys.viewAttachment.tr()} ${subIndex + 1}' : LocaleKeys.viewAttachment.tr(),
style: const TextStyle(
fontSize: 14,
color: MyColors.green9CColor,
decoration: TextDecoration.underline,
decorationColor: MyColors.green9CColor,
),
),
],
),
),
);
}).toList(),
)
: hasSubValues
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (displayValue.isNotEmpty) displayValue.toText14(color: MyColors.darkTextColor),
if (displayValue.isNotEmpty) 8.height,
...data.subValues!
.map(
(subValue) => Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [const Text("", style: TextStyle(fontSize: 14)), Expanded(child: subValue.toText14(color: MyColors.darkTextColor))],
),
),
)
.toList(),
],
)
: (displayValue.isNotEmpty ? displayValue : "-").toText14(color: MyColors.darkTextColor),
),
],
),
),
if (!isLast) const Padding(padding: EdgeInsets.only(left: 14, right: 14), child: Divider(height: 1, thickness: 1, color: Color(0xffefefef))),
],
);
}).toList(),
),
),
);
},
).paddingOnly(bottom: 20),
);
}
}

@ -1,7 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart';
@ -34,6 +33,7 @@ import 'package:mohem_flutter_app/widgets/shimmer/offers_shimmer_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:signalr_netcore/signalr_client.dart'; import 'package:signalr_netcore/signalr_client.dart';
import 'package:url_launcher/url_launcher.dart';
late HubConnection chatHubConnection; late HubConnection chatHubConnection;
@ -155,6 +155,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
data.fetchLeaveTicketBalance(context, DateTime.now()); data.fetchLeaveTicketBalance(context, DateTime.now());
data.fetchMenuEntries(); data.fetchMenuEntries();
data.fetchEventActivity(); data.fetchEventActivity();
data.fetchGreetingCards();
data.getCategoryOffersListAPI(context); data.getCategoryOffersListAPI(context);
marathonProvider.getMarathonDetailsFromApi(); marathonProvider.getMarathonDetailsFromApi();
marathonProvider.getMarathonTutorial(); marathonProvider.getMarathonTutorial();
@ -167,8 +168,9 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
// await data.fetchTicketBooking(); // await data.fetchTicketBooking();
// if (data.ticketBookingResponse != null && !data.ticketBookingResponse!.success) { // if (data.ticketBookingResponse != null && !data.ticketBookingResponse!.success) {
// // data.fetchTicketBalance(); // data.fetchTicketBalance();
// } // }
//continue here //continue here
} }
@ -423,8 +425,102 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
), ),
], ],
).paddingOnly(left: 21, right: 21, top: 7, bottom: 21), ).paddingOnly(left: 21, right: 21, top: 7, bottom: 21),
eventActivityWidget(context), Consumer<DashboardProviderModel>(
builder: (BuildContext context, DashboardProviderModel model, Widget? child) {
if (model.isGreetingCardsLoading) {
return const GreetingCardShimmer();
} else if (model.isDisplayEidGreetings && model.greetingCardsList != null && model.greetingCardsList!.isNotEmpty) {
return SizedBox(
height: 120,
child: ListView.separated(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 21),
itemCount: model.greetingCardsList!.length,
separatorBuilder: (context, index) => const SizedBox(width: 12),
itemBuilder: (context, index) {
var card = model.greetingCardsList![index];
return SizedBox(
width: MediaQuery.of(context).size.width - 42,
child: Directionality(
textDirection: AppState().isArabic(context) ? ui.TextDirection.rtl : ui.TextDirection.ltr,
child: Stack(
children: [
Transform.flip(
flipX: !AppState().isArabic(context),
child: SvgPicture.network(
AppState().isArabic(context)
? (card.backgroundImageUrlAr ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg")
: (card.backgroundImageUrlEn ?? "https://www.hmg.com/Lists/CS_Greeting_Cards/Attachments/5/CS_Ramadan_26.jpg"),
fit: BoxFit.contain,
placeholderBuilder: (context) => ClipRRect(borderRadius: BorderRadius.circular(18), child: Container(height: 80, color: Colors.white).toShimmer()),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(width: AppState().isArabic(context) ? 20 : 50),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
AppState().isArabic(context) ? card.titleAr ?? '' : card.titleEn ?? '',
style: TextStyle(
fontSize: AppState().isArabic(context) ? 20 : 18,
letterSpacing: -0.2,
fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins',
fontWeight: FontWeight.w700,
height: 24 / 16,
color: const Color(0xFF3B3E4F),
),
),
const SizedBox(height: 4),
Text(
AppState().isArabic(context) ? card.descriptionAr ?? '' : card.descriptionEn ?? '',
style: TextStyle(
fontSize: AppState().isArabic(context) ? 16 : 14,
letterSpacing: -0.2,
fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins',
fontWeight: FontWeight.w500,
color: const Color(0xFF3B3E4F),
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
(AppState().isArabic(context)
? card.buttonTextN!.toText12(isUnderLine: true, color: const Color(0xFF3B3D4A))
: card.buttonText!.toText12(isUnderLine: true, color: const Color(0xFF3B3D4A)))
.onPress(() {
launchUrl(Uri.parse(AppState().isArabic(context) ? card.urlAr! : card.urlEn!));
}),
],
).paddingOnly(bottom: 10, right: 15, left: 15),
],
).paddingOnly(left: AppState().isArabic(context) ? 10 : 36, right: AppState().isArabic(context) ? 66 : 10, top: 6, bottom: 40),
],
),
),
);
},
),
).paddingOnly(bottom: 0);
} else {
return const SizedBox();
}
},
),
// eventActivityWidget(context),
if (isDisplayMazaya) ...[ if (isDisplayMazaya) ...[
Column( Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -471,7 +567,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins', fontFamily: AppState().isArabic(context) ? 'Cairo' : 'Poppins',
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
height: 24 / 16, height: 24 / 16,
color: Color(0xFF5D5E5E), color: const Color(0xFF5D5E5E),
), ),
), ),
TextSpan( TextSpan(
@ -577,11 +673,9 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
6.width, 6.width,
Container( Container(
padding: const EdgeInsets.only(left: 8, right: 8), padding: const EdgeInsets.only(left: 8, right: 8),
decoration: BoxDecoration( decoration: BoxDecoration(color: MyColors.yellowColor, borderRadius: BorderRadius.circular(10)),
color: MyColors.yellowColor, child: LocaleKeys.newString.tr().toText10(isBold: true),
borderRadius: BorderRadius.circular(10),
), ),
child: LocaleKeys.newString.tr().toText10(isBold: true)),
], ],
), ),
], ],
@ -589,7 +683,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
), ),
LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() { LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() {
Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); Navigator.pushNamed(context, AppRoutes.offersAndDiscounts);
}) }),
], ],
).paddingOnly(left: 21, right: 21), ).paddingOnly(left: 21, right: 21),
Consumer<DashboardProviderModel>( Consumer<DashboardProviderModel>(
@ -618,28 +712,22 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
height: 73, height: 73,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: const BorderRadius.all( borderRadius: const BorderRadius.all(Radius.circular(100)),
Radius.circular(100),
),
border: Border.all(color: MyColors.lightGreyE3Color, width: 1), border: Border.all(color: MyColors.lightGreyE3Color, width: 1),
), ),
child: ClipRRect( child: ClipRRect(
borderRadius: const BorderRadius.all( borderRadius: const BorderRadius.all(Radius.circular(50)),
Radius.circular(50),
),
child: Hero( child: Hero(
tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!, tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!,
transitionOnUserGestures: true, transitionOnUserGestures: true,
child: Image.network( child: Image.network(data.getOffersList[index].logo ?? "", fit: BoxFit.contain),
data.getOffersList[index].logo ?? "",
fit: BoxFit.contain,
),
), ),
), ),
), ),
4.height, 4.height,
Expanded( Expanded(
child: AppState().isArabic(context) child:
AppState().isArabic(context)
? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1) ? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1)
: data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1), : data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1),
), ),
@ -649,7 +737,8 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
); );
}, },
separatorBuilder: (BuildContext cxt, int index) => 8.width, separatorBuilder: (BuildContext cxt, int index) => 8.width,
itemCount: 9), itemCount: 9,
),
); );
}, },
), ),

@ -6,14 +6,19 @@ import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/lottie_consts.dart'; import 'package:mohem_flutter_app/classes/lottie_consts.dart';
import 'package:mohem_flutter_app/classes/utils.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/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_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/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/dashboard/menu_entries.dart';
import 'package:mohem_flutter_app/models/itg/advertisement.dart' as ads; import 'package:mohem_flutter_app/models/itg/advertisement.dart' as ads;
import 'package:mohem_flutter_app/provider/dashboard_provider_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/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/my_video_progress_indicator.dart'; import 'package:mohem_flutter_app/widgets/my_video_progress_indicator.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
@ -26,7 +31,7 @@ class ITGAdsScreen extends StatefulWidget {
class _ITGAdsScreenState extends State<ITGAdsScreen> { class _ITGAdsScreenState extends State<ITGAdsScreen> {
late Future<VideoPlayerController> _futureController; late Future<VideoPlayerController> _futureController;
late VideoPlayerController _controller; VideoPlayerController? _controller;
bool skip = false; bool skip = false;
bool isVideo = false; bool isVideo = false;
bool isImage = false; bool isImage = false;
@ -125,7 +130,7 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
@override @override
void dispose() { void dispose() {
if (_controller != null) _controller.dispose(); _controller?.dispose();
super.dispose(); super.dispose();
} }
@ -166,11 +171,11 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
child: isAudio child: isAudio
? Lottie.asset(MyLottieConsts.audioPlaybackLottie) ? Lottie.asset(MyLottieConsts.audioPlaybackLottie)
: AspectRatio( : AspectRatio(
aspectRatio: _controller.value.aspectRatio, aspectRatio: _controller!.value.aspectRatio,
child: Stack( child: Stack(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
children: [ children: [
VideoPlayer(_controller), VideoPlayer(_controller!),
if (advertisementData?.isOptional ?? false) if (advertisementData?.isOptional ?? false)
Positioned( Positioned(
top: 4, top: 4,
@ -230,7 +235,7 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
MyVideoProgressIndicator( MyVideoProgressIndicator(
_controller, _controller!,
allowScrubbing: false, allowScrubbing: false,
//padding: EdgeInsets.only(left: 60, right: 60), //padding: EdgeInsets.only(left: 60, right: 60),
), ),
@ -386,6 +391,28 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
if (advertisementData!.actionButtonsColl![index].actionValue.toLowerCase() == "skip") { if (advertisementData!.actionButtonsColl![index].actionValue.toLowerCase() == "skip") {
Navigator.pop(context); Navigator.pop(context);
} else { } else {
if (advertisementData!.actionButtonsColl![index].actionType!.toLowerCase() == 'redirect' && advertisementData!.actionButtonsColl![index].actionValue!.toLowerCase() ==
'external') {
Uri uri = Uri.parse(advertisementData!.actionButtonsColl![index].url!);
await launchUrl(uri, mode: LaunchMode.externalApplication).catchError((err) {
// print(err);
Utils.showToast('Could not launch');
});
Navigator.pop(context);
} else if (advertisementData!.actionButtonsColl![index].actionType!.toLowerCase() == 'redirect' && advertisementData!.actionButtonsColl![index].actionValue!.toLowerCase() ==
'internal') {
await Navigator.pushNamed(context, advertisementData!.actionButtonsColl![index].url!);
} else if(advertisementData!.actionButtonsColl![index].actionType!.toLowerCase() == 'eit' && advertisementData!.actionButtonsColl![index].actionValue!.toLowerCase() ==
'internal'){
var pro = Provider.of<DashboardProviderModel>(context, listen: false);
List<GetMenuEntriesList> _menuList =
pro.getMenuEntriesList?.where((element) => element.parentMenuName == advertisementData!.actionButtonsColl![index].url && (element.menuEntryType == "FUNCTION" || element.menuEntryType == "MENU")).toList() ?? [];
Navigator.pushNamed(context, AppRoutes.servicesMenuListScreen, arguments: ServicesMenuListScreenParams(advertisementData!.advertisementTitle!, _menuList));
}
else{
Uri uri = Uri.parse(advertisementData!.actionButtonsColl![index].iconOrImage); Uri uri = Uri.parse(advertisementData!.actionButtonsColl![index].iconOrImage);
// if (await canLaunchUrl(uri)) { // if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication).catchError((err) { await launchUrl(uri, mode: LaunchMode.externalApplication).catchError((err) {
@ -397,6 +424,7 @@ class _ITGAdsScreenState extends State<ITGAdsScreen> {
// Utils.showToast('Could not launch'); // Utils.showToast('Could not launch');
// } // }
} }
}
}, },
), ),
), ),

@ -1,13 +1,17 @@
import 'package:easy_localization/src/public_ext.dart'; import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:mohem_flutter_app/api/eit_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/string_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/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/sso_auth_model.dart';
import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart';
import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart';
import 'package:mohem_flutter_app/ui/screens/ticket/ticket_detailed_screen.dart';
import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart'; import 'package:mohem_flutter_app/widgets/shimmer/dashboard_shimmer_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -117,8 +121,29 @@ class MenusWidget extends StatelessWidget {
), ),
], ],
).paddingOnly(left: 10, right: 10, bottom: 6, top: 6), ).paddingOnly(left: 10, right: 10, bottom: 6, top: 6),
).onPress(() { ).onPress(() async {
Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS")); Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS"));
// var pro = Provider.of<DashboardProviderModel>(context, listen: false);
//
// // if (menuEntry.menuName == "HMG_TICKET_REQUESTS") {
// Utils.showLoading(context);
// //Ticket Work
// if (pro.ticketBookingResponse != null && pro.ticketBookingResponse!.success) {
// SSOAuthModel? ssoToken = await pro.fetchSSOAuthRedirection(clientID: pro.ticketBookingResponse!.clientId);
// if (ssoToken != null) {
// dynamic url = await pro.fetchURLRedirection(token: ssoToken.data!.accessToken!);
// await pro.fetchTicketAccuralBalance(context, DateTime.now());
// pro.ticketHistoryTransactionList = await EITApiClient().getEITTransactions("HMG_TICKET_ITENARY_HR_EIT_SS", isCompleteList: true);
//
// Utils.hideLoading(context);
// // Here Need Work
// Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => TicketDetailedScreen(url: url, jwtToken: ssoToken.data!.accessToken)));
// }
// //}
// } else {
// Navigator.pushNamed(context, AppRoutes.dynamicScreen, arguments: DynamicListViewParams(LocaleKeys.ticketBalance.tr(), "HMG_TKT_NEW_EIT_SS"));
// }
}), }),
], ],
); );

@ -92,7 +92,7 @@ class ServicesWidget extends StatelessWidget {
aspectRatio: 105 / 105, aspectRatio: 105 / 105,
child: child:
data.isServicesMenusLoading data.isServicesMenusLoading
? ServicesMenuShimmer() ? const ServicesMenuShimmer()
: Container( : Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
@ -266,7 +266,6 @@ class ServicesWidget extends StatelessWidget {
await pro.fetchTicketAccuralBalance(context, DateTime.now()); await pro.fetchTicketAccuralBalance(context, DateTime.now());
pro.ticketHistoryTransactionList = await EITApiClient().getEITTransactions("HMG_TICKET_ITENARY_HR_EIT_SS", isCompleteList: true); pro.ticketHistoryTransactionList = await EITApiClient().getEITTransactions("HMG_TICKET_ITENARY_HR_EIT_SS", isCompleteList: true);
Utils.hideLoading(context); Utils.hideLoading(context);
// Here Need Work // Here Need Work
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => TicketDetailedScreen(url: url, jwtToken: ssoToken.data!.accessToken))); Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => TicketDetailedScreen(url: url, jwtToken: ssoToken.data!.accessToken)));
@ -311,7 +310,7 @@ class ServicesWidget extends StatelessWidget {
padding: const EdgeInsets.only(left: 21, right: 21, top: 13, bottom: 13), padding: const EdgeInsets.only(left: 21, right: 21, top: 13, bottom: 13),
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemBuilder: (cxt, index) { itemBuilder: (cxt, index) {
return AspectRatio(aspectRatio: 105 / 105, child: ServicesMenuShimmer()); return AspectRatio(aspectRatio: 105 / 105, child: const ServicesMenuShimmer());
}, },
separatorBuilder: (cxt, index) => 9.width, separatorBuilder: (cxt, index) => 9.width,
itemCount: 4, itemCount: 4,

@ -0,0 +1,106 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/get_employee_parking_details_model.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
class ParkingQrScreen extends StatefulWidget {
const ParkingQrScreen({Key? key}) : super(key: key);
@override
_RequestDetailsState createState() => _RequestDetailsState();
}
class _RequestDetailsState extends State<ParkingQrScreen> {
GetEmployeeParking? qrData;
@override
void initState() {
super.initState();
getTicketDetails();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBarWidget(context, title: LocaleKeys.parkingQr.tr()),
body:
qrData?.getEmployeeParking == null
? Center(child: Text(LocaleKeys.noDataAvailable.tr()))
: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Container(
padding: const EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [BoxShadow(color: Colors.grey.withValues(alpha: 0.2), spreadRadius: 5, blurRadius: 10, offset: const Offset(0, 3))],
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// QR Code Image
if (qrData!.getEmployeeParking!.qrCodeImageBase64 != null && qrData!.getEmployeeParking!.qrCodeImageBase64!.isNotEmpty)
Image.memory(Utils.dataFromBase64String(qrData!.getEmployeeParking!.qrCodeImageBase64!), width: 300, height: 300, fit: BoxFit.contain)
else
Container(
width: 300,
height: 300,
color: MyColors.lightGreyEFColor,
child: Center(child: Text(LocaleKeys.noDataAvailable.tr(), style: const TextStyle(color: MyColors.grey67Color))),
),
10.height,
Container(height: 1, color: MyColors.lightGreyE3Color, margin: const EdgeInsets.symmetric(vertical: 10)),
20.height,
SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Employee Code
if (qrData!.getEmployeeParking!.employeeCode != null && qrData!.getEmployeeParking!.employeeCode!.isNotEmpty) ...[
Text(LocaleKeys.employeeNumber.tr(), style: const TextStyle(fontSize: 14, color: MyColors.grey67Color, fontWeight: FontWeight.w400)),
8.height,
Text(qrData!.getEmployeeParking!.employeeCode!, style: const TextStyle(fontSize: 18, color: MyColors.darkTextColor, fontWeight: FontWeight.w600)),
8.height,
],
if (qrData!.getEmployeeParking!.createdAt != null) ...[
Text(LocaleKeys.creationDate.tr(), style: const TextStyle(fontSize: 14, color: MyColors.grey67Color, fontWeight: FontWeight.w400)),
8.height,
Text(
DateFormat('dd MMM yyyy, hh:mm a').format(qrData!.getEmployeeParking!.createdAt!),
style: const TextStyle(fontSize: 16, color: MyColors.darkTextColor, fontWeight: FontWeight.w500),
),
],
],
),
),
],
),
),
),
),
),
);
}
void getTicketDetails() async {
try {
Utils.showLoading(context);
qrData = await DashboardApiClient().getEmployeeParkingQrCode();
Utils.hideLoading(context);
setState(() {});
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
}

@ -0,0 +1,333 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_svg/flutter_svg.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/inAppWebView.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/dashboard/courses_response_model.dart';
import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart';
import 'package:mohem_flutter_app/theme/colors.dart' as theme_colors;
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
import 'package:mohem_flutter_app/widgets/sso_webview_widget.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
class CoursesScreen extends StatefulWidget {
const CoursesScreen({Key? key}) : super(key: key);
@override
_CoursesScreenState createState() => _CoursesScreenState();
}
class _CoursesScreenState extends State<CoursesScreen> {
late DashboardProviderModel data;
final RefreshController _refreshController = RefreshController(initialRefresh: false);
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
data = Provider.of<DashboardProviderModel>(context, listen: false);
_onRefresh();
});
}
void _onRefresh() async {
await data.fetchCourses(context);
_refreshController.refreshCompleted();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBarWidget(
context,
title: LocaleKeys.courses.tr(),
),
body: Consumer<DashboardProviderModel>(
builder: (context, provider, child) {
return SmartRefresher(
enablePullDown: true,
enablePullUp: false,
controller: _refreshController,
onRefresh: _onRefresh,
child: provider.isCoursesLoading
? _buildShimmerLoading()
: provider.coursesList.isEmpty
? _buildEmptyState()
: _buildCoursesList(provider.coursesList),
);
},
),
);
}
Widget _buildShimmerLoading() {
return ListView.builder(
padding: const EdgeInsets.all(21),
itemCount: 5,
itemBuilder: (context, index) {
return Container(
margin: const EdgeInsets.only(bottom: 12),
height: 150,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: const Color(0xff000000).withOpacity(.05),
blurRadius: 26,
offset: const Offset(0, -3),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 20,
width: 200,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(4),
),
).toShimmer(),
12.height,
Container(
height: 14,
width: 100,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(4),
),
).toShimmer(),
const Spacer(),
Container(
height: 40,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(6),
),
).toShimmer(),
],
).paddingAll(14),
);
},
);
}
Widget _buildEmptyState() {
return Utils.getNoDataWidget(context);
}
Widget _buildCoursesList(List<CourseStatus> courses) {
return ListView.separated(
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
padding: const EdgeInsets.all(21),
itemBuilder: (BuildContext context, int index) {
return _buildCourseCard(courses[index]);
},
separatorBuilder: (BuildContext context, int index) => 12.height,
itemCount: courses.length,
);
}
Widget _buildCourseCard(CourseStatus course) {
bool isArabic = AppState().isArabic(context);
String courseName = isArabic && course.cNameAr != null && course.cNameAr!.isNotEmpty
? course.cNameAr!
: course.cFullname ?? '';
String status = course.cStatus ?? 'Unknown';
Color statusColor = _getStatusColor(status);
return InkWell(
onTap: () => _openCourse(course.cUrl, course.token),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Course Title
Row(
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: MyColors.lightGreyEFColor,
borderRadius: BorderRadius.circular(8),
),
child: const Icon(
Icons.school_rounded,
color: MyColors.gradiantStartColor,
size: 20,
),
),
12.width,
Expanded(
child: courseName.toText14(isBold: true, color: MyColors.darkTextColor),
),
],
),
12.height,
// Status Badge
Row(
children: [
Icon(
_getStatusIcon(status),
size: 16,
color: statusColor,
),
6.width,
LocaleKeys.status.tr().toText11(color: MyColors.grey98Color),
8.width,
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: statusColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: statusColor.withOpacity(0.3),
width: 1,
),
),
child: status.toText10(color: statusColor, isBold: true),
),
],
),
10.height,
// Start Date
if (course.cEnddate != null && course.cEnddate!.isNotEmpty)
Row(
children: [
const Icon(
Icons.calendar_month_rounded,
size: 16,
color: MyColors.darkIconColor,
),
6.width,
LocaleKeys.endDateT.tr().toText11(color: MyColors.grey98Color),
8.width,
Expanded(
child: _formatDate(course.cEnddate!).toText11(
color: MyColors.darkTextColor,
isBold: true,
),
),
],
),
if (course.cStartdate != null && course.cStartdate!.isNotEmpty) 14.height,
// Open Button
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
LocaleKeys.open.tr().toText12(color: MyColors.gradiantStartColor, isUnderLine: true),
6.width,
RotatedBox(
quarterTurns: AppState().isArabic(context) ? 2 : 4,
child: SvgPicture.asset(
"assets/images/arrow_next.svg",
color: MyColors.gradiantStartColor,
width: 16,
height: 16,
),
),
],
),
],
).objectContainerView(),
);
}
IconData _getStatusIcon(String status) {
if (status.toLowerCase().contains('passed')) {
return Icons.check_circle_rounded;
} else if (status.toLowerCase().contains('not passed') || status.toLowerCase().contains('failed')) {
return Icons.cancel_rounded;
} else if (status.toLowerCase().contains('in progress')) {
return Icons.pending_rounded;
} else {
return Icons.info_rounded;
}
}
Color _getStatusColor(String status) {
if (status.toLowerCase().contains('passed') && !status.toLowerCase().contains('not passed')) {
return Colors.green;
} else if (status.toLowerCase().contains('not passed') || status.toLowerCase().contains('failed')) {
return Colors.red;
} else if (status.toLowerCase().contains('in progress')) {
return Colors.yellow[700]!;
} else {
return MyColors.grey98Color;
}
}
DateTime? _parseDate(String? date) {
if (date == null || date.isEmpty) return null;
try {
return DateTime.parse(date.replaceAll(' ', 'T'));
} catch (e) {
try {
DateFormat format = DateFormat('yyyy-MM-dd HH:mm:ss');
return format.parse(date);
} catch (e) {
return null;
}
}
}
String _formatDate(String date) {
DateTime? dateTime = _parseDate(date);
if (dateTime == null) return date;
bool isArabic = AppState().isArabic(context);
DateFormat format = DateFormat('dd MMM yyyy, hh:mm a', isArabic ? 'ar' : 'en');
return format.format(dateTime);
}
void _openCourse(String? url, String? jwtToken) {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => SsoLoginWebView(url: url, jwtToken: jwtToken)));
//Utils.showToast(LocaleKeys.courseUrlNotAvailable.tr());
// return;
// }
//
// MyInAppBrowser browser = MyInAppBrowser(
// onExitCallback: () {},
// onLoadStartCallback: (String url) {},
// );
//
// var settings = InAppBrowserClassSettings(
// webViewSettings: InAppWebViewSettings(
// useShouldOverrideUrlLoading: false,
// transparentBackground: false,
// ),
// browserSettings: InAppBrowserSettings(
// hideUrlBar: true,
// hideTitleBar: false,
// toolbarTopBackgroundColor: theme_colors.primaryColor,
// ),
// );
//
// browser.openUrlRequest(
// urlRequest: URLRequest(url: WebUri(url)),
// settings: settings,
// );
}
@override
void dispose() {
_refreshController.dispose();
super.dispose();
}
}

@ -150,7 +150,9 @@ class _MowadhafhiHRRequestState extends State<MowadhafhiHRRequest> {
isReadOnly: false, isReadOnly: false,
onChange: (String value) { onChange: (String value) {
debugPrint(value); debugPrint(value);
setState(() {
description = value; description = value;
});
}, },
), ),
], ],
@ -171,7 +173,7 @@ class _MowadhafhiHRRequestState extends State<MowadhafhiHRRequest> {
} }
bool checkValidation() { bool checkValidation() {
if (selectedServiceType == null || selectedDepartment == null || selectedSection == null || selectedTopic == null) { if (selectedServiceType == null || selectedDepartment == null || selectedSection == null || selectedTopic == null || description == "") {
return false; return false;
} else { } else {
return true; return true;

@ -9,6 +9,7 @@ import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.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/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_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/dashboard/get_accural_ticket_balance_model.dart'; import 'package:mohem_flutter_app/models/dashboard/get_accural_ticket_balance_model.dart';
import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
@ -55,7 +56,7 @@ class _TicketDetailedScreenState extends State<TicketDetailedScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: AppBarWidget(context, title: "Ticket Details"), appBar: AppBarWidget(context, title:LocaleKeys.ticketDetails.tr()),
body: Column( body: Column(
children: <Widget>[ children: <Widget>[
ListView( ListView(
@ -74,7 +75,7 @@ class _TicketDetailedScreenState extends State<TicketDetailedScreen> {
children: <Widget>[ children: <Widget>[
Row( Row(
children: <Widget>[ children: <Widget>[
"Current Ticket Balance".toText20().expanded, LocaleKeys.currentTicketBalance.tr().toText20().expanded,
Row( Row(
children: <Widget>[ children: <Widget>[
const Icon(Icons.calendar_month_rounded, color: MyColors.darkIconColor, size: 16), const Icon(Icons.calendar_month_rounded, color: MyColors.darkIconColor, size: 16),
@ -118,7 +119,7 @@ class _TicketDetailedScreenState extends State<TicketDetailedScreen> {
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
children: <Widget>[ children: <Widget>[
"Tickets History".toText20().expanded, LocaleKeys.ticketHistory.tr().toText20().expanded,
12.height, 12.height,
ListView.separated( ListView.separated(
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
@ -175,7 +176,7 @@ class _TicketDetailedScreenState extends State<TicketDetailedScreen> {
], ],
], ],
).expanded, ).expanded,
DefaultButton("Proceed For Booking", () { DefaultButton(LocaleKeys.proceedBooking.tr(), () {
if (widget.url != null && widget.jwtToken != null) { if (widget.url != null && widget.jwtToken != null) {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => SsoLoginWebView(url: widget.url, jwtToken: widget.jwtToken))); Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => SsoLoginWebView(url: widget.url, jwtToken: widget.jwtToken)));
} }

@ -21,7 +21,11 @@ class ApprovalLevelfragment extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (wFHistory.isNotEmpty) wFHistory = wFHistory.reversed.toList(); if (wFHistory.isNotEmpty) {
//TODO: This COde is Written For Future. If Needed Enable to Filter The Empty Action Requests.
// wFHistory = wFHistory.where((item) => item.action != null && item.action!.isNotEmpty).toList();
wFHistory = wFHistory.reversed.toList();
}
return Container( return Container(
width: double.infinity, width: double.infinity,
height: double.infinity, height: double.infinity,
@ -164,8 +168,8 @@ class ApprovalLevelfragment extends StatelessWidget {
if (wFHistory[index].date!.isEmpty || wFHistory[index].action!.toLowerCase() == "NO ACTION" || wFHistory[index + 1].date! == "") { if (wFHistory[index].date!.isEmpty || wFHistory[index].action!.toLowerCase() == "NO ACTION" || wFHistory[index + 1].date! == "") {
return ""; return "";
} else { } else {
DateTime dateTimeTo = DateUtil.convertSimpleStringDateToDate(wFHistory[index].date!); DateTime dateTimeTo = DateUtil.convertSimpleStringDateToDate(wFHistory[index].date!, isITG: true);
DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(wFHistory[index + 1].date!); DateTime dateTimeFrom = DateUtil.convertSimpleStringDateToDate(wFHistory[index + 1].date!, isITG: true);
Duration duration = dateTimeTo.difference(dateTimeFrom); Duration duration = dateTimeTo.difference(dateTimeFrom);
return "Action duration: " + DateUtil.formatDuration(duration); return "Action duration: " + DateUtil.formatDuration(duration);
} }

@ -141,7 +141,7 @@ void galleryImageAndroid(Function(String, File) image) async {
} }
void cameraImageAndroid(Function(String, File) image) async { void cameraImageAndroid(Function(String, File) image) async {
File _image = File(( await picker.pickMedia())?.path ?? ""); File _image = File((await picker.pickImage(source: ImageSource.camera, imageQuality: 20))?.path ?? "");
String fileName = _image.path; String fileName = _image.path;
var bytes = File(fileName).readAsBytesSync(); var bytes = File(fileName).readAsBytesSync();
String base64Encode = base64.encode(bytes); String base64Encode = base64.encode(bytes);
@ -159,7 +159,7 @@ class _BottomSheet extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
padding: const EdgeInsets.symmetric(vertical: 12.0), padding: const EdgeInsets.symmetric(vertical: 12.0),
decoration: BoxDecoration( borderRadius: const BorderRadius.only(topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0))), decoration: const BoxDecoration( borderRadius: BorderRadius.only(topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0))),
child: SafeArea( child: SafeArea(
top: false, top: false,
child: Column( child: Column(

@ -8,6 +8,8 @@ import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:shimmer/shimmer.dart'; import 'package:shimmer/shimmer.dart';
class GetAttendanceTrackingShimmer extends StatelessWidget { class GetAttendanceTrackingShimmer extends StatelessWidget {
const GetAttendanceTrackingShimmer({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
@ -85,6 +87,8 @@ class GetAttendanceTrackingShimmer extends StatelessWidget {
} }
class MenuShimmer extends StatelessWidget { class MenuShimmer extends StatelessWidget {
const MenuShimmer({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
@ -122,6 +126,8 @@ class MenuShimmer extends StatelessWidget {
} }
class ServicesHeaderShimmer extends StatelessWidget { class ServicesHeaderShimmer extends StatelessWidget {
const ServicesHeaderShimmer({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Row(
@ -145,6 +151,8 @@ class ServicesHeaderShimmer extends StatelessWidget {
} }
class ServicesMenuShimmer extends StatelessWidget { class ServicesMenuShimmer extends StatelessWidget {
const ServicesMenuShimmer({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
@ -188,6 +196,75 @@ class ServicesMenuShimmer extends StatelessWidget {
} }
} }
class GreetingCardShimmer extends StatelessWidget {
const GreetingCardShimmer({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 100,
decoration: BoxDecoration(
color: const Color(0xFFFAF4E7),
border: Border.all(width: 2, color: const Color(0xFFE7E7E7)),
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 65,
height: 81,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(10),
),
).toShimmer(),
const SizedBox(width: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 150,
height: 16,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4),
),
).toShimmer(),
const SizedBox(height: 8),
Container(
width: 120,
height: 16,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4),
),
).toShimmer(),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
width: 60,
height: 12,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4),
),
).toShimmer(),
],
),
],
).paddingOnly(left: 8, right: 8, top: 6, bottom: 12),
).paddingOnly(left: 21, right: 21, top: 14, bottom: 14);
}
}
class MarathonBannerShimmer extends StatelessWidget { class MarathonBannerShimmer extends StatelessWidget {
const MarathonBannerShimmer({Key? key}) : super(key: key); const MarathonBannerShimmer({Key? key}) : super(key: key);
@ -305,3 +382,4 @@ class ChatHomeShimmer extends StatelessWidget {
)); ));
} }
} }

@ -15,10 +15,13 @@ class SsoLoginWebView extends StatefulWidget {
class _SsoLoginWebViewState extends State<SsoLoginWebView> { class _SsoLoginWebViewState extends State<SsoLoginWebView> {
late final WebViewController _controller; late final WebViewController _controller;
String? url;
@override @override
void initState() { void initState() {
// TODO: implement initState // TODO: implement initState
url = widget.url ?? "https://Paxes-release.techmaster.in/SSO/HMG";
super.initState(); super.initState();
_controller = _controller =
WebViewController() WebViewController()
@ -46,7 +49,7 @@ class _SsoLoginWebViewState extends State<SsoLoginWebView> {
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<body onload="document.forms[0].submit()"> <body onload="document.forms[0].submit()">
<form method="POST" action="https://Paxes-release.techmaster.in/SSO/HMG"> <form method="POST" action="$url">
<input type="hidden" name="JWTToken" value="${widget.jwtToken}" /> <input type="hidden" name="JWTToken" value="${widget.jwtToken}" />
</form> </form>
<h1>Redirecting...</h1> <h1>Redirecting...</h1>
@ -56,6 +59,6 @@ class _SsoLoginWebViewState extends State<SsoLoginWebView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(title: Text('Logging in...')), body: WebViewWidget(controller: _controller)); return Scaffold(appBar: null, body:SafeArea(child: WebViewWidget(controller: _controller)));
} }
} }

@ -17,8 +17,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
#version: 3.6.8+300078 version: 3.6.8+300078
version: 3.9.2+1 #version: 3.9.2+1
environment: environment:
sdk: ^3.7.0 sdk: ^3.7.0
@ -105,6 +105,9 @@ dependencies:
audio_waveforms: ^1.3.0 audio_waveforms: ^1.3.0
rxdart: ^0.27.7 rxdart: ^0.27.7
#Speech to Text
speech_to_text: ^7.0.0
#Encryption #Encryption
flutter_des: ^2.1.0 flutter_des: ^2.1.0

Loading…
Cancel
Save