Merge remote-tracking branch 'origin/master' into labs_graph_pdf

labs_graph_pdf
tahaalam 1 day ago
commit 2babda2d63

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.3 KiB

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="40" height="40" rx="10" fill="#0B85F7"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.25 20C9.25 25.928 14.072 30.75 20 30.75C25.928 30.75 30.75 25.928 30.75 20C30.75 14.0721 25.9282 9.25021 20.0004 9.25C14.0724 9.25 9.25 14.072 9.25 20ZM28.9732 17.75C29.154 18.4705 29.25 19.2243 29.25 20C29.25 20.7757 29.154 21.5295 28.9732 22.25H24.5746C24.687 21.5359 24.751 20.7846 24.751 19.9997C24.751 19.2151 24.687 18.464 24.5747 17.75H28.9732ZM28.4553 16.25H24.2585C23.6395 13.9132 22.5564 12.0788 21.7158 10.9096C24.7331 11.4779 27.2382 13.5166 28.4553 16.25ZM23.049 17.75C23.1761 18.4613 23.25 19.213 23.25 19.9997C23.25 20.7866 23.1761 21.5386 23.049 22.25H16.9511C16.8239 21.5386 16.75 20.7866 16.75 19.9997C16.75 19.2131 16.8239 18.4613 16.9509 17.75H23.049ZM17.309 16.25H22.6909C21.966 13.828 20.7108 12.0282 20 11.1427C19.2892 12.0276 18.0339 13.8277 17.309 16.25ZM15.4263 17.75C15.314 18.464 15.25 19.2151 15.25 19.9997C15.25 20.7846 15.3141 21.5359 15.4264 22.25H11.0268C10.846 21.5295 10.75 20.7757 10.75 20C10.75 19.2243 10.846 18.4705 11.0268 17.75H15.4263ZM11.5447 16.25H15.7424C16.3613 13.9131 17.4442 12.0786 18.2848 10.9094C15.2672 11.4776 12.7619 13.5164 11.5447 16.25ZM21.7159 29.0904C24.7331 28.522 27.2382 26.4834 28.4553 23.75H24.2584C23.6395 26.0869 22.5565 27.9213 21.7159 29.0904ZM20 28.8568C20.7107 27.9719 21.9659 26.1721 22.6908 23.75H17.3093C18.0342 26.1717 19.2893 27.9713 20 28.8568ZM18.2858 29.0907C17.4451 27.9217 16.3618 26.0871 15.7427 23.75H11.5447C12.7621 26.4839 15.2678 28.5228 18.2858 29.0907Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.5 7.5C18.5 8.60457 17.6046 9.5 16.5 9.5C15.3954 9.5 14.5 8.60457 14.5 7.5C14.5 6.39543 15.3954 5.5 16.5 5.5C17.6046 5.5 18.5 6.39543 18.5 7.5Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.9255 1.5H12.0745C14.2504 1.49998 15.9852 1.49996 17.3453 1.68282C18.7497 1.87164 19.9035 2.27175 20.8159 3.18414C21.7283 4.09653 22.1284 5.25033 22.3172 6.65471C22.5 8.01485 22.5 9.74959 22.5 11.9256V12.0744C22.5 14.2504 22.5 15.9851 22.3172 17.3453C22.1284 18.7497 21.7283 19.9035 20.8159 20.8159C19.9035 21.7283 18.7497 22.1284 17.3453 22.3172C15.9851 22.5 14.2504 22.5 12.0744 22.5H11.9256C9.74959 22.5 8.01485 22.5 6.65471 22.3172C5.25033 22.1284 4.09653 21.7283 3.18414 20.8159C2.27175 19.9035 1.87164 18.7497 1.68282 17.3453C1.49996 15.9852 1.49998 14.2504 1.5 12.0745V11.9255C1.49998 9.74958 1.49996 8.01484 1.68282 6.65471C1.87164 5.25033 2.27175 4.09653 3.18414 3.18414C4.09653 2.27175 5.25033 1.87164 6.65471 1.68282C8.01485 1.49996 9.74958 1.49998 11.9255 1.5ZM6.92121 3.66499C5.73861 3.82399 5.0772 4.1195 4.59835 4.59835C4.1195 5.0772 3.82399 5.73861 3.66499 6.92121C3.50213 8.13258 3.5 9.73256 3.5 12C3.5 12.2688 3.50003 12.5282 3.50036 12.7786C3.78795 12.7608 4.07624 12.7521 4.36474 12.7527C7.17775 12.6952 9.92747 13.572 12.124 15.2364C13.9124 16.5915 15.2416 18.3991 15.9596 20.4377C16.3674 20.4138 16.7385 20.3808 17.0788 20.335C17.2221 20.3157 17.3578 20.2945 17.4864 20.2711C16.9795 18.6882 16.1544 17.2258 15.0687 15.9582C14.8393 15.6904 14.9291 15.27 15.2648 15.1622C16.122 14.887 16.9998 14.7468 17.8878 14.7501C18.7607 14.7494 19.6259 14.889 20.4723 15.162C20.4994 14.2767 20.5 13.2378 20.5 12C20.5 9.73256 20.4979 8.13258 20.335 6.92121C20.176 5.73861 19.8805 5.0772 19.4017 4.59835C18.9228 4.1195 18.2614 3.82399 17.0788 3.66499C15.8674 3.50213 14.2674 3.5 12 3.5C9.73256 3.5 8.13258 3.50213 6.92121 3.66499Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@ -435,7 +435,6 @@
"serviceInformation": "معلومات الخدمة", "serviceInformation": "معلومات الخدمة",
"homeHealthCare": "الرعاية الصحية المنزلية", "homeHealthCare": "الرعاية الصحية المنزلية",
"noAppointmentAvailable": "لا توجد مواعيد متاحة", "noAppointmentAvailable": "لا توجد مواعيد متاحة",
"homeHealthCareText": "تقدم هذه الخدمة مجموعة من خدمات الرعاية الصحية المنزلية، والمتابعة المستمرة والشاملة في أماكن إقامتهم لأولئك الذين لا يمكنهم الوصول إلى المرافق الصحية، مثل (تحليلات المختبر - الأشعة - التطعيمات - العلاج الطبيعي)، إلخ.",
"loginRegister": "تسجيل الدخول / التسجيل", "loginRegister": "تسجيل الدخول / التسجيل",
"orderLog": "سجل الطلب", "orderLog": "سجل الطلب",
"infoLab": "تتيح لك هذه الخدمة عرض نتائج جميع الفحوصات المخبرية التي أجريت في مجموعة الحبيب الطبية بالإضافة إلى إرسال التقرير عبر البريد الإلكتروني.", "infoLab": "تتيح لك هذه الخدمة عرض نتائج جميع الفحوصات المخبرية التي أجريت في مجموعة الحبيب الطبية بالإضافة إلى إرسال التقرير عبر البريد الإلكتروني.",
@ -448,7 +447,7 @@
"lakumPoint": "نقطة", "lakumPoint": "نقطة",
"wishlist": "قائمة الرغبات", "wishlist": "قائمة الرغبات",
"products": "المنتجات", "products": "المنتجات",
"reviews": "التقييمات", "reviews": "التعليقات",
"brands": "العلامات التجارية", "brands": "العلامات التجارية",
"productDetails": "تفاصيل المنتج", "productDetails": "تفاصيل المنتج",
"medicationRefill": "إعادة تعبئة الدواء", "medicationRefill": "إعادة تعبئة الدواء",
@ -812,7 +811,7 @@
"awaitingApproval": "انتظر القبول", "awaitingApproval": "انتظر القبول",
"news": "أخبار", "news": "أخبار",
"ready": "جاهز", "ready": "جاهز",
"enterValidNationalId": "الرجاء إدخال رقم الهوية الوطنية أو رقم الملف الصحيح", "enterValidNationalId": "رقم الهوية أو رقم الملف غير صحيح",
"enterValidPhoneNumber": "الرجاء إدخال رقم هاتف صالح", "enterValidPhoneNumber": "الرجاء إدخال رقم هاتف صالح",
"cannotEnterSaudiOrUAENumber": "لا يمكنك إدخال أرقام هواتف السعودية (00966) أو الإمارات (00971) عند اختيار دولة 'أخرى'", "cannotEnterSaudiOrUAENumber": "لا يمكنك إدخال أرقام هواتف السعودية (00966) أو الإمارات (00971) عند اختيار دولة 'أخرى'",
"medicalCentersWithCount": "{count} مراكز طبية", "medicalCentersWithCount": "{count} مراكز طبية",
@ -1275,7 +1274,7 @@
"noVitalSignsRecordedYet": "لا توجد علامات حيوية مسجلة بعد", "noVitalSignsRecordedYet": "لا توجد علامات حيوية مسجلة بعد",
"appointmentsAndVisits": "المواعيد والزيارات", "appointmentsAndVisits": "المواعيد والزيارات",
"labAndRadiology": "المختبر والأشعة", "labAndRadiology": "المختبر والأشعة",
"activeMedicationsAndPrescriptions": "الأدوية النشطة والوصفات الطبية", "activeMedicationsAndPrescriptions": "الوصفات الطبية",
"allPrescriptions": "جميع الوصفات", "allPrescriptions": "جميع الوصفات",
"allMedications": "جميع الأدوية", "allMedications": "جميع الأدوية",
"youDontHaveAnyPrescriptionsYet": "ليس لديك أي وصفات طبية بعد.", "youDontHaveAnyPrescriptionsYet": "ليس لديك أي وصفات طبية بعد.",
@ -1583,5 +1582,14 @@
"continueCash": "متابعة الدفع نقدًا", "continueCash": "متابعة الدفع نقدًا",
"timeFor": "الوقت", "timeFor": "الوقت",
"hmgPolicies": "سياسات مجموعة الحبيب الطبية", "hmgPolicies": "سياسات مجموعة الحبيب الطبية",
"darkMode": "المظهر الداكن" "darkMode": "المظهر الداكن",
"generateAiAnalysisResult": "قم بإجراء تحليل لهذا المختبر AI",
"ratings": "التقييمات",
"hmgPharmacyText": "صيدلية الحبيب، المتجر الصيدلاني الإلكتروني المتكامل الذي تقدمه لكم مجموعة خدمات الدكتور سليمان الحبيب الطبية.",
"insuranceRequestSubmittedSuccessfully": "تم إرسال طلب تحديث بيانات التأمين بنجاح. سيتم إعلامك بمجرد الانتهاء.",
"updatingEmailAddress": "جارٍ تحديث عنوان البريد الإلكتروني، يرجى الانتظار...",
"verifyInsurance": "التحقق من التأمين",
"tests": "تحليل",
"calendarPermissionAlert": "يرجى منح إذن الوصول إلى التقويم من إعدادات التطبيق لضبط تذكير تناول الدواء.",
"sortByLocation": "الترتيب حسب الموقع"
} }

@ -802,7 +802,7 @@
"notNow": "Not Now", "notNow": "Not Now",
"pendingActivation": "Pending Activation", "pendingActivation": "Pending Activation",
"awaitingApproval": "Awaiting Approval", "awaitingApproval": "Awaiting Approval",
"enterValidNationalId": "Please enter a valid national ID or file number", "enterValidNationalId": "Invalid Identification or file number",
"enterValidPhoneNumber": "Please enter a valid phone number", "enterValidPhoneNumber": "Please enter a valid phone number",
"cannotEnterSaudiOrUAENumber": "You cannot enter Saudi Arabia (00966) or UAE (00971) phone numbers when 'Others' country is selected", "cannotEnterSaudiOrUAENumber": "You cannot enter Saudi Arabia (00966) or UAE (00971) phone numbers when 'Others' country is selected",
"ready": "Ready", "ready": "Ready",
@ -1266,7 +1266,7 @@
"noVitalSignsRecordedYet": "No vital signs recorded yet", "noVitalSignsRecordedYet": "No vital signs recorded yet",
"appointmentsAndVisits": "Appointments & visits", "appointmentsAndVisits": "Appointments & visits",
"labAndRadiology": "Lab & Radiology", "labAndRadiology": "Lab & Radiology",
"activeMedicationsAndPrescriptions": "Active Medications & Prescriptions", "activeMedicationsAndPrescriptions": "Recent Prescriptions",
"allPrescriptions": "All Prescriptions", "allPrescriptions": "All Prescriptions",
"allMedications": "All Medications", "allMedications": "All Medications",
"youDontHaveAnyPrescriptionsYet": "You don't have any prescriptions yet.", "youDontHaveAnyPrescriptionsYet": "You don't have any prescriptions yet.",
@ -1576,5 +1576,14 @@
"continueCash": "Continue as cash", "continueCash": "Continue as cash",
"timeFor": "Time For", "timeFor": "Time For",
"hmgPolicies": "HMG Policies", "hmgPolicies": "HMG Policies",
"darkMode": "Dark Mode" "darkMode": "Dark Mode",
"generateAiAnalysisResult": "Generate AI analysis for this result",
"ratings": "Ratings",
"hmgPharmacyText": "Al Habib Pharmacy, the complete online Pharmaceutical store brought to you by Dr. Sulaiman Al Habib Medical Services Group.",
"insuranceRequestSubmittedSuccessfully": "Your insurance update request has been successfully submitted. You will be notified once completed.",
"updatingEmailAddress": "Updating email address, Please wait...",
"verifyInsurance": "Verify Insurance",
"tests": "tests",
"calendarPermissionAlert": "Please grant calendar access permission from app settings to set medication reminder.",
"sortByLocation": "Sort by location"
} }

@ -11,6 +11,12 @@
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
478CFA942E638C8E0064F3D7 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */; }; 478CFA942E638C8E0064F3D7 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */; };
47C1AAC72F425ACF00DA1231 /* Penguin.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47C1AAC12F425AC800DA1231 /* Penguin.xcframework */; };
47C1AAC82F425ACF00DA1231 /* Penguin.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 47C1AAC12F425AC800DA1231 /* Penguin.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
47C1AAC92F425AD000DA1231 /* PenguinINRenderer.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47C1AAC22F425AC800DA1231 /* PenguinINRenderer.xcframework */; };
47C1AACA2F425AD000DA1231 /* PenguinINRenderer.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 47C1AAC22F425AC800DA1231 /* PenguinINRenderer.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
47C1AACB2F425AD100DA1231 /* PenNavUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47C1AAC32F425AC800DA1231 /* PenNavUI.xcframework */; };
47C1AACC2F425AD100DA1231 /* PenNavUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 47C1AAC32F425AC800DA1231 /* PenNavUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
61243B492EC5FA3700D46FA0 /* PenguinModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B422EC5FA3700D46FA0 /* PenguinModel.swift */; }; 61243B492EC5FA3700D46FA0 /* PenguinModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B422EC5FA3700D46FA0 /* PenguinModel.swift */; };
61243B4C2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B3D2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift */; }; 61243B4C2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B3D2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift */; };
61243B502EC5FA3700D46FA0 /* PenguinView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B452EC5FA3700D46FA0 /* PenguinView.swift */; }; 61243B502EC5FA3700D46FA0 /* PenguinView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B452EC5FA3700D46FA0 /* PenguinView.swift */; };
@ -18,12 +24,6 @@
61243B562EC5FA3700D46FA0 /* PenguinNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */; }; 61243B562EC5FA3700D46FA0 /* PenguinNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */; };
61243B572EC5FA3700D46FA0 /* PenguinViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B462EC5FA3700D46FA0 /* PenguinViewFactory.swift */; }; 61243B572EC5FA3700D46FA0 /* PenguinViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B462EC5FA3700D46FA0 /* PenguinViewFactory.swift */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
765A5A8C2F35CD8B0003FF7D /* Penguin.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A802F35CD730003FF7D /* Penguin.xcframework */; };
765A5A8D2F35CD8B0003FF7D /* Penguin.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A802F35CD730003FF7D /* Penguin.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
765A5A8E2F35CD8B0003FF7D /* PenguinINRenderer.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A812F35CD730003FF7D /* PenguinINRenderer.xcframework */; };
765A5A8F2F35CD8B0003FF7D /* PenguinINRenderer.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A812F35CD730003FF7D /* PenguinINRenderer.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
765A5A902F35CD8B0003FF7D /* PenNavUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A822F35CD730003FF7D /* PenNavUI.xcframework */; };
765A5A912F35CD8B0003FF7D /* PenNavUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A822F35CD730003FF7D /* PenNavUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
76AA18AE2F3B2A4D00DC8DFC /* ring_30Sec.caf in Resources */ = {isa = PBXBuildFile; fileRef = 76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */; }; 76AA18AE2F3B2A4D00DC8DFC /* ring_30Sec.caf in Resources */ = {isa = PBXBuildFile; fileRef = 76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */; };
76AA18AF2F3B2A4D00DC8DFC /* ring_30Sec.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 76AA18AD2F3B2A4D00DC8DFC /* ring_30Sec.mp3 */; }; 76AA18AF2F3B2A4D00DC8DFC /* ring_30Sec.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 76AA18AD2F3B2A4D00DC8DFC /* ring_30Sec.mp3 */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
@ -49,9 +49,9 @@
dstPath = ""; dstPath = "";
dstSubfolderSpec = 10; dstSubfolderSpec = 10;
files = ( files = (
765A5A8F2F35CD8B0003FF7D /* PenguinINRenderer.xcframework in Embed Frameworks */, 47C1AACA2F425AD000DA1231 /* PenguinINRenderer.xcframework in Embed Frameworks */,
765A5A8D2F35CD8B0003FF7D /* Penguin.xcframework in Embed Frameworks */, 47C1AAC82F425ACF00DA1231 /* Penguin.xcframework in Embed Frameworks */,
765A5A912F35CD8B0003FF7D /* PenNavUI.xcframework in Embed Frameworks */, 47C1AACC2F425AD100DA1231 /* PenNavUI.xcframework in Embed Frameworks */,
); );
name = "Embed Frameworks"; name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -66,6 +66,9 @@
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; }; 478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
478CFA952E6E20A60064F3D7 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; }; 478CFA952E6E20A60064F3D7 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
47C1AAC12F425AC800DA1231 /* Penguin.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Penguin.xcframework; sourceTree = "<group>"; };
47C1AAC22F425AC800DA1231 /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = PenguinINRenderer.xcframework; sourceTree = "<group>"; };
47C1AAC32F425AC800DA1231 /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = PenNavUI.xcframework; sourceTree = "<group>"; };
61243B3D2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMGPenguinInPlatformBridge.swift; sourceTree = "<group>"; }; 61243B3D2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMGPenguinInPlatformBridge.swift; sourceTree = "<group>"; };
61243B422EC5FA3700D46FA0 /* PenguinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinModel.swift; sourceTree = "<group>"; }; 61243B422EC5FA3700D46FA0 /* PenguinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinModel.swift; sourceTree = "<group>"; };
61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinNavigator.swift; sourceTree = "<group>"; }; 61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinNavigator.swift; sourceTree = "<group>"; };
@ -75,9 +78,6 @@
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7595037DD52211B91157B0F3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; }; 7595037DD52211B91157B0F3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
765A5A802F35CD730003FF7D /* Penguin.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Penguin.xcframework; sourceTree = "<group>"; };
765A5A812F35CD730003FF7D /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = PenguinINRenderer.xcframework; sourceTree = "<group>"; };
765A5A822F35CD730003FF7D /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = PenNavUI.xcframework; sourceTree = "<group>"; };
769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = "<group>"; }; 769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = "<group>"; };
76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = ring_30Sec.caf; sourceTree = "<group>"; }; 76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = ring_30Sec.caf; sourceTree = "<group>"; };
76AA18AD2F3B2A4D00DC8DFC /* ring_30Sec.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ring_30Sec.mp3; sourceTree = "<group>"; }; 76AA18AD2F3B2A4D00DC8DFC /* ring_30Sec.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ring_30Sec.mp3; sourceTree = "<group>"; };
@ -99,9 +99,9 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
765A5A8C2F35CD8B0003FF7D /* Penguin.xcframework in Frameworks */, 47C1AAC92F425AD000DA1231 /* PenguinINRenderer.xcframework in Frameworks */,
765A5A902F35CD8B0003FF7D /* PenNavUI.xcframework in Frameworks */, 47C1AACB2F425AD100DA1231 /* PenNavUI.xcframework in Frameworks */,
765A5A8E2F35CD8B0003FF7D /* PenguinINRenderer.xcframework in Frameworks */, 47C1AAC72F425ACF00DA1231 /* Penguin.xcframework in Frameworks */,
DE1EF78253E64BE86845D2CC /* Pods_Runner.framework in Frameworks */, DE1EF78253E64BE86845D2CC /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -140,9 +140,9 @@
766D8CB22EC60BE600D05E07 /* Frameworks */ = { 766D8CB22EC60BE600D05E07 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
765A5A802F35CD730003FF7D /* Penguin.xcframework */, 47C1AAC12F425AC800DA1231 /* Penguin.xcframework */,
765A5A812F35CD730003FF7D /* PenguinINRenderer.xcframework */, 47C1AAC22F425AC800DA1231 /* PenguinINRenderer.xcframework */,
765A5A822F35CD730003FF7D /* PenNavUI.xcframework */, 47C1AAC32F425AC800DA1231 /* PenNavUI.xcframework */,
D562310E31D1DDEFA02A6C12 /* Pods_Runner.framework */, D562310E31D1DDEFA02A6C12 /* Pods_Runner.framework */,
); );
name = Frameworks; name = Frameworks;
@ -523,10 +523,11 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3; CURRENT_PROJECT_VERSION = 15;
DEVELOPMENT_TEAM = 3A359E86ZF; DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Dr. Alhabib";
IPHONEOS_DEPLOYMENT_TARGET = 15.6; IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -709,10 +710,11 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3; CURRENT_PROJECT_VERSION = 15;
DEVELOPMENT_TEAM = 3A359E86ZF; DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Dr. Alhabib";
IPHONEOS_DEPLOYMENT_TARGET = 15.6; IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -738,10 +740,11 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3; CURRENT_PROJECT_VERSION = 15;
DEVELOPMENT_TEAM = 3A359E86ZF; DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Dr. Alhabib";
IPHONEOS_DEPLOYMENT_TARGET = 15.6; IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",

@ -1,128 +1 @@
{ {"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]}
"images" : [
{
"filename" : "Icon-App-20x20@2x.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "Icon-App-20x20@3x.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"filename" : "Icon-App-29x29@1x.png",
"idiom" : "iphone",
"scale" : "1x",
"size" : "29x29"
},
{
"filename" : "Icon-App-29x29@2x.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "Icon-App-29x29@3x.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"filename" : "Icon-App-40x40@2x.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "Icon-App-40x40@3x.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"filename" : "Icon-App-60x60@2x.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"filename" : "Icon-App-60x60@3x.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"filename" : "Icon-App-20x20@1x.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"filename" : "Icon-App-20x20@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "Icon-App-29x29@1x.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"filename" : "Icon-App-29x29@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "Icon-App-40x40@1x.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"filename" : "Icon-App-40x40@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "Icon-App-76x76@1x.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"filename" : "Icon-App-76x76@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"filename" : "Icon-App-83.5x83.5@2x.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"filename" : "icon.jpg",
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
},
{
"filename" : "Icon-App-76x76@2x.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "76x76"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -13,7 +13,7 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>Dr. Alhabib Beta</string> <string>Dr. Alhabib</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
@ -101,7 +101,6 @@
<array> <array>
<string>audio</string> <string>audio</string>
<string>fetch</string> <string>fetch</string>
<string>location</string>
<string>remote-notification</string> <string>remote-notification</string>
<string>voip</string> <string>voip</string>
</array> </array>

@ -184,15 +184,15 @@ class ApiClientImp implements ApiClient {
body[_appState.isAuthenticated ? 'TokenID' : 'LogInTokenID'] = _appState.appAuthToken; body[_appState.isAuthenticated ? 'TokenID' : 'LogInTokenID'] = _appState.appAuthToken;
} }
if (url.contains("HMGAI_Lab_Analyze_Orders_API")) { // if (url.contains("HMGAI_Lab_Analyze_Orders_API")) {
url = "https://uat.hmgwebservices.com/Services/Patients.svc/REST/HMGAI_Lab_Analyze_Orders_API"; // url = "https://uat.hmgwebservices.com/Services/Patients.svc/REST/HMGAI_Lab_Analyze_Orders_API";
body['TokenID'] = "@dm!n"; // body['TokenID'] = "@dm!n";
} // }
//
if (url.contains("HMGAI_Lab_Analyzer_API")) { // if (url.contains("HMGAI_Lab_Analyzer_API")) {
url = "https://uat.hmgwebservices.com/Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API"; // url = "https://uat.hmgwebservices.com/Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API";
body['TokenID'] = "@dm!n"; // body['TokenID'] = "@dm!n";
} // }
if (url == 'https://uat.hmgwebservices.com/Services/NHIC.svc/REST/GetPatientInfo') { if (url == 'https://uat.hmgwebservices.com/Services/NHIC.svc/REST/GetPatientInfo') {
url = "https://hmgwebservices.com/Services/NHIC.svc/REST/GetPatientInfo"; url = "https://hmgwebservices.com/Services/NHIC.svc/REST/GetPatientInfo";
@ -200,7 +200,7 @@ class ApiClientImp implements ApiClient {
} }
// body['TokenID'] = "@dm!n"; // body['TokenID'] = "@dm!n";
// body['PatientID'] = 809289; // body['PatientID'] = 1231755;
// body['PatientTypeID'] = 1; // body['PatientTypeID'] = 1;
// body['PatientOutSA'] = 0; // body['PatientOutSA'] = 0;
// body['SessionID'] = "45786230487560q"; // body['SessionID'] = "45786230487560q";
@ -359,7 +359,8 @@ class ApiClientImp implements ApiClient {
onFailure( onFailure(
parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
statusCode, statusCode,
failureType: ServerFailure("Error While Fetching data"), // failureType: ServerFailure("Error While Fetching data"),
failureType: ServerFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']),
); );
logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
} }

@ -233,7 +233,8 @@ class ApiConsts {
static String getAiOverViewLabOrder = "Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API"; static String getAiOverViewLabOrder = "Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API";
// ************ static values for Api **************** // ************ static values for Api ****************
static final double appVersionID = 20.2; static final double appVersionID = 20.5;
// static final double appVersionID = 50.7; // static final double appVersionID = 50.7;
static final int appChannelId = 3; static final int appChannelId = 3;
static final String appIpAddress = "10.20.10.20"; static final String appIpAddress = "10.20.10.20";
@ -777,8 +778,7 @@ var GET_CUSTOMER_INFO = "VerifyCustomer";
//Pharmacy //Pharmacy
var GET_PHARMACY_CATEGORISE = var GET_PHARMACY_CATEGORISE = 'categories?fields=id,name,namen,description,image,localized_names,display_order,parent_category_id,is_leaf&parent_id=0';
'categories?fields=id,name,namen,description,image,localized_names,display_order,parent_category_id,is_leaf&parent_id=0';
var GET_OFFERS_CATEGORISE = 'discountcategories'; var GET_OFFERS_CATEGORISE = 'discountcategories';
var GET_OFFERS_PRODUCTS = 'offerproducts/'; var GET_OFFERS_PRODUCTS = 'offerproducts/';
var GET_CATEGORISE_PARENT = 'categories?fields=id,name,namen,description,image,localized_names,display_order,parent_category_id,is_leaf&parent_id='; var GET_CATEGORISE_PARENT = 'categories?fields=id,name,namen,description,image,localized_names,display_order,parent_category_id,is_leaf&parent_id=';
@ -920,6 +920,10 @@ const DASHBOARD = 'Services/Patients.svc/REST/PatientDashboard';
const SEND_PATIENT_IMMEDIATE_UPDATE_INSURANCE_REQUEST = 'Services/OUTPs.svc/REST/PatientCompanyUpdate'; const SEND_PATIENT_IMMEDIATE_UPDATE_INSURANCE_REQUEST = 'Services/OUTPs.svc/REST/PatientCompanyUpdate';
const PROFILE_SETTING = 'Services/Patients.svc/REST/GetPateintInfoForUpdate';
const SAVE_SETTING = 'Services/Patients.svc/REST/UpdatePateintInfo';
class ApiKeyConstants { class ApiKeyConstants {
static final String googleMapsApiKey = 'AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng'; static final String googleMapsApiKey = 'AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng';
} }

@ -17,6 +17,8 @@ class AppAssets {
static const String email = '$svgBasePath/email.svg'; static const String email = '$svgBasePath/email.svg';
static const String globe = '$svgBasePath/globe.svg'; static const String globe = '$svgBasePath/globe.svg';
static const String globeOther = '$svgBasePath/globe_other.svg'; static const String globeOther = '$svgBasePath/globe_other.svg';
// static const String globeOther = '$svgBasePath/globe_other.svg';
static const String cancel = '$svgBasePath/cancel.svg'; static const String cancel = '$svgBasePath/cancel.svg';
static const String bell = '$svgBasePath/bell.svg'; static const String bell = '$svgBasePath/bell.svg';
static const String login1 = '$svgBasePath/login1.svg'; static const String login1 = '$svgBasePath/login1.svg';
@ -333,6 +335,8 @@ class AppAssets {
static const String changeLanguageHomePageIcon = '$svgBasePath/change_language_home_page.svg'; static const String changeLanguageHomePageIcon = '$svgBasePath/change_language_home_page.svg';
static const String aiOverView = '$svgBasePath/ai_overview.svg'; static const String aiOverView = '$svgBasePath/ai_overview.svg';
static const String darkModeIcon = '$svgBasePath/dark_mode_icon.svg'; static const String darkModeIcon = '$svgBasePath/dark_mode_icon.svg';
static const String biometricLockIcon = '$svgBasePath/biometric_lock_icon.svg';
static const String imageIcon = '$svgBasePath/image_icon.svg';
// PNGS // // PNGS //
static const String hmgLogo = '$pngBasePath/hmg_logo.png'; static const String hmgLogo = '$pngBasePath/hmg_logo.png';

@ -50,6 +50,7 @@ import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart'; import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart'; import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart'; import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_repo.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart'; import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
import 'package:hmg_patient_app_new/features/qr_parking/qr_parking_repo.dart'; import 'package:hmg_patient_app_new/features/qr_parking/qr_parking_repo.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart'; import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart';
@ -172,6 +173,7 @@ class AppDependencies {
getIt.registerLazySingleton<NotificationsRepo>(() => NotificationsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt())); getIt.registerLazySingleton<NotificationsRepo>(() => NotificationsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<AskDoctorRepo>(() => AskDoctorRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt())); getIt.registerLazySingleton<AskDoctorRepo>(() => AskDoctorRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<ServicesPriceListRepo>(() => ServicesPriceListRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt())); getIt.registerLazySingleton<ServicesPriceListRepo>(() => ServicesPriceListRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<ProfileSettingsRepo>(() => ProfileSettingsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
// ViewModels // ViewModels
// Global/shared VMs LazySingleton // Global/shared VMs LazySingleton
@ -224,7 +226,11 @@ class AppDependencies {
authenticationRepo: getIt(), cacheService: getIt(), navigationService: getIt(), dialogService: getIt(), appState: getIt(), errorHandlerService: getIt(), localAuthService: getIt()), authenticationRepo: getIt(), cacheService: getIt(), navigationService: getIt(), dialogService: getIt(), appState: getIt(), errorHandlerService: getIt(), localAuthService: getIt()),
); );
getIt.registerLazySingleton<ProfileSettingsViewModel>(() => ProfileSettingsViewModel(cacheService: getIt<CacheService>())); getIt.registerLazySingleton<ProfileSettingsViewModel>(() => ProfileSettingsViewModel(
cacheService: getIt<CacheService>(),
profileSettingsRepo: getIt<ProfileSettingsRepo>(),
errorHandlerService: getIt<ErrorHandlerService>(),
));
getIt.registerLazySingleton<DateRangeSelectorRangeViewModel>(() => DateRangeSelectorRangeViewModel()); getIt.registerLazySingleton<DateRangeSelectorRangeViewModel>(() => DateRangeSelectorRangeViewModel());

@ -94,7 +94,27 @@ class LocationUtils {
permissionGranted = await Geolocator.requestPermission(); permissionGranted = await Geolocator.requestPermission();
if (permissionGranted != LocationPermission.whileInUse && permissionGranted != LocationPermission.always) { if (permissionGranted != LocationPermission.whileInUse && permissionGranted != LocationPermission.always) {
appState.resetLocation(); appState.resetLocation();
onFailure?.call(); if (onFailure == null && isShowConfirmDialog) {
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
navigationService.navigatorKey.currentContext!,
child: Utils.getWarningWidget(
loadingText: "Please grant location permission from app settings to see better results",
isShowActionButtons: true,
onCancelTap: () {
navigationService.pop();
},
onConfirmTap: () async {
navigationService.pop();
openAppSettings();
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
} else {
onFailure?.call();
}
return; return;
} }
} else if (permissionGranted == LocationPermission.deniedForever) { } else if (permissionGranted == LocationPermission.deniedForever) {

@ -1,9 +1,16 @@
import 'dart:async'; import 'dart:async';
import 'package:device_calendar_plus/device_calendar_plus.dart'; import 'package:device_calendar_plus/device_calendar_plus.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:jiffy/jiffy.dart' show Jiffy; import 'package:jiffy/jiffy.dart' show Jiffy;
import 'package:manage_calendar_events/manage_calendar_events.dart' hide Calendar; import 'package:manage_calendar_events/manage_calendar_events.dart' hide Calendar;
import 'package:permission_handler/permission_handler.dart';
class CalenderUtilsNew { class CalenderUtilsNew {
final DeviceCalendar calender = DeviceCalendar.instance; final DeviceCalendar calender = DeviceCalendar.instance;
@ -17,7 +24,26 @@ class CalenderUtilsNew {
Future<void> getCalenders() async { Future<void> getCalenders() async {
CalendarPermissionStatus result = await DeviceCalendar.instance.hasPermissions(); CalendarPermissionStatus result = await DeviceCalendar.instance.hasPermissions();
if (result != CalendarPermissionStatus.granted) await DeviceCalendar.instance.requestPermissions(); if (result != CalendarPermissionStatus.granted) {
// await DeviceCalendar.instance.requestPermissions();
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!),
GetIt.instance<NavigationService>().navigatorKey.currentContext!,
child: Utils.getWarningWidget(
loadingText: LocaleKeys.calendarPermissionAlert.tr(),
isShowActionButtons: true,
onCancelTap: () {
GetIt.instance<NavigationService>().pop();
},
onConfirmTap: () async {
GetIt.instance<NavigationService>().pop();
openAppSettings();
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
var calenders = await calender.listCalendars(); var calenders = await calender.listCalendars();
calenders.forEach((calender) { calenders.forEach((calender) {
if (!calender.readOnly) { if (!calender.readOnly) {

@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart'; import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart';
@ -32,6 +33,13 @@ class ValidationUtils {
isCorrectID = false; isCorrectID = false;
} }
if(nationalId!.length == 10) {
if (Utils.isSAUDIIDValid(nationalId!) == false) {
_dialogService.showExceptionBottomSheet(message: LocaleKeys.enterValidNationalId.tr(), onOkPressed: onOkPress);
isCorrectID = false;
}
}
if (nationalId != null && nationalId.isNotEmpty && selectedCountry != null) { if (nationalId != null && nationalId.isNotEmpty && selectedCountry != null) {
if (selectedCountry == CountryEnum.saudiArabia) { if (selectedCountry == CountryEnum.saudiArabia) {
if (!validateIqama(nationalId)) { if (!validateIqama(nationalId)) {

@ -258,12 +258,12 @@ extension EmailValidator on String {
style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 17.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'), style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 17.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
); );
Widget toText18({Color? color, FontWeight? weight, bool isBold = false, bool isCenter = false, int? maxlines, TextOverflow? textOverflow}) => Text( Widget toText18({Color? color, FontWeight? weight, bool isBold = false, bool isCenter = false, int? maxlines, TextOverflow? textOverflow, bool isEnglishOnly = false,}) => Text(
maxLines: maxlines, maxLines: maxlines,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
this, this,
overflow: textOverflow, overflow: textOverflow,
style: TextStyle(fontSize: 18.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4), style: TextStyle(fontSize: 18.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4, fontFamily: (isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),),
); );
Widget toText19({Color? color, bool isBold = false}) => Text( Widget toText19({Color? color, bool isBold = false}) => Text(
@ -320,9 +320,9 @@ extension EmailValidator on String {
height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.f, letterSpacing: -1, fontFamily: isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins', fontWeight: isBold ? FontWeight.bold : weight ?? FontWeight.normal), height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.f, letterSpacing: -1, fontFamily: isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins', fontWeight: isBold ? FontWeight.bold : weight ?? FontWeight.normal),
); );
Widget toText44({Color? color, bool isBold = false}) => Text( Widget toText44({Color? color, bool isBold = false, bool isEnglishOnly = false,}) => Text(
this, this,
style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: (isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),),
); );
Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) { Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) {

@ -1,7 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/extensions/int_extensions.dart'; import 'package:hmg_patient_app_new/extensions/int_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:shimmer/shimmer.dart'; import 'package:shimmer/shimmer.dart';
import 'package:sizer/sizer.dart'; import 'package:sizer/sizer.dart';
@ -152,6 +154,7 @@ extension SmoothContainerExtension on ShapeBorder {
BorderSide? side, BorderSide? side,
BorderRadius? customBorder, BorderRadius? customBorder,
bool hasShadow = false, bool hasShadow = false,
bool hasDenseShadow = false,
}) { }) {
final bgColor = backgroundColor ?? color; final bgColor = backgroundColor ?? color;
return ShapeDecoration( return ShapeDecoration(
@ -161,17 +164,17 @@ extension SmoothContainerExtension on ShapeBorder {
smoothness: 1, smoothness: 1,
side: side ?? BorderSide.none, side: side ?? BorderSide.none,
), ),
shadows: shadows: hasShadow
// hasShadow ? [
// ? [ BoxShadow(
// BoxShadow( // color: hasDenseShadow ? const Color(0xff000000).withOpacity(.06) : const Color(0xff000000).withOpacity(.1),
// color: const Color(0xff000000).withOpacity(.05), color: getIt.get<ProfileSettingsViewModel>().isDarkMode ? Color(0xff3a3a3a).withOpacity(1.0) : Color(0xffE1E1E1).withOpacity(1.0),
// blurRadius: 32, blurRadius: 0,
// offset: const Offset(0, 0), spreadRadius: 0,
// ) offset: const Offset(1, 0),
// ] )
// : ]
[], : [],
); );
} }
} }

@ -47,7 +47,7 @@ class AskDoctorRepoImp implements AskDoctorRepo {
try { try {
final list = response['PatientDoctorAppointmentResultList']; final list = response['PatientDoctorAppointmentResultList'];
final clinicsList = list.map((item) => AskDoctorAppointmentHistoryList.fromJson(item as Map<String, dynamic>)).toList().cast<AskDoctorAppointmentHistoryList>(); final clinicsList = list != null ? list.map((item) => AskDoctorAppointmentHistoryList.fromJson(item as Map<String, dynamic>)).toList().cast<AskDoctorAppointmentHistoryList>() : [];
apiResponse = GenericApiModel<List<AskDoctorAppointmentHistoryList>>( apiResponse = GenericApiModel<List<AskDoctorAppointmentHistoryList>>(
messageStatus: messageStatus, messageStatus: messageStatus,

@ -143,7 +143,7 @@ class AskDoctorAppointmentHistoryList {
noOfPatientsRate = json['NoOfPatientsRate']; noOfPatientsRate = json['NoOfPatientsRate'];
projectName = json['ProjectName']; projectName = json['ProjectName'];
qR = json['QR']; qR = json['QR'];
speciality = json['Speciality'].cast<String>(); // speciality = json['Speciality'].cast<String>();
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {

@ -28,6 +28,7 @@ import 'package:hmg_patient_app_new/features/authentication/models/resp_models/a
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_user_staus_nhic_response_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_user_staus_nhic_response_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
@ -619,11 +620,12 @@ class AuthenticationViewModel extends ChangeNotifier {
} else { } else {
activation.list!.first.isParentUser = true; activation.list!.first.isParentUser = true;
} }
activation.list!.first.bloodGroup = activation.patientBlodType; activation.list!.first.bloodGroup = activation.patientBloodType;
activation.list!.first.zipCode = selectedCountrySignup == CountryEnum.others ? '0' : selectedCountrySignup.countryCode; activation.list!.first.zipCode = selectedCountrySignup == CountryEnum.others ? '0' : selectedCountrySignup.countryCode;
_appState.setAuthenticatedUser(activation.list!.first); _appState.setAuthenticatedUser(activation.list!.first);
_appState.setPrivilegeModelList(activation.list!.first.listPrivilege!); _appState.setPrivilegeModelList(activation.list!.first.listPrivilege!);
_appState.setUserBloodGroup = activation.patientBlodType ?? "N/A"; // _appState.setUserBloodGroup = activation.patientBlodType ?? "N/A";
_appState.setUserBloodGroup = activation.patientBloodType ?? "N/A";
} }
// _appState.setUserBloodGroup = (activation.patientBlodType ?? ""); // _appState.setUserBloodGroup = (activation.patientBlodType ?? "");
_appState.setAppAuthToken = activation.authenticationTokenId; _appState.setAppAuthToken = activation.authenticationTokenId;
@ -646,6 +648,7 @@ class AuthenticationViewModel extends ChangeNotifier {
await clearDefaultInputValues(); await clearDefaultInputValues();
myAppointmentsVM.setIsAppointmentDataToBeLoaded(true); myAppointmentsVM.setIsAppointmentDataToBeLoaded(true);
getIt.get<InsuranceViewModel>().setIsInsuranceDataToBeLoaded(true); getIt.get<InsuranceViewModel>().setIsInsuranceDataToBeLoaded(true);
getIt.get<HmgServicesViewModel>().setHasVitalSignDataLoaded(false);
if (isUserAgreedBefore) { if (isUserAgreedBefore) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
navigateToHomeScreen(); navigateToHomeScreen();

@ -20,6 +20,8 @@ import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:sms_otp_auto_verify/sms_otp_auto_verify.dart'; import 'package:sms_otp_auto_verify/sms_otp_auto_verify.dart';
import 'dart:ui' as ui;
typedef OnDone = void Function(String text); typedef OnDone = void Function(String text);
class ProvidedPinBoxTextAnimation { class ProvidedPinBoxTextAnimation {
@ -564,23 +566,27 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
SizedBox(height: 16.h), SizedBox(height: 16.h),
Center( Center(
child: OTPWidget( child: Directionality(
maxLength: _otpLength, textDirection: ui.TextDirection.ltr,
controller: _otpController, child: OTPWidget(
pinBoxWidth: 70.h, maxLength: _otpLength,
pinBoxHeight: 100.h, controller: _otpController,
pinBoxRadius: 16, pinBoxWidth: 70.h,
pinBoxBorderWidth: 0, pinBoxHeight: 100.h,
pinBoxOuterPadding: EdgeInsets.symmetric(horizontal: 4.h), pinBoxRadius: 16,
defaultBorderColor: Colors.transparent, pinBoxBorderWidth: 0,
textBorderColor: Colors.transparent, pinBoxOuterPadding: EdgeInsets.symmetric(horizontal: 4.h),
pinBoxColor: AppColors.whiteColor, defaultBorderColor: Colors.transparent,
autoFocus: true, textBorderColor: Colors.transparent,
onTextChanged: _onOtpChanged, pinBoxColor: AppColors.whiteColor,
pinTextStyle: TextStyle( autoFocus: true,
fontSize: 40.f, onTextChanged: _onOtpChanged,
fontWeight: FontWeight.bold, pinTextStyle: TextStyle(
color: AppColors.whiteColor, fontSize: 40.f,
fontWeight: FontWeight.bold,
color: AppColors.whiteColor,
fontFamily: "Poppins"
),
), ),
), ),
), ),
@ -601,7 +607,7 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
children: [ children: [
LocaleKeys.resendIn.tr(context: context).toText16(color: AppColors.inputLabelTextColor), LocaleKeys.resendIn.tr(context: context).toText16(color: AppColors.inputLabelTextColor),
SizedBox(width: 2.h), SizedBox(width: 2.h),
' ($minutes:$seconds). '.toText16(color: AppColors.inputLabelTextColor) ' ($minutes:$seconds). '.toText16(color: AppColors.inputLabelTextColor, isEnglishOnly: true)
], ],
); );
}, },

@ -49,6 +49,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
bool isDoctorSearchByNameStarted = false; bool isDoctorSearchByNameStarted = false;
bool isAppointmentNearestGateLoading = false; bool isAppointmentNearestGateLoading = false;
bool isLiveCareSelectedFromHomePage = false;
bool isLiveCareSchedule = false; bool isLiveCareSchedule = false;
bool isGetDocForHealthCal = false; bool isGetDocForHealthCal = false;
bool showSortFilterButtons = false; bool showSortFilterButtons = false;
@ -318,6 +319,11 @@ class BookAppointmentsViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
setIsLiveCareSelectedFromHomePage(bool isLiveCareSelectedFromHomePage) {
this.isLiveCareSelectedFromHomePage = isLiveCareSelectedFromHomePage;
notifyListeners();
}
setIsWaitingAppointmentSelected(bool isWaitingAppointmentSelected) { setIsWaitingAppointmentSelected(bool isWaitingAppointmentSelected) {
this.isWaitingAppointmentSelected = isWaitingAppointmentSelected; this.isWaitingAppointmentSelected = isWaitingAppointmentSelected;
notifyListeners(); notifyListeners();
@ -423,9 +429,25 @@ class BookAppointmentsViewModel extends ChangeNotifier {
calculationID = null; calculationID = null;
isGetDocForHealthCal = false; isGetDocForHealthCal = false;
selectedTabIndex = index; selectedTabIndex = index;
checkLiveCareSymptomCheckerStatus();
notifyListeners(); notifyListeners();
} }
bool checkLiveCareSymptomCheckerStatus() {
bool isAllowed = false;
if (selectedTabIndex == 1) {
if (_appState.isAuthenticated) {
isAllowed = true;
} else {
isAllowed = false;
}
} else {
isAllowed = true;
}
return isAllowed;
}
/// this function will decide which clinic api to be called /// this function will decide which clinic api to be called
/// either api for region flow or the select clinic api /// either api for region flow or the select clinic api
Future<void> getClinics() async { Future<void> getClinics() async {
@ -536,6 +558,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
clearSearchFilters(); clearSearchFilters();
getFiltersFromDoctorList(); getFiltersFromDoctorList();
_groupDoctorsList(); _groupDoctorsList();
setIsNearestAppointmentSelected(true);
notifyListeners(); notifyListeners();
if (onSuccess != null) { if (onSuccess != null) {
onSuccess(apiResponse); onSuccess(apiResponse);

@ -12,6 +12,7 @@ import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_p
import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_status_coc_response_model.dart'; import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_status_coc_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:permission_handler/permission_handler.dart';
class ContactUsViewModel extends ChangeNotifier { class ContactUsViewModel extends ChangeNotifier {
ContactUsRepo contactUsRepo; ContactUsRepo contactUsRepo;
@ -22,6 +23,7 @@ class ContactUsViewModel extends ChangeNotifier {
bool isHMGHospitalsListSelected = true; bool isHMGHospitalsListSelected = true;
bool isLiveChatProjectsListLoading = false; bool isLiveChatProjectsListLoading = false;
bool isSendFeedbackTabSelected = true; bool isSendFeedbackTabSelected = true;
bool hasLocationEnabled = false;
List<GetHMGLocationsModel> hmgHospitalsLocationsList = []; List<GetHMGLocationsModel> hmgHospitalsLocationsList = [];
List<GetHMGLocationsModel> hmgPharmacyLocationsList = []; List<GetHMGLocationsModel> hmgPharmacyLocationsList = [];
@ -52,11 +54,12 @@ class ContactUsViewModel extends ChangeNotifier {
ContactUsViewModel({required this.contactUsRepo, required this.errorHandlerService, required this.appState}); ContactUsViewModel({required this.contactUsRepo, required this.errorHandlerService, required this.appState});
initContactUsViewModel() { initContactUsViewModel() async {
isHMGLocationsListLoading = true; isHMGLocationsListLoading = true;
isHMGHospitalsListSelected = true; isHMGHospitalsListSelected = true;
isLiveChatProjectsListLoading = true; isLiveChatProjectsListLoading = true;
isCOCItemsListLoading = true; isCOCItemsListLoading = true;
hasLocationEnabled = false;
hmgHospitalsLocationsList.clear(); hmgHospitalsLocationsList.clear();
hmgPharmacyLocationsList.clear(); hmgPharmacyLocationsList.clear();
liveChatProjectsList.clear(); liveChatProjectsList.clear();
@ -65,6 +68,18 @@ class ContactUsViewModel extends ChangeNotifier {
selectedFeedbackType = FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد'); selectedFeedbackType = FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد');
setPatientFeedbackSelectedAppointment(null); setPatientFeedbackSelectedAppointment(null);
getHMGLocations(); getHMGLocations();
if (await Permission.location.isGranted) {
setHasLocationEnabled(true);
} else {
setHasLocationEnabled(false);
}
notifyListeners();
}
setHasLocationEnabled(bool hasLocationEnabled) {
this.hasLocationEnabled = hasLocationEnabled;
notifyListeners(); notifyListeners();
} }
@ -128,6 +143,8 @@ class ContactUsViewModel extends ChangeNotifier {
hmgPharmacyLocationsList.add(location); hmgPharmacyLocationsList.add(location);
} }
} }
sortHMGLocations(hasLocationEnabled);
isHMGLocationsListLoading = false; isHMGLocationsListLoading = false;
notifyListeners(); notifyListeners();
if (onSuccess != null) { if (onSuccess != null) {
@ -138,6 +155,17 @@ class ContactUsViewModel extends ChangeNotifier {
); );
} }
sortHMGLocations(bool isByLocation) {
if (isByLocation) {
hmgHospitalsLocationsList.sort((a, b) => a.distanceInKilometers.compareTo(b.distanceInKilometers));
hmgPharmacyLocationsList.sort((a, b) => a.distanceInKilometers.compareTo(b.distanceInKilometers));
} else {
hmgHospitalsLocationsList.sort((a, b) => a.locationName!.compareTo(b.locationName!));
hmgPharmacyLocationsList.sort((a, b) => a.locationName!.compareTo(b.locationName!));
}
notifyListeners();
}
Future<void> getLiveChatProjectsList({Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getLiveChatProjectsList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
isLiveChatProjectsListLoading = true; isLiveChatProjectsListLoading = true;
liveChatProjectsList.clear(); liveChatProjectsList.clear();

@ -3,6 +3,7 @@ import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/models/patient_advance_balance_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart';
@ -40,18 +41,22 @@ class HabibWalletRepoImp implements HabibWalletRepo {
}, },
onSuccess: (response, statusCode, {messageStatus, errorMessage}) { onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try { try {
// final list = response['ListPLO']; final list = response['List_PatientAdvanceBalanceAmount'];
// if (list == null || list.isEmpty) { // if (list == null || list.isEmpty) {
// throw Exception("lab list is empty"); // throw Exception("lab list is empty");
// } // }
// final labOrders = list.map((item) => PatientLabOrdersResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<PatientLabOrdersResponseModel>(); final List<PatientAdvanceBalanceResponseModel> balanceAmountList = list.map((item) => PatientAdvanceBalanceResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<PatientAdvanceBalanceResponseModel>();
for (var element in balanceAmountList) {
element.totalAmount = response['TotalAdvanceBalanceAmount'];
}
apiResponse = GenericApiModel<dynamic>( apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus, messageStatus: messageStatus,
statusCode: statusCode, statusCode: statusCode,
errorMessage: null, errorMessage: null,
data: response["TotalAdvanceBalanceAmount"], data: balanceAmountList,
); );
} catch (e) { } catch (e) {
failure = DataParsingFailure(e.toString()); failure = DataParsingFailure(e.toString());

@ -1,6 +1,7 @@
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:hmg_patient_app_new/features/habib_wallet/habib_wallet_repo.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_repo.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/models/patient_advance_balance_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart';
@ -30,6 +31,8 @@ class HabibWalletViewModel extends ChangeNotifier {
num selectedRechargeType = 1; num selectedRechargeType = 1;
List<PatientAdvanceBalanceResponseModel> habibWalletBalanceList = [];
HabibWalletViewModel({required this.habibWalletRepo, required this.errorHandlerService}); HabibWalletViewModel({required this.habibWalletRepo, required this.errorHandlerService});
initHabibWalletProvider() { initHabibWalletProvider() {
@ -39,6 +42,7 @@ class HabibWalletViewModel extends ChangeNotifier {
walletRechargeAmount = 0; walletRechargeAmount = 0;
selectedRechargeType = 1; selectedRechargeType = 1;
advancePaymentHospitals.clear(); advancePaymentHospitals.clear();
habibWalletBalanceList.clear();
selectedHospital = null; selectedHospital = null;
fileNumber = ''; fileNumber = '';
depositorName = ''; depositorName = '';
@ -103,7 +107,13 @@ class HabibWalletViewModel extends ChangeNotifier {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
habibWalletAmount = apiResponse.data!; habibWalletBalanceList = apiResponse.data;
habibWalletAmount = habibWalletBalanceList.first.totalAmount ?? 0.0;
habibWalletBalanceList.sort((a, b) => b.patientAdvanceBalanceAmount!.compareTo(a.patientAdvanceBalanceAmount!));
habibWalletBalanceList.removeWhere((element) => element.patientAdvanceBalanceAmount == 0);
isWalletAmountLoading = false; isWalletAmountLoading = false;
notifyListeners(); notifyListeners();
if (onSuccess != null) { if (onSuccess != null) {

@ -0,0 +1,27 @@
class PatientAdvanceBalanceResponseModel {
num? distanceInKilometers;
num? patientAdvanceBalanceAmount;
String? projectDescription;
int? projectID;
num? totalAmount;
PatientAdvanceBalanceResponseModel({this.distanceInKilometers, this.patientAdvanceBalanceAmount, this.projectDescription, this.projectID, this.totalAmount});
PatientAdvanceBalanceResponseModel.fromJson(Map<String, dynamic> json) {
distanceInKilometers = json['DistanceInKilometers'];
patientAdvanceBalanceAmount = json['PatientAdvanceBalanceAmount'];
projectDescription = json['ProjectDescription'];
projectID = json['ProjectID'];
totalAmount = json['TotalAmount'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data['DistanceInKilometers'] = distanceInKilometers;
data['PatientAdvanceBalanceAmount'] = patientAdvanceBalanceAmount;
data['ProjectDescription'] = projectDescription;
data['ProjectID'] = projectID;
data['TotalAmount'] = totalAmount;
return data;
}
}

@ -85,6 +85,11 @@ class HmgServicesViewModel extends ChangeNotifier {
List<Covid19GetTestProceduresResp> covidTestProcedureList = []; List<Covid19GetTestProceduresResp> covidTestProcedureList = [];
Covid19GetPaymentInfo? covidPaymentInfo; Covid19GetPaymentInfo? covidPaymentInfo;
void setHasVitalSignDataLoaded(bool hasVitalSignDataLoaded) {
this.hasVitalSignDataLoaded = hasVitalSignDataLoaded;
notifyListeners();
}
Future<void> getOrdersList() async {} Future<void> getOrdersList() async {}
// HHC multiple services selection // HHC multiple services selection

@ -13,6 +13,7 @@ class InsuranceViewModel extends ChangeNotifier {
bool isInsuranceHistoryLoading = false; bool isInsuranceHistoryLoading = false;
bool isInsuranceDetailsLoading = false; bool isInsuranceDetailsLoading = false;
bool isInsuranceUpdateDetailsLoading = false; bool isInsuranceUpdateDetailsLoading = false;
bool isInsuranceExpiryBannerShown = false;
bool isInsuranceDataToBeLoaded = true; bool isInsuranceDataToBeLoaded = true;
bool isInsuranceApprovalsLoading = false; bool isInsuranceApprovalsLoading = false;
@ -49,6 +50,11 @@ class InsuranceViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
setIsInsuranceExpiryBannerShown(bool isInsuranceExpiryBannerShown) {
this.isInsuranceExpiryBannerShown = isInsuranceExpiryBannerShown;
notifyListeners();
}
setIsInsuranceHistoryLoading(bool val) { setIsInsuranceHistoryLoading(bool val) {
isInsuranceHistoryLoading = val; isInsuranceHistoryLoading = val;
notifyListeners(); notifyListeners();
@ -88,9 +94,10 @@ class InsuranceViewModel extends ChangeNotifier {
(failure) async { (failure) async {
debugPrint("InsuranceViewModel: API call failed - ${failure.toString()}"); debugPrint("InsuranceViewModel: API call failed - ${failure.toString()}");
isInsuranceLoading = false; isInsuranceLoading = false;
isInsuranceDataToBeLoaded = false; isInsuranceDataToBeLoaded = true;
isInsuranceExpired = false; isInsuranceExpired = false;
isInsuranceActive = false; isInsuranceActive = false;
isInsuranceExpiryBannerShown = false;
notifyListeners(); notifyListeners();
}, },
(apiResponse) { (apiResponse) {
@ -111,6 +118,8 @@ class InsuranceViewModel extends ChangeNotifier {
debugPrint("InsuranceViewModel: Insurance card expired: $isInsuranceExpired"); debugPrint("InsuranceViewModel: Insurance card expired: $isInsuranceExpired");
} }
isInsuranceExpiryBannerShown = isInsuranceExpired;
isInsuranceActive = patientInsuranceList.first.isActive ?? false; isInsuranceActive = patientInsuranceList.first.isActive ?? false;
// isInsuranceActive = true; // isInsuranceActive = true;
@ -148,6 +157,9 @@ class InsuranceViewModel extends ChangeNotifier {
} }
Future<void> getPatientInsuranceDetailsForUpdate(String patientID, String identificationNo, {Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientInsuranceDetailsForUpdate(String patientID, String identificationNo, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
patientInsuranceUpdateResponseModel = null;
notifyListeners();
final result = await insuranceRepo.getPatientInsuranceDetailsForUpdate(patientId: patientID, identificationNo: identificationNo); final result = await insuranceRepo.getPatientInsuranceDetailsForUpdate(patientId: patientID, identificationNo: identificationNo);
result.fold( result.fold(
@ -214,7 +226,7 @@ class InsuranceViewModel extends ChangeNotifier {
(failure) async { (failure) async {
notifyListeners(); notifyListeners();
if (onError != null) { if (onError != null) {
onError(failure.toString()); onError(failure.message.toString());
} }
}, },
(apiResponse) { (apiResponse) {

@ -106,6 +106,11 @@ class LabViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
closeAILabResultAnalysis() {
labOrderResponseByAi = null;
notifyListeners();
}
void setIsSortByClinic(bool value) { void setIsSortByClinic(bool value) {
isSortByClinic = value; isSortByClinic = value;
patientLabOrdersViewList = isSortByClinic ? patientLabOrdersByClinic : patientLabOrdersByHospital; patientLabOrdersViewList = isSortByClinic ? patientLabOrdersByClinic : patientLabOrdersByHospital;
@ -144,21 +149,26 @@ class LabViewModel extends ChangeNotifier {
isLabOrdersLoading = false; isLabOrdersLoading = false;
isLabResultsLoading = false; isLabResultsLoading = false;
// --- Build groups by clinic and by hospital (projectName) ---
final clinicMap = <String, List<PatientLabOrdersResponseModel>>{};
final hospitalMap = <String, List<PatientLabOrdersResponseModel>>{};
for (var order in patientLabOrders) { for (var order in patientLabOrders) {
final clinicKey = (order.clinicDescription ?? 'Unknown').trim(); order.testDetails!.sort((a, b) => a.description!.compareTo(b.description!));
clinicMap.putIfAbsent(clinicKey, () => []).add(order);
final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim();
hospitalMap.putIfAbsent(hospitalKey, () => []).add(order);
} }
patientLabOrdersByClinic = clinicMap.values.toList(); // --- Build groups by clinic and by hospital (projectName) ---
patientLabOrdersByHospital = hospitalMap.values.toList(); // final clinicMap = <String, List<PatientLabOrdersResponseModel>>{};
patientLabOrdersViewList = isSortByClinic ? patientLabOrdersByClinic : patientLabOrdersByHospital; // final hospitalMap = <String, List<PatientLabOrdersResponseModel>>{};
//
// for (var order in patientLabOrders) {
// final clinicKey = (order.clinicDescription ?? 'Unknown').trim();
// clinicMap.putIfAbsent(clinicKey, () => []).add(order);
//
// final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim();
// hospitalMap.putIfAbsent(hospitalKey, () => []).add(order);
// }
// patientLabOrdersByClinic = clinicMap.values.toList();
// patientLabOrdersByHospital = hospitalMap.values.toList();
// patientLabOrdersViewList = isSortByClinic ? patientLabOrdersByClinic : patientLabOrdersByHospital;
// patientLabOrdersViewList = patientLabOrdersByClinic;
filterSuggestions(); filterSuggestions();
getUniqueTestDescription(); getUniqueTestDescription();

@ -634,6 +634,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
Future<void> getPatientMyDoctors({Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientMyDoctors({Function(dynamic)? onSuccess, Function(String)? onError}) async {
// if (!isAppointmentDataToBeLoaded) return; // if (!isAppointmentDataToBeLoaded) return;
isPatientMyDoctorsLoading = true; isPatientMyDoctorsLoading = true;
patientMyDoctorsList.clear();
notifyListeners(); notifyListeners();
final result = await myAppointmentsRepo.getPatientDoctorsList(); final result = await myAppointmentsRepo.getPatientDoctorsList();

@ -60,6 +60,9 @@ class MyInvoicesViewModel extends ChangeNotifier {
(failure) async { (failure) async {
isInvoiceDetailsLoading = false; isInvoiceDetailsLoading = false;
notifyListeners(); notifyListeners();
if (onError != null) {
onError(failure.message);
}
}, },
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {

@ -19,6 +19,7 @@ import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/map/map_utility_screen.dart'; import 'package:hmg_patient_app_new/widgets/map/map_utility_screen.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:permission_handler/permission_handler.dart';
class PrescriptionsViewModel extends ChangeNotifier { class PrescriptionsViewModel extends ChangeNotifier {
bool isPrescriptionsOrdersLoading = false; bool isPrescriptionsOrdersLoading = false;
@ -68,9 +69,9 @@ class PrescriptionsViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<bool> checkIfReminderExistForPrescription(int index) async {
checkIfReminderExistForPrescription(int index) async {
prescriptionDetailsList[index].hasReminder = await CalenderUtilsNew.instance.checkIfEventExist(prescriptionDetailsList[index].itemID?.toString() ?? ""); prescriptionDetailsList[index].hasReminder = await CalenderUtilsNew.instance.checkIfEventExist(prescriptionDetailsList[index].itemID?.toString() ?? "");
return prescriptionDetailsList[index].hasReminder ?? false;
} }
setPrescriptionsDetailsLoading() { setPrescriptionsDetailsLoading() {
@ -157,14 +158,16 @@ class PrescriptionsViewModel extends ChangeNotifier {
(failure) async { (failure) async {
onError!(failure.message); onError!(failure.message);
}, },
(apiResponse) { (apiResponse) async {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
prescriptionDetailsList = apiResponse.data!; prescriptionDetailsList = apiResponse.data!;
prescriptionDetailsList.forEach((element) async { if (await Permission.calendarFullAccess.isGranted && await Permission.calendarWriteOnly.isGranted) {
await checkIfReminderExistForPrescription(prescriptionDetailsList.indexOf(element)); prescriptionDetailsList.forEach((element) async {
}); await checkIfReminderExistForPrescription(prescriptionDetailsList.indexOf(element));
});
}
isPrescriptionsDetailsLoading = false; isPrescriptionsDetailsLoading = false;
notifyListeners(); notifyListeners();
if (onSuccess != null) { if (onSuccess != null) {

@ -0,0 +1,100 @@
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class ProfileSettingsRepo {
/// Updates general patient info (name, phone, etc.).
Future<Either<Failure, GenericApiModel<dynamic>>> updatePatientInfo({
required Map<String, dynamic> patientInfo,
});
/// Deactivates (deletes) the patient's account.
Future<Either<Failure, GenericApiModel<dynamic>>> deactivateAccount();
}
class ProfileSettingsRepoImp implements ProfileSettingsRepo {
final ApiClient apiClient;
final LoggerService loggerService;
ProfileSettingsRepoImp({
required this.loggerService,
required this.apiClient,
});
@override
Future<Either<Failure, GenericApiModel<dynamic>>> updatePatientInfo({
required Map<String, dynamic> patientInfo,
}) async {
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
SAVE_SETTING,
body: patientInfo,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<dynamic>>> deactivateAccount() async {
final Map<String, dynamic> body = {};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
// TODO: Replace with actual deactivate-account endpoint once available
'Services/Patients.svc/REST/Patient_DeactivateAccount',
body: body,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
}

@ -1,18 +1,42 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_repo.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart'; import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
class ProfileSettingsViewModel extends ChangeNotifier { class ProfileSettingsViewModel extends ChangeNotifier {
static const String _darkModeKey = 'is_dark_mode'; static const String _darkModeKey = 'is_dark_mode';
final CacheService _cacheService; final CacheService _cacheService;
final ProfileSettingsRepo profileSettingsRepo;
final ErrorHandlerService errorHandlerService;
// Dark-mode state
bool _isDarkMode = false; bool _isDarkMode = false;
bool get isDarkMode => _isDarkMode; bool get isDarkMode => _isDarkMode;
ProfileSettingsViewModel({required CacheService cacheService}) // Update email state
: _cacheService = cacheService; bool isUpdateEmailLoading = false;
bool isUpdateEmailSuccess = false;
String? updateEmailError;
// Update patient info state
bool isUpdatePatientInfoLoading = false;
bool isUpdatePatientInfoSuccess = false;
String? updatePatientInfoError;
// Deactivate account state
bool isDeactivateAccountLoading = false;
bool isDeactivateAccountSuccess = false;
String? deactivateAccountError;
ProfileSettingsViewModel({
required CacheService cacheService,
required this.profileSettingsRepo,
required this.errorHandlerService,
}) : _cacheService = cacheService;
// Dark mode
/// Call once at app startup (before the first frame) to restore the /// Call once at app startup (before the first frame) to restore the
/// persisted dark-mode preference. /// persisted dark-mode preference.
@ -30,6 +54,75 @@ class ProfileSettingsViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
// Update patient info
Future<void> updatePatientInfo({
required Map<String, dynamic> patientInfo,
Function(dynamic)? onSuccess,
Function(String)? onError,
}) async {
isUpdatePatientInfoLoading = true;
isUpdatePatientInfoSuccess = false;
updatePatientInfoError = null;
notifyListeners();
final result = await profileSettingsRepo.updatePatientInfo(patientInfo: patientInfo);
result.fold(
(failure) {
isUpdatePatientInfoLoading = false;
updatePatientInfoError = failure.message;
notifyListeners();
if (onError != null) {
onError(failure.message);
} else {
errorHandlerService.handleError(failure: failure);
}
},
(response) {
isUpdatePatientInfoLoading = false;
isUpdatePatientInfoSuccess = true;
notifyListeners();
onSuccess?.call(response.data);
},
);
}
// Deactivate account
Future<void> deactivateAccount({
Function(dynamic)? onSuccess,
Function(String)? onError,
}) async {
isDeactivateAccountLoading = true;
isDeactivateAccountSuccess = false;
deactivateAccountError = null;
notifyListeners();
final result = await profileSettingsRepo.deactivateAccount();
result.fold(
(failure) {
isDeactivateAccountLoading = false;
deactivateAccountError = failure.message;
notifyListeners();
if (onError != null) {
onError(failure.message);
} else {
errorHandlerService.handleError(failure: failure);
}
},
(response) {
isDeactivateAccountLoading = false;
isDeactivateAccountSuccess = true;
notifyListeners();
onSuccess?.call(response.data);
},
);
}
// Helpers
void notify() { void notify() {
notifyListeners(); notifyListeners();
} }

@ -68,17 +68,17 @@ class RadiologyViewModel extends ChangeNotifier {
filteredRadiologyOrders = List.from(patientRadiologyOrders); filteredRadiologyOrders = List.from(patientRadiologyOrders);
tempRadiologyOrders = [...patientRadiologyOrders]; tempRadiologyOrders = [...patientRadiologyOrders];
final clinicMap = <String, List<PatientRadiologyResponseModel>>{}; // final clinicMap = <String, List<PatientRadiologyResponseModel>>{};
final hospitalMap = <String, List<PatientRadiologyResponseModel>>{}; // final hospitalMap = <String, List<PatientRadiologyResponseModel>>{};
for (var order in patientRadiologyOrders) { // for (var order in patientRadiologyOrders) {
final clinicKey = (order.clinicDescription ?? 'Unknown').trim(); // final clinicKey = (order.clinicDescription ?? 'Unknown').trim();
clinicMap.putIfAbsent(clinicKey, () => []).add(order); // clinicMap.putIfAbsent(clinicKey, () => []).add(order);
final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim(); // final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim();
hospitalMap.putIfAbsent(hospitalKey, () => []).add(order); // hospitalMap.putIfAbsent(hospitalKey, () => []).add(order);
} // }
patientRadiologyOrdersByClinic = clinicMap.values.toList(); // patientRadiologyOrdersByClinic = clinicMap.values.toList();
patientRadiologyOrdersByHospital = hospitalMap.values.toList(); // patientRadiologyOrdersByHospital = hospitalMap.values.toList();
patientRadiologyOrdersViewList = isSortByClinic ? patientRadiologyOrdersByClinic : patientRadiologyOrdersByHospital; // patientRadiologyOrdersViewList = isSortByClinic ? patientRadiologyOrdersByClinic : patientRadiologyOrdersByHospital;
isRadiologyOrdersLoading = false; isRadiologyOrdersLoading = false;
filterSuggestions(); filterSuggestions();
@ -173,7 +173,7 @@ class RadiologyViewModel extends ChangeNotifier {
} }
filterSuggestions() { filterSuggestions() {
final List<String> labels = patientRadiologyOrders.map((detail) => detail.description).whereType<String>().toList(); final List<String> labels = patientRadiologyOrders.map((detail) => detail.procedureName.toString().trim()).whereType<String>().toList();
_radiologySuggestionsList = labels.toSet().toList(); _radiologySuggestionsList = labels.toSet().toList();
notifyListeners(); notifyListeners();
} }
@ -193,7 +193,7 @@ class RadiologyViewModel extends ChangeNotifier {
patientRadiologyOrdersByHospital = hospitalMap.values.toList(); patientRadiologyOrdersByHospital = hospitalMap.values.toList();
patientRadiologyOrdersViewList = isSortByClinic ? patientRadiologyOrdersByClinic : patientRadiologyOrdersByHospital; patientRadiologyOrdersViewList = isSortByClinic ? patientRadiologyOrdersByClinic : patientRadiologyOrdersByHospital;
} else { } else {
filteredRadiologyOrders = filteredRadiologyOrders.where((desc) => (desc.description ?? "").toLowerCase().contains(query.toLowerCase())).toList(); filteredRadiologyOrders = filteredRadiologyOrders.where((desc) => (desc.procedureName ?? "").toLowerCase().contains(query.toLowerCase())).toList();
final clinicMap = <String, List<PatientRadiologyResponseModel>>{}; final clinicMap = <String, List<PatientRadiologyResponseModel>>{};
final hospitalMap = <String, List<PatientRadiologyResponseModel>>{}; final hospitalMap = <String, List<PatientRadiologyResponseModel>>{};
@ -206,6 +206,8 @@ class RadiologyViewModel extends ChangeNotifier {
patientRadiologyOrdersByClinic = clinicMap.values.toList(); patientRadiologyOrdersByClinic = clinicMap.values.toList();
patientRadiologyOrdersByHospital = hospitalMap.values.toList(); patientRadiologyOrdersByHospital = hospitalMap.values.toList();
patientRadiologyOrdersViewList = isSortByClinic ? patientRadiologyOrdersByClinic : patientRadiologyOrdersByHospital; patientRadiologyOrdersViewList = isSortByClinic ? patientRadiologyOrdersByClinic : patientRadiologyOrdersByHospital;
patientRadiologyOrders = filteredRadiologyOrders;
} }
notifyListeners(); notifyListeners();
} }

@ -436,7 +436,6 @@ abstract class LocaleKeys {
static const serviceInformation = 'serviceInformation'; static const serviceInformation = 'serviceInformation';
static const homeHealthCare = 'homeHealthCare'; static const homeHealthCare = 'homeHealthCare';
static const noAppointmentAvailable = 'noAppointmentAvailable'; static const noAppointmentAvailable = 'noAppointmentAvailable';
static const homeHealthCareText = 'homeHealthCareText';
static const loginRegister = 'loginRegister'; static const loginRegister = 'loginRegister';
static const orderLog = 'orderLog'; static const orderLog = 'orderLog';
static const infoLab = 'infoLab'; static const infoLab = 'infoLab';
@ -746,6 +745,7 @@ abstract class LocaleKeys {
static const infoTodo = 'infoTodo'; static const infoTodo = 'infoTodo';
static const familyInfo = 'familyInfo'; static const familyInfo = 'familyInfo';
static const rrtdDetails = 'rrtdDetails'; static const rrtdDetails = 'rrtdDetails';
static const homeHealthCareText = 'homeHealthCareText';
static const onlineCheckInAgreement = 'onlineCheckInAgreement'; static const onlineCheckInAgreement = 'onlineCheckInAgreement';
static const infoEreferral = 'infoEreferral'; static const infoEreferral = 'infoEreferral';
static const erConsultation = 'erConsultation'; static const erConsultation = 'erConsultation';
@ -1577,5 +1577,14 @@ abstract class LocaleKeys {
static const timeFor = 'timeFor'; static const timeFor = 'timeFor';
static const hmgPolicies = 'hmgPolicies'; static const hmgPolicies = 'hmgPolicies';
static const darkMode = 'darkMode'; static const darkMode = 'darkMode';
static const generateAiAnalysisResult = 'generateAiAnalysisResult';
static const ratings = 'ratings';
static const hmgPharmacyText = 'hmgPharmacyText';
static const insuranceRequestSubmittedSuccessfully = 'insuranceRequestSubmittedSuccessfully';
static const updatingEmailAddress = 'updatingEmailAddress';
static const verifyInsurance = 'verifyInsurance';
static const tests = 'tests';
static const calendarPermissionAlert = 'calendarPermissionAlert';
static const sortByLocation = 'sortByLocation';
} }

@ -14,6 +14,7 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/ask_doctor/ask_doctor_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart';
import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart'; import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart';
@ -31,6 +32,8 @@ import 'package:hmg_patient_app_new/presentation/appointments/appointment_paymen
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_doctor_card.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_doctor_card.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/ask_doctor_request_type_select.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/ask_doctor_request_type_select.dart';
import 'package:hmg_patient_app_new/presentation/ask_doctor/ask_doctor_page.dart';
import 'package:hmg_patient_app_new/presentation/ask_doctor/doctor_response_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart';
import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart'; import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_detail_page.dart'; import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_detail_page.dart';
@ -69,12 +72,12 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
@override @override
void initState() { void initState() {
scheduleMicrotask(() async { scheduleMicrotask(() async {
CalenderUtilsNew calendarUtils = await CalenderUtilsNew.instance; if (!AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)) {
var doesExist = await calendarUtils.checkIfEventExist("${widget.patientAppointmentHistoryResponseModel.appointmentNo}"); CalenderUtilsNew calendarUtils = await CalenderUtilsNew.instance;
myAppointmentsViewModel.setAppointmentReminder(doesExist, widget.patientAppointmentHistoryResponseModel); var doesExist = await calendarUtils.checkIfEventExist("${widget.patientAppointmentHistoryResponseModel.appointmentNo}");
setState((){ myAppointmentsViewModel.setAppointmentReminder(doesExist, widget.patientAppointmentHistoryResponseModel);
setState(() {});
}); }
}); });
super.initState(); super.initState();
@ -556,6 +559,22 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
// ), // ),
// ); // );
}), }),
MedicalFileCard(
label: LocaleKeys.doctorResponses.tr(context: context),
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.ask_doctor_medical_file_icon,
isLargeText: true,
iconSize: 36.w,
).onPress(() {
getIt.get<AskDoctorViewModel>().initAskDoctorViewModel();
getIt.get<AskDoctorViewModel>().getDoctorResponses();
Navigator.of(context).push(
CustomPageRoute(
page: DoctorResponsePage(),
),
);
}),
], ],
), ),
// Column( // Column(
@ -839,8 +858,8 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
onPressed: () { onPressed: () {
openDoctorScheduleCalendar(); openDoctorScheduleCalendar();
}, },
backgroundColor: AppColors.successColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.successColor, borderColor: AppColors.primaryRedColor,
textColor: Colors.white, textColor: Colors.white,
fontSize: 16.f, fontSize: 16.f,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,

@ -93,8 +93,6 @@ class _MyDoctorsPageState extends State<MyDoctorsPage> {
borderRadius: 10, borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, height: 40.h,
), ),
SizedBox(width: 8.h), SizedBox(width: 8.h),
CustomButton( CustomButton(
@ -280,7 +278,7 @@ class _MyDoctorsPageState extends State<MyDoctorsPage> {
runSpacing: 4.h, runSpacing: 4.h,
children: [ children: [
AppCustomChipWidget( AppCustomChipWidget(
labelText: isSortByClinic ? (doctor?.clinicName ?? "") : (doctor?.projectName ?? ""), labelText: isSortByClinic ? (doctor?.projectName ?? "") : (doctor?.clinicName ?? ""),
), ),
], ],
), ),

@ -104,8 +104,8 @@ class AppointmentCard extends StatelessWidget {
AppCustomChipWidget( AppCustomChipWidget(
labelText: labelText:
isLoading ? 'OutPatient' : (appState.isArabic() ? patientAppointmentHistoryResponseModel.isInOutPatientDescriptionN! : patientAppointmentHistoryResponseModel.isInOutPatientDescription!), isLoading ? 'OutPatient' : (appState.isArabic() ? patientAppointmentHistoryResponseModel.isInOutPatientDescriptionN! : patientAppointmentHistoryResponseModel.isInOutPatientDescription!),
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.1), backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.1),
textColor: AppColors.primaryRedColor, textColor: AppColors.warningColorYellow,
).toShimmer2(isShow: isLoading), ).toShimmer2(isShow: isLoading),
AppCustomChipWidget( AppCustomChipWidget(
labelText: isLoading ? 'Booked' : AppointmentType.getAppointmentStatusType(patientAppointmentHistoryResponseModel.patientStatusType!), labelText: isLoading ? 'Booked' : AppointmentType.getAppointmentStatusType(patientAppointmentHistoryResponseModel.patientStatusType!),
@ -161,9 +161,13 @@ class AppointmentCard extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
(isLoading ? 'John Doe' : "${patientAppointmentHistoryResponseModel.doctorTitle} ${patientAppointmentHistoryResponseModel.doctorNameObj!}") Row(
.toText16(isBold: true, maxlines: 1) children: [
.toShimmer2(isShow: isLoading), (isLoading ? 'Dr' : "${patientAppointmentHistoryResponseModel.doctorTitle}").toText16(isBold: true, maxlines: 1),
(isLoading ? 'John Doe' : " ${patientAppointmentHistoryResponseModel.doctorNameObj!.truncate(20)}")
.toText16(isBold: true, maxlines: 1, isEnglishOnly: !Utils.isArabicText(patientAppointmentHistoryResponseModel.doctorNameObj ?? "John Doe"))
],
).toShimmer2(isShow: isLoading),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Wrap( Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,
@ -325,12 +329,19 @@ class AppointmentCard extends StatelessWidget {
flex: 1, flex: 1,
child: Container( child: Container(
height: (isFoldable || isTablet) ? 50.h : 40.h, height: (isFoldable || isTablet) ? 50.h : 40.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.textColor, borderRadius: 10.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.transparent,
borderRadius: 10.h,
side: BorderSide(
color: AppColors.textColor,
width: 1.2,
),
),
child: Transform.flip( child: Transform.flip(
flipX: appState.isArabic(), flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets( child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon, icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.whiteColor, iconColor: AppColors.textColor,
width: 24.w, width: 24.w,
height: 24.h, height: 24.h,
fit: BoxFit.contain, fit: BoxFit.contain,
@ -397,9 +408,10 @@ class AppointmentCard extends StatelessWidget {
return CustomButton( return CustomButton(
text: LocaleKeys.rebookSameDoctor.tr(context: context), text: LocaleKeys.rebookSameDoctor.tr(context: context),
onPressed: () => openDoctorScheduleCalendar(context), onPressed: () => openDoctorScheduleCalendar(context),
backgroundColor: AppColors.greyColor, backgroundColor: AppColors.transparent,
borderColor: AppColors.greyColor, borderColor: AppColors.textColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
borderWidth: 1.h,
fontSize: (isFoldable || isTablet) ? 12.f : 14.f, fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderRadius: 12.r, borderRadius: 12.r,
@ -420,7 +432,9 @@ class AppointmentCard extends StatelessWidget {
), ),
); );
} else { } else {
bookAppointmentsViewModel.getAppointmentNearestGate(projectID: patientAppointmentHistoryResponseModel.projectID, clinicID: patientAppointmentHistoryResponseModel.clinicID); if (!AppointmentType.isArrived(patientAppointmentHistoryResponseModel)) {
bookAppointmentsViewModel.getAppointmentNearestGate(projectID: patientAppointmentHistoryResponseModel.projectID, clinicID: patientAppointmentHistoryResponseModel.clinicID);
}
Navigator.of(context) Navigator.of(context)
.push( .push(
CustomPageRoute( CustomPageRoute(

@ -16,11 +16,7 @@ import 'dart:ui' as ui;
class AppointmentDoctorCard extends StatelessWidget { class AppointmentDoctorCard extends StatelessWidget {
const AppointmentDoctorCard( const AppointmentDoctorCard(
{super.key, {super.key, required this.patientAppointmentHistoryResponseModel, required this.onRescheduleTap, required this.onCancelTap, required this.onAskDoctorTap, this.renderWidgetForERDisplay = false});
required this.patientAppointmentHistoryResponseModel,
required this.onRescheduleTap,
required this.onCancelTap,
required this.onAskDoctorTap, this.renderWidgetForERDisplay = false});
final PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel; final PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
final VoidCallback onRescheduleTap; final VoidCallback onRescheduleTap;
@ -82,7 +78,7 @@ class AppointmentDoctorCard extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
patientAppointmentHistoryResponseModel.doctorNameObj!.toText16(isBold: true), patientAppointmentHistoryResponseModel.doctorNameObj!.toText16(isBold: true, isEnglishOnly: !Utils.isArabicText(patientAppointmentHistoryResponseModel.doctorNameObj ?? "")),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Wrap( Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,
@ -107,20 +103,16 @@ class AppointmentDoctorCard extends StatelessWidget {
richText: "${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)} ${DateUtil.formatDateToTimeLang( richText: "${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)} ${DateUtil.formatDateToTimeLang(
DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate),
false, false,
)}".toText10(isEnglishOnly: true), )}"
.toText10(isEnglishOnly: true),
), ),
), ),
AppCustomChipWidget( AppCustomChipWidget(
labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w), labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w),
icon: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! icon: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppAssets.walkin_appointment_icon : AppAssets.small_livecare_icon,
? AppAssets.walkin_appointment_icon
: AppAssets.small_livecare_icon,
iconColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : Colors.white, iconColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : Colors.white,
labelText: patientAppointmentHistoryResponseModel.isLiveCareAppointment! labelText: patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? LocaleKeys.livecare.tr(context: context) : LocaleKeys.walkin.tr(context: context),
? LocaleKeys.livecare.tr(context: context) backgroundColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.greyColor : AppColors.successColor,
: LocaleKeys.walkin.tr(context: context),
backgroundColor:
!patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.greyColor : AppColors.successColor,
textColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : Colors.white, textColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : Colors.white,
), ),
], ],
@ -163,25 +155,27 @@ class AppointmentDoctorCard extends StatelessWidget {
icon: AppAssets.ask_doctor_icon, icon: AppAssets.ask_doctor_icon,
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
) )
: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! :
? CustomButton( // !patientAppointmentHistoryResponseModel.isLiveCareAppointment!
text: LocaleKeys.rebookSameDoctor.tr(), // ? CustomButton(
onPressed: () { // text: LocaleKeys.rebookSameDoctor.tr(),
onRescheduleTap(); // onPressed: () {
}, // onRescheduleTap();
backgroundColor: AppColors.greyColor, // },
borderColor: AppColors.greyColor, // backgroundColor: AppColors.greyColor,
textColor: AppColors.blackColor, // borderColor: AppColors.greyColor,
fontSize: 12.f, // textColor: AppColors.blackColor,
fontWeight: FontWeight.w500, // fontSize: 12.f,
borderRadius: 12.r, // fontWeight: FontWeight.w500,
padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), // borderRadius: 12.r,
height: 40.h, // padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
icon: AppAssets.rebook_appointment_icon, // height: 40.h,
iconColor: AppColors.blackColor, // icon: AppAssets.rebook_appointment_icon,
iconSize: 14.h, // iconColor: AppColors.blackColor,
) // iconSize: 14.h,
: SizedBox.shrink(); // )
// :
SizedBox.shrink();
} else { } else {
return patientAppointmentHistoryResponseModel.isLiveCareAppointment! return patientAppointmentHistoryResponseModel.isLiveCareAppointment!
? CustomButton( ? CustomButton(

@ -65,7 +65,8 @@ class QuickLoginState extends State<QuickLogin> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Image.asset(AppAssets.lockIcon, height: 100), // Image.asset(AppAssets.lockIcon, height: 100),
Utils.buildSvgWithAssets(icon: AppAssets.biometricLockIcon, iconColor: AppColors.textColor, width: 100.h, height: 100.h),
SizedBox(height: 10.h), SizedBox(height: 10.h),
LocaleKeys.enableQuickLogin.tr(context: context).toText26(isBold: true), LocaleKeys.enableQuickLogin.tr(context: context).toText26(isBold: true),
// Text( // Text(

@ -206,7 +206,7 @@ class _SavedLogin extends State<SavedLogin> {
}, },
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor, textColor: AppColors.textColor,
icon: AppAssets.sms), icon: AppAssets.sms),
), ),
Row( Row(
@ -232,6 +232,7 @@ class _SavedLogin extends State<SavedLogin> {
textColor: AppColors.textColor, textColor: AppColors.textColor,
icon: AppAssets.whatsapp, icon: AppAssets.whatsapp,
iconColor: null, iconColor: null,
applyThemeColor: false,
), ),
), ),
], ],

@ -59,9 +59,19 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
bookAppointmentsViewModel.initBookAppointmentViewModel(); bookAppointmentsViewModel.initBookAppointmentViewModel();
bookAppointmentsViewModel.getLocation(); bookAppointmentsViewModel.getLocation();
immediateLiveCareViewModel.initImmediateLiveCare(); immediateLiveCareViewModel.initImmediateLiveCare();
if (appState.isAuthenticated) {
getIt.get<MyAppointmentsViewModel>().getPatientMyDoctors();
}
}); });
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
showUnKnownClinicBottomSheet(); if (bookAppointmentsViewModel.selectedTabIndex == 1) {
if (appState.isAuthenticated) {
getIt.get<MyAppointmentsViewModel>().getPatientMyDoctors();
showUnKnownClinicBottomSheet();
}
} else {
showUnKnownClinicBottomSheet();
}
}); });
super.initState(); super.initState();
} }
@ -203,7 +213,9 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
), ),
), ),
), ),
_buildSymptomsBottomCard(), Consumer<BookAppointmentsViewModel>(builder: (context, bookAppointmentsVM, child) {
return _buildSymptomsBottomCard();
}),
], ],
), ),
); );
@ -414,12 +426,13 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
} }
Widget _buildSymptomsBottomCard() { Widget _buildSymptomsBottomCard() {
return Container( return bookAppointmentsViewModel.checkLiveCareSymptomCheckerStatus()
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r), ? Container(
child: Row( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
children: [ child: Row(
Expanded( children: [
child: Column( Expanded(
child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -442,7 +455,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
) )
], ],
).paddingAll(24.w), ).paddingAll(24.w),
); )
: SizedBox.shrink();
} }
void openRegionListBottomSheet(BuildContext context, RegionBottomSheetType type) { void openRegionListBottomSheet(BuildContext context, RegionBottomSheetType type) {

@ -1,4 +1,3 @@
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:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
@ -101,18 +100,12 @@ class DoctorProfilePage extends StatelessWidget {
children: [ children: [
Column( Column(
children: [ children: [
Utils.buildSvgWithAssets( Utils.buildSvgWithAssets(icon: AppAssets.doctor_profile_rating_icon, width: 48.w, height: 48.h, fit: BoxFit.contain, applyThemeColor: false),
icon: AppAssets.doctor_profile_rating_icon,
width: 48.w,
height: 48.h,
fit: BoxFit.contain,
applyThemeColor: false
),
SizedBox(height: 16.h), SizedBox(height: 16.h),
"Ratings".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor), LocaleKeys.ratings.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
bookAppointmentsViewModel.doctorsProfileResponseModel.decimalDoctorRate bookAppointmentsViewModel.doctorsProfileResponseModel.decimalDoctorRate
.toString() .toString()
.toText16(isBold: true, color: AppColors.textColor, isUnderLine: true, decorationColor: AppColors.textColor), .toText16(isBold: true, color: AppColors.textColor, isUnderLine: true, decorationColor: AppColors.textColor, fontFamily: "Poppins"),
], ],
).onPress(() { ).onPress(() {
bookAppointmentsViewModel.getDoctorRatingDetails(); bookAppointmentsViewModel.getDoctorRatingDetails();
@ -128,18 +121,12 @@ class DoctorProfilePage extends StatelessWidget {
SizedBox(width: 36.w), SizedBox(width: 36.w),
Column( Column(
children: [ children: [
Utils.buildSvgWithAssets( Utils.buildSvgWithAssets(icon: AppAssets.doctor_profile_reviews_icon, width: 48.w, height: 48.h, fit: BoxFit.contain, applyThemeColor: false),
icon: AppAssets.doctor_profile_reviews_icon,
width: 48.w,
height: 48.h,
fit: BoxFit.contain,
applyThemeColor: false
),
SizedBox(height: 16.h), SizedBox(height: 16.h),
"Reviews".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor), LocaleKeys.reviews.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
bookAppointmentsViewModel.doctorsProfileResponseModel.noOfPatientsRate bookAppointmentsViewModel.doctorsProfileResponseModel.noOfPatientsRate
.toString() .toString()
.toText16(isBold: true, color: AppColors.textColor, isUnderLine: true, decorationColor: AppColors.textColor), .toText16(isBold: true, color: AppColors.textColor, isUnderLine: true, decorationColor: AppColors.textColor, fontFamily: "Poppins"),
], ],
).onPress(() { ).onPress(() {
bookAppointmentsViewModel.getDoctorRatingDetails(); bookAppointmentsViewModel.getDoctorRatingDetails();

@ -46,7 +46,7 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
void initState() { void initState() {
_scrollController = ScrollController(); _scrollController = ScrollController();
scheduleMicrotask(() { scheduleMicrotask(() {
bookAppointmentsViewModel.setIsNearestAppointmentSelected(false); bookAppointmentsViewModel.setIsNearestAppointmentSelected(true);
if (bookAppointmentsViewModel.isLiveCareSchedule) { if (bookAppointmentsViewModel.isLiveCareSchedule) {
bookAppointmentsViewModel.getLiveCareDoctorsList(); bookAppointmentsViewModel.getLiveCareDoctorsList();
} else { } else {

@ -90,59 +90,64 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
// ), // ),
SizedBox( SizedBox(
height: 350.h, height: 350.h,
child: SfCalendar( child: Localizations.override(
controller: _calendarController, context: context,
minDate: DateTime.now(), locale: const Locale('en'),
showNavigationArrow: true, child: SfCalendar(
headerHeight: 60.h, controller: _calendarController,
headerStyle: CalendarHeaderStyle( minDate: DateTime.now(),
backgroundColor: AppColors.scaffoldBgColor, showNavigationArrow: true,
textAlign: TextAlign.start, headerHeight: 60.h,
textStyle: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor, fontFamily: "Poppins"), headerStyle: CalendarHeaderStyle(
), backgroundColor: AppColors.scaffoldBgColor,
viewHeaderStyle: ViewHeaderStyle( textAlign: TextAlign.start,
backgroundColor: AppColors.scaffoldBgColor, textStyle: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor, fontFamily: "Poppins"),
dayTextStyle: TextStyle(fontSize: 14.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.textColor),
),
view: CalendarView.month,
todayHighlightColor: Colors.transparent,
todayTextStyle: TextStyle(color: AppColors.textColor, fontWeight: FontWeight.bold),
selectionDecoration: ShapeDecoration(
color: AppColors.transparent,
shape: SmoothRectangleBorder(
borderRadius: BorderRadius.circular(10.r),
smoothness: 1,
side: BorderSide(color: AppColors.primaryRedColor, width: 1.5),
), ),
), viewHeaderStyle: ViewHeaderStyle(
cellBorderColor: AppColors.transparent, backgroundColor: AppColors.scaffoldBgColor,
dataSource: MeetingDataSource(_getDataSource()), dayTextStyle: TextStyle(fontSize: 14.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.textColor, fontFamily: "Poppins"),
monthCellBuilder: (context, details) => Padding(
padding: EdgeInsets.all(12.h),
child: details.date.day.toString().toText14(
isCenter: true,
color: details.date == _calendarController.selectedDate ? AppColors.primaryRedColor : AppColors.textColor,
),
),
monthViewSettings: MonthViewSettings(
dayFormat: "EEE",
appointmentDisplayMode: MonthAppointmentDisplayMode.indicator,
showTrailingAndLeadingDates: false,
appointmentDisplayCount: 1,
monthCellStyle: MonthCellStyle(
textStyle: TextStyle(fontSize: 19.f),
), ),
view: CalendarView.month,
todayHighlightColor: Colors.transparent,
todayTextStyle: TextStyle(color: AppColors.textColor, fontWeight: FontWeight.bold, fontFamily: "Poppins"),
selectionDecoration: ShapeDecoration(
color: AppColors.transparent,
shape: SmoothRectangleBorder(
borderRadius: BorderRadius.circular(10.r),
smoothness: 1,
side: BorderSide(color: AppColors.primaryRedColor, width: 1.5),
),
),
cellBorderColor: AppColors.transparent,
dataSource: MeetingDataSource(_getDataSource()),
monthCellBuilder: (context, details) => Padding(
padding: EdgeInsets.all(12.h),
child: details.date.day.toString().toText14(
isCenter: true,
color: details.date == _calendarController.selectedDate ? AppColors.primaryRedColor : AppColors.textColor,
isEnglishOnly: true,
),
),
monthViewSettings: MonthViewSettings(
dayFormat: "EEE",
appointmentDisplayMode: MonthAppointmentDisplayMode.indicator,
showTrailingAndLeadingDates: false,
appointmentDisplayCount: 1,
monthCellStyle: MonthCellStyle(
textStyle: TextStyle(fontSize: 19.f),
),
),
onTap: (CalendarTapDetails details) {
_calendarController.selectedDate = details.date;
_onDaySelected(details.date!);
},
), ),
onTap: (CalendarTapDetails details) {
_calendarController.selectedDate = details.date;
_onDaySelected(details.date!);
},
), ),
), ),
SizedBox(height: 10.h), SizedBox(height: 10.h),
Transform.translate( Transform.translate(
offset: const Offset(0.0, -10.0), offset: const Offset(0.0, -10.0),
child: selectedDateDisplay.toText16(weight: FontWeight.w500), child: selectedDateDisplay.toText16(weight: FontWeight.w500, isEnglishOnly: true),
), ),
//TODO: Add Next Day Span here //TODO: Add Next Day Span here
dayEvents.isNotEmpty dayEvents.isNotEmpty
@ -153,23 +158,23 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
child: Wrap( child: Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,
alignment: WrapAlignment.start, alignment: WrapAlignment.start,
spacing: 6.h, spacing: 6.h,
runSpacing: 6.h, runSpacing: 6.h,
children: List.generate( children: List.generate(
dayEvents.length, // Generate a large number of items to ensure scrolling dayEvents.length, // Generate a large number of items to ensure scrolling
(index) => TimeSlotChip( (index) => TimeSlotChip(
label: dayEvents[index].isoTime!, label: dayEvents[index].isoTime!,
isSelected: index == selectedButtonIndex, isSelected: index == selectedButtonIndex,
onTap: () { onTap: () {
setState(() { setState(() {
selectedButtonIndex = index; selectedButtonIndex = index;
selectedTime = dayEvents[index].isoTime!; selectedTime = dayEvents[index].isoTime!;
}); });
}, },
),
),
),
), ),
),
),
),
) )
: Utils.getNoDataWidget(context, noDataText: LocaleKeys.noFreeSlot.tr(context: context)), : Utils.getNoDataWidget(context, noDataText: LocaleKeys.noFreeSlot.tr(context: context)),
@ -179,7 +184,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
isDisabled: dayEvents.isEmpty, isDisabled: dayEvents.isEmpty,
onPressed: () async { onPressed: () async {
if (appState.isAuthenticated) { if (appState.isAuthenticated) {
if(selectedTime == LocaleKeys.waitingAppointment.tr(context: context)){ if (selectedTime == LocaleKeys.waitingAppointment.tr(context: context)) {
bookAppointmentsViewModel.setWaitingAppointmentProjectID(bookAppointmentsViewModel.selectedDoctor.projectID!); bookAppointmentsViewModel.setWaitingAppointmentProjectID(bookAppointmentsViewModel.selectedDoctor.projectID!);
bookAppointmentsViewModel.setWaitingAppointmentDoctor(bookAppointmentsViewModel.selectedDoctor); bookAppointmentsViewModel.setWaitingAppointmentDoctor(bookAppointmentsViewModel.selectedDoctor);
@ -351,26 +356,20 @@ class TimeSlotChip extends StatelessWidget {
side: BorderSide(color: isSelected ? AppColors.warningColorYellow : AppColors.borderOnlyColor.withOpacity(0.2), width: 1), side: BorderSide(color: isSelected ? AppColors.warningColorYellow : AppColors.borderOnlyColor.withOpacity(0.2), width: 1),
), ),
), ),
child: label.toText12( child: label.toText12(color: isSelected ? AppColors.whiteColor : Colors.black87, fontWeight: FontWeight.w500, isEnglishOnly: true),
color: isSelected ? AppColors.whiteColor : Colors.black87,
fontWeight: FontWeight.w500,
),
) )
: Container( : Container(
padding: EdgeInsets.symmetric(horizontal: 14.h, vertical: 8.h), padding: EdgeInsets.symmetric(horizontal: 14.h, vertical: 8.h),
decoration: ShapeDecoration( decoration: ShapeDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
shape: SmoothRectangleBorder( shape: SmoothRectangleBorder(
borderRadius: BorderRadius.circular(8.h), borderRadius: BorderRadius.circular(8.h),
smoothness: 1, smoothness: 1,
side: BorderSide(color: isSelected ? AppColors.primaryRedColor : AppColors.borderOnlyColor.withOpacity(0.2), width: 1), side: BorderSide(color: isSelected ? AppColors.primaryRedColor : AppColors.borderOnlyColor.withOpacity(0.2), width: 1),
), ),
), ),
child: label.toText12( child: label.toText12(color: isSelected ? AppColors.primaryRedColor : AppColors.textColor, fontWeight: FontWeight.w500, isEnglishOnly: true),
color: isSelected ? AppColors.primaryRedColor : AppColors.textColor, ),
fontWeight: FontWeight.w500,
),
),
); );
} }
} }

@ -109,7 +109,7 @@ class DoctorCard extends StatelessWidget {
: doctorsListResponseModel.speciality!.first) : doctorsListResponseModel.speciality!.first)
: "") : "")
.toString() .toString()
.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor, maxLine: 2) .toText12(fontWeight: FontWeight.w500, color: AppColors.textColor, maxLine: 2, isEnglishOnly: true)
.toShimmer2(isShow: isLoading), .toShimmer2(isShow: isLoading),
), ),
SizedBox(width: 6.w), SizedBox(width: 6.w),

@ -20,13 +20,20 @@ class DoctorRatingDetails extends StatelessWidget {
: Column( : Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
bookAppointmentsVM.doctorsProfileResponseModel.actualDoctorRate!.ceilToDouble().toString().toText44(isBold: true), bookAppointmentsVM.doctorsProfileResponseModel.actualDoctorRate!.ceilToDouble().toString().toText44(isBold: true, isEnglishOnly: true),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"${bookAppointmentsVM.doctorsProfileResponseModel.noOfPatientsRate} ${LocaleKeys.reviews.tr(context: context)}" Row(
.toText16(weight: FontWeight.w500, color: AppColors.greyInfoTextColor), children: [
"${bookAppointmentsVM.doctorsProfileResponseModel.noOfPatientsRate} "
.toText16(weight: FontWeight.w500, color: AppColors.greyInfoTextColor, isEnglishOnly: true),
LocaleKeys.reviews.tr(context: context)
.toText16(weight: FontWeight.w500, color: AppColors.greyInfoTextColor,),
],
),
RatingBar( RatingBar(
initialRating: bookAppointmentsVM.doctorsProfileResponseModel.actualDoctorRate!.toDouble(), initialRating: bookAppointmentsVM.doctorsProfileResponseModel.actualDoctorRate!.toDouble(),
direction: Axis.horizontal, direction: Axis.horizontal,
@ -75,7 +82,7 @@ class DoctorRatingDetails extends StatelessWidget {
), ),
Container( Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
child: Text("${getRatingWidth(bookAppointmentsVM.doctorDetailsList[0].ratio).round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)), child: Text("${getRatingWidth(bookAppointmentsVM.doctorDetailsList[0].ratio).round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600, fontFamily: "Poppins")),
), ),
], ],
), ),
@ -95,7 +102,7 @@ class DoctorRatingDetails extends StatelessWidget {
), ),
Container( Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
child: Text("${bookAppointmentsVM.doctorDetailsList[1].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)), child: Text("${bookAppointmentsVM.doctorDetailsList[1].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600, fontFamily: "Poppins")),
), ),
], ],
), ),
@ -115,7 +122,7 @@ class DoctorRatingDetails extends StatelessWidget {
), ),
Container( Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
child: Text("${bookAppointmentsVM.doctorDetailsList[2].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)), child: Text("${bookAppointmentsVM.doctorDetailsList[2].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600, fontFamily: "Poppins")),
), ),
], ],
), ),
@ -135,7 +142,7 @@ class DoctorRatingDetails extends StatelessWidget {
), ),
Container( Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
child: Text("${bookAppointmentsVM.doctorDetailsList[3].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)), child: Text("${bookAppointmentsVM.doctorDetailsList[3].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600, fontFamily: "Poppins")),
), ),
], ],
), ),
@ -156,7 +163,7 @@ class DoctorRatingDetails extends StatelessWidget {
), ),
Container( Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
child: Text("${bookAppointmentsVM.doctorDetailsList[4].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)), child: Text("${bookAppointmentsVM.doctorDetailsList[4].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600, fontFamily: "Poppins")),
), ),
], ],
), ),

@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/presentation/contact_us/live_chat_page.dart'
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
class ContactUs extends StatelessWidget { class ContactUs extends StatelessWidget {
ContactUs({super.key}); ContactUs({super.key});
@ -33,6 +34,15 @@ class ContactUs extends StatelessWidget {
contactUsViewModel = Provider.of<ContactUsViewModel>(context); contactUsViewModel = Provider.of<ContactUsViewModel>(context);
return Column( return Column(
children: [ children: [
checkInOptionCard(
AppAssets.call_fill,
LocaleKeys.callNow.tr(),
// LocaleKeys.viewNearestHMGLocationsviewNearestHMGLocations.tr(),
"Call for immediate assistance",
).onPress(() {
launchUrl(Uri.parse("tel://" + "+966 92 006 6666"));
}),
SizedBox(height: 16.h),
checkInOptionCard( checkInOptionCard(
AppAssets.location, AppAssets.location,
LocaleKeys.findUs.tr(), LocaleKeys.findUs.tr(),
@ -46,26 +56,25 @@ class ContactUs extends StatelessWidget {
page: FindUsPage(), page: FindUsPage(),
), ),
); );
}, onFailure: () {
contactUsViewModel.initContactUsViewModel();
Navigator.pop(context);
Navigator.of(context).push(
CustomPageRoute(
page: FindUsPage(),
),
);
}, onLocationDeniedForever: () {
contactUsViewModel.initContactUsViewModel();
Navigator.pop(context);
Navigator.of(context).push(
CustomPageRoute(
page: FindUsPage(),
),
);
}); });
}), }),
SizedBox(height: 16.h), SizedBox(height: 16.h),
checkInOptionCard(
AppAssets.feedbackFill,
LocaleKeys.feedback.tr(),
LocaleKeys.provideFeedbackOnServices.tr(),
).onPress(() {
contactUsViewModel.setSelectedFeedbackType(
FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد'),
);
contactUsViewModel.setIsSendFeedbackTabSelected(true);
Navigator.pop(context);
Navigator.of(context).push(
CustomPageRoute(
page: FeedbackPage(),
),
);
}),
SizedBox(height: 16.h),
checkInOptionCard( checkInOptionCard(
AppAssets.ask_doctor_icon, AppAssets.ask_doctor_icon,
LocaleKeys.liveChat.tr(), LocaleKeys.liveChat.tr(),

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
@ -20,11 +21,14 @@ class FindUsPage extends StatelessWidget {
late AppState appState; late AppState appState;
late ContactUsViewModel contactUsViewModel; late ContactUsViewModel contactUsViewModel;
late LocationUtils locationUtils;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
contactUsViewModel = Provider.of<ContactUsViewModel>(context); contactUsViewModel = Provider.of<ContactUsViewModel>(context);
appState = getIt.get<AppState>(); appState = getIt.get<AppState>();
locationUtils = getIt.get<LocationUtils>();
locationUtils.isShowConfirmDialog = true;
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView( body: CollapsingListView(
@ -47,8 +51,48 @@ class FindUsPage extends StatelessWidget {
contactUsVM.setHMGHospitalsListSelected(index == 0); contactUsVM.setHMGHospitalsListSelected(index == 0);
}, },
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
Row(
mainAxisSize: MainAxisSize.max,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.sortByLocation.tr(context: context).toText14(isBold: true),
SizedBox(height: 4.h),
"Sort the locations by nearest to your location".toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
],
),
const Spacer(),
Switch(
activeThumbColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: .15),
value: contactUsVM.hasLocationEnabled,
onChanged: (newValue) async {
if (newValue) {
locationUtils.getCurrentLocation(
onSuccess: (value) {
// if (contactUsVM.hmgHospitalsLocationsList.isNotEmpty) {
// contactUsVM.sortHMGLocations(true);
// contactUsVM.setHasLocationEnabled(newValue);
// } else {
contactUsVM.initContactUsViewModel();
contactUsVM.setHasLocationEnabled(newValue);
contactUsVM.sortHMGLocations(true);
// }
},
onFailure: () {},
);
} else {
contactUsVM.sortHMGLocations(false);
contactUsVM.setHasLocationEnabled(newValue);
}
// bookAppointmentsVM.setIsNearestAppointmentSelected(newValue);
},
),
],
).paddingSymmetrical(24.h, 12.h),
ListView.separated( ListView.separated(
padding: EdgeInsets.only(top: 16.h), padding: EdgeInsets.only(top: 4.h),
shrinkWrap: true, shrinkWrap: true,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
itemCount: contactUsVM.isHMGLocationsListLoading itemCount: contactUsVM.isHMGLocationsListLoading

@ -6,24 +6,30 @@ import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart';
import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_hmg_locations.dart'; import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_hmg_locations.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:map_launcher/map_launcher.dart'; import 'package:map_launcher/map_launcher.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
class FindUsItemCard extends StatelessWidget { class FindUsItemCard extends StatelessWidget {
FindUsItemCard({super.key, required this.getHMGLocationsModel}); FindUsItemCard({super.key, required this.getHMGLocationsModel});
late AppState appState; late AppState appState;
late ContactUsViewModel contactUsViewModel;
GetHMGLocationsModel getHMGLocationsModel; GetHMGLocationsModel getHMGLocationsModel;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
appState = getIt.get<AppState>(); appState = getIt.get<AppState>();
contactUsViewModel = getIt.get<ContactUsViewModel>();
return DecoratedBox( return DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
@ -45,71 +51,108 @@ class FindUsItemCard extends StatelessWidget {
); );
} }
Widget get hospitalName => Row( Widget get hospitalName => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Image.network( (getHMGLocationsModel.distanceInKilometers != 0 && contactUsViewModel.hasLocationEnabled)
getHMGLocationsModel.projectImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", ? Column(
width: 40.h, children: [
height: 40.h, AppCustomChipWidget(
fit: BoxFit.cover, labelText: "${getHMGLocationsModel.distanceInKilometers ?? ""} km",
).circle(100).toShimmer2(isShow: false).paddingOnly(right: 10), labelPadding: EdgeInsetsDirectional.only(start: -4.h, end: 8.w),
Expanded( icon: AppAssets.location_red,
child: Text( // iconColor: AppColors.primaryRedColor,
getHMGLocationsModel.locationName!, // backgroundColor: AppColors.secondaryLightRedColor,
style: TextStyle( // textColor: AppColors.errorColor,
fontWeight: FontWeight.w600, ),
fontSize: 16, SizedBox(
color: AppColors.blackColor, height: 16.h,
), ),
), ],
) )
: SizedBox.shrink(),
Row(
children: [
Image.network(
getHMGLocationsModel.projectImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
width: 40.h,
height: 40.h,
fit: BoxFit.cover,
).circle(100).toShimmer2(isShow: false).paddingOnly(right: 10),
Expanded(
child: Text(
getHMGLocationsModel.locationName!,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
color: AppColors.blackColor,
),
),
)
],
),
], ],
); );
Widget get distanceInfo => Row( Widget get distanceInfo => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
AppCustomChipWidget( Expanded(
labelText: "${getHMGLocationsModel.distanceInKilometers ?? ""} km", flex: 7,
icon: AppAssets.location_red, child: CustomButton(
iconColor: AppColors.primaryRedColor, text: LocaleKeys.getDirections.tr(),
backgroundColor: AppColors.secondaryLightRedColor, onPressed: () async {
textColor: AppColors.errorColor, await MapLauncher.showMarker(
), mapType: MapType.google,
Row( coords: Coords(double.parse(getHMGLocationsModel.latitude ?? "0.0"), double.parse(getHMGLocationsModel.longitude ?? "0.0")),
children: [ title: getHMGLocationsModel.locationName ?? "Hospital",
AppCustomChipWidget( ).catchError((err) {
labelText: LocaleKeys.getDirections.tr(), MapLauncher.showMarker(
icon: AppAssets.directions_icon, mapType: Platform.isIOS ? MapType.apple : MapType.google,
iconColor: AppColors.whiteColor,
backgroundColor: AppColors.textColor.withValues(alpha: 0.8),
textColor: AppColors.whiteColor,
onChipTap: () async {
await MapLauncher.showMarker(
mapType: MapType.google,
coords: Coords(double.parse(getHMGLocationsModel.latitude ?? "0.0"), double.parse(getHMGLocationsModel.longitude ?? "0.0")), coords: Coords(double.parse(getHMGLocationsModel.latitude ?? "0.0"), double.parse(getHMGLocationsModel.longitude ?? "0.0")),
title: getHMGLocationsModel.locationName ?? "Hospital", title: getHMGLocationsModel.locationName ?? "Hospital",
).catchError((err) { );
MapLauncher.showMarker( });
mapType: Platform.isIOS ? MapType.apple : MapType.google, },
coords: Coords(double.parse(getHMGLocationsModel.latitude ?? "0.0"), double.parse(getHMGLocationsModel.longitude ?? "0.0")), backgroundColor: AppColors.transparent,
title: getHMGLocationsModel.locationName ?? "Hospital", borderColor: AppColors.textColor,
); textColor: AppColors.blackColor,
}); borderWidth: 1.h,
}, fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppAssets.directions_icon,
iconColor: AppColors.blackColor,
iconSize: 16.h,
),
),
SizedBox(width: 8.w),
Expanded(
flex: 1,
child: Container(
height: (isFoldable || isTablet) ? 50.h : 40.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.transparent,
borderRadius: 10.h,
side: BorderSide(
color: AppColors.textColor,
width: 1.2,
),
), ),
SizedBox(width: 4.w), child: Transform.flip(
AppCustomChipWidget( flipX: appState.isArabic(),
labelText: LocaleKeys.callNow.tr(), child: Utils.buildSvgWithAssets(
icon: AppAssets.call_fill, icon: AppAssets.call_fill,
iconColor: Colors.white, iconColor: AppColors.textColor,
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 1.0), width: 5.w,
textColor: Colors.white, height: 5.h,
onChipTap: () { fit: BoxFit.scaleDown,
launchUrl(Uri.parse("tel://" + "${getHMGLocationsModel.phoneNumber}")); ),
},
), ),
], ).onPress(() {
launchUrl(Uri.parse("tel://" + "${getHMGLocationsModel.phoneNumber}"));
}),
), ),
], ],
); );

@ -35,7 +35,7 @@ class EmergencyServicesPage extends StatelessWidget {
return CollapsingListView( return CollapsingListView(
title: LocaleKeys.emergencyServices.tr(), title: LocaleKeys.emergencyServices.tr(),
requests: () { history: () {
emergencyServicesViewModel.changeOrderDisplayItems(OrderDislpay.ALL); emergencyServicesViewModel.changeOrderDisplayItems(OrderDislpay.ALL);
Navigator.of(context).push(CustomPageRoute(page: ErHistoryListing(), direction: AxisDirection.up)); Navigator.of(context).push(CustomPageRoute(page: ErHistoryListing(), direction: AxisDirection.up));
}, },

@ -1,3 +1,5 @@
import 'dart:async';
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:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
@ -26,6 +28,16 @@ class HabibWalletPage extends StatefulWidget {
class _HabibWalletState extends State<HabibWalletPage> { class _HabibWalletState extends State<HabibWalletPage> {
late HabibWalletViewModel habibWalletVM; late HabibWalletViewModel habibWalletVM;
@override
void initState() {
scheduleMicrotask(() async {
habibWalletVM.initHabibWalletProvider();
habibWalletVM.getPatientBalanceAmount();
});
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
habibWalletVM = Provider.of<HabibWalletViewModel>(context, listen: false); habibWalletVM = Provider.of<HabibWalletViewModel>(context, listen: false);
@ -44,8 +56,10 @@ class _HabibWalletState extends State<HabibWalletPage> {
width: double.infinity, width: double.infinity,
height: 180.h, height: 180.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.blackBgColor, // color: AppColors.blackBgColor,
borderRadius: 24, color: Color(0xFF2E3039),
borderRadius: 24.r,
hasShadow: true
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
@ -59,18 +73,18 @@ class _HabibWalletState extends State<HabibWalletPage> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
"${_appState.getAuthenticatedUser()!.firstName!} ${_appState.getAuthenticatedUser()!.lastName!}".toText19(isBold: true, color: AppColors.whiteColor), "${_appState.getAuthenticatedUser()!.firstName!} ${_appState.getAuthenticatedUser()!.lastName!}".toText19(isBold: true, color: Colors.white),
"MRN: ${_appState.getAuthenticatedUser()!.patientId!}".toText14(weight: FontWeight.w500, color: AppColors.greyTextColor), "MRN: ${_appState.getAuthenticatedUser()!.patientId!}".toText14(weight: FontWeight.w500, color: AppColors.greyTextColor),
], ],
).expanded, ).expanded,
Utils.buildSvgWithAssets(icon: AppAssets.habiblogo, width: 24.h, height: 24.h), Utils.buildSvgWithAssets(icon: AppAssets.habiblogo, width: 24.h, height: 24.h, applyThemeColor: false),
], ],
), ),
Spacer(), Spacer(),
LocaleKeys.balanceAmount.tr(context: context).toText14(weight: FontWeight.w500, color: AppColors.whiteColor), LocaleKeys.balanceAmount.tr(context: context).toText14(weight: FontWeight.w500, color: Colors.white),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) { Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, textColor: AppColors.whiteColor, iconColor: AppColors.whiteColor, iconSize: 13, isExpanded: false) return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, textColor: Colors.white, iconColor: Colors.white, iconSize: 16, isExpanded: false)
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h); .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h);
}), }),
], ],
@ -86,7 +100,7 @@ class _HabibWalletState extends State<HabibWalletPage> {
icon: AppAssets.recharge_icon, icon: AppAssets.recharge_icon,
iconSize: 24.w, iconSize: 24.w,
backgroundColor: AppColors.infoColor, backgroundColor: AppColors.infoColor,
textColor: AppColors.whiteColor, textColor: Colors.white,
text: LocaleKeys.recharge.tr(context: context), text: LocaleKeys.recharge.tr(context: context),
borderWidth: 0.w, borderWidth: 0.w,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -99,12 +113,42 @@ class _HabibWalletState extends State<HabibWalletPage> {
page: RechargeWalletPage(), page: RechargeWalletPage(),
)) ))
.then((val) { .then((val) {
habibWalletVM.initHabibWalletProvider();
habibWalletVM.getPatientBalanceAmount(); habibWalletVM.getPatientBalanceAmount();
}); });
}, },
), ),
], ],
), ),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: false,
),
child: Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
return ListView.separated(
itemCount: habibWalletVM.habibWalletBalanceList.length,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.only(top: 8, bottom: 8),
shrinkWrap: true,
itemBuilder: (context, index) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: habibWalletVM.habibWalletBalanceList[index].projectDescription!.toText16(weight: FontWeight.w500, color: AppColors.textColor)),
Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletBalanceList[index].patientAdvanceBalanceAmount!, textColor: AppColors.textColor, iconColor: AppColors.textColor, iconSize: 18.h, isExpanded: false, fontSize: 28.f, fontWeight: FontWeight.w500),
],
).paddingSymmetrical(0, 12.h);
},
separatorBuilder: (BuildContext context, int index) {
return Divider(height: 1, color: AppColors.textColor.withAlpha(20));
},
).paddingSymmetrical(16.h, 24.h).toShimmer2(isShow: habibWalletVM.isWalletAmountLoading);
}),
),
SizedBox(height: 24.h),
], ],
), ),
), ),

@ -83,13 +83,15 @@ class AppUpdatePage extends StatelessWidget {
}).catchError((e) { }).catchError((e) {
print(e.toString()); print(e.toString());
Utils.openWebView( Utils.openWebView(
url: "https://play.google.com/store/apps/details?id=com.ejada.hmg", // url: "https://play.google.com/store/apps/details?id=com.ejada.hmg",
url: "https://play.google.com/store/apps/details?id=com.cloudsolutions.HMGPatientApp",
); );
}); });
} }
if (Platform.isIOS) { if (Platform.isIOS) {
Utils.openWebView( Utils.openWebView(
url: "https://itunes.apple.com/app/id733503978", // url: "https://itunes.apple.com/app/id733503978",
url: "https://itunes.apple.com/app/id6758851027",
); );
} }
} }

@ -165,8 +165,8 @@ class LandingPageData {
serviceName: "home_health_care", serviceName: "home_health_care",
icon: AppAssets.homeBottom, icon: AppAssets.homeBottom,
title: LocaleKeys.homeHealthCare, title: LocaleKeys.homeHealthCare,
subtitle: LocaleKeys.liveCareServiceDesc, subtitle: LocaleKeys.homeHealthCareText,
largeCardIcon: AppAssets.homeHealthCareService, largeCardIcon: AppAssets.homeHealthCareService,
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
iconColor: AppColors.whiteColor, iconColor: AppColors.whiteColor,
isBold: false, isBold: false,
@ -175,8 +175,8 @@ class LandingPageData {
serviceName: "pharmacy", serviceName: "pharmacy",
icon: AppAssets.pharmacy_icon, //359846 icon: AppAssets.pharmacy_icon, //359846
title: LocaleKeys.hmgPharmacy, title: LocaleKeys.hmgPharmacy,
subtitle: LocaleKeys.liveCareServiceDesc, subtitle: LocaleKeys.hmgPharmacyText,
largeCardIcon: AppAssets.pharmacyService, largeCardIcon: AppAssets.pharmacyService,
backgroundColor: AppColors.pharmacyBGColor, backgroundColor: AppColors.pharmacyBGColor,
iconColor: null, iconColor: null,
isBold: true, isBold: true,

File diff suppressed because it is too large Load Diff

@ -1,6 +1,7 @@
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:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -92,12 +93,12 @@ class LargeServiceCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
serviceCardData.title.tr(context: context).toText14(isBold: true, color: AppColors.textColor), serviceCardData.title.tr(context: context).toText14(isBold: true, color: AppColors.textColor),
serviceCardData.subtitle.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight), serviceCardData.subtitle.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight, maxLine: 2),
], ],
), ),
), ),
], ],
).paddingSymmetrical(16.w, 0.h).expanded, ).paddingSymmetrical(8.w, 0.h).expanded,
CustomButton( CustomButton(
text: serviceCardData.isBold ? LocaleKeys.visitPharmacyOnline.tr(context: context) : LocaleKeys.bookNow.tr(context: context), text: serviceCardData.isBold ? LocaleKeys.visitPharmacyOnline.tr(context: context) : LocaleKeys.bookNow.tr(context: context),
onPressed: () { onPressed: () {
@ -177,7 +178,9 @@ class FadedLargeServiceCard extends StatelessWidget {
children: [ children: [
ClipRRect( ClipRRect(
borderRadius: BorderRadius.circular(24.r), borderRadius: BorderRadius.circular(24.r),
child: Image.asset(serviceCardData.largeCardIcon, fit: BoxFit.cover, width: 520.w, height: 250.h), child: Transform.flip(
flipX: getIt.get<AppState>().isArabic(),
child: Image.asset(serviceCardData.largeCardIcon, fit: BoxFit.cover, width: 520.w, height: 250.h)),
), ),
Positioned( Positioned(
top: 0, top: 0,
@ -216,11 +219,14 @@ class FadedLargeServiceCard extends StatelessWidget {
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(8.h), padding: EdgeInsets.all(8.h),
child: Utils.buildSvgWithAssets( child: Transform.flip(
icon: serviceCardData.icon, flipX: getIt.get<AppState>().isArabic(),
iconColor: serviceCardData.iconColor, child: Utils.buildSvgWithAssets(
fit: BoxFit.contain, icon: serviceCardData.icon,
applyThemeColor: false iconColor: serviceCardData.iconColor,
fit: BoxFit.contain,
applyThemeColor: false
),
), ),
), ),
), ),
@ -229,10 +235,10 @@ class FadedLargeServiceCard extends StatelessWidget {
], ],
), ),
SizedBox(height: 10.h), SizedBox(height: 10.h),
serviceCardData.subtitle.tr(context: context).toText14(weight: FontWeight.w500, color: AppColors.blackBgColor, letterSpacing: 0), serviceCardData.subtitle.tr(context: context).toText14(weight: FontWeight.w500, color: AppColors.blackBgColor, letterSpacing: 0, maxlines: 2),
SizedBox(height: 12.h), SizedBox(height: 12.h),
CustomButton( CustomButton(
text: serviceCardData.isBold ? "Visit Pharmacy Online".needTranslation : LocaleKeys.bookNow.tr(context: context), text: serviceCardData.isBold ? LocaleKeys.visitPharmacyOnline.tr(context: context) : LocaleKeys.bookNow.tr(context: context),
onPressed: () { onPressed: () {
handleOnTap(); handleOnTap();
}, },
@ -255,6 +261,7 @@ class FadedLargeServiceCard extends StatelessWidget {
case "livecare": case "livecare":
{ {
getIt.get<BookAppointmentsViewModel>().onTabChanged(1); getIt.get<BookAppointmentsViewModel>().onTabChanged(1);
getIt.get<BookAppointmentsViewModel>().setIsLiveCareSelectedFromHomePage(true);
Navigator.of(getIt.get<NavigationService>().navigatorKey.currentContext!).push( Navigator.of(getIt.get<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute( CustomPageRoute(
page: BookAppointmentPage(), page: BookAppointmentPage(),

@ -1,10 +1,20 @@
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:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/profile_settings.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart';
import 'package:smooth_corner/smooth_corner.dart';
class WelcomeWidget extends StatelessWidget { class WelcomeWidget extends StatelessWidget {
final String name; final String name;
@ -20,33 +30,41 @@ class WelcomeWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return Column(
onTap: onTap, children: [
borderRadius: BorderRadius.circular(30), InkWell(
child: Row( onTap: onTap,
mainAxisSize: MainAxisSize.min, borderRadius: BorderRadius.circular(30),
spacing: 8.h, child: Row(
children: [
Image.asset(imageUrl, width: 40, height: 40),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 4.h,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
spacing: 8.h,
children: [ children: [
LocaleKeys.welcome.tr(context: context).toText14(color: AppColors.greyTextColor, height: 1, weight: FontWeight.w500), Icon(Icons.menu, color: AppColors.textColor).onPress(() {
Row( Navigator.of(context).push(springPageRoute(ProfileSettings()));
}),
Image.asset(imageUrl, width: 40, height: 40),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 4.h, spacing: 4.h,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Flexible(child: name.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, height: 1)), LocaleKeys.welcome.tr(context: context).toText14(color: AppColors.greyTextColor, height: 1, weight: FontWeight.w500),
Icon(Icons.keyboard_arrow_down, size: 20, color: AppColors.greyTextColor), Row(
spacing: 4.h,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Flexible(child: name.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, height: 1, isEnglishOnly: true)),
// Icon(Icons.keyboard_arrow_down, size: 20, color: AppColors.greyTextColor),
Utils.buildSvgWithAssets(icon: AppAssets.arrowRight, height: 22.h, width: 22.w)
],
),
], ],
), ).expanded,
], ],
).expanded, ),
], ),
), ],
); );
} }
} }

@ -8,6 +8,7 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart';
import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_all_orders_resp_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_all_orders_resp_model.dart';
import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_services_resp_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_services_resp_model.dart';
@ -33,11 +34,13 @@ class HhcProceduresPage extends StatefulWidget {
} }
class _HhcProceduresPageState extends State<HhcProceduresPage> { class _HhcProceduresPageState extends State<HhcProceduresPage> {
late AppState appState;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
final HmgServicesViewModel hmgServicesViewModel = context.read<HmgServicesViewModel>(); final HmgServicesViewModel hmgServicesViewModel = context.read<HmgServicesViewModel>();
final AppState appState = getIt.get<AppState>();
scheduleMicrotask(() async { scheduleMicrotask(() async {
final user = appState.getAuthenticatedUser(); final user = appState.getAuthenticatedUser();
@ -445,11 +448,12 @@ class _HhcProceduresPageState extends State<HhcProceduresPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
appState = getIt.get<AppState>();
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView( body: CollapsingListView(
title: LocaleKeys.homeHealthCare.tr(context: context), title: LocaleKeys.homeHealthCare.tr(context: context),
history: () => Navigator.of(context).push(CustomPageRoute(page: HhcOrderDetailPage(), direction: AxisDirection.up)), history: () => appState.isAuthenticated ? Navigator.of(context).push(CustomPageRoute(page: HhcOrderDetailPage(), direction: AxisDirection.up)) : null,
bottomChild: Consumer( bottomChild: Consumer(
builder: (BuildContext context, HmgServicesViewModel hmgServicesViewModel, Widget? child) { builder: (BuildContext context, HmgServicesViewModel hmgServicesViewModel, Widget? child) {
if (hmgServicesViewModel.isHhcOrdersLoading || hmgServicesViewModel.isHhcServicesLoading) { if (hmgServicesViewModel.isHhcOrdersLoading || hmgServicesViewModel.isHhcServicesLoading) {
@ -467,8 +471,14 @@ class _HhcProceduresPageState extends State<HhcProceduresPage> {
padding: EdgeInsets.all(24.w), padding: EdgeInsets.all(24.w),
child: CustomButton( child: CustomButton(
borderWidth: 0, borderWidth: 0,
text: LocaleKeys.createNewRequest.tr(context: context), text: appState.isAuthenticated ? LocaleKeys.createNewRequest.tr(context: context) : LocaleKeys.loginToUseService.tr(context: context),
onPressed: () => _buildServicesListBottomsSheet(hmgServicesViewModel.hhcServicesList), onPressed: () {
if(appState.isAuthenticated) {
_buildServicesListBottomsSheet(hmgServicesViewModel.hhcServicesList);
} else {
getIt<AuthenticationViewModel>().onLoginPressed();
}
},
textColor: AppColors.whiteColor, textColor: AppColors.whiteColor,
borderRadius: 12.r, borderRadius: 12.r,
borderColor: Colors.transparent, borderColor: Colors.transparent,
@ -492,12 +502,13 @@ class _HhcProceduresPageState extends State<HhcProceduresPage> {
} else { } else {
return Column( return Column(
children: [ children: [
appState.isAuthenticated ?
Center( Center(
child: Utils.getNoDataWidget( child: Utils.getNoDataWidget(
context, context,
noDataText: LocaleKeys.youHaveNoPendingRequests.tr(context: context), noDataText: LocaleKeys.youHaveNoPendingRequests.tr(context: context),
), ),
), ) : LocaleKeys.homeHealthCareText.tr(context: context).toText18(weight: FontWeight.w500).paddingSymmetrical(24.h, 24.h),
], ],
); );
} }

@ -63,8 +63,8 @@ class InsuranceApprovalDetailsPage extends StatelessWidget {
), ),
AppCustomChipWidget( AppCustomChipWidget(
labelText: appState.isArabic() ? insuranceApprovalResponseModel.isInOutPatientDescriptionN! : insuranceApprovalResponseModel.isInOutPatientDescription!, labelText: appState.isArabic() ? insuranceApprovalResponseModel.isInOutPatientDescriptionN! : insuranceApprovalResponseModel.isInOutPatientDescription!,
backgroundColor: AppColors.primaryRedColor.withOpacity(0.1), backgroundColor: AppColors.warningColorYellow.withOpacity(0.1),
textColor: AppColors.primaryRedColor, textColor: AppColors.warningColorYellow,
), ),
], ],
), ),

@ -51,7 +51,7 @@ class _InsuranceApprovalsPageState extends State<InsuranceApprovalsPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ListView.separated( ListView.separated(
padding: EdgeInsets.only(top: 24.h), padding: EdgeInsets.only(top: 12.h),
shrinkWrap: true, shrinkWrap: true,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
itemCount: insuranceVM.isInsuranceApprovalsLoading itemCount: insuranceVM.isInsuranceApprovalsLoading

@ -48,11 +48,11 @@ class _InsuranceHomePageState extends State<InsuranceHomePage> {
insuranceViewModel = Provider.of<InsuranceViewModel>(context, listen: false); insuranceViewModel = Provider.of<InsuranceViewModel>(context, listen: false);
return CollapsingListView( return CollapsingListView(
title: "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.updateInsurance.tr(context: context)}", title: "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.updateInsurance.tr(context: context)}",
history: () { // history: () {
insuranceViewModel.setIsInsuranceHistoryLoading(true); // // insuranceViewModel.setIsInsuranceHistoryLoading(true);
insuranceViewModel.getPatientInsuranceCardHistory(); // // insuranceViewModel.getPatientInsuranceCardHistory();
showCommonBottomSheetWithoutHeight(context, child: InsuranceHistory(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false); // showCommonBottomSheetWithoutHeight(context, child: InsuranceHistory(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false);
}, // },
child: SingleChildScrollView( child: SingleChildScrollView(
child: Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) { child: Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
return Column( return Column(
@ -66,12 +66,23 @@ class _InsuranceHomePageState extends State<InsuranceHomePage> {
isLoading: true, isLoading: true,
).paddingSymmetrical(24.h, 24.h) ).paddingSymmetrical(24.h, 24.h)
: insuranceVM.patientInsuranceList.isNotEmpty : insuranceVM.patientInsuranceList.isNotEmpty
? Padding( ? ListView.builder(
padding: EdgeInsets.only(top: 24.h), shrinkWrap: true,
child: PatientInsuranceCard( padding: EdgeInsets.all(16.h),
insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first, physics: const BouncingScrollPhysics(),
isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))) itemBuilder: (context, index) {
.paddingSymmetrical(24.w, 0.h), return Column(
children: [
PatientInsuranceCard(
insuranceCardDetailsModel: insuranceVM.patientInsuranceList[index],
isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))),
SizedBox(
height: 12.h,
)
],
);
},
itemCount: insuranceVM.patientInsuranceList.length,
) )
: Padding( : Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.12), padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.12),

@ -9,8 +9,11 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_approval_response_model.dart'; import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_approval_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/insurance/insurance_approval_details_page.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
class InsuranceApprovalCard extends StatelessWidget { class InsuranceApprovalCard extends StatelessWidget {
InsuranceApprovalCard({super.key, required this.insuranceApprovalResponseModel, required this.isLoading, required this.appState}); InsuranceApprovalCard({super.key, required this.insuranceApprovalResponseModel, required this.isLoading, required this.appState});
@ -64,8 +67,8 @@ class InsuranceApprovalCard extends StatelessWidget {
: appState.isArabic() : appState.isArabic()
? insuranceApprovalResponseModel.isInOutPatientDescriptionN! ? insuranceApprovalResponseModel.isInOutPatientDescriptionN!
: insuranceApprovalResponseModel.isInOutPatientDescription!, : insuranceApprovalResponseModel.isInOutPatientDescription!,
backgroundColor: AppColors.primaryRedColor.withOpacity(0.1), backgroundColor: AppColors.warningColorYellow.withOpacity(0.1),
textColor: AppColors.primaryRedColor, textColor: AppColors.warningColorYellow,
).toShimmer2(isShow: isLoading), ).toShimmer2(isShow: isLoading),
], ],
).toShimmer2(isShow: isLoading), ).toShimmer2(isShow: isLoading),
@ -111,12 +114,30 @@ class InsuranceApprovalCard extends StatelessWidget {
), ),
], ],
), ),
Row( SizedBox(
mainAxisAlignment: MainAxisAlignment.end, height: 12.h,
children: [ ),
Transform.flip( CustomButton(
flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon_small, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)), text: LocaleKeys.viewDetails.tr(context: context),
], onPressed: () async {
Navigator.of(context).push(
CustomPageRoute(
page: InsuranceApprovalDetailsPage(insuranceApprovalResponseModel: insuranceApprovalResponseModel),
),
);
},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: isTablet || isFoldable ? 46.h : 40.h,
// height: 40.h,
// icon: AppAssets.insurance,
// iconColor: AppColors.primaryRedColor,
iconSize: 16.h,
).toShimmer2(isShow: isLoading), ).toShimmer2(isShow: isLoading),
], ],
), ),

@ -3,11 +3,13 @@ import 'package:flutter/cupertino.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
@ -75,21 +77,18 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
], ],
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Row( Wrap(
direction: Axis.horizontal,
spacing: 4.h,
runSpacing: 4.h,
children: [ children: [
Wrap( AppCustomChipWidget(
direction: Axis.horizontal, icon: AppAssets.doctor_calendar_icon,
spacing: 4.h, labelText:
runSpacing: 4.h, "${LocaleKeys.expiryOn.tr(context: context)} ${DateUtil.formatDateToDate(DateTime.parse(insuranceViewModel.patientInsuranceUpdateResponseModel!.effectiveTo!), false)}",
children: [ ),
AppCustomChipWidget( AppCustomChipWidget(
icon: AppAssets.doctor_calendar_icon, labelText: "Member ID: ${insuranceViewModel.patientInsuranceUpdateResponseModel!.memberID!}",
labelText: "${LocaleKeys.expiryOn.tr(context: context)} ${insuranceViewModel.patientInsuranceUpdateResponseModel!.effectiveTo}",
),
AppCustomChipWidget(
labelText: "Member ID: ${insuranceViewModel.patientInsuranceUpdateResponseModel!.memberID!}",
),
],
), ),
], ],
), ),
@ -106,39 +105,51 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
iconSize: 20.w, iconSize: 20.w,
text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}", text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}",
onPressed: () { onPressed: () {
LoaderBottomSheet.showLoader(); if (insuranceViewModel.patientInsuranceUpdateResponseModel != null) {
insuranceViewModel.updatePatientInsuranceCard( LoaderBottomSheet.showLoader();
patientID: appState.getAuthenticatedUser()!.patientId!, getIt<MyAppointmentsViewModel>().sendPatientUpdateRequest(onSuccess: (val) {
patientType: appState.getAuthenticatedUser()!.patientType!, LoaderBottomSheet.hideLoader();
patientIdentificationID: appState.getAuthenticatedUser()!.patientIdentificationNo!, insuranceViewModel.setIsInsuranceDataToBeLoaded(true);
mobileNo: appState.getAuthenticatedUser()!.mobileNumber!, insuranceViewModel.initInsuranceProvider();
insuranceCardImage: "", Navigator.pop(context);
onSuccess: (val) { }, onError: (err) {
LoaderBottomSheet.hideLoader(); insuranceViewModel.updatePatientInsuranceCard(
showCommonBottomSheetWithoutHeight( patientID: appState.getAuthenticatedUser()!.patientId!,
title: LocaleKeys.success.tr(context: context), patientType: appState.getAuthenticatedUser()!.patientType!,
context, patientIdentificationID: appState.getAuthenticatedUser()!.patientIdentificationNo!,
child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr(context: context)), mobileNo: appState.getAuthenticatedUser()!.mobileNumber!,
callBackFunc: () { insuranceCardImage: "",
Navigator.pop(context); onSuccess: (val) {
}, LoaderBottomSheet.hideLoader();
isFullScreen: false, showCommonBottomSheetWithoutHeight(
isCloseButtonVisible: true, title: LocaleKeys.success.tr(context: context),
); context,
}, child: Utils.getSuccessWidget(loadingText: LocaleKeys.insuranceRequestSubmittedSuccessfully.tr(context: context)),
onError: (err) { callBackFunc: () {
LoaderBottomSheet.hideLoader(); Navigator.pop(context);
showCommonBottomSheetWithoutHeight( },
title: LocaleKeys.notice.tr(context: context), isFullScreen: false,
context, isCloseButtonVisible: false,
child: Utils.getErrorWidget(loadingText: err.toString()), );
callBackFunc: () { // Future.delayed(Duration(milliseconds: 2000)).then((value) async {
Navigator.pop(context); // Navigator.pop(context);
// });
}, },
isFullScreen: false, onError: (err) {
isCloseButtonVisible: true, LoaderBottomSheet.hideLoader();
); showCommonBottomSheetWithoutHeight(
}); title: LocaleKeys.notice.tr(context: context),
context,
child: Utils.getErrorWidget(loadingText: err.toString()),
callBackFunc: () {
Navigator.pop(context);
},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
});
}
}, },
backgroundColor: insuranceViewModel.patientInsuranceUpdateResponseModel != null ? AppColors.successColor : AppColors.lightGrayBGColor, backgroundColor: insuranceViewModel.patientInsuranceUpdateResponseModel != null ? AppColors.successColor : AppColors.lightGrayBGColor,
borderColor: AppColors.successColor.withOpacity(0.01), borderColor: AppColors.successColor.withOpacity(0.01),

@ -52,57 +52,69 @@ class PatientInsuranceCard extends StatelessWidget {
children: [ children: [
SizedBox( SizedBox(
width: MediaQuery.of(context).size.width * 0.4, width: MediaQuery.of(context).size.width * 0.4,
child: "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText18(isBold: true, textOverflow: TextOverflow.clip)), child: "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText18(isBold: true, textOverflow: TextOverflow.clip, isEnglishOnly: true)),
LocaleKeys.policyNumber.tr(namedArgs: {'number': insuranceCardDetailsModel.insurancePolicyNo ?? ''}, context: context).toText12(isBold: true, color: AppColors.lightGrayColor), Row(
children: [
"${LocaleKeys.policyNumber.tr(context: context)}${insuranceCardDetailsModel.insurancePolicyNo}".toText12(isBold: true, color: AppColors.lightGrayColor),
],
),
], ],
), ),
AppCustomChipWidget( AppCustomChipWidget(
icon: insuranceViewModel.isInsuranceExpired icon: isCurrentPatientInsuranceExpired(insuranceCardDetailsModel.cardValidTo!)
? AppAssets.cancel_circle_icon ? AppAssets.cancel_circle_icon
: insuranceViewModel.isInsuranceActive : insuranceViewModel.isInsuranceActive
? AppAssets.insurance_active_icon ? AppAssets.insurance_active_icon
: AppAssets.alertSquare, : AppAssets.alertSquare,
labelText: insuranceViewModel.isInsuranceExpired labelText: isCurrentPatientInsuranceExpired(insuranceCardDetailsModel.cardValidTo!)
? LocaleKeys.insuranceExpired.tr(context: context) ? LocaleKeys.insuranceExpired.tr(context: context)
: insuranceViewModel.isInsuranceActive : insuranceViewModel.isInsuranceActive
? LocaleKeys.insuranceActive.tr(context: context) ? LocaleKeys.insuranceActive.tr(context: context)
: LocaleKeys.insuranceInActive.tr(context: context), : LocaleKeys.insuranceInActive.tr(context: context),
iconColor: insuranceViewModel.isInsuranceExpired iconColor: isCurrentPatientInsuranceExpired(insuranceCardDetailsModel.cardValidTo!)
? AppColors.primaryRedColor ? AppColors.primaryRedColor
: insuranceViewModel.isInsuranceActive : insuranceViewModel.isInsuranceActive
? AppColors.successColor ? AppColors.successColor
: AppColors.warningColorYellow, : AppColors.warningColorYellow,
textColor: insuranceViewModel.isInsuranceExpired textColor: isCurrentPatientInsuranceExpired(insuranceCardDetailsModel.cardValidTo!)
? AppColors.primaryRedColor ? AppColors.primaryRedColor
: insuranceViewModel.isInsuranceActive : insuranceViewModel.isInsuranceActive
? AppColors.successColor ? AppColors.successColor
: AppColors.warningColorYellow, : AppColors.warningColorYellow,
iconSize: 12.w, iconSize: 12.w,
deleteIcon: insuranceViewModel.isInsuranceActive ? null : AppAssets.forward_chevron_icon, deleteIcon: insuranceViewModel.isInsuranceActive ? null : AppAssets.forward_chevron_icon,
deleteIconColor: AppColors.warningColorYellow, deleteIconColor: insuranceViewModel.isInsuranceExpired
? AppColors.primaryRedColor
: insuranceViewModel.isInsuranceActive
? AppColors.successColor
: AppColors.warningColorYellow,
deleteIconHasColor: true, deleteIconHasColor: true,
onChipTap: () { onChipTap: () {
if (!insuranceViewModel.isInsuranceActive) { if (!insuranceViewModel.isInsuranceActive) {
showCommonBottomSheetWithoutHeight( insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true);
title: LocaleKeys.notice.tr(context: context), insuranceViewModel.getPatientInsuranceDetailsForUpdate(
context, appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString());
child: Utils.getWarningWidget( showCommonBottomSheetWithoutHeight(context, child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false);
loadingText: LocaleKeys.insuranceInActiveContactSupport.tr(context: context), // showCommonBottomSheetWithoutHeight(
confirmText: LocaleKeys.contactUs.tr(context: context), // title: LocaleKeys.notice.tr(context: context),
isShowActionButtons: true, // context,
onCancelTap: () { // child: Utils.getWarningWidget(
Navigator.pop(context); // loadingText: LocaleKeys.insuranceInActiveContactSupport.tr(context: context),
}, // confirmText: LocaleKeys.contactUs.tr(context: context),
onConfirmTap: () async { // isShowActionButtons: true,
launchUrl(Uri.parse("tel://" + "+966 92 006 6666")); // onCancelTap: () {
}), // Navigator.pop(context);
callBackFunc: () {}, // },
isFullScreen: false, // onConfirmTap: () async {
isCloseButtonVisible: true, // launchUrl(Uri.parse("tel://" + "+966 92 006 6666"));
); // }),
// callBackFunc: () {},
// isFullScreen: false,
// isCloseButtonVisible: true,
// );
} }
}, },
backgroundColor: insuranceViewModel.isInsuranceExpired backgroundColor: isCurrentPatientInsuranceExpired(insuranceCardDetailsModel.cardValidTo!)
? AppColors.primaryRedColor.withOpacity(0.1) ? AppColors.primaryRedColor.withOpacity(0.1)
: insuranceViewModel.isInsuranceActive : insuranceViewModel.isInsuranceActive
? AppColors.successColor.withOpacity(0.1) ? AppColors.successColor.withOpacity(0.1)
@ -122,7 +134,23 @@ class PatientInsuranceCard extends StatelessWidget {
), ),
SizedBox(height: 12.h), SizedBox(height: 12.h),
insuranceCardDetailsModel.groupName!.toText12(isBold: true), insuranceCardDetailsModel.groupName!.toText12(isBold: true),
insuranceCardDetailsModel.companyName!.toText12(isBold: true), Row(
children: [
insuranceCardDetailsModel.companyName!.toText12(isBold: true),
SizedBox(
width: 6.h,
),
Container(
padding: EdgeInsets.symmetric(horizontal: 6.h, vertical: 4.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.infoColor,
borderRadius: 50.r,
),
child: (insuranceCardDetailsModel.subCategoryDesc!.length > 5 ? insuranceCardDetailsModel.subCategoryDesc!.substring(0, 12) : insuranceCardDetailsModel.subCategoryDesc!)
.toText8(isBold: true, color: AppColors.whiteColor),
),
],
),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Wrap( Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,
@ -142,9 +170,10 @@ class PatientInsuranceCard extends StatelessWidget {
isInsuranceExpired isInsuranceExpired
? CustomButton( ? CustomButton(
icon: AppAssets.update_insurance_card_icon, icon: AppAssets.update_insurance_card_icon,
iconColor: AppColors.successColor, iconColor: AppColors.warningColorYellow,
iconSize: 15.h, iconSize: 15.h,
text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}", // text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}",
text: LocaleKeys.verifyInsurance.tr(context: context),
onPressed: () { onPressed: () {
insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true); insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true);
insuranceViewModel.getPatientInsuranceDetailsForUpdate( insuranceViewModel.getPatientInsuranceDetailsForUpdate(
@ -157,9 +186,9 @@ class PatientInsuranceCard extends StatelessWidget {
isCloseButtonVisible: false, isCloseButtonVisible: false,
isFullScreen: false); isFullScreen: false);
}, },
backgroundColor: AppColors.bgGreenColor.withOpacity(0.20), backgroundColor: AppColors.warningColorYellow.withOpacity(0.20),
borderColor: AppColors.bgGreenColor.withOpacity(0.0), borderColor: AppColors.warningColorYellow.withOpacity(0.0),
textColor: AppColors.bgGreenColor, textColor: AppColors.warningColorYellow,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderRadius: 12, borderRadius: 12,
@ -172,4 +201,10 @@ class PatientInsuranceCard extends StatelessWidget {
), ),
).paddingSymmetrical(0.h, 0.h); ).paddingSymmetrical(0.h, 0.h);
} }
bool isCurrentPatientInsuranceExpired(String cardValidTo) {
return DateTime.now().isAfter(
DateUtil.convertStringToDate(cardValidTo),
);
}
} }

@ -59,7 +59,7 @@ class LabOrderByTest extends StatelessWidget {
icon: AppAssets.view_report_icon, icon: AppAssets.view_report_icon,
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
iconSize: 16.h, iconSize: 16.h,
text: LocaleKeys.viewReport.tr(context: context), text: LocaleKeys.viewResults.tr(context: context),
onPressed: () { onPressed: () {
onTap(); onTap();
}, },

File diff suppressed because one or more lines are too long

@ -164,7 +164,7 @@ class LabResultByClinic extends StatelessWidget {
padding: EdgeInsets.only(right: 4.w, left: 4.w), padding: EdgeInsets.only(right: 4.w, left: 4.w),
child: Utils.buildSvgWithAssets(icon: AppAssets.aiOverView, width: 16.h, height: 16.h, iconColor: Colors.white), child: Utils.buildSvgWithAssets(icon: AppAssets.aiOverView, width: 16.h, height: 16.h, iconColor: Colors.white),
), ),
LocaleKeys.generateAiAnalysis.tr(context: context).toText16(isBold: true) LocaleKeys.generateAiAnalysis.tr(context: context).toText16(isBold: true, color: Colors.white)
], ],
), ),
).paddingSymmetrical(24.h, 24.h).onPress(() async { ).paddingSymmetrical(24.h, 24.h).onPress(() async {

@ -2,11 +2,14 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_order_response_by_ai_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_order_response_by_ai_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
class AiAnalysisWidget extends StatelessWidget { class AiAnalysisWidget extends StatelessWidget {
final LabOrderResponseByAi data; final LabOrderResponseByAi data;
@ -71,6 +74,16 @@ class AiAnalysisWidget extends StatelessWidget {
), ),
], ],
), ),
SizedBox(height: 16.h),
CustomButton(
height: 50.h,
text: LocaleKeys.close.tr(context: context),
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
onPressed: () {
getIt.get<LabViewModel>().closeAILabResultAnalysis();
},
),
], ],
), ),
), ),

@ -114,15 +114,15 @@ class LabOrderResultItem extends StatelessWidget {
), ),
CustomButton( CustomButton(
icon: AppAssets.view_report_icon, icon: AppAssets.view_report_icon,
iconColor: AppColors.primaryRedColor, iconColor: AppColors.infoColor,
iconSize: 16.h, iconSize: 16.h,
text: LocaleKeys.viewReport.tr(context: context), text: LocaleKeys.viewReport.tr(context: context),
onPressed: () { onPressed: () {
onTap(); onTap();
}, },
backgroundColor: AppColors.secondaryLightRedColor, backgroundColor: AppColors.infoColor.withAlpha(20),
borderColor: AppColors.secondaryLightRedColor, borderColor: AppColors.infoColor.withAlpha(0),
textColor: AppColors.primaryRedColor, textColor: AppColors.infoColor,
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderRadius: 12, borderRadius: 12,

@ -35,97 +35,99 @@ class LabResultDetails extends StatelessWidget {
LabViewModel labViewModel = Provider.of<LabViewModel>(context, listen: false); LabViewModel labViewModel = Provider.of<LabViewModel>(context, listen: false);
final appState = getIt.get<AppState>(); final appState = getIt.get<AppState>();
return Scaffold( return Scaffold(
body: Column( body: Consumer<LabViewModel>(builder: (context, labVM, child) {
children: [ return Column(
Expanded( children: [
child: CollapsingListView( Expanded(
title: LocaleKeys.labResultDetails.tr(context: context), child: CollapsingListView(
// aiOverview: () async { title: LocaleKeys.labResultDetails.tr(context: context),
// final _dialogService = getIt.get<DialogService>(); // aiOverview: () async {
// await _dialogService.showCommonBottomSheetWithoutH( // final _dialogService = getIt.get<DialogService>();
// message: LocaleKeys.aiDisclaimer.tr(), // await _dialogService.showCommonBottomSheetWithoutH(
// label: LocaleKeys.consent.tr(), // message: LocaleKeys.aiDisclaimer.tr(),
// okLabel: LocaleKeys.acceptLbl.tr(), // label: LocaleKeys.consent.tr(),
// cancelLabel: LocaleKeys.rejectView.tr(), // okLabel: LocaleKeys.acceptLbl.tr(),
// onOkPressed: () { // cancelLabel: LocaleKeys.rejectView.tr(),
// context.pop(); // onOkPressed: () {
// labViewModel.getAiOverviewSingleLabResult(langId: appState.getLanguageID().toString(), recentLabResult: recentLabResult, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context)); // context.pop();
// }, // labViewModel.getAiOverviewSingleLabResult(langId: appState.getLanguageID().toString(), recentLabResult: recentLabResult, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context));
// onCancelPressed: () { // },
// context.pop(); // onCancelPressed: () {
// }); // context.pop();
// }, // });
child: SingleChildScrollView( // },
child: Column( child: SingleChildScrollView(
spacing: 16.h, child: Column(
children: [ spacing: 16.h,
LabNameAndStatus(context), children: [
getLabDescription(context), LabNameAndStatus(context),
LabGraph(context), getLabDescription(context),
Selector<LabViewModel, LabOrderResponseByAi?>( LabGraph(context),
selector: (_, model) => model.labOrderResponseByAi, Selector<LabViewModel, LabOrderResponseByAi?>(
builder: (_, aiData, __) { selector: (_, model) => model.labOrderResponseByAi,
if (aiData != null) { builder: (_, aiData, __) {
return AiAnalysisWidget(data: aiData).paddingOnly(bottom: 16.h); if (aiData != null) {
} return AiAnalysisWidget(data: aiData).paddingOnly(bottom: 16.h);
return const SizedBox.shrink(); }
}, return const SizedBox.shrink();
), },
], ),
).paddingAll(24.h), ],
).paddingAll(24.h),
),
), ),
), ),
), labVM.labOrderResponseByAi == null ? Container(
Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor,
color: AppColors.whiteColor, borderRadius: 24.h,
borderRadius: 24.h, hasShadow: true,
hasShadow: true,
),
child: Container(
height: 56.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.r),
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
stops: [0.236, 1.0], // 53.6% and 100%
colors: [
Color(0xFF8A38F5), // Transparent
Color(0xFFE20BBB), // Solid #F8F8F8
],
),
), ),
child: Row( child: Container(
crossAxisAlignment: CrossAxisAlignment.center, height: 56.h,
mainAxisAlignment: MainAxisAlignment.center, decoration: BoxDecoration(
children: [ borderRadius: BorderRadius.circular(12.r),
Padding( gradient: LinearGradient(
padding: EdgeInsets.only(right: 4.w, left: 4.w), begin: Alignment.centerLeft,
child: Utils.buildSvgWithAssets(icon: AppAssets.aiOverView, width: 16.h, height: 16.h, iconColor: Colors.white), end: Alignment.centerRight,
stops: [0.236, 1.0], // 53.6% and 100%
colors: [
Color(0xFF8A38F5), // Transparent
Color(0xFFE20BBB), // Solid #F8F8F8
],
), ),
LocaleKeys.generateAiAnalysis.tr(context: context).toText16(isBold: true) ),
], child: Row(
), crossAxisAlignment: CrossAxisAlignment.center,
).paddingSymmetrical(24.h, 24.h).onPress(() async { mainAxisAlignment: MainAxisAlignment.center,
final _dialogService = getIt.get<DialogService>(); children: [
await _dialogService.showCommonBottomSheetWithoutH( Padding(
message: LocaleKeys.aiDisclaimer.tr(), padding: EdgeInsets.only(right: 4.w, left: 4.w),
label: LocaleKeys.consent.tr(), child: Utils.buildSvgWithAssets(icon: AppAssets.aiOverView, width: 16.h, height: 16.h, iconColor: Colors.white),
okLabel: LocaleKeys.acceptLbl.tr(), ),
cancelLabel: LocaleKeys.rejectView.tr(), LocaleKeys.generateAiAnalysisResult.tr(context: context).toText16(isBold: true, color: Colors.white)
onOkPressed: () { ],
context.pop(); ),
labViewModel.getAiOverviewSingleLabResult( ).paddingSymmetrical(24.h, 24.h).onPress(() async {
langId: appState.getLanguageID().toString(), recentLabResult: recentLabResult, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context)); final _dialogService = getIt.get<DialogService>();
}, await _dialogService.showCommonBottomSheetWithoutH(
onCancelPressed: () { message: LocaleKeys.aiDisclaimer.tr(),
context.pop(); label: LocaleKeys.consent.tr(),
}); okLabel: LocaleKeys.acceptLbl.tr(),
}), cancelLabel: LocaleKeys.rejectView.tr(),
), onOkPressed: () {
], context.pop();
), labViewModel.getAiOverviewSingleLabResult(
langId: appState.getLanguageID().toString(), recentLabResult: recentLabResult, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context));
},
onCancelPressed: () {
context.pop();
});
}),
) : SizedBox.shrink(),
],
);
}),
); );
} }

@ -85,6 +85,8 @@ import '../../features/active_prescriptions/active_prescriptions_view_model.dart
import '../prescriptions/prescription_detail_page.dart'; import '../prescriptions/prescription_detail_page.dart';
import 'widgets/medical_file_appointment_card.dart'; import 'widgets/medical_file_appointment_card.dart';
import 'dart:ui' as ui;
class MedicalFilePage extends StatefulWidget { class MedicalFilePage extends StatefulWidget {
bool showBackIcon; bool showBackIcon;
@ -197,18 +199,23 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
), ),
SizedBox(width: 4.h), SizedBox(width: 4.h),
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, height: 22.h, width: 22.w) Utils.buildSvgWithAssets(icon: AppAssets.arrowRight, height: 22.h, width: 22.w)
], ],
).onPress(() { ).onPress(() {
DialogService dialogService = getIt.get<DialogService>(); Navigator.of(context).push(
dialogService.showFamilyBottomSheetWithoutH( CustomPageRoute(
label: LocaleKeys.familyTitle.tr(context: context), page: FamilyMedicalScreen(),
message: "", ),
isShowManageButton: true, );
onSwitchPress: (FamilyFileResponseModelLists profile) { // DialogService dialogService = getIt.get<DialogService>();
medicalFileViewModel.switchFamilyFiles(responseID: profile.responseId, patientID: profile.patientId, phoneNumber: profile.mobileNumber); // dialogService.showFamilyBottomSheetWithoutH(
}, // label: LocaleKeys.familyTitle.tr(context: context),
profiles: medicalFileViewModel.patientFamilyFiles); // message: "",
// isShowManageButton: true,
// onSwitchPress: (FamilyFileResponseModelLists profile) {
// medicalFileViewModel.switchFamilyFiles(responseID: profile.responseId, patientID: profile.patientId, phoneNumber: profile.mobileNumber);
// },
// profiles: medicalFileViewModel.patientFamilyFiles);
}), }),
isLeading: widget.showBackIcon, isLeading: widget.showBackIcon,
// leadingCallback: () { // leadingCallback: () {
@ -281,9 +288,9 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
), ),
AppCustomChipWidget( AppCustomChipWidget(
icon: AppAssets.blood_icon, icon: AppAssets.blood_icon,
labelText: LocaleKeys.bloodGroup.tr(namedArgs: {'bloodType': appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup}, context: context), labelText: appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup,
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
), ),
Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) { Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
@ -310,27 +317,35 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
: AppColors.warningColorYellow, : AppColors.warningColorYellow,
iconSize: 12.w, iconSize: 12.w,
deleteIcon: insuranceVM.isInsuranceActive ? null : AppAssets.forward_chevron_icon, deleteIcon: insuranceVM.isInsuranceActive ? null : AppAssets.forward_chevron_icon,
deleteIconColor: AppColors.warningColorYellow, deleteIconColor: insuranceVM.isInsuranceExpired
? AppColors.primaryRedColor
: insuranceVM.isInsuranceActive
? AppColors.successColor
: AppColors.warningColorYellow,
deleteIconHasColor: true, deleteIconHasColor: true,
onChipTap: () { onChipTap: () {
if (!insuranceVM.isInsuranceActive) { if (!insuranceVM.isInsuranceActive) {
showCommonBottomSheetWithoutHeight( insuranceVM.setIsInsuranceUpdateDetailsLoading(true);
title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!), insuranceVM.getPatientInsuranceDetailsForUpdate(
navigationService.navigatorKey.currentContext!, appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString());
child: Utils.getWarningWidget( showCommonBottomSheetWithoutHeight(context, child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false);
loadingText: LocaleKeys.insuranceInActiveContactSupport.tr(context: context), // showCommonBottomSheetWithoutHeight(
confirmText: LocaleKeys.contactUs.tr(context: context), // title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
isShowActionButtons: true, // navigationService.navigatorKey.currentContext!,
onCancelTap: () { // child: Utils.getWarningWidget(
navigationService.pop(); // loadingText: LocaleKeys.insuranceInActiveContactSupport.tr(context: context),
}, // confirmText: LocaleKeys.contactUs.tr(context: context),
onConfirmTap: () async { // isShowActionButtons: true,
launchUrl(Uri.parse("tel://" + "+966 92 006 6666")); // onCancelTap: () {
}), // navigationService.pop();
callBackFunc: () {}, // },
isFullScreen: false, // onConfirmTap: () async {
isCloseButtonVisible: true, // launchUrl(Uri.parse("tel://" + "+966 92 006 6666"));
); // }),
// callBackFunc: () {},
// isFullScreen: false,
// isCloseButtonVisible: true,
// );
} }
}, },
backgroundColor: insuranceVM.isInsuranceExpired backgroundColor: insuranceVM.isInsuranceExpired
@ -507,7 +522,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
), ),
ExpandableListItem( ExpandableListItem(
title: LocaleKeys.trackerAndOthers.tr(context: context).toText18(weight: FontWeight.w600), title: LocaleKeys.healthTrackers.tr(context: context).toText18(weight: FontWeight.w600),
expandedBackgroundColor: Colors.transparent, expandedBackgroundColor: Colors.transparent,
children: [ children: [
SizedBox(height: 10.h), SizedBox(height: 10.h),
@ -739,7 +754,26 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
).paddingSymmetrical(0.w, 0.h), ).paddingSymmetrical(0.w, 0.h),
SizedBox(height: 24.h), SizedBox(height: 24.h),
LocaleKeys.activeMedicationsAndPrescriptions.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2), Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.activeMedicationsAndPrescriptions.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2),
Row(
children: [
LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
SizedBox(width: 2.w),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
).onPress(() {
// myAppointmentsViewModel.getPatientMyDoctors();
Navigator.of(context).push(
CustomPageRoute(
page: PrescriptionsListPage(),
),
);
}),
],
),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) { Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) {
return prescriptionVM.isPrescriptionsOrdersLoading return prescriptionVM.isPrescriptionsOrdersLoading
@ -784,11 +818,15 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
runSpacing: 4.w, runSpacing: 4.w,
children: [ children: [
AppCustomChipWidget(labelText: prescriptionVM.patientPrescriptionOrders[index].clinicDescription!), AppCustomChipWidget(labelText: prescriptionVM.patientPrescriptionOrders[index].clinicDescription!),
AppCustomChipWidget( Directionality(
icon: AppAssets.doctor_calendar_icon, textDirection: ui.TextDirection.ltr,
labelText: DateUtil.formatDateToDate( child: AppCustomChipWidget(
DateUtil.convertStringToDate(prescriptionVM.patientPrescriptionOrders[index].appointmentDate), icon: AppAssets.doctor_calendar_icon,
false, labelText: DateUtil.formatDateToDate(
DateUtil.convertStringToDate(prescriptionVM.patientPrescriptionOrders[index].appointmentDate),
false,
),
isEnglishOnly: true,
), ),
), ),
], ],
@ -816,55 +854,55 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Divider(color: AppColors.dividerColor), // Divider(color: AppColors.dividerColor),
SizedBox(height: 16.h), // SizedBox(height: 16.h),
Row( // Row(
children: [ // children: [
Expanded( // Expanded(
child: CustomButton( // child: CustomButton(
text: LocaleKeys.allPrescriptions.tr(context: context), // text: LocaleKeys.allPrescriptions.tr(context: context),
onPressed: () { // onPressed: () {
Navigator.of(context).push( // Navigator.of(context).push(
CustomPageRoute( // CustomPageRoute(
page: PrescriptionsListPage(), // page: PrescriptionsListPage(),
), // ),
); // );
}, // },
backgroundColor: AppColors.secondaryLightRedColor, // backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor, // borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor, // textColor: AppColors.primaryRedColor,
fontSize: 12.f, // fontSize: 12.f,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 12.r, // borderRadius: 12.r,
height: 40.h, // height: 40.h,
icon: AppAssets.requests, // icon: AppAssets.requests,
iconColor: AppColors.primaryRedColor, // iconColor: AppColors.primaryRedColor,
iconSize: 16.w, // iconSize: 16.w,
), // ),
), // ),
SizedBox(width: 6.w), // SizedBox(width: 6.w),
Expanded( // Expanded(
child: CustomButton( // child: CustomButton(
text: LocaleKeys.allMedications.tr(context: context), // text: LocaleKeys.allMedications.tr(context: context),
onPressed: () { Navigator.of(context).push( // onPressed: () { Navigator.of(context).push(
CustomPageRoute( // CustomPageRoute(
page: ActiveMedicationPage(), // page: ActiveMedicationPage(),
), // ),
);}, // );},
backgroundColor: AppColors.secondaryLightRedColor, // backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor, // borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor, // textColor: AppColors.primaryRedColor,
fontSize: 12.f, // fontSize: 12.f,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 12.h, // borderRadius: 12.h,
height: 40.h, // height: 40.h,
icon: AppAssets.all_medications_icon, // icon: AppAssets.all_medications_icon,
iconColor: AppColors.primaryRedColor, // iconColor: AppColors.primaryRedColor,
iconSize: 16.h, // iconSize: 16.h,
), // ),
), // ),
], // ],
), // ),
], ],
), ),
), ),
@ -897,7 +935,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
], ],
).onPress(() { ).onPress(() {
myAppointmentsViewModel.getPatientMyDoctors(); // myAppointmentsViewModel.getPatientMyDoctors();
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
page: MyDoctorsPage(), page: MyDoctorsPage(),
@ -1196,6 +1234,26 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
// Requests Tab Data // Requests Tab Data
return Column( return Column(
children: [ children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"${LocaleKeys.sick.tr(context: context)} ${LocaleKeys.sickSubtitle.tr(context: context)}".toText16(isBold: true),
Row(
children: [
LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
),
],
).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: PatientSickleavesListPage(),
),
);
}),
SizedBox(height: 16.h),
Consumer<MedicalFileViewModel>(builder: (context, medicalFileVM, child) { Consumer<MedicalFileViewModel>(builder: (context, medicalFileVM, child) {
return medicalFileVM.isPatientSickLeaveListLoading return medicalFileVM.isPatientSickLeaveListLoading
? PatientSickLeaveCard( ? PatientSickLeaveCard(
@ -1265,20 +1323,20 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
), ),
); );
}), }),
MedicalFileCard( // MedicalFileCard(
label: LocaleKeys.sickLeaveReport.tr(context: context), // label: LocaleKeys.sickLeaveReport.tr(context: context),
textColor: AppColors.blackColor, // textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor, // backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.sick_leave_report_icon, // svgIcon: AppAssets.sick_leave_report_icon,
isLargeText: true, // isLargeText: true,
iconSize: 36.h, // iconSize: 36.h,
).onPress(() { // ).onPress(() {
Navigator.of(context).push( // Navigator.of(context).push(
CustomPageRoute( // CustomPageRoute(
page: PatientSickleavesListPage(), // page: PatientSickleavesListPage(),
), // ),
); // );
}), // }),
], ],
).paddingSymmetrical(0.w, 0.0), ).paddingSymmetrical(0.w, 0.0),
SizedBox(height: 24.h), SizedBox(height: 24.h),
@ -1289,12 +1347,12 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( // Row(
children: [ // children: [
LocaleKeys.healthTrackers.tr(context: context).toText16(weight: FontWeight.w500, color: AppColors.textColor), // LocaleKeys.healthTrackers.tr(context: context).toText16(weight: FontWeight.w500, color: AppColors.textColor),
], // ],
), // ),
SizedBox(height: 16.h), // SizedBox(height: 16.h),
GridView( GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, crossAxisCount: 3,
@ -1333,11 +1391,11 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
).paddingSymmetrical(0.w, 0.0), ).paddingSymmetrical(0.w, 0.0),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row( // Row(
children: [ // children: [
LocaleKeys.others.tr(context: context).toText16(weight: FontWeight.w500, color: AppColors.textColor), // LocaleKeys.others.tr(context: context).toText16(weight: FontWeight.w500, color: AppColors.textColor),
], // ],
), // ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
GridView( GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
@ -1350,21 +1408,22 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
shrinkWrap: true, shrinkWrap: true,
children: [ children: [
MedicalFileCard( // MedicalFileCard(
label: LocaleKeys.askYourDoctor.tr(context: context), // label: LocaleKeys.askYourDoctor.tr(context: context),
textColor: AppColors.blackColor, // textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor, // backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.ask_doctor_medical_file_icon, // svgIcon: AppAssets.ask_doctor_medical_file_icon,
isLargeText: true, // isLargeText: true,
iconSize: 36.w, // iconSize: 36.w,
).onPress(() { // ).onPress(() {
getIt.get<AskDoctorViewModel>().initAskDoctorViewModel(); // getIt.get<AskDoctorViewModel>().initAskDoctorViewModel();
Navigator.of(context).push( // Navigator.of(context).push(
CustomPageRoute( // CustomPageRoute(
page: AskDoctorPage(), // page: AskDoctorPage(),
), // ),
); // );
}), // }),
// MedicalFileCard( // MedicalFileCard(
// label: LocaleKeys.internetPairing.tr(context: context), // label: LocaleKeys.internetPairing.tr(context: context),
// textColor: AppColors.blackColor, // textColor: AppColors.blackColor,

@ -57,48 +57,48 @@ class _PatientSickleavesListPageState extends State<PatientSickleavesListPage> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SizedBox(height: 16.h), // SizedBox(height: 16.h),
// Clinic & Hospital Sort // Clinic & Hospital Sort
Row( // Row(
children: [ // children: [
CustomButton( // CustomButton(
text: LocaleKeys.byClinic.tr(context: context), // text: LocaleKeys.byClinic.tr(context: context),
onPressed: () { // onPressed: () {
model.setIsSickLeavesSortByClinic(true); // model.setIsSickLeavesSortByClinic(true);
}, // },
backgroundColor: model.isSickLeavesSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, // backgroundColor: model.isSickLeavesSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor,
borderColor: model.isSickLeavesSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2), // borderColor: model.isSickLeavesSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2),
textColor: model.isSickLeavesSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, // textColor: model.isSickLeavesSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor,
fontSize: 12, // fontSize: 12,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 10, // borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, // height: 40.h,
), // ),
SizedBox(width: 8.h), // SizedBox(width: 8.h),
CustomButton( // CustomButton(
text: LocaleKeys.byHospital.tr(context: context), // text: LocaleKeys.byHospital.tr(context: context),
onPressed: () { // onPressed: () {
model.setIsSickLeavesSortByClinic(false); // model.setIsSickLeavesSortByClinic(false);
}, // },
backgroundColor: model.isSickLeavesSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, // backgroundColor: model.isSickLeavesSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor,
borderColor: model.isSickLeavesSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor, // borderColor: model.isSickLeavesSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor,
textColor: model.isSickLeavesSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, // textColor: model.isSickLeavesSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor,
fontSize: 12, // fontSize: 12,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 10, // borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, // height: 40.h,
), // ),
], // ],
).paddingSymmetrical(24.h, 0.h), // ).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 20.h), // SizedBox(height: 20.h),
// Expandable list // Expandable list
ListView.builder( ListView.builder(
itemCount: model.isPatientSickLeaveListLoading itemCount: model.isPatientSickLeaveListLoading
? 4 ? 4
: model.patientSickLeaveList.isNotEmpty : model.patientSickLeaveList.isNotEmpty
? model.patientSickLeavesViewList.length ? model.patientSickLeaveList.length
: 1, : 1,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
@ -122,155 +122,322 @@ class _PatientSickleavesListPageState extends State<PatientSickleavesListPage> {
curve: Curves.easeInOut, curve: Curves.easeInOut,
margin: EdgeInsets.symmetric(vertical: 8.h), margin: EdgeInsets.symmetric(vertical: 8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
child: InkWell( child: Container(
onTap: () { padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 16.h),
setState(() { child: Column(
expandedIndex = isExpanded ? null : index; crossAxisAlignment: CrossAxisAlignment.start,
}); children: [
}, AppCustomChipWidget(
child: Column( labelText:
crossAxisAlignment: CrossAxisAlignment.start, "${getIt.get<AppState>().isArabic() ? model.patientSickLeaveList[index].isInOutPatientDescriptionN : model.patientSickLeaveList[index].isInOutPatientDescription}",
children: [ backgroundColor: AppColors.warningColorYellow.withOpacity(0.1),
Padding( textColor: AppColors.warningColorYellow,
padding: EdgeInsets.all(16.h), ),
child: Column( SizedBox(height: 16.h),
crossAxisAlignment: CrossAxisAlignment.start, Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.network(
model.patientSickLeaveList[index].doctorImageURL!,
width: 24.h,
height: 24.h,
fit: BoxFit.fill,
).circle(100),
SizedBox(width: 8.h),
Expanded(child: model.patientSickLeaveList[index].doctorName!.toText14(weight: FontWeight.w500)),
],
),
SizedBox(height: 8.h),
Wrap(
direction: Axis.horizontal,
spacing: 6.h,
runSpacing: 6.h,
children: [ children: [
Row( AppCustomChipWidget(
mainAxisAlignment: MainAxisAlignment.spaceBetween, labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(model.patientSickLeaveList[index].appointmentDate), false),
children: [ ),
CustomButton( AppCustomChipWidget(
text: "${model.patientSickLeavesViewList[index].sickLeavesList!.length} ${LocaleKeys.sickSubtitle.tr(context: context)} Available", labelText: model.isSickLeavesSortByClinic ? model.patientSickLeaveList[index].projectName! : model.patientSickLeaveList[index].clinicName!,
onPressed: () {}, ),
backgroundColor: AppColors.greyColor, AppCustomChipWidget(
borderColor: AppColors.greyColor, labelText: "${model.patientSickLeaveList[index].sickLeaveDays} Days",
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
Icon(isExpanded ? Icons.expand_less : Icons.expand_more),
],
), ),
SizedBox(height: 8.h),
model.patientSickLeavesViewList[index].filterName!.toText16(isBold: true)
], ],
), ),
), SizedBox(height: 12.h),
AnimatedSwitcher( Row(
duration: Duration(milliseconds: 500), children: [
switchInCurve: Curves.easeIn, Expanded(
switchOutCurve: Curves.easeOut, flex: 6,
transitionBuilder: (Widget child, Animation<double> animation) { child: CustomButton(
return FadeTransition( text: LocaleKeys.downloadReport.tr(context: context),
opacity: animation, onPressed: () async {
child: SizeTransition( LoaderBottomSheet.showLoader();
sizeFactor: animation, await medicalFileViewModel.getPatientSickLeavePDF(model.patientSickLeaveList[index], appState.getAuthenticatedUser()!).then((val) async {
axisAlignment: 0.0, LoaderBottomSheet.hideLoader();
child: child, if (medicalFileViewModel.patientSickLeavePDFBase64.isNotEmpty) {
String path = await Utils.createFileFromString(medicalFileViewModel.patientSickLeavePDFBase64, "pdf");
try {
OpenFilex.open(path);
} catch (ex) {
debugPrint("Error opening file: $ex");
}
}
});
},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppAssets.download,
iconColor: AppColors.primaryRedColor,
iconSize: 14.h,
),
), ),
); ],
}, ),
child: isExpanded // SizedBox(height: 12.h),
? Container( // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
key: ValueKey<int>(index), // SizedBox(height: 12.h),
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h), ],
child: Column( ),
crossAxisAlignment: CrossAxisAlignment.start, // Column(
children: [ // crossAxisAlignment: CrossAxisAlignment.start,
...model.patientSickLeavesViewList[index].sickLeavesList!.map((sickLeave) { // children: [
return Column( // ...model.patientSickLeaveList[index].sickLeavesList!.map((sickLeave) {
crossAxisAlignment: CrossAxisAlignment.start, // return Column(
children: [ // crossAxisAlignment: CrossAxisAlignment.start,
Row( // children: [
mainAxisSize: MainAxisSize.min, // Row(
children: [ // mainAxisSize: MainAxisSize.min,
Image.network( // children: [
sickLeave.doctorImageURL!, // Image.network(
width: 24.h, // sickLeave.doctorImageURL!,
height: 24.h, // width: 24.h,
fit: BoxFit.fill, // height: 24.h,
).circle(100), // fit: BoxFit.fill,
SizedBox(width: 8.h), // ).circle(100),
Expanded(child: sickLeave.doctorName!.toText14(weight: FontWeight.w500)), // SizedBox(width: 8.h),
], // Expanded(child: sickLeave.doctorName!.toText14(weight: FontWeight.w500)),
), // ],
SizedBox(height: 8.h), // ),
Wrap( // SizedBox(height: 8.h),
direction: Axis.horizontal, // Wrap(
spacing: 6.h, // direction: Axis.horizontal,
runSpacing: 6.h, // spacing: 6.h,
children: [ // runSpacing: 6.h,
AppCustomChipWidget( // children: [
labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(sickLeave.appointmentDate), false), // AppCustomChipWidget(
), // labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(sickLeave.appointmentDate), false),
AppCustomChipWidget( // ),
labelText: model.isSickLeavesSortByClinic ? sickLeave.projectName! : sickLeave.clinicName!, // AppCustomChipWidget(
), // labelText: model.isSickLeavesSortByClinic ? sickLeave.projectName! : sickLeave.clinicName!,
AppCustomChipWidget( // ),
labelText: "${sickLeave.sickLeaveDays} Days", // AppCustomChipWidget(
), // labelText: "${sickLeave.sickLeaveDays} Days",
], // ),
), // ],
SizedBox(height: 12.h), // ),
Row( // SizedBox(height: 12.h),
children: [ // Row(
Expanded( // children: [
flex: 6, // Expanded(
child: CustomButton( // flex: 6,
text: LocaleKeys.downloadReport.tr(context: context), // child: CustomButton(
onPressed: () async { // text: LocaleKeys.downloadReport.tr(context: context),
LoaderBottomSheet.showLoader(); // onPressed: () async {
await medicalFileViewModel.getPatientSickLeavePDF(sickLeave, appState.getAuthenticatedUser()!).then((val) async { // LoaderBottomSheet.showLoader();
LoaderBottomSheet.hideLoader(); // await medicalFileViewModel.getPatientSickLeavePDF(sickLeave, appState.getAuthenticatedUser()!).then((val) async {
if (medicalFileViewModel.patientSickLeavePDFBase64.isNotEmpty) { // LoaderBottomSheet.hideLoader();
String path = await Utils.createFileFromString(medicalFileViewModel.patientSickLeavePDFBase64, "pdf"); // if (medicalFileViewModel.patientSickLeavePDFBase64.isNotEmpty) {
try { // String path = await Utils.createFileFromString(medicalFileViewModel.patientSickLeavePDFBase64, "pdf");
OpenFilex.open(path); // try {
} catch (ex) { // OpenFilex.open(path);
debugPrint("Error opening file: $ex"); // } catch (ex) {
} // debugPrint("Error opening file: $ex");
} // }
}); // }
}, // });
backgroundColor: AppColors.secondaryLightRedColor, // },
borderColor: AppColors.secondaryLightRedColor, // backgroundColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor, // borderColor: AppColors.secondaryLightRedColor,
fontSize: 14, // textColor: AppColors.primaryRedColor,
fontWeight: FontWeight.w500, // fontSize: 14,
borderRadius: 12, // fontWeight: FontWeight.w500,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // borderRadius: 12,
height: 40.h, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
icon: AppAssets.download, // height: 40.h,
iconColor: AppColors.primaryRedColor, // icon: AppAssets.download,
iconSize: 14.h, // iconColor: AppColors.primaryRedColor,
), // iconSize: 14.h,
), // ),
], // ),
), // ],
SizedBox(height: 12.h), // ),
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // SizedBox(height: 12.h),
SizedBox(height: 12.h), // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
], // SizedBox(height: 12.h),
); // ],
}), // );
], // }),
), // ],
) // ),
: SizedBox.shrink(), )
), // InkWell(
], // onTap: () {
// setState(() {
// expandedIndex = isExpanded ? null : index;
// });
// },
// child:
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Padding(
// padding: EdgeInsets.all(16.h),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// CustomButton(
// text: "${model.patientSickLeavesViewList[index].sickLeavesList!.length} ${LocaleKeys.sickSubtitle.tr(context: context)} Available",
// onPressed: () {},
// backgroundColor: AppColors.greyColor,
// borderColor: AppColors.greyColor,
// textColor: AppColors.blackColor,
// fontSize: 10,
// fontWeight: FontWeight.w500,
// borderRadius: 8,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 30.h,
// ),
// Icon(isExpanded ? Icons.expand_less : Icons.expand_more),
// ],
// ),
// SizedBox(height: 8.h),
// model.patientSickLeavesViewList[index].filterName!.toText16(isBold: true)
// ],
// ),
// ),
// // AnimatedSwitcher(
// // duration: Duration(milliseconds: 500),
// // switchInCurve: Curves.easeIn,
// // switchOutCurve: Curves.easeOut,
// // transitionBuilder: (Widget child, Animation<double> animation) {
// // return FadeTransition(
// // opacity: animation,
// // child: SizeTransition(
// // sizeFactor: animation,
// // axisAlignment: 0.0,
// // child: child,
// // ),
// // );
// // },
// // child: isExpanded
// // ? Container(
// // key: ValueKey<int>(index),
// // padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
// // child: Column(
// // crossAxisAlignment: CrossAxisAlignment.start,
// // children: [
// // ...model.patientSickLeavesViewList[index].sickLeavesList!.map((sickLeave) {
// // return Column(
// // crossAxisAlignment: CrossAxisAlignment.start,
// // children: [
// // Row(
// // mainAxisSize: MainAxisSize.min,
// // children: [
// // Image.network(
// // sickLeave.doctorImageURL!,
// // width: 24.h,
// // height: 24.h,
// // fit: BoxFit.fill,
// // ).circle(100),
// // SizedBox(width: 8.h),
// // Expanded(child: sickLeave.doctorName!.toText14(weight: FontWeight.w500)),
// // ],
// // ),
// // SizedBox(height: 8.h),
// // Wrap(
// // direction: Axis.horizontal,
// // spacing: 6.h,
// // runSpacing: 6.h,
// // children: [
// // AppCustomChipWidget(
// // labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(sickLeave.appointmentDate), false),
// // ),
// // AppCustomChipWidget(
// // labelText: model.isSickLeavesSortByClinic ? sickLeave.projectName! : sickLeave.clinicName!,
// // ),
// // AppCustomChipWidget(
// // labelText: "${sickLeave.sickLeaveDays} Days",
// // ),
// // ],
// // ),
// // SizedBox(height: 12.h),
// // Row(
// // children: [
// // Expanded(
// // flex: 6,
// // child: CustomButton(
// // text: LocaleKeys.downloadReport.tr(context: context),
// // onPressed: () async {
// // LoaderBottomSheet.showLoader();
// // await medicalFileViewModel.getPatientSickLeavePDF(sickLeave, appState.getAuthenticatedUser()!).then((val) async {
// // LoaderBottomSheet.hideLoader();
// // if (medicalFileViewModel.patientSickLeavePDFBase64.isNotEmpty) {
// // String path = await Utils.createFileFromString(medicalFileViewModel.patientSickLeavePDFBase64, "pdf");
// // try {
// // OpenFilex.open(path);
// // } catch (ex) {
// // debugPrint("Error opening file: $ex");
// // }
// // }
// // });
// // },
// // backgroundColor: AppColors.secondaryLightRedColor,
// // borderColor: AppColors.secondaryLightRedColor,
// // textColor: AppColors.primaryRedColor,
// // fontSize: 14,
// // fontWeight: FontWeight.w500,
// // borderRadius: 12,
// // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// // height: 40.h,
// // icon: AppAssets.download,
// // iconColor: AppColors.primaryRedColor,
// // iconSize: 14.h,
// // ),
// // ),
// // ],
// // ),
// // SizedBox(height: 12.h),
// // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
// // SizedBox(height: 12.h),
// // ],
// // );
// // }),
// // ],
// // ),
// // )
// // : SizedBox.shrink(),
// // ),
// ],
// ),
// ),
), ),
),
),
), ),
), ),
) )
: Utils.getNoDataWidget(context, noDataText: LocaleKeys.youDontHaveAnySickLeavesYet.tr(context: context)); : Utils.getNoDataWidget(context, noDataText: LocaleKeys.youDontHaveAnySickLeavesYet.tr(context: context));
}, },
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 24.h),
], ],
); );
}), }),

@ -74,7 +74,7 @@ class MedicalFileAppointmentCard extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
(patientAppointmentHistoryResponseModel.doctorNameObj ?? "").toText14(isBold: true, maxlines: 1).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading), (patientAppointmentHistoryResponseModel.doctorNameObj ?? "").toText14(isBold: true, maxlines: 1, isEnglishOnly: !Utils.isArabicText(patientAppointmentHistoryResponseModel.doctorNameObj ?? "")).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
(patientAppointmentHistoryResponseModel.clinicName ?? "") (patientAppointmentHistoryResponseModel.clinicName ?? "")
.toText12(maxLine: 1, fontWeight: FontWeight.w500, color: AppColors.greyTextColor) .toText12(maxLine: 1, fontWeight: FontWeight.w500, color: AppColors.greyTextColor)
.toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading), .toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),

@ -40,18 +40,17 @@ class PatientSickLeaveCard extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( // Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ // children: [
"${LocaleKeys.sick.tr(context: context)} ${LocaleKeys.sickSubtitle.tr(context: context)}".toText16(isBold: true).toShimmer2(isShow: isLoading), // AppCustomChipWidget(
AppCustomChipWidget( // labelText: isLoading ? "" : getStatusText(context),
labelText: isLoading ? "" : getStatusText(context), // backgroundColor: getStatusColor().withOpacity(0.15),
backgroundColor: getStatusColor().withOpacity(0.15), // textColor: getStatusColor(),
textColor: getStatusColor(), // ).toShimmer2(isShow: isLoading, width: 100.h),
).toShimmer2(isShow: isLoading, width: 100.h), // ],
], // ),
), // SizedBox(height: 16.h),
SizedBox(height: 16.h),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [

@ -1,3 +1,5 @@
import 'dart:async';
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:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
@ -9,16 +11,22 @@ import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_update_details_card.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:provider/provider.dart';
class FamilyCards extends StatefulWidget { class FamilyCards extends StatefulWidget {
final List<FamilyFileResponseModelLists> profiles; final List<FamilyFileResponseModelLists> profiles;
late List<FamilyFileResponseModelLists>? profileViewList;
final Function(FamilyFileResponseModelLists) onSelect; final Function(FamilyFileResponseModelLists) onSelect;
final Function(FamilyFileResponseModelLists) onRemove; final Function(FamilyFileResponseModelLists) onRemove;
final bool isShowDetails; final bool isShowDetails;
@ -28,11 +36,12 @@ class FamilyCards extends StatefulWidget {
final bool isShowRemoveButton; final bool isShowRemoveButton;
final bool isForWalletRecharge; final bool isForWalletRecharge;
const FamilyCards( FamilyCards(
{super.key, {super.key,
required this.profiles, required this.profiles,
required this.onSelect, required this.onSelect,
required this.onRemove, required this.onRemove,
this.profileViewList,
this.isShowDetails = false, this.isShowDetails = false,
this.isBottomSheet = false, this.isBottomSheet = false,
this.isRequestDesign = false, this.isRequestDesign = false,
@ -46,9 +55,22 @@ class FamilyCards extends StatefulWidget {
class _FamilyCardsState extends State<FamilyCards> { class _FamilyCardsState extends State<FamilyCards> {
AppState appState = getIt<AppState>(); AppState appState = getIt<AppState>();
late InsuranceViewModel insuranceViewModel;
@override
void initState() {
scheduleMicrotask(() {
insuranceViewModel.initInsuranceProvider();
});
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
widget.profileViewList = [];
widget.profileViewList!.addAll(widget.profiles);
widget.profileViewList!.removeWhere((element) => element.responseId == appState.getAuthenticatedUser()?.patientId);
insuranceViewModel = Provider.of<InsuranceViewModel>(context, listen: false);
DialogService dialogService = getIt.get<DialogService>(); DialogService dialogService = getIt.get<DialogService>();
if (widget.isRequestDesign) { if (widget.isRequestDesign) {
return Column( return Column(
@ -71,15 +93,15 @@ class _FamilyCardsState extends State<FamilyCards> {
], ],
), ),
SizedBox(height: 24.h), SizedBox(height: 24.h),
widget.profiles.where((profile) => profile.isRequestFromMySide ?? false).isEmpty widget.profileViewList!.where((profile) => profile.isRequestFromMySide ?? false).isEmpty
? Utils.getNoDataWidget(context) ? Utils.getNoDataWidget(context)
: ListView.builder( : ListView.builder(
shrinkWrap: true, shrinkWrap: true,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
itemCount: widget.profiles.where((profile) => profile.isRequestFromMySide ?? false).length, itemCount: widget.profileViewList!.where((profile) => profile.isRequestFromMySide ?? false).length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final mySideProfiles = widget.profiles.where((profile) => profile.isRequestFromMySide ?? false).toList(); final mySideProfiles = widget.profileViewList!.where((profile) => profile.isRequestFromMySide ?? false).toList();
FamilyFileResponseModelLists profile = mySideProfiles[index]; FamilyFileResponseModelLists profile = mySideProfiles[index];
return Container( return Container(
margin: EdgeInsets.only(bottom: 12.h), margin: EdgeInsets.only(bottom: 12.h),
@ -102,7 +124,7 @@ class _FamilyCardsState extends State<FamilyCards> {
: profile.status == FamilyFileEnum.active.toInt : profile.status == FamilyFileEnum.active.toInt
? AppColors.lightGreenColor ? AppColors.lightGreenColor
: AppColors.lightGrayBGColor, : AppColors.lightGrayBGColor,
chipText: profile.statusDescription ?? "N/A", chipText: profile.statusDescription ?? " N/A",
iconAsset: null, iconAsset: null,
isShowBorder: false, isShowBorder: false,
borderRadius: 8.h, borderRadius: 8.h,
@ -146,113 +168,252 @@ class _FamilyCardsState extends State<FamilyCards> {
], ],
); );
} else { } else {
return GridView.builder( return Column(
shrinkWrap: true, children: [
physics: NeverScrollableScrollPhysics(), Container(
itemCount: widget.profiles.length, width: double.infinity,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r),
crossAxisCount: 2, child: Padding(
crossAxisSpacing: 10.w, padding: EdgeInsets.all(16.w),
mainAxisSpacing: 10.h, child: Column(
childAspectRatio: widget.isShowDetails ? 0.56.h : 0.64.h, crossAxisAlignment: CrossAxisAlignment.start,
),
padding: EdgeInsets.only(bottom: 20.h),
itemBuilder: (context, index) {
final profile = widget.profiles[index];
final isActive = (profile.responseId == appState.getAuthenticatedUser()?.patientId);
final isParentUser = appState.getAuthenticatedUser()?.isParentUser ?? false;
final canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID);
return Container(
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 15.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24),
child: Opacity(
opacity: isActive || profile.status == FamilyFileEnum.pending.toInt || !canSwitch ? 0.4 : 1.0, // Fade all content if active
child: Stack(
children: [ children: [
Column( Row(
mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Utils.buildImgWithAssets( Image.asset(appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg, width: 56.w, height: 56.h),
icon: profile.gender == null SizedBox(width: 8.w),
? AppAssets.dummyUser Column(
: profile.gender == 1 crossAxisAlignment: CrossAxisAlignment.start,
? ((profile.age ?? 0) < 7 ? AppAssets.babyBoyImg : AppAssets.maleImg) children: [
: (profile.age! < 7 ? AppAssets.babyGirlImg : AppAssets.femaleImg), SizedBox(
width: 72.h, width: MediaQuery.of(context).size.width * 0.6,
height: 70.h, child: "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}"
.toText18(isBold: true, weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 2),
),
SizedBox(height: 4.h),
Wrap(
direction: Axis.horizontal,
spacing: 4.w,
runSpacing: 6.w,
children: [
AppCustomChipWidget(
icon: AppAssets.file_icon,
richText: "${LocaleKeys.fileno.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}".toText10(isEnglishOnly: true),
labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w),
),
AppCustomChipWidget(
icon: AppAssets.checkmark_icon,
labelText: LocaleKeys.verified.tr(context: context),
iconColor: AppColors.successColor,
labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w),
),
],
),
],
)
],
),
SizedBox(height: 16.h),
Divider(color: AppColors.dividerColor, height: 1.h),
SizedBox(height: 16.h),
Wrap(
direction: Axis.horizontal,
spacing: 4.h,
runSpacing: 4.h,
children: [
AppCustomChipWidget(
labelText: LocaleKeys.ageYearsOld.tr(namedArgs: {'age': '${appState.getAuthenticatedUser()!.age}', 'yearsOld': LocaleKeys.yearsOld.tr(context: context)}, context: context),
labelPadding: EdgeInsetsDirectional.only(start: 8.w, end: 8.w),
), ),
SizedBox(height: 8.h), AppCustomChipWidget(
(profile.patientName ?? "Unknown").toText14(isBold: false, isCenter: true, maxlines: 1, weight: FontWeight.w600), icon: AppAssets.blood_icon,
SizedBox(height: 8.h), labelText: appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup,
CustomChipWidget( iconColor: AppColors.primaryRedColor,
chipType: ChipTypeEnum.alert, labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w),
backgroundColor: AppColors.lightGrayBGColor, padding: EdgeInsets.zero,
chipText: "Relation:${profile.relationship ?? " N/A"}", ),
iconAsset: AppAssets.heart, Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
isShowBorder: false, return AppCustomChipWidget(
borderRadius: 8.h, icon: insuranceVM.isInsuranceExpired
textColor: AppColors.textColor), ? AppAssets.cancel_circle_icon
widget.isShowDetails ? SizedBox(height: 4.h) : SizedBox(), : insuranceVM.isInsuranceActive
widget.isShowDetails ? AppAssets.insurance_active_icon
? CustomChipWidget( : AppAssets.alertSquare,
labelText: insuranceVM.isInsuranceExpired
? LocaleKeys.insuranceExpired.tr(context: context)
: insuranceVM.isInsuranceActive
? LocaleKeys.insuranceActive.tr(context: context)
: LocaleKeys.insuranceInActive.tr(context: context),
iconColor: insuranceVM.isInsuranceExpired
? AppColors.primaryRedColor
: insuranceVM.isInsuranceActive
? AppColors.successColor
: AppColors.warningColorYellow,
textColor: insuranceVM.isInsuranceExpired
? AppColors.primaryRedColor
: insuranceVM.isInsuranceActive
? AppColors.successColor
: AppColors.warningColorYellow,
iconSize: 12.w,
deleteIcon: insuranceVM.isInsuranceActive ? null : AppAssets.forward_chevron_icon,
deleteIconColor: insuranceVM.isInsuranceExpired
? AppColors.primaryRedColor
: insuranceVM.isInsuranceActive
? AppColors.successColor
: AppColors.warningColorYellow,
deleteIconHasColor: true,
onChipTap: () {
if (!insuranceVM.isInsuranceActive) {
insuranceVM.setIsInsuranceUpdateDetailsLoading(true);
insuranceVM.getPatientInsuranceDetailsForUpdate(
appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString());
showCommonBottomSheetWithoutHeight(context, child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false);
// showCommonBottomSheetWithoutHeight(
// title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
// navigationService.navigatorKey.currentContext!,
// child: Utils.getWarningWidget(
// loadingText: LocaleKeys.insuranceInActiveContactSupport.tr(context: context),
// confirmText: LocaleKeys.contactUs.tr(context: context),
// isShowActionButtons: true,
// onCancelTap: () {
// navigationService.pop();
// },
// onConfirmTap: () async {
// launchUrl(Uri.parse("tel://" + "+966 92 006 6666"));
// }),
// callBackFunc: () {},
// isFullScreen: false,
// isCloseButtonVisible: true,
// );
}
},
backgroundColor: insuranceVM.isInsuranceExpired
? AppColors.primaryRedColor.withOpacity(0.1)
: insuranceVM.isInsuranceActive
? AppColors.successColor.withOpacity(0.1)
: AppColors.warningColorYellow.withOpacity(0.1),
labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: insuranceVM.isInsuranceActive ? 6.w : 0.w),
).toShimmer2(isShow: insuranceVM.isInsuranceLoading);
}),
],
),
],
),
),
).paddingSymmetrical(0.w, 0.0),
SizedBox(height: 16.h),
GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: widget.profileViewList!.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10.w,
mainAxisSpacing: 10.h,
childAspectRatio: widget.isShowDetails ? 0.56.h : 0.74.h,
),
padding: EdgeInsets.only(bottom: 20.h),
itemBuilder: (context, index) {
final profile = widget.profileViewList![index];
final isActive = (profile.responseId == appState.getAuthenticatedUser()?.patientId);
final isParentUser = appState.getAuthenticatedUser()?.isParentUser ?? false;
final canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID);
return Container(
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 15.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
child: Opacity(
opacity: isActive || profile.status == FamilyFileEnum.pending.toInt || !canSwitch ? 0.4 : 1.0, // Fade all content if active
child: Stack(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Utils.buildImgWithAssets(
icon: profile.gender == null
? AppAssets.dummyUser
: profile.gender == 1
? ((profile.age ?? 0) < 7 ? AppAssets.babyBoyImg : AppAssets.maleImg)
: (profile.age! < 7 ? AppAssets.babyGirlImg : AppAssets.femaleImg),
width: 72.h,
height: 70.h,
),
SizedBox(height: 8.h),
(profile.patientName ?? "Unknown").toText14(isBold: false, isCenter: true, maxlines: 1, weight: FontWeight.w600),
SizedBox(height: 8.h),
CustomChipWidget(
chipType: ChipTypeEnum.alert, chipType: ChipTypeEnum.alert,
backgroundColor: AppColors.lightGrayBGColor, backgroundColor: AppColors.lightGrayBGColor,
chipText: "Age:${profile.age ?? "N/A"} Years", chipText: "Relation: ${profile.relationship ?? " N/A"}",
iconAsset: AppAssets.heart,
isShowBorder: false, isShowBorder: false,
borderRadius: 8.h, borderRadius: 8.h,
textColor: AppColors.textColor, textColor: AppColors.textColor),
) widget.isShowDetails ? SizedBox(height: 4.h) : SizedBox(),
: SizedBox(), widget.isShowDetails
widget.isShowDetails ? CustomChipWidget(
? SizedBox(height: 8.h) chipType: ChipTypeEnum.alert,
: SizedBox( backgroundColor: AppColors.lightGrayBGColor,
height: 4.h, chipText: "Age: ${profile.age ?? "N/A"} Years",
), isShowBorder: false,
Spacer(), borderRadius: 8.h,
widget.isForWalletRecharge ? CustomButton( textColor: AppColors.textColor,
height: 40.h, )
onPressed: () { : SizedBox(),
widget.onSelect(profile); widget.isShowDetails
// if (canSwitch) widget.onSelect(profile); ? SizedBox(height: 8.h)
}, : SizedBox(
text: LocaleKeys.select.tr(context: context), height: 4.h,
backgroundColor: AppColors.secondaryLightRedColor, ),
borderColor: AppColors.secondaryLightRedColor, Spacer(),
textColor: AppColors.primaryRedColor, widget.isForWalletRecharge
fontSize: 13.h, ? CustomButton(
icon: AppAssets.activeCheck, height: 40.h,
iconColor: isActive || !canSwitch ? (isActive ? null : AppColors.greyTextColor) : AppColors.primaryRedColor, onPressed: () {
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 0), widget.onSelect(profile);
).paddingOnly(top: 0, bottom: 0) : CustomButton( // if (canSwitch) widget.onSelect(profile);
height: 40.h, },
onPressed: () { text: LocaleKeys.select.tr(context: context),
if (canSwitch) widget.onSelect(profile); backgroundColor: AppColors.secondaryLightRedColor,
}, borderColor: AppColors.secondaryLightRedColor,
text: isActive ? LocaleKeys.active.tr(context: context) : LocaleKeys.switchLogin.tr(context: context), textColor: AppColors.primaryRedColor,
backgroundColor: isActive || !canSwitch ? Colors.grey.shade200 : AppColors.secondaryLightRedColor, fontSize: 13.h,
borderColor: isActive || !canSwitch ? Colors.grey.shade200 : AppColors.secondaryLightRedColor, icon: AppAssets.activeCheck,
textColor: isActive || !canSwitch ? AppColors.greyTextColor : AppColors.primaryRedColor, iconColor: isActive || !canSwitch ? (isActive ? null : AppColors.greyTextColor) : AppColors.primaryRedColor,
fontSize: 13.h, padding: EdgeInsets.symmetric(vertical: 0, horizontal: 0),
icon: isActive ? AppAssets.activeCheck : AppAssets.switch_user, ).paddingOnly(top: 0, bottom: 0)
iconColor: isActive || !canSwitch ? (isActive ? null : AppColors.greyTextColor) : AppColors.primaryRedColor, : CustomButton(
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 0), height: 40.h,
).paddingOnly(top: 0, bottom: 0), onPressed: () {
if (canSwitch) widget.onSelect(profile);
},
text: isActive ? LocaleKeys.active.tr(context: context) : LocaleKeys.switchLogin.tr(context: context),
backgroundColor: isActive || !canSwitch ? Colors.grey.shade200 : AppColors.secondaryLightRedColor,
borderColor: isActive || !canSwitch ? Colors.grey.shade200 : AppColors.secondaryLightRedColor,
textColor: isActive || !canSwitch ? AppColors.greyTextColor : AppColors.primaryRedColor,
fontSize: 13.h,
icon: isActive ? AppAssets.activeCheck : AppAssets.switch_user,
iconColor: isActive || !canSwitch ? (isActive ? null : AppColors.greyTextColor) : AppColors.primaryRedColor,
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 0),
).paddingOnly(top: 0, bottom: 0),
],
),
if (widget.isShowRemoveButton) ...[
Positioned(
top: 0,
right: 0,
child: Utils.buildSvgWithAssets(icon: AppAssets.deleteIcon).onPress(() {
if (!isActive) widget.onRemove(profile);
}),
),
],
], ],
), ),
if (widget.isShowRemoveButton) ...[ ),
Positioned( );
top: 0, },
right: 0, ),
child: Utils.buildSvgWithAssets(icon: AppAssets.deleteIcon).onPress(() { ],
if (!isActive) widget.onRemove(profile);
}),
),
],
],
),
),
);
},
); );
} }
} }
@ -260,15 +421,15 @@ class _FamilyCardsState extends State<FamilyCards> {
Widget manageFamily() { Widget manageFamily() {
NavigationService navigationService = getIt<NavigationService>(); NavigationService navigationService = getIt<NavigationService>();
return widget.profiles.where((profile) => !(profile.isRequestFromMySide ?? false)).isEmpty return widget.profileViewList!.where((profile) => !(profile.isRequestFromMySide ?? false)).isEmpty
? Utils.getNoDataWidget(context) ? Utils.getNoDataWidget(context)
: ListView.builder( : ListView.builder(
shrinkWrap: true, shrinkWrap: true,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
padding: EdgeInsetsGeometry.zero, padding: EdgeInsetsGeometry.zero,
itemCount: widget.profiles.where((profile) => !(profile.isRequestFromMySide ?? false)).length, itemCount: widget.profileViewList!.where((profile) => !(profile.isRequestFromMySide ?? false)).length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final otherProfiles = widget.profiles.where((profile) => !(profile.isRequestFromMySide ?? false)).toList(); final otherProfiles = widget.profileViewList!.where((profile) => !(profile.isRequestFromMySide ?? false)).toList();
FamilyFileResponseModelLists profile = otherProfiles[index]; FamilyFileResponseModelLists profile = otherProfiles[index];
return Container( return Container(
margin: EdgeInsets.only(bottom: 12.h), margin: EdgeInsets.only(bottom: 12.h),

@ -9,6 +9,7 @@ import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_invoices/models/get_invoice_details_response_model.dart'; import 'package:hmg_patient_app_new/features/my_invoices/models/get_invoice_details_response_model.dart';
import 'package:hmg_patient_app_new/features/my_invoices/models/get_invoices_list_response_model.dart';
import 'package:hmg_patient_app_new/features/my_invoices/my_invoices_view_model.dart'; import 'package:hmg_patient_app_new/features/my_invoices/my_invoices_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
@ -20,8 +21,9 @@ import 'package:provider/provider.dart';
class MyInvoicesDetailsPage extends StatefulWidget { class MyInvoicesDetailsPage extends StatefulWidget {
GetInvoiceDetailsResponseModel getInvoiceDetailsResponseModel; GetInvoiceDetailsResponseModel getInvoiceDetailsResponseModel;
GetInvoicesListResponseModel getInvoicesListResponseModel;
MyInvoicesDetailsPage({super.key, required this.getInvoiceDetailsResponseModel}); MyInvoicesDetailsPage({super.key, required this.getInvoiceDetailsResponseModel, required this.getInvoicesListResponseModel});
@override @override
State<MyInvoicesDetailsPage> createState() => _MyInvoicesDetailsPageState(); State<MyInvoicesDetailsPage> createState() => _MyInvoicesDetailsPageState();
@ -82,6 +84,26 @@ class _MyInvoicesDetailsPageState extends State<MyInvoicesDetailsPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Wrap(
alignment: WrapAlignment.start,
direction: Axis.horizontal,
spacing: 6.w,
runSpacing: 6.h,
children: [
AppCustomChipWidget(
icon: AppAssets.walkin_appointment_icon,
iconColor: AppColors.textColor,
labelText: LocaleKeys.walkin.tr(context: context),
textColor: AppColors.textColor,
),
AppCustomChipWidget(
labelText: LocaleKeys.outPatient.tr(context: context),
backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.1),
textColor: AppColors.warningColorYellow,
),
],
),
SizedBox(height: 16.h),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -93,6 +115,29 @@ class _MyInvoicesDetailsPageState extends State<MyInvoicesDetailsPage> {
height: 63.h, height: 63.h,
fit: BoxFit.cover, fit: BoxFit.cover,
).circle(100.r), ).circle(100.r),
Transform.translate(
offset: Offset(0.0, -20.h),
child: Container(
width: 40.w,
height: 40.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
shape: BoxShape.circle, // Makes the container circular
border: Border.all(
color: AppColors.scaffoldBgColor, // Color of the border
width: 1.5.w, // Width of the border
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h, applyThemeColor: false),
SizedBox(height: 2.h),
"${widget.getInvoicesListResponseModel.decimalDoctorRate}".toText11(isBold: true, color: AppColors.textColor),
],
),
).circle(100),
),
], ],
), ),
SizedBox(width: 16.w), SizedBox(width: 16.w),
@ -138,41 +183,46 @@ class _MyInvoicesDetailsPageState extends State<MyInvoicesDetailsPage> {
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Container( Row(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( mainAxisSize: MainAxisSize.max,
color: AppColors.whiteColor, children: [
borderRadius: 20.h, Container(
hasShadow: true, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
), color: AppColors.whiteColor,
child: Padding( borderRadius: 20.h,
padding: EdgeInsets.all(14.h), hasShadow: true,
child: Column( ),
crossAxisAlignment: CrossAxisAlignment.start, child: Padding(
children: [ padding: EdgeInsets.all(14.h),
widget.getInvoiceDetailsResponseModel.listConsultation!.first.procedureName!.toText16(isBold: true), child: Column(
SizedBox(height: 16.h), crossAxisAlignment: CrossAxisAlignment.start,
Wrap(
direction: Axis.horizontal,
spacing: 6.w,
runSpacing: 6.h,
children: [ children: [
AppCustomChipWidget( widget.getInvoiceDetailsResponseModel.listConsultation!.first.procedureName!.toText16(isBold: true),
labelText: "${LocaleKeys.quantity.tr()}: ${widget.getInvoiceDetailsResponseModel.listConsultation!.first.quantity!}", SizedBox(height: 16.h),
labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), Wrap(
), direction: Axis.horizontal,
AppCustomChipWidget( spacing: 6.w,
labelText: "${LocaleKeys.price.tr()}: ${widget.getInvoiceDetailsResponseModel.listConsultation!.first.price!} ${LocaleKeys.sar.tr()}", runSpacing: 6.h,
labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), children: [
), AppCustomChipWidget(
AppCustomChipWidget( labelText: "${LocaleKeys.quantity.tr()}: ${widget.getInvoiceDetailsResponseModel.listConsultation!.first.quantity!}",
labelText: "${LocaleKeys.total.tr()}: ${widget.getInvoiceDetailsResponseModel.listConsultation!.first.total!} ${LocaleKeys.sar.tr()}", labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w),
labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), ),
AppCustomChipWidget(
labelText: "${LocaleKeys.price.tr()}: ${widget.getInvoiceDetailsResponseModel.listConsultation!.first.price!} ${LocaleKeys.sar.tr()}",
labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w),
),
AppCustomChipWidget(
labelText: "${LocaleKeys.total.tr()}: ${widget.getInvoiceDetailsResponseModel.listConsultation!.first.total!} ${LocaleKeys.sar.tr()}",
labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w),
),
],
), ),
], ],
), ),
], ),
), ),
), ],
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Container( Container(

@ -86,7 +86,7 @@ class _MyInvoicesListState extends State<MyInvoicesList> {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
page: MyInvoicesDetailsPage(getInvoiceDetailsResponseModel: myInvoicesVM.invoiceDetailsResponseModel), page: MyInvoicesDetailsPage(getInvoiceDetailsResponseModel: myInvoicesVM.invoiceDetailsResponseModel, getInvoicesListResponseModel: myInvoicesVM.allInvoicesList[index],),
), ),
); );
}, },

@ -47,8 +47,8 @@ class InvoiceListCard extends StatelessWidget {
), ),
AppCustomChipWidget( AppCustomChipWidget(
labelText: LocaleKeys.outPatient.tr(context: context), labelText: LocaleKeys.outPatient.tr(context: context),
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.1), backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.1),
textColor: AppColors.primaryRedColor, textColor: AppColors.warningColorYellow,
), ),
], ],
), ),

@ -4,6 +4,8 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
@ -23,6 +25,8 @@ import 'package:open_filex/open_filex.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'dart:ui' as ui;
class PrescriptionDetailPage extends StatefulWidget { class PrescriptionDetailPage extends StatefulWidget {
PrescriptionDetailPage({super.key, required this.prescriptionsResponseModel, required this.isFromAppointments}); PrescriptionDetailPage({super.key, required this.prescriptionsResponseModel, required this.isFromAppointments});
@ -61,8 +65,9 @@ class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
title: LocaleKeys.prescriptions.tr(context: context), title: LocaleKeys.prescriptions.tr(context: context),
instructions: () async { instructions: widget.prescriptionsResponseModel.isInOutPatient!
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPrescriptionPDFPleaseWait.tr(context: context)); ? () async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPrescriptionPDFPleaseWait.tr(context: context));
await prescriptionsViewModel.getPrescriptionInstructionsPDF(widget.prescriptionsResponseModel, onSuccess: (val) { await prescriptionsViewModel.getPrescriptionInstructionsPDF(widget.prescriptionsResponseModel, onSuccess: (val) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
if (prescriptionsViewModel.prescriptionInstructionsPDFLink.isNotEmpty) { if (prescriptionsViewModel.prescriptionInstructionsPDFLink.isNotEmpty) {
@ -87,7 +92,8 @@ class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
isCloseButtonVisible: true, isCloseButtonVisible: true,
); );
}); });
}, }
: null,
child: SingleChildScrollView( child: SingleChildScrollView(
child: Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) { child: Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) {
return Column( return Column(
@ -105,6 +111,13 @@ class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
AppCustomChipWidget(
labelText:
"${getIt.get<AppState>().isArabic() ? widget.prescriptionsResponseModel.isInOutPatientDescriptionN : widget.prescriptionsResponseModel.isInOutPatientDescription}",
backgroundColor: AppColors.warningColorYellow.withOpacity(0.1),
textColor: AppColors.warningColorYellow,
),
SizedBox(height: 16.h),
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -124,11 +137,15 @@ class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
spacing: 4.h, spacing: 4.h,
runSpacing: 4.h, runSpacing: 4.h,
children: [ children: [
AppCustomChipWidget( Directionality(
icon: AppAssets.doctor_calendar_icon, textDirection: ui.TextDirection.ltr,
labelText: DateUtil.formatDateToDate( child: AppCustomChipWidget(
DateUtil.convertStringToDate(widget.prescriptionsResponseModel.appointmentDate), false), icon: AppAssets.doctor_calendar_icon,
labelPadding: EdgeInsetsDirectional.only(start: -4.h, end: 8.h), labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.prescriptionsResponseModel.appointmentDate), false),
isEnglishOnly: true
,
labelPadding: EdgeInsetsDirectional.only(start: -4.h, end: 8.h),
),
), ),
AppCustomChipWidget( AppCustomChipWidget(
labelText: widget.prescriptionsResponseModel.clinicDescription!, labelText: widget.prescriptionsResponseModel.clinicDescription!,
@ -225,9 +242,7 @@ class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
hasShadow: true, hasShadow: true,
), ),
child: CustomButton( child: CustomButton(
text: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! text: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? LocaleKeys.resendOrder.tr(context: context) : LocaleKeys.prescriptionDeliveryError.tr(context: context),
? LocaleKeys.resendOrder.tr(context: context)
: LocaleKeys.prescriptionDeliveryError.tr(context: context),
onPressed: () async { onPressed: () async {
if (widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported!) { if (widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported!) {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPrescriptionDetails.tr(context: context)); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPrescriptionDetails.tr(context: context));
@ -237,18 +252,16 @@ class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
}); });
} }
}, },
backgroundColor: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.greyF7Color, backgroundColor: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.15),
borderColor: AppColors.successColor.withOpacity(0.01), borderColor: AppColors.successColor.withOpacity(0.01),
textColor: textColor: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? Colors.white : AppColors.textColor.withOpacity(0.35),
widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? Colors.white : AppColors.textColor.withOpacity(0.35),
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderRadius: 12, borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 50.h, height: 50.h,
icon: AppAssets.prescription_refill_icon, icon: AppAssets.prescription_refill_icon,
iconColor: iconColor: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? Colors.white : AppColors.textColor.withOpacity(0.35),
widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? Colors.white : AppColors.textColor.withOpacity(0.35),
iconSize: 20.h, iconSize: 20.h,
).paddingSymmetrical(24.h, 24.h), ).paddingSymmetrical(24.h, 24.h),
), ),

@ -47,7 +47,7 @@ class PrescriptionItemView extends StatelessWidget {
fit: BoxFit.fill, fit: BoxFit.fill,
).toShimmer2(isShow: isLoading).circle(100), ).toShimmer2(isShow: isLoading).circle(100),
Expanded( Expanded(
child: (isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].itemDescription!).toText16(isBold: true, maxlines: 2).toShimmer2(isShow: isLoading), child: (isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].itemDescription!).toText16(isBold: true, maxlines: 2, isEnglishOnly: true).toShimmer2(isShow: isLoading),
), ),
], ],
).paddingSymmetrical(16.h, 0.h), ).paddingSymmetrical(16.h, 0.h),
@ -78,7 +78,9 @@ class PrescriptionItemView extends StatelessWidget {
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.prescription_remarks_icon, width: 18.h, height: 18.h), Utils.buildSvgWithAssets(icon: AppAssets.prescription_remarks_icon, width: 18.h, height: 18.h),
SizedBox(width: 9.h), SizedBox(width: 9.h),
Expanded(child: "${LocaleKeys.remarks.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].remarks!}".toText10(isBold: true)), Expanded(
child: "${LocaleKeys.remarks.tr(context: context)} ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].remarks!}".toText10(isBold: true, isEnglishOnly: true),
),
], ],
).paddingSymmetrical(16.h, 0.h), ).paddingSymmetrical(16.h, 0.h),
SizedBox(height: 14.h), SizedBox(height: 14.h),
@ -95,61 +97,65 @@ class PrescriptionItemView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.setReminder.tr(context: context).toText13(isBold: true), LocaleKeys.setReminder.tr(context: context).toText13(isBold: true),
"Notify me before the consumption time".toText10(color: AppColors.textColorLight), "Notify me before the consumption time".toText10(color: AppColors.textColorLight, isEnglishOnly: true),
], ],
).toShimmer2(isShow: isLoading).expanded, ).toShimmer2(isShow: isLoading).expanded,
Switch( Switch(
activeColor: AppColors.successColor, activeColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: .15), activeTrackColor: AppColors.successColor.withValues(alpha: .15),
value: isLoading ? false : prescriptionVM.prescriptionDetailsList[index].hasReminder!, value: isLoading ? false : prescriptionVM.prescriptionDetailsList[index].hasReminder!,
// value: prescriptionVM.prescriptionDetailsList[index].hasReminder ?? false,
onChanged: (newValue) async { onChanged: (newValue) async {
CalenderUtilsNew calender = CalenderUtilsNew.instance; CalenderUtilsNew calender = CalenderUtilsNew.instance;
if (prescriptionVM.prescriptionDetailsList[index].hasReminder ?? false) { if (await prescriptionVM.checkIfReminderExistForPrescription(index)) {
LoaderBottomSheet.showLoader(loadingText: "Removing Reminders"); prescriptionVM.prescriptionDetailsList[index].hasReminder = true;
bool resultValue = await calender.checkAndRemoveMultipleItems(id: prescriptionVM.prescriptionDetailsList[index].itemID.toString()); if (prescriptionVM.prescriptionDetailsList[index].hasReminder ?? false) {
LoaderBottomSheet.showLoader(loadingText: "Removing Reminders");
bool resultValue = await calender.checkAndRemoveMultipleItems(id: prescriptionVM.prescriptionDetailsList[index].itemID.toString());
prescriptionVM.setPrescriptionItemReminder(newValue, prescriptionVM.prescriptionDetailsList[index]); prescriptionVM.setPrescriptionItemReminder(newValue, prescriptionVM.prescriptionDetailsList[index]);
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
return; return;
}
} else {
DateTime startDate = DateTime.now();
DateTime endDate = DateTime(startDate.year, startDate.month, startDate.day + prescriptionVM.prescriptionDetailsList[index].days!.toInt());
BottomSheetUtils().showReminderBottomSheet(
context,
endDate,
"",
prescriptionVM.prescriptionDetailsList[index].itemID.toString(),
"",
"",
title: "${prescriptionVM.prescriptionDetailsList[index].itemDescription} Prescription Reminder",
description:
"${prescriptionVM.prescriptionDetailsList[index].itemDescription} ${prescriptionVM.prescriptionDetailsList[index].frequency} ${prescriptionVM.prescriptionDetailsList[index].route} ",
onSuccess: () {},
isMultiAllowed: true,
onMultiDateSuccess: (int selectedIndex) async {
bool isEventAdded = await calender.createMultipleEvents(
reminderMinutes: selectedIndex,
frequencyNumber: prescriptionVM.prescriptionDetailsList[index].frequencyNumber?.toInt(),
days: prescriptionVM.prescriptionDetailsList[index].days!.toInt(),
orderDate: prescriptionVM.prescriptionDetailsList[index].orderDate!,
itemDescriptionN: prescriptionVM.prescriptionDetailsList[index].itemDescription!,
route: prescriptionVM.prescriptionDetailsList[index].route!,
onFailure: (errorMessage) => prescriptionVM.showError(errorMessage),
prescriptionNumber: prescriptionVM.prescriptionDetailsList[index].itemID.toString(),
);
prescriptionVM.setPrescriptionItemReminder(isEventAdded, prescriptionVM.prescriptionDetailsList[index]);
// setCalender(context,
// eventId: prescriptionVM.prescriptionDetailsList[index].itemID.toString(),
// selectedMinutes: selectedIndex,
// frequencyNumber: prescriptionVM.prescriptionDetailsList[index].frequencyNumber?.toInt(),
// days: prescriptionVM.prescriptionDetailsList[index].days!.toInt(),
// orderDate: prescriptionVM.prescriptionDetailsList[index].orderDate!,
// itemDescriptionN: prescriptionVM.prescriptionDetailsList[index].itemDescription!,
// route: prescriptionVM.prescriptionDetailsList[index].route!);
},
);
} }
DateTime startDate = DateTime.now();
DateTime endDate = DateTime(startDate.year, startDate.month, startDate.day + prescriptionVM.prescriptionDetailsList[index].days!.toInt());
BottomSheetUtils().showReminderBottomSheet(
context,
endDate,
"",
prescriptionVM.prescriptionDetailsList[index].itemID.toString(),
"",
"",
title: "${prescriptionVM.prescriptionDetailsList[index].itemDescription} Prescription Reminder",
description:
"${prescriptionVM.prescriptionDetailsList[index].itemDescription} ${prescriptionVM.prescriptionDetailsList[index].frequency} ${prescriptionVM.prescriptionDetailsList[index].route} ",
onSuccess: () {},
isMultiAllowed: true,
onMultiDateSuccess: (int selectedIndex) async {
bool isEventAdded = await calender.createMultipleEvents(
reminderMinutes: selectedIndex,
frequencyNumber: prescriptionVM.prescriptionDetailsList[index].frequencyNumber?.toInt(),
days: prescriptionVM.prescriptionDetailsList[index].days!.toInt(),
orderDate: prescriptionVM.prescriptionDetailsList[index].orderDate!,
itemDescriptionN: prescriptionVM.prescriptionDetailsList[index].itemDescription!,
route: prescriptionVM.prescriptionDetailsList[index].route!,
onFailure: (errorMessage) => prescriptionVM.showError(errorMessage),
prescriptionNumber: prescriptionVM.prescriptionDetailsList[index].itemID.toString(),
);
prescriptionVM.setPrescriptionItemReminder(isEventAdded, prescriptionVM.prescriptionDetailsList[index]);
// setCalender(context,
// eventId: prescriptionVM.prescriptionDetailsList[index].itemID.toString(),
// selectedMinutes: selectedIndex,
// frequencyNumber: prescriptionVM.prescriptionDetailsList[index].frequencyNumber?.toInt(),
// days: prescriptionVM.prescriptionDetailsList[index].days!.toInt(),
// orderDate: prescriptionVM.prescriptionDetailsList[index].orderDate!,
// itemDescriptionN: prescriptionVM.prescriptionDetailsList[index].itemDescription!,
// route: prescriptionVM.prescriptionDetailsList[index].route!);
},
);
}, },
).toShimmer2(isShow: isLoading), ).toShimmer2(isShow: isLoading),
], ],

@ -24,6 +24,8 @@ import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'dart:ui' as ui;
class PrescriptionsListPage extends StatefulWidget { class PrescriptionsListPage extends StatefulWidget {
const PrescriptionsListPage({super.key}); const PrescriptionsListPage({super.key});
@ -67,52 +69,52 @@ class _PrescriptionsListPageState extends State<PrescriptionsListPage> {
children: [ children: [
SizedBox(height: 16.h), SizedBox(height: 16.h),
// Clinic & Hospital Sort // Clinic & Hospital Sort
Row( // Row(
children: [ // children: [
CustomButton( // CustomButton(
text: LocaleKeys.byClinic.tr(context: context), // text: LocaleKeys.byClinic.tr(context: context),
onPressed: () { // onPressed: () {
model.setIsSortByClinic(true); // model.setIsSortByClinic(true);
}, // },
backgroundColor: model.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, // backgroundColor: model.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor,
borderColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2), // borderColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2),
textColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, // textColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor,
fontSize: 12, // fontSize: 12,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 10, // borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, // height: 40.h,
), // ),
SizedBox(width: 8.h), // SizedBox(width: 8.h),
CustomButton( // CustomButton(
text: LocaleKeys.byHospital.tr(context: context), // text: LocaleKeys.byHospital.tr(context: context),
onPressed: () { // onPressed: () {
model.setIsSortByClinic(false); // model.setIsSortByClinic(false);
}, // },
backgroundColor: model.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, // backgroundColor: model.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor,
borderColor: model.isSortByClinic ? AppColors.textColor.withOpacity(0.2) : AppColors.primaryRedColor, // borderColor: model.isSortByClinic ? AppColors.textColor.withOpacity(0.2) : AppColors.primaryRedColor,
textColor: model.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, // textColor: model.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor,
fontSize: 12, // fontSize: 12,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 10, // borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, // height: 40.h,
), // ),
], // ],
).paddingSymmetrical(24.h, 0.h), // ).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 20.h), // SizedBox(height: 20.h),
// Expandable list // Expandable list
ListView.builder( ListView.builder(
itemCount: model.isPrescriptionsOrdersLoading itemCount: model.isPrescriptionsOrdersLoading
? 4 ? 4
: model.patientPrescriptionOrders.isNotEmpty : model.patientPrescriptionOrders.isNotEmpty
? model.patientPrescriptionOrdersViewList.length ? model.patientPrescriptionOrders.length
: 1, : 1,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
padding: const EdgeInsets.only(left: 0, right: 8), padding: const EdgeInsets.only(left: 0, right: 8),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final isExpanded = expandedIndex == index; // final isExpanded = expandedIndex == index;
return model.isPrescriptionsOrdersLoading return model.isPrescriptionsOrdersLoading
? LabResultItemView( ? LabResultItemView(
onTap: () {}, onTap: () {},
@ -132,177 +134,415 @@ class _PrescriptionsListPageState extends State<PrescriptionsListPage> {
curve: Curves.easeInOut, curve: Curves.easeInOut,
margin: EdgeInsets.symmetric(vertical: 8.h), margin: EdgeInsets.symmetric(vertical: 8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
child: InkWell( child: Container(
onTap: () { key: ValueKey<int>(index),
setState(() { padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 16.h),
expandedIndex = isExpanded ? null : index;
});
},
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Padding( AppCustomChipWidget(
padding: EdgeInsets.all(16.h), labelText:
child: Column( "${getIt.get<AppState>().isArabic() ? model.patientPrescriptionOrders[index].isInOutPatientDescriptionN : model.patientPrescriptionOrders[index].isInOutPatientDescription}",
crossAxisAlignment: CrossAxisAlignment.start, backgroundColor: AppColors.warningColorYellow.withOpacity(0.1),
children: [ textColor: AppColors.warningColorYellow,
Row( ),
mainAxisAlignment: MainAxisAlignment.spaceBetween, SizedBox(height: 16.h),
children: [ Row(
CustomButton( mainAxisSize: MainAxisSize.min,
text: "${model.patientPrescriptionOrdersViewList[index].prescriptionsList!.length} Prescriptions Available", children: [
onPressed: () {}, Image.network(
backgroundColor: AppColors.greyColor, model.patientPrescriptionOrders[index].doctorImageURL!,
borderColor: AppColors.greyColor, width: 24.h,
textColor: AppColors.blackColor, height: 24.h,
fontSize: 10, fit: BoxFit.fill,
fontWeight: FontWeight.w500, ).circle(100),
borderRadius: 8, SizedBox(width: 8.h),
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), Expanded(child: model.patientPrescriptionOrders[index].doctorName!.toText14(weight: FontWeight.w500)),
height: 30.h, ],
), ),
Icon(isExpanded ? Icons.expand_less : Icons.expand_more), SizedBox(height: 8.h),
], Wrap(
direction: Axis.horizontal,
spacing: 6.h,
runSpacing: 6.h,
children: [
Directionality(
textDirection: ui.TextDirection.ltr,
child: AppCustomChipWidget(
labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(model.patientPrescriptionOrders[index].appointmentDate), false),
isEnglishOnly: true,
), ),
SizedBox(height: 8.h), ),
(model.patientPrescriptionOrdersViewList[index].filterName ?? "").toText16(isBold: true) AppCustomChipWidget(
], labelText: model.patientPrescriptionOrders[index].name,
), ),
AppCustomChipWidget(
labelText: model.patientPrescriptionOrders[index].clinicDescription!,
),
],
), ),
AnimatedSwitcher( SizedBox(height: 8.h),
duration: Duration(milliseconds: 500), Row(
switchInCurve: Curves.easeIn, children: [
switchOutCurve: Curves.easeOut, Expanded(
transitionBuilder: (Widget child, Animation<double> animation) { flex: 6,
return FadeTransition( child: CustomButton(
opacity: animation, text: model.patientPrescriptionOrders[index].isHomeMedicineDeliverySupported!
child: SizeTransition( ? LocaleKeys.resendOrder.tr(context: context)
sizeFactor: animation, : LocaleKeys.prescriptionDeliveryError.tr(context: context),
axisAlignment: 0.0, onPressed: () async {
child: child, if (model.patientPrescriptionOrders[index].isHomeMedicineDeliverySupported!) {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPrescriptionDetails.tr(context: context));
await prescriptionsViewModel.getPrescriptionDetails(prescriptionsViewModel.patientPrescriptionOrders[index], onSuccess: (val) {
LoaderBottomSheet.hideLoader();
prescriptionsViewModel.initiatePrescriptionDelivery();
});
}
},
backgroundColor: model.patientPrescriptionOrders[index].isHomeMedicineDeliverySupported!
? AppColors.successColor.withOpacity(0.15)
: AppColors.textColor.withOpacity(0.15),
borderColor: AppColors.successColor.withOpacity(0.01),
textColor: model.patientPrescriptionOrders[index].isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.35),
fontSize: model.patientPrescriptionOrders[index].isHomeMedicineDeliverySupported! ? 14.f : 12.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppAssets.prescription_refill_icon,
iconColor: model.patientPrescriptionOrders[index].isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.35),
iconSize: 16.h,
), ),
); ),
}, SizedBox(width: 8.h),
child: isExpanded Expanded(
? Container( flex: 1,
key: ValueKey<int>(index), child: Container(
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h), height: 40.h,
child: Column( width: 40.w,
crossAxisAlignment: CrossAxisAlignment.start, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
children: [ color: AppColors.textColor,
...model.patientPrescriptionOrdersViewList[index].prescriptionsList!.map((prescription) { borderRadius: 12,
return Column( ),
crossAxisAlignment: CrossAxisAlignment.start, child: Padding(
children: [ padding: EdgeInsets.all(12.h),
Row( child: Transform.flip(
mainAxisSize: MainAxisSize.min, flipX: appState.isArabic(),
children: [ child: Utils.buildSvgWithAssets(
Image.network( icon: AppAssets.forward_arrow_icon_small,
prescription.doctorImageURL!, iconColor: AppColors.whiteColor,
width: 24.h, fit: BoxFit.contain,
height: 24.h, ),
fit: BoxFit.fill, ),
).circle(100), ),
SizedBox(width: 8.h), ).onPress(() {
Expanded(child: prescription.doctorName!.toText14(weight: FontWeight.w500)), model.setPrescriptionsDetailsLoading();
], Navigator.of(context).push(
), CustomPageRoute(
SizedBox(height: 8.h), page: PrescriptionDetailPage(
Wrap( prescriptionsResponseModel: model.patientPrescriptionOrders[index],
direction: Axis.horizontal, isFromAppointments: false,
spacing: 6.h, ),
runSpacing: 6.h,
children: [
AppCustomChipWidget(
labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(prescription.appointmentDate), false),
),
AppCustomChipWidget(
labelText: model.isSortByClinic ? prescription.name ?? "" : prescription.clinicDescription!,
),
],
),
SizedBox(height: 8.h),
Row(
children: [
Expanded(
flex: 6,
child: CustomButton(
text: prescription.isHomeMedicineDeliverySupported!
? LocaleKeys.resendOrder.tr(context: context)
: LocaleKeys.prescriptionDeliveryError.tr(context: context),
onPressed: () async {
if (prescription.isHomeMedicineDeliverySupported!) {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPrescriptionDetails.tr(context: context));
await prescriptionsViewModel.getPrescriptionDetails(prescriptionsViewModel.patientPrescriptionOrders[index],
onSuccess: (val) {
LoaderBottomSheet.hideLoader();
prescriptionsViewModel.initiatePrescriptionDelivery();
});
}
},
backgroundColor:
prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor.withOpacity(0.15) : AppColors.greyF7Color,
borderColor: AppColors.successColor.withOpacity(0.01),
textColor: prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.35),
fontSize: prescription.isHomeMedicineDeliverySupported! ? 14.f : 12.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppAssets.prescription_refill_icon,
iconColor: prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.35),
iconSize: 16.h,
),
),
SizedBox(width: 8.h),
Expanded(
flex: 1,
child: Container(
height: 40.h,
width: 40.w,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.textColor,
borderRadius: 12,
),
child: Padding(
padding: EdgeInsets.all(12.h),
child: Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon_small,
iconColor: AppColors.whiteColor,
fit: BoxFit.contain,
),
),
),
).onPress(() {
model.setPrescriptionsDetailsLoading();
Navigator.of(context).push(
CustomPageRoute(
page: PrescriptionDetailPage(
prescriptionsResponseModel: prescription,
isFromAppointments: false,
),
),
);
}),
),
],
),
SizedBox(height: 12.h),
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
SizedBox(height: 12.h),
],
);
}).toList(),
],
), ),
) );
: SizedBox.shrink(), }),
),
],
), ),
// SizedBox(height: 12.h),
// Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
// SizedBox(height: 12.h),
], ],
), ),
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// ...model.patientPrescriptionOrders.map((prescription) {
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisSize: MainAxisSize.min,
// children: [
// Image.network(
// prescription.doctorImageURL!,
// width: 24.h,
// height: 24.h,
// fit: BoxFit.fill,
// ).circle(100),
// SizedBox(width: 8.h),
// Expanded(child: prescription.doctorName!.toText14(weight: FontWeight.w500)),
// ],
// ),
// SizedBox(height: 8.h),
// Wrap(
// direction: Axis.horizontal,
// spacing: 6.h,
// runSpacing: 6.h,
// children: [
// Directionality(
// textDirection: ui.TextDirection.ltr,
// child: AppCustomChipWidget(
// labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(prescription.appointmentDate), false), isEnglishOnly: true,
// ),
// ),
// AppCustomChipWidget(
// labelText: model.isSortByClinic ? prescription.name ?? "" : prescription.clinicDescription!,
// ),
// ],
// ),
// SizedBox(height: 8.h),
// Row(
// children: [
// Expanded(
// flex: 6,
// child: CustomButton(
// text: prescription.isHomeMedicineDeliverySupported!
// ? LocaleKeys.resendOrder.tr(context: context)
// : LocaleKeys.prescriptionDeliveryError.tr(context: context),
// onPressed: () async {
// if (prescription.isHomeMedicineDeliverySupported!) {
// LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPrescriptionDetails.tr(context: context));
// await prescriptionsViewModel.getPrescriptionDetails(prescriptionsViewModel.patientPrescriptionOrders[index],
// onSuccess: (val) {
// LoaderBottomSheet.hideLoader();
// prescriptionsViewModel.initiatePrescriptionDelivery();
// });
// }
// },
// backgroundColor:
// prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor.withOpacity(0.15) : AppColors.greyF7Color,
// borderColor: AppColors.successColor.withOpacity(0.01),
// textColor: prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.35),
// fontSize: prescription.isHomeMedicineDeliverySupported! ? 14.f : 12.f,
// fontWeight: FontWeight.w500,
// borderRadius: 12.r,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 40.h,
// icon: AppAssets.prescription_refill_icon,
// iconColor: prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.35),
// iconSize: 16.h,
// ),
// ),
// SizedBox(width: 8.h),
// Expanded(
// flex: 1,
// child: Container(
// height: 40.h,
// width: 40.w,
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// color: AppColors.textColor,
// borderRadius: 12,
// ),
// child: Padding(
// padding: EdgeInsets.all(12.h),
// child: Transform.flip(
// flipX: appState.isArabic(),
// child: Utils.buildSvgWithAssets(
// icon: AppAssets.forward_arrow_icon_small,
// iconColor: AppColors.whiteColor,
// fit: BoxFit.contain,
// ),
// ),
// ),
// ).onPress(() {
// model.setPrescriptionsDetailsLoading();
// Navigator.of(context).push(
// CustomPageRoute(
// page: PrescriptionDetailPage(
// prescriptionsResponseModel: prescription,
// isFromAppointments: false,
// ),
// ),
// );
// }),
// ),
// ],
// ),
// SizedBox(height: 12.h),
// Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
// SizedBox(height: 12.h),
// ],
// );
// }).toList(),
// ],
// ),
), ),
// InkWell(
// onTap: () {
// setState(() {
// expandedIndex = isExpanded ? null : index;
// });
// },
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Padding(
// padding: EdgeInsets.all(16.h),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// CustomButton(
// text: "${model.patientPrescriptionOrdersViewList[index].prescriptionsList!.length} Prescriptions Available",
// onPressed: () {},
// backgroundColor: AppColors.greyColor,
// borderColor: AppColors.greyColor,
// textColor: AppColors.blackColor,
// fontSize: 10,
// fontWeight: FontWeight.w500,
// borderRadius: 8,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 30.h,
// ),
// Icon(isExpanded ? Icons.expand_less : Icons.expand_more),
// ],
// ),
// SizedBox(height: 8.h),
// (model.patientPrescriptionOrdersViewList[index].filterName ?? "").toText16(isBold: true)
// ],
// ),
// ),
// AnimatedSwitcher(
// duration: Duration(milliseconds: 500),
// switchInCurve: Curves.easeIn,
// switchOutCurve: Curves.easeOut,
// transitionBuilder: (Widget child, Animation<double> animation) {
// return FadeTransition(
// opacity: animation,
// child: SizeTransition(
// sizeFactor: animation,
// axisAlignment: 0.0,
// child: child,
// ),
// );
// },
// // child: isExpanded
// // ? Container(
// // key: ValueKey<int>(index),
// // padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
// // child: Column(
// // crossAxisAlignment: CrossAxisAlignment.start,
// // children: [
// // ...model.patientPrescriptionOrdersViewList[index].prescriptionsList!.map((prescription) {
// // return Column(
// // crossAxisAlignment: CrossAxisAlignment.start,
// // children: [
// // Row(
// // mainAxisSize: MainAxisSize.min,
// // children: [
// // Image.network(
// // prescription.doctorImageURL!,
// // width: 24.h,
// // height: 24.h,
// // fit: BoxFit.fill,
// // ).circle(100),
// // SizedBox(width: 8.h),
// // Expanded(child: prescription.doctorName!.toText14(weight: FontWeight.w500)),
// // ],
// // ),
// // SizedBox(height: 8.h),
// // Wrap(
// // direction: Axis.horizontal,
// // spacing: 6.h,
// // runSpacing: 6.h,
// // children: [
// // Directionality(
// // textDirection: ui.TextDirection.ltr,
// // child: AppCustomChipWidget(
// // labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(prescription.appointmentDate), false), isEnglishOnly: true,
// // ),
// // ),
// // AppCustomChipWidget(
// // labelText: model.isSortByClinic ? prescription.name ?? "" : prescription.clinicDescription!,
// // ),
// // ],
// // ),
// // SizedBox(height: 8.h),
// // Row(
// // children: [
// // Expanded(
// // flex: 6,
// // child: CustomButton(
// // text: prescription.isHomeMedicineDeliverySupported!
// // ? LocaleKeys.resendOrder.tr(context: context)
// // : LocaleKeys.prescriptionDeliveryError.tr(context: context),
// // onPressed: () async {
// // if (prescription.isHomeMedicineDeliverySupported!) {
// // LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPrescriptionDetails.tr(context: context));
// // await prescriptionsViewModel.getPrescriptionDetails(prescriptionsViewModel.patientPrescriptionOrders[index],
// // onSuccess: (val) {
// // LoaderBottomSheet.hideLoader();
// // prescriptionsViewModel.initiatePrescriptionDelivery();
// // });
// // }
// // },
// // backgroundColor:
// // prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor.withOpacity(0.15) : AppColors.greyF7Color,
// // borderColor: AppColors.successColor.withOpacity(0.01),
// // textColor: prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.35),
// // fontSize: prescription.isHomeMedicineDeliverySupported! ? 14.f : 12.f,
// // fontWeight: FontWeight.w500,
// // borderRadius: 12.r,
// // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// // height: 40.h,
// // icon: AppAssets.prescription_refill_icon,
// // iconColor: prescription.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.textColor.withOpacity(0.35),
// // iconSize: 16.h,
// // ),
// // ),
// // SizedBox(width: 8.h),
// // Expanded(
// // flex: 1,
// // child: Container(
// // height: 40.h,
// // width: 40.w,
// // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// // color: AppColors.textColor,
// // borderRadius: 12,
// // ),
// // child: Padding(
// // padding: EdgeInsets.all(12.h),
// // child: Transform.flip(
// // flipX: appState.isArabic(),
// // child: Utils.buildSvgWithAssets(
// // icon: AppAssets.forward_arrow_icon_small,
// // iconColor: AppColors.whiteColor,
// // fit: BoxFit.contain,
// // ),
// // ),
// // ),
// // ).onPress(() {
// // model.setPrescriptionsDetailsLoading();
// // Navigator.of(context).push(
// // CustomPageRoute(
// // page: PrescriptionDetailPage(
// // prescriptionsResponseModel: prescription,
// // isFromAppointments: false,
// // ),
// // ),
// // );
// // }),
// // ),
// // ],
// // ),
// // SizedBox(height: 12.h),
// // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
// // SizedBox(height: 12.h),
// // ],
// // );
// // }).toList(),
// // ],
// // ),
// // )
// // : SizedBox.shrink(),
// ),
// ],
// ),
// ),
), ),
), ),
), ),

@ -15,14 +15,19 @@ import 'package:hmg_patient_app_new/extensions/int_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart';
import 'package:hmg_patient_app_new/features/contact_us/models/feedback_type.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart'; import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart';
import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.dart';
import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_update_details_card.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/widgets/update_email_widget.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/app_language_change.dart'; import 'package:hmg_patient_app_new/widgets/app_language_change.dart';
@ -48,6 +53,7 @@ class ProfileSettingsState extends State<ProfileSettings> {
scheduleMicrotask(() { scheduleMicrotask(() {
insuranceViewModel.initInsuranceProvider(); insuranceViewModel.initInsuranceProvider();
}); });
_loadPermissions();
super.initState(); super.initState();
} }
@ -86,10 +92,13 @@ class ProfileSettingsState extends State<ProfileSettings> {
int length = 3; int length = 3;
final SwiperController _controller = SwiperController(); final SwiperController _controller = SwiperController();
late InsuranceViewModel insuranceViewModel; late InsuranceViewModel insuranceViewModel;
late ContactUsViewModel contactUsViewModel;
String _permissionsLabel = "";
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
insuranceViewModel = Provider.of<InsuranceViewModel>(context, listen: false); insuranceViewModel = Provider.of<InsuranceViewModel>(context, listen: false);
contactUsViewModel = Provider.of<ContactUsViewModel>(context, listen: false);
return CollapsingListView( return CollapsingListView(
title: LocaleKeys.profileAndSettings.tr(context: context), title: LocaleKeys.profileAndSettings.tr(context: context),
logout: () { logout: () {
@ -97,102 +106,109 @@ class ProfileSettingsState extends State<ProfileSettings> {
}, },
isClose: true, isClose: true,
child: SingleChildScrollView( child: SingleChildScrollView(
padding: EdgeInsets.only(top: 24.h, bottom: 24.h), padding: EdgeInsets.only(top: 0.h, bottom: 24.h),
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
child: Consumer2<ProfileSettingsViewModel, MedicalFileViewModel>( child: Consumer2<ProfileSettingsViewModel, MedicalFileViewModel>(
builder: (context, profileVm, medicalVm, child) { builder: (context, profileVm, medicalVm, child) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Swiper( // SizedBox(
itemCount: medicalVm.patientFamilyFiles.length, // height: dynamicItemHeight(context) + 20 + 30, // itemHeight + shadow padding (10 top + 10 bottom) + pagination dots space
layout: SwiperLayout.STACK, // child: Swiper(
loop: true, // itemCount: medicalVm.patientFamilyFiles.length,
itemHeight: dynamicItemHeight(context), // layout: SwiperLayout.STACK,
itemWidth: SizeUtils.width - 30.w, // loop: true,
indicatorLayout: PageIndicatorLayout.COLOR, // itemHeight: dynamicItemHeight(context) + 20,
axisDirection: AxisDirection.right, // // extra space for shadow
controller: _controller, // itemWidth: SizeUtils.width - 30.w,
pagination: SwiperPagination( // indicatorLayout: PageIndicatorLayout.COLOR,
alignment: Alignment.bottomCenter, // axisDirection: getIt.get<AppState>().isArabic() ? AxisDirection.left : AxisDirection.right,
margin: EdgeInsets.only(top: (210.h + 8.h + 24.h)), // controller: _controller,
builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor), // pagination: SwiperPagination(
), // alignment: Alignment.bottomCenter,
itemBuilder: (BuildContext context, int index) { // margin: EdgeInsets.only(top: (180.h + 20 + 8.h + 24.h)),
return FamilyCardWidget( // builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor),
profile: medicalVm.patientFamilyFiles[index], // ),
onAddFamilyMemberPress: () { // itemBuilder: (BuildContext context, int index) {
DialogService dialogService = getIt.get<DialogService>(); // return Padding(
dialogService.showAddFamilyFileSheet( // padding: const EdgeInsets.symmetric(vertical: 10),
label: LocaleKeys.addFamilyMember.tr(context: context), // child: FamilyCardWidget(
message: LocaleKeys.pleaseFillBelowFieldToAddNewFamilyMember.tr(context: context), // profile: medicalVm.patientFamilyFiles[index],
onVerificationPress: () { // onAddFamilyMemberPress: () {
medicalVm.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms); // DialogService dialogService = getIt.get<DialogService>();
}); // dialogService.showAddFamilyFileSheet(
}, // label: LocaleKeys.addFamilyMember.tr(context: context),
onFamilySwitchPress: (FamilyFileResponseModelLists profile) { // message: LocaleKeys.pleaseFillBelowFieldToAddNewFamilyMember.tr(context: context),
medicalVm.switchFamilyFiles(responseID: profile.responseId, patientID: profile.patientId, phoneNumber: profile.mobileNumber); // onVerificationPress: () {
}, // medicalVm.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms);
).paddingOnly(right: 16.w, left: 8.w); // });
}, // },
), // onFamilySwitchPress: (FamilyFileResponseModelLists profile) {
SizedBox(height: 5.h), // medicalVm.switchFamilyFiles(responseID: profile.responseId, patientID: profile.patientId, phoneNumber: profile.mobileNumber);
GridView( // },
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: isTablet ? 3 : 2), // ).paddingOnly(right: 16.w, left: 8.w),
physics: const NeverScrollableScrollPhysics(), // );
padding: EdgeInsets.only(left: 24.w, right: 24.w, bottom: 24.h), // },
shrinkWrap: true, // ),
children: [ // ),
Container( // SizedBox(height: 16.h),
padding: EdgeInsets.all(16.w), // GridView(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: isTablet ? 3 : 2),
color: AppColors.whiteColor, // physics: const NeverScrollableScrollPhysics(),
borderRadius: 20.r, // padding: EdgeInsets.only(left: 24.w, right: 24.w, bottom: 24.h),
hasShadow: true, // shrinkWrap: true,
), // children: [
child: Column( // Container(
crossAxisAlignment: CrossAxisAlignment.start, // padding: EdgeInsets.all(16.w),
// spacing: 4.h, // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
children: [ // color: AppColors.whiteColor,
Row( // borderRadius: 20.r,
spacing: 8.w, // hasShadow: true,
crossAxisAlignment: CrossAxisAlignment.center, // ),
children: [ // child: Column(
Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.w, height: 40.h, applyThemeColor: false), // crossAxisAlignment: CrossAxisAlignment.start,
LocaleKeys.habibWallet.tr(context: context).toText16(weight: FontWeight.w600, maxlines: 2).expanded, // // spacing: 4.h,
Utils.buildSvgWithAssets(icon: getIt.get<AppState>().isArabic() ? AppAssets.arrow_back : AppAssets.arrow_forward), // children: [
], // Row(
), // spacing: 8.w,
Spacer(), // crossAxisAlignment: CrossAxisAlignment.center,
Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) { // children: [
return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, isExpanded: false) // Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.w, height: 40.h, applyThemeColor: false),
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h); // LocaleKeys.habibWallet.tr(context: context).toText16(weight: FontWeight.w600, maxlines: 2).expanded,
}), // Utils.buildSvgWithAssets(icon: getIt.get<AppState>().isArabic() ? AppAssets.arrow_back : AppAssets.arrow_forward),
Spacer(), // ],
CustomButton( // ),
height: 40.h, // Spacer(),
icon: AppAssets.recharge_icon, // Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
iconSize: 22.w, // return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, isExpanded: false)
iconColor: AppColors.infoColor, // .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h);
textColor: AppColors.infoColor, // }),
text: LocaleKeys.recharge.tr(context: context), // Spacer(),
borderWidth: 0.w, // CustomButton(
fontWeight: FontWeight.w500, // height: 40.h,
borderColor: Colors.transparent, // icon: AppAssets.recharge_icon,
backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08), // iconSize: 22.w,
padding: EdgeInsets.all(8.w), // iconColor: AppColors.infoColor,
fontSize: 14.f, // textColor: AppColors.infoColor,
onPressed: () { // text: LocaleKeys.recharge.tr(context: context),
Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); // borderWidth: 0.w,
}, // fontWeight: FontWeight.w500,
), // borderColor: Colors.transparent,
], // backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08),
).onPress(() { // padding: EdgeInsets.all(8.w),
Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage())); // fontSize: 14.f,
}), // onPressed: () {
), // Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage()));
], // },
), // ),
// ],
// ).onPress(() {
// Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage()));
// }),
// ),
// ],
// ),
LocaleKeys.quickActions.tr(context: context).toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w), LocaleKeys.quickActions.tr(context: context).toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w),
Container( Container(
margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h), margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h),
@ -226,41 +242,49 @@ class ProfileSettingsState extends State<ProfileSettings> {
], ],
), ),
), ),
Container( // Container(
margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h), // margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h),
padding: EdgeInsets.only(top: 4.h, bottom: 4.h), // padding: EdgeInsets.only(top: 4.h, bottom: 4.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true), // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
child: Column( // child: Column(
children: [ // children: [
actionItem(AppAssets.language_change, LocaleKeys.language.tr(context: context), () { // actionItem(AppAssets.language_change, LocaleKeys.language.tr(context: context), () {
showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.language.tr(context: context), child: AppLanguageChange(), callBackFunc: () {}, isFullScreen: false); // showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.language.tr(context: context), child: AppLanguageChange(), callBackFunc: () {}, isFullScreen: false);
}, trailingLabel: Utils.appState.isArabic() ? "العربية" : "English"), // }, trailingLabel: Utils.appState.isArabic() ? "العربية" : "English"),
1.divider, // 1.divider,
actionItem(AppAssets.bell, LocaleKeys.notificationsSettings.tr(context: context), () { // actionItem(AppAssets.bell, LocaleKeys.notificationsSettings.tr(context: context), () {
openAppSettings(); // openAppSettings();
}), // }),
// 1.divider, // // 1.divider,
// actionItem(AppAssets.touch_face_id, LocaleKeys.touchIDFaceIDServices.tr(context: context), () {}, switchValue: true), // // actionItem(AppAssets.touch_face_id, LocaleKeys.touchIDFaceIDServices.tr(context: context), () {}, switchValue: true),
], // ],
), // ),
), // ),
LocaleKeys.personalInformation.tr(context: context).toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w), // LocaleKeys.personalInformation.tr(context: context).toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w),
Container( // Container(
margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h), // margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h),
padding: EdgeInsets.only(top: 4.h, bottom: 4.h), // padding: EdgeInsets.only(top: 4.h, bottom: 4.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true), // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
child: Column( // child: Column(
children: [ // children: [
actionItem(AppAssets.email_transparent, LocaleKeys.updateEmailAddress.tr(context: context), () {}), // actionItem(AppAssets.email_transparent, LocaleKeys.updateEmailAddress.tr(context: context), () {
// 1.divider, // showCommonBottomSheetWithoutHeight(
// actionItem(AppAssets.smart_phone_fill, "Phone Number".needTranslation, () {}), // context,
// 1.divider, // title: LocaleKeys.updateEmailAddress.tr(context: context),
// actionItem(AppAssets.my_address, "My Addresses".needTranslation, () {}), // child: UpdateEmailDialog(),
// 1.divider, // callBackFunc: () {},
// actionItem(AppAssets.emergency, "Emergency Contact".needTranslation, () {}), // isFullScreen: false,
], // );
), // }),
), // // 1.divider,
// // actionItem(AppAssets.smart_phone_fill, "Phone Number".needTranslation, () {}),
// // 1.divider,
// // actionItem(AppAssets.my_address, "My Addresses".needTranslation, () {}),
// // 1.divider,
// // actionItem(AppAssets.emergency, "Emergency Contact".needTranslation, () {}),
// ],
// ),
// ),
LocaleKeys.helpAndSupport.tr(context: context).toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w), LocaleKeys.helpAndSupport.tr(context: context).toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w),
Container( Container(
margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h), margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h),
@ -272,6 +296,22 @@ class ProfileSettingsState extends State<ProfileSettings> {
launchUrl(Uri.parse("tel://" + "+966 92 006 6666")); launchUrl(Uri.parse("tel://" + "+966 92 006 6666"));
}, trailingLabel: "92 006 6666"), }, trailingLabel: "92 006 6666"),
1.divider, 1.divider,
actionItem(AppAssets.permission, LocaleKeys.permissionsProfile.tr(context: context), () {
openAppSettings();
}, trailingLabel: getCurrentPermissions()),
actionItem(AppAssets.feedbackFill, LocaleKeys.feedback.tr(context: context), () {
contactUsViewModel.setSelectedFeedbackType(
FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد'),
);
contactUsViewModel.setIsSendFeedbackTabSelected(true);
Navigator.pop(context);
Navigator.of(context).push(
CustomPageRoute(
page: FeedbackPage(),
),
);
}, trailingLabel: ""),
1.divider,
// actionItem(AppAssets.permission, LocaleKeys.permissions.tr(context: context), () {}, trailingLabel: "Location, Camera"), // actionItem(AppAssets.permission, LocaleKeys.permissions.tr(context: context), () {}, trailingLabel: "Location, Camera"),
// 1.divider, // 1.divider,
actionItem(AppAssets.rate, LocaleKeys.rateApp.tr(context: context), () { actionItem(AppAssets.rate, LocaleKeys.rateApp.tr(context: context), () {
@ -314,6 +354,34 @@ class ProfileSettingsState extends State<ProfileSettings> {
); );
} }
Future<void> _loadPermissions() async {
final Map<String, Permission> permissionMap = {
'Camera': Permission.camera,
'Microphone': Permission.microphone,
'Location': Permission.location,
'Notifications': Permission.notification,
'Calendar': Permission.calendarFullAccess,
};
final List<String> granted = [];
for (final entry in permissionMap.entries) {
if (await entry.value.isGranted) {
granted.add(entry.key);
}
}
if (mounted) {
setState(() {
_permissionsLabel = granted.isEmpty ? 'No permissions granted' : granted.join(', ');
});
}
}
String getCurrentPermissions() {
return _permissionsLabel;
}
Widget actionItem(String icon, String label, VoidCallback onPress, {String trailingLabel = "", bool? switchValue, ValueChanged<bool>? onSwitchChanged, bool isExternalLink = false}) { Widget actionItem(String icon, String label, VoidCallback onPress, {String trailingLabel = "", bool? switchValue, ValueChanged<bool>? onSwitchChanged, bool isExternalLink = false}) {
return SizedBox( return SizedBox(
height: 56.h, height: 56.h,
@ -361,9 +429,7 @@ class FamilyCardWidget extends StatelessWidget {
return Container( return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
borderRadius: 24.r, borderRadius: 24.r, hasShadow: true, hasDenseShadow: true),
hasShadow: true,
),
child: Column( child: Column(
children: [ children: [
Column( Column(
@ -378,11 +444,25 @@ class FamilyCardWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
"${profile.patientName}".toText18(isBold: true, weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1), "${profile.patientName}".toText18(isBold: true, weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1, isEnglishOnly: true),
AppCustomChipWidget( Wrap(
icon: AppAssets.file_icon, direction: Axis.horizontal,
labelText: "${LocaleKeys.fileNo.tr(context: context)}: ${profile.responseId}", spacing: 4.w,
iconSize: 12.w, runSpacing: 6.w,
children: [
AppCustomChipWidget(
labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w),
icon: AppAssets.file_icon,
labelText: "${LocaleKeys.fileno.tr(context: context)}: ${profile.responseId}",
iconSize: 12.w,
),
isActive ? AppCustomChipWidget(
icon: AppAssets.checkmark_icon,
labelText: LocaleKeys.verified.tr(context: context),
iconColor: AppColors.successColor,
labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w),
) : SizedBox.shrink(),
],
), ),
], ],
).expanded, ).expanded,
@ -400,18 +480,20 @@ class FamilyCardWidget extends StatelessWidget {
AppCustomChipWidget( AppCustomChipWidget(
labelText: LocaleKeys.ageYearsOld.tr(namedArgs: {'age': profile.age.toString(), 'yearsOld': LocaleKeys.yearsOld.tr(context: context)}), labelText: LocaleKeys.ageYearsOld.tr(namedArgs: {'age': profile.age.toString(), 'yearsOld': LocaleKeys.yearsOld.tr(context: context)}),
), ),
isActive && appState.getAuthenticatedUser()!.bloodGroup != null // isActive && appState.getAuthenticatedUser()!.bloodGroup != null
? AppCustomChipWidget( // ?
icon: AppAssets.blood_icon, isActive ? AppCustomChipWidget(
icon: AppAssets.blood_icon,
labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 8.w), labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 8.w),
labelText: "Blood: ${appState.getAuthenticatedUser()!.bloodGroup ?? ""}", labelText: appState.getAuthenticatedUser()!.bloodGroup ?? "N/A",
iconColor: AppColors.primaryRedColor) iconColor: AppColors.primaryRedColor)
: SizedBox(), : SizedBox(),
Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) { Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
return AppCustomChipWidget( return isActive
icon: insuranceVM.isInsuranceExpired ? AppCustomChipWidget(
? AppAssets.cancel_circle_icon icon: insuranceVM.isInsuranceExpired
: insuranceVM.isInsuranceActive ? AppAssets.cancel_circle_icon
: insuranceVM.isInsuranceActive
? AppAssets.insurance_active_icon ? AppAssets.insurance_active_icon
: AppAssets.alertSquare, : AppAssets.alertSquare,
labelText: insuranceVM.isInsuranceExpired labelText: insuranceVM.isInsuranceExpired
@ -431,27 +513,34 @@ class FamilyCardWidget extends StatelessWidget {
: AppColors.warningColorYellow, : AppColors.warningColorYellow,
iconSize: 12.w, iconSize: 12.w,
deleteIcon: insuranceVM.isInsuranceActive ? null : AppAssets.forward_chevron_icon, deleteIcon: insuranceVM.isInsuranceActive ? null : AppAssets.forward_chevron_icon,
deleteIconColor: AppColors.warningColorYellow, deleteIconColor: insuranceVM.isInsuranceExpired
? AppColors.primaryRedColor
: insuranceVM.isInsuranceActive
? AppColors.successColor
: AppColors.warningColorYellow,
deleteIconHasColor: true, deleteIconHasColor: true,
onChipTap: () { onChipTap: () {
if (!insuranceVM.isInsuranceActive) { if (!insuranceVM.isInsuranceActive) {
showCommonBottomSheetWithoutHeight( insuranceVM.setIsInsuranceUpdateDetailsLoading(true);
title: LocaleKeys.notice.tr(context: context), insuranceVM.getPatientInsuranceDetailsForUpdate(appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString());
context, showCommonBottomSheetWithoutHeight(context, child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false);
child: Utils.getWarningWidget( // showCommonBottomSheetWithoutHeight(
loadingText: LocaleKeys.insuranceInActiveContactSupport.tr(context: context), // title: LocaleKeys.notice.tr(context: context),
confirmText: LocaleKeys.contactUs.tr(context: context), // context,
isShowActionButtons: true, // child: Utils.getWarningWidget(
onCancelTap: () { // loadingText: LocaleKeys.insuranceInActiveContactSupport.tr(context: context),
Navigator.pop(context); // confirmText: LocaleKeys.contactUs.tr(context: context),
}, // isShowActionButtons: true,
onConfirmTap: () async { // onCancelTap: () {
launchUrl(Uri.parse("tel://" + "+966 92 006 6666")); // Navigator.pop(context);
}), // },
callBackFunc: () {}, // onConfirmTap: () async {
isFullScreen: false, // launchUrl(Uri.parse("tel://" + "+966 92 006 6666"));
isCloseButtonVisible: true, // }),
); // callBackFunc: () {},
// isFullScreen: false,
// isCloseButtonVisible: true,
// );
} }
}, },
backgroundColor: insuranceVM.isInsuranceExpired backgroundColor: insuranceVM.isInsuranceExpired
@ -460,7 +549,8 @@ class FamilyCardWidget extends StatelessWidget {
? AppColors.successColor.withOpacity(0.1) ? AppColors.successColor.withOpacity(0.1)
: AppColors.warningColorYellow.withOpacity(0.1), : AppColors.warningColorYellow.withOpacity(0.1),
labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: insuranceVM.isInsuranceActive ? 6.w : 0.w), labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: insuranceVM.isInsuranceActive ? 6.w : 0.w),
).toShimmer2(isShow: insuranceVM.isInsuranceLoading); ).toShimmer2(isShow: insuranceVM.isInsuranceLoading)
: SizedBox.shrink();
}), }),
], ],
), ),

@ -0,0 +1,106 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:provider/provider.dart';
class UpdateEmailDialog extends StatefulWidget {
UpdateEmailDialog({super.key});
@override
State<UpdateEmailDialog> createState() => _UpdateEmailDialogState();
}
class _UpdateEmailDialogState extends State<UpdateEmailDialog> {
late FocusNode _textFieldFocusNode;
late TextEditingController? textController;
ProfileSettingsViewModel? profileSettingsViewModel;
@override
void initState() {
_textFieldFocusNode = FocusNode();
textController = TextEditingController();
textController!.text = getIt.get<AppState>().getAuthenticatedUser()!.emailAddress ?? "";
super.initState();
}
@override
void dispose() {
_textFieldFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
profileSettingsViewModel = Provider.of<ProfileSettingsViewModel>(context);
return GestureDetector(
onTap: () {
_textFieldFocusNode.unfocus();
FocusScope.of(context).unfocus();
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Enter the new email address to be updated in your HMG File: ".toText16(textAlign: TextAlign.start, weight: FontWeight.w500),
SizedBox(height: 12.h),
TextInputWidget(
labelText: LocaleKeys.email.tr(),
hintText: "demo@gmail.com",
controller: textController,
focusNode: _textFieldFocusNode,
autoFocus: true,
padding: EdgeInsets.all(8.h),
keyboardType: TextInputType.emailAddress,
isEnable: true,
isReadOnly: false,
prefix: null,
isBorderAllowed: false,
isAllowLeadingIcon: true,
fontSize: 14.f,
isCountryDropDown: false,
leadingIcon: AppAssets.email,
fontFamily: "Poppins",
),
SizedBox(height: 12.h),
CustomButton(
text: LocaleKeys.submit.tr(context: context),
onPressed: () {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.updatingEmailAddress.tr(context: context));
profileSettingsViewModel!.updatePatientInfo(
patientInfo: {"EmailAddress": textController!.text},
onSuccess: (response) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.success.tr(context: context), child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()),
callBackFunc: () async {
Navigator.of(context).pop();
}, isFullScreen: false);
},
onError: (error) {
LoaderBottomSheet.hideLoader();
// Show error message
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(error)),
);
},
);
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: const Color(0xFFffffff),
),
],
),
);
}
}

@ -3,6 +3,8 @@ import 'dart:async';
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_staggered_animations/flutter_staggered_animations.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
@ -24,6 +26,8 @@ import 'package:provider/provider.dart';
import '../../features/radiology/radiology_view_model.dart'; import '../../features/radiology/radiology_view_model.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'dart:ui' as ui;
class RadiologyOrdersPage extends StatefulWidget { class RadiologyOrdersPage extends StatefulWidget {
const RadiologyOrdersPage({super.key}); const RadiologyOrdersPage({super.key});
@ -94,40 +98,40 @@ class _RadiologyOrdersPageState extends State<RadiologyOrdersPage> {
children: [ children: [
// Clinic / Hospital toggle // Clinic / Hospital toggle
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row( // Row(
children: [ // children: [
CustomButton( // CustomButton(
text: LocaleKeys.byClinic.tr(context: context), // text: LocaleKeys.byClinic.tr(context: context),
onPressed: () { // onPressed: () {
model.setIsSortByClinic(true); // model.setIsSortByClinic(true);
}, // },
backgroundColor: model.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, // backgroundColor: model.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor,
borderColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2), // borderColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2),
textColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, // textColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor,
fontSize: 12, // fontSize: 12,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 10, // borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, // height: 40.h,
), // ),
SizedBox(width: 8.h), // SizedBox(width: 8.h),
CustomButton( // CustomButton(
text: LocaleKeys.byHospital.tr(context: context), // text: LocaleKeys.byHospital.tr(context: context),
onPressed: () { // onPressed: () {
model.setIsSortByClinic(false); // model.setIsSortByClinic(false);
}, // },
backgroundColor: model.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, // backgroundColor: model.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor,
borderColor: model.isSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor, // borderColor: model.isSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor,
textColor: model.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, // textColor: model.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor,
fontSize: 12, // fontSize: 12,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 10, // borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, // height: 40.h,
), // ),
], // ],
), // ),
SizedBox(height: 8.h), // SizedBox(height: 8.h),
selectedFilterText.isNotEmpty selectedFilterText.isNotEmpty
? AppCustomChipWidget( ? AppCustomChipWidget(
padding: EdgeInsets.symmetric(horizontal: 5.h), padding: EdgeInsets.symmetric(horizontal: 5.h),
@ -165,199 +169,525 @@ class _RadiologyOrdersPageState extends State<RadiologyOrdersPage> {
); );
} }
if (model.patientRadiologyOrdersViewList.isEmpty) { if (model.patientRadiologyOrders.isEmpty) {
return Utils.getNoDataWidget(ctx, noDataText: LocaleKeys.youDontHaveRadiologyOrders.tr(context: context)); return Utils.getNoDataWidget(ctx, noDataText: LocaleKeys.youDontHaveRadiologyOrders.tr(context: context));
} }
return ListView.builder( // return ListView.builder(
shrinkWrap: true, // shrinkWrap: true,
physics: NeverScrollableScrollPhysics(), // physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero, // padding: EdgeInsets.zero,
itemCount: model.patientRadiologyOrdersViewList.length, // itemCount: model.patientRadiologyOrdersViewList.length,
itemBuilder: (context, index) { // itemBuilder: (context, index) {
final group = model.patientRadiologyOrdersViewList[index]; // final group = model.patientRadiologyOrdersViewList[index];
final displayName = model.isSortByClinic ? (group.first.clinicDescription ?? 'Unknown') : (group.first.projectName ?? 'Unknown'); // final displayName = model.isSortByClinic ? (group.first.clinicDescription ?? 'Unknown') : (group.first.projectName ?? 'Unknown');
final isExpanded = expandedIndex == index; // final isExpanded = expandedIndex == index;
return AnimationConfiguration.staggeredList( // return AnimationConfiguration.staggeredList(
// position: index,
// duration: const Duration(milliseconds: 400),
// child: SlideAnimation(
// verticalOffset: 50.0,
// child: FadeInAnimation(
// child: AnimatedContainer(
// duration: const Duration(milliseconds: 300),
// curve: Curves.easeInOut,
// margin: EdgeInsets.symmetric(vertical: 8.h),
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// color: AppColors.whiteColor,
// borderRadius: 20.h,
// hasShadow: true,
// ),
// child: InkWell(
// onTap: () {
// setState(() {
// expandedIndex = isExpanded ? null : index;
// });
// WidgetsBinding.instance.addPostFrameCallback((_) {
// final key = _groupKeys.putIfAbsent(index, () => GlobalKey());
// if (key.currentContext != null && expandedIndex == index) {
// Future.delayed(const Duration(milliseconds: 450), () {
// if (key.currentContext != null) {
// Scrollable.ensureVisible(
// key.currentContext!,
// duration: const Duration(milliseconds: 350),
// curve: Curves.easeInOut,
// alignment: 0.0,
// );
// }
// });
// }
// });
// },
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Padding(
// key: _groupKeys.putIfAbsent(index, () => GlobalKey()),
// padding: EdgeInsets.all(16.h),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// AppCustomChipWidget(labelText: "${group.length} ${LocaleKeys.results.tr(context: context)}"),
// Icon(isExpanded ? Icons.expand_less : Icons.expand_more),
// ],
// ),
// SizedBox(height: 8.h),
// Text(
// displayName,
// style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w600),
// overflow: TextOverflow.ellipsis,
// ),
// ],
// ),
// ),
// AnimatedSwitcher(
// duration: const Duration(milliseconds: 500),
// switchInCurve: Curves.easeIn,
// switchOutCurve: Curves.easeOut,
// transitionBuilder: (Widget child, Animation<double> animation) {
// return FadeTransition(
// opacity: animation,
// child: SizeTransition(
// sizeFactor: animation,
// axisAlignment: 0.0,
// child: child,
// ),
// );
// },
// child: isExpanded
// ? Container(
// key: ValueKey<int>(index),
// padding: EdgeInsets.symmetric(horizontal: 16.w),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// ...group.map<Widget>((order) {
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisSize: MainAxisSize.min,
// children: [
// Image.network(
// order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
// width: 24.w,
// height: 24.h,
// fit: BoxFit.cover,
// ).circle(100),
// SizedBox(width: 8.h),
// Expanded(
// child: (order.doctorName ?? '').toString().toText14(weight: FontWeight.w500),
// ),
// ],
// ),
// SizedBox(height: 8.h),
// Wrap(
// direction: Axis.horizontal,
// spacing: 4.h,
// runSpacing: 4.h,
// children: [
// if ((order.description ?? '').isNotEmpty)
// AppCustomChipWidget(
// labelText: (order.description ?? '').toString(),
// ),
// Directionality(
// textDirection: ui.TextDirection.ltr,
// child: AppCustomChipWidget(
// labelText: DateUtil.formatDateToDate(
// (order.orderDate ?? order.appointmentDate),
// false,
// ), isEnglishOnly: true,
// ),
// ),
// AppCustomChipWidget(
// labelText: model.isSortByClinic ? (order.projectName ?? '') : (order.clinicDescription ?? ''),
// ),
// ],
// ),
// SizedBox(height: 12.h),
// Row(
// children: [
// Expanded(flex: 2, child: const SizedBox()),
// Expanded(
// flex: 2,
// child: CustomButton(
// icon: AppAssets.view_report_icon,
// iconColor: AppColors.primaryRedColor,
// iconSize: 16.h,
// text: LocaleKeys.viewResults.tr(context: context),
// onPressed: () {
// model.navigationService.push(
// CustomPageRoute(
// page: RadiologyResultPage(patientRadiologyResponseModel: order),
// ),
// );
// },
// backgroundColor: AppColors.secondaryLightRedColor,
// borderColor: AppColors.secondaryLightRedColor,
// textColor: AppColors.primaryRedColor,
// fontSize: 14,
// fontWeight: FontWeight.w500,
// borderRadius: 12,
// padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 40.h,
// ),
// ),
// ],
// ),
// SizedBox(height: 12.h),
// Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
// SizedBox(height: 12.h),
// ],
// );
// }).toList(),
// ],
// ),
// )
// : const SizedBox.shrink(),
// ),
// ],
// ),
// ),
// ),
// ),
// ),
// );
// },
// );
return ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
itemCount: model.patientRadiologyOrders.length,
itemBuilder: (context, index) {
final group = model.patientRadiologyOrders[index];
final isExpanded = expandedIndex == index;
return AnimationConfiguration.staggeredList(
position: index, position: index,
duration: const Duration(milliseconds: 400), duration: const Duration(milliseconds: 500),
child: SlideAnimation( child: SlideAnimation(
verticalOffset: 50.0, verticalOffset: 100.0,
child: FadeInAnimation( child: FadeInAnimation(
child: AnimatedContainer( child: AnimatedContainer(
duration: const Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
curve: Curves.easeInOut, curve: Curves.easeInOut,
margin: EdgeInsets.symmetric(vertical: 8.h), margin: EdgeInsets.symmetric(vertical: 8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
),
child: InkWell( child: InkWell(
onTap: () { onTap: () {
setState(() { setState(() {
expandedIndex = isExpanded ? null : index; expandedIndex = isExpanded ? null : index;
}); });
WidgetsBinding.instance.addPostFrameCallback((_) {
final key = _groupKeys.putIfAbsent(index, () => GlobalKey());
if (key.currentContext != null && expandedIndex == index) {
Future.delayed(const Duration(milliseconds: 450), () {
if (key.currentContext != null) {
Scrollable.ensureVisible(
key.currentContext!,
duration: const Duration(milliseconds: 350),
curve: Curves.easeInOut,
alignment: 0.0,
);
}
});
}
});
}, },
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Padding( Padding(
key: _groupKeys.putIfAbsent(index, () => GlobalKey()),
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
AppCustomChipWidget(
labelText: "${getIt.get<AppState>().isArabic() ? group.isInOutPatientDescriptionN : group.isInOutPatientDescription}",
backgroundColor: AppColors.warningColorYellow.withOpacity(0.1),
textColor: AppColors.warningColorYellow,
),
SizedBox(height: 16.h),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisSize: MainAxisSize.min,
children: [ children: [
AppCustomChipWidget(labelText: "${group.length} ${LocaleKeys.results.tr(context: context)}"), Image.network(
Icon(isExpanded ? Icons.expand_less : Icons.expand_more), group.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
width: 24.w,
height: 24.h,
fit: BoxFit.cover,
).circle(100),
SizedBox(width: 8.h),
Expanded(child: (group.doctorName ?? "").toString().toText14(weight: FontWeight.w500)),
], ],
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Text( Wrap(
displayName, direction: Axis.horizontal,
style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w600), spacing: 4.h,
overflow: TextOverflow.ellipsis, runSpacing: 4.h,
children: [
Directionality(
textDirection: ui.TextDirection.ltr,
child: AppCustomChipWidget(
labelText: DateUtil.formatDateToDate(group.orderDate!, false),
isEnglishOnly: true,
)),
AppCustomChipWidget(
labelText: (group.projectName ?? ""),
),
AppCustomChipWidget(
labelText: (group.clinicDescription ?? ""),
),
],
), ),
SizedBox(height: 16.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${group.procedureName.toString().trim() ?? ""}".toText14(weight: FontWeight.w500),
// "Lorem ipsum text".toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 16.h),
CustomButton(
text: LocaleKeys.viewReport.tr(),
onPressed: () {
model.navigationService.push(
CustomPageRoute(
page: RadiologyResultPage(patientRadiologyResponseModel: group),
),
);
},
backgroundColor: AppColors.infoColor.withAlpha(20),
borderColor: AppColors.infoColor.withAlpha(0),
textColor: AppColors.infoColor,
fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
height: 40.h,
iconSize: 14.h,
icon: AppAssets.view_report_icon,
iconColor: AppColors.infoColor,
),
],
)
], ],
), ),
), ),
AnimatedSwitcher( // AnimatedSwitcher(
duration: const Duration(milliseconds: 500), // duration: Duration(milliseconds: 500),
switchInCurve: Curves.easeIn, // switchInCurve: Curves.easeIn,
switchOutCurve: Curves.easeOut, // switchOutCurve: Curves.easeOut,
transitionBuilder: (Widget child, Animation<double> animation) { // transitionBuilder: (Widget child, Animation<double> animation) {
return FadeTransition( // return FadeTransition(
opacity: animation, // opacity: animation,
child: SizeTransition( // child: SizeTransition(
sizeFactor: animation, // sizeFactor: animation,
axisAlignment: 0.0, // axisAlignment: 0.0,
child: child, // child: child,
), // ),
); // );
}, // },
child: isExpanded // child: isExpanded
? Container( // ? Container(
key: ValueKey<int>(index), // key: ValueKey<int>(index),
padding: EdgeInsets.symmetric(horizontal: 16.w), // padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 0.h),
child: Column( // child: Column(
crossAxisAlignment: CrossAxisAlignment.start, // children: [
children: [ // ListView.separated(
...group.map<Widget>((order) { // shrinkWrap: true,
return Column( // physics: NeverScrollableScrollPhysics(),
crossAxisAlignment: CrossAxisAlignment.start, // padding: EdgeInsets.zero,
children: [ // itemBuilder: (cxt, index) {
Row( // PatientRadiologyResponseModel order = group;
mainAxisSize: MainAxisSize.min, // return Column(
children: [ // crossAxisAlignment: CrossAxisAlignment.start,
Image.network( // children: [
order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", // "${order.procedureName ?? ""}".toText14(weight: FontWeight.w500),
width: 24.w, // "Lorem ipsum text".toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
height: 24.h, // // SizedBox(height: 4.h),
fit: BoxFit.cover, // // order.testDetails![index].testDescriptionEn!.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
).circle(100), // // Row(
SizedBox(width: 8.h), // // mainAxisSize: MainAxisSize.min,
Expanded( // // children: [
child: (order.doctorName ?? '').toString().toText14(weight: FontWeight.w500), // // Image.network(
), // // order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
], // // width: 24.w,
), // // height: 24.h,
SizedBox(height: 8.h), // // fit: BoxFit.cover,
Wrap( // // ).circle(100),
direction: Axis.horizontal, // // SizedBox(width: 8.h),
spacing: 4.h, // // Expanded(child: (order.doctorName ?? order.doctorNameEnglish ?? "").toString().toText14(weight: FontWeight.w500)),
runSpacing: 4.h, // // ],
children: [ // // ),
if ((order.description ?? '').isNotEmpty) // // SizedBox(height: 8.h),
AppCustomChipWidget( // // Wrap(
labelText: (order.description ?? '').toString(), // // direction: Axis.horizontal,
), // // spacing: 4.h,
AppCustomChipWidget( // // runSpacing: 4.h,
labelText: DateUtil.formatDateToDate( // // children: [
(order.orderDate ?? order.appointmentDate), // // AppCustomChipWidget(
false, // // labelText: ("${LocaleKeys.orderNo.tr(context: context)}: ${order.orderNo!}"), isEnglishOnly: true,
), // // ),
), // // Directionality(
AppCustomChipWidget( // // textDirection: ui.TextDirection.ltr,
labelText: model.isSortByClinic ? (order.projectName ?? '') : (order.clinicDescription ?? ''), // // child: AppCustomChipWidget(
), // // labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false),
], // // isEnglishOnly: true,
), // // )),
SizedBox(height: 12.h), // // AppCustomChipWidget(
Row( // // labelText: labViewModel.isSortByClinic ? (order.projectName ?? "") : (order.clinicDescription ?? ""),
children: [ // // ),
Expanded(flex: 2, child: const SizedBox()), // // ],
Expanded( // // ),
flex: 2, // // // Row(
child: CustomButton( // // // children: [
icon: AppAssets.view_report_icon, // // // CustomButton(
iconColor: AppColors.primaryRedColor, // // // text: ("Order No: ".needTranslation + order.orderNo!),
iconSize: 16.h, // // // onPressed: () {},
text: LocaleKeys.viewResults.tr(context: context), // // // backgroundColor: AppColors.greyColor,
onPressed: () { // // // borderColor: AppColors.greyColor,
model.navigationService.push( // // // textColor: AppColors.blackColor,
CustomPageRoute( // // // fontSize: 10,
page: RadiologyResultPage(patientRadiologyResponseModel: order), // // // fontWeight: FontWeight.w500,
), // // // borderRadius: 8,
); // // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
}, // // // height: 24.h,
backgroundColor: AppColors.secondaryLightRedColor, // // // ),
borderColor: AppColors.secondaryLightRedColor, // // // SizedBox(width: 8.h),
textColor: AppColors.primaryRedColor, // // // CustomButton(
fontSize: 14, // // // text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false),
fontWeight: FontWeight.w500, // // // onPressed: () {},
borderRadius: 12, // // // backgroundColor: AppColors.greyColor,
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0), // // // borderColor: AppColors.greyColor,
height: 40.h, // // // textColor: AppColors.blackColor,
), // // // fontSize: 10,
), // // // fontWeight: FontWeight.w500,
], // // // borderRadius: 8,
), // // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
SizedBox(height: 12.h), // // // height: 24.h,
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // // // ),
SizedBox(height: 12.h), // // // ],
], // // // ),
); // // // SizedBox(height: 8.h),
}).toList(), // // // Row(
], // // // children: [
), // // // CustomButton(
) // // // text: model.isSortByClinic ? (order.clinicDescription ?? "") : (order.projectName ?? ""),
: const SizedBox.shrink(), // // // onPressed: () {},
), // // // backgroundColor: AppColors.greyColor,
// // // borderColor: AppColors.greyColor,
// // // textColor: AppColors.blackColor,
// // // fontSize: 10,
// // // fontWeight: FontWeight.w500,
// // // borderRadius: 8,
// // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// // // height: 24.h,
// // // ),
// // // ],
// // // ),
// // SizedBox(height: 12.h),
// // Row(
// // children: [
// // Expanded(flex: 2, child: SizedBox()),
// // // Expanded(
// // // flex: 1,
// // // child: Container(
// // // height: 40.h,
// // // width: 40.w,
// // // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// // // color: AppColors.textColor,
// // // borderRadius: 12,
// // // ),
// // // child: Padding(
// // // padding: EdgeInsets.all(12.h),
// // // child: Transform.flip(
// // // flipX: _appState.isArabic(),
// // // child: Utils.buildSvgWithAssets(
// // // icon: AppAssets.forward_arrow_icon_small,
// // // iconColor: AppColors.whiteColor,
// // // fit: BoxFit.contain,
// // // ),
// // // ),
// // // ),
// // // ).onPress(() {
// // // model.currentlySelectedPatientOrder = order;
// // // labProvider.getPatientLabResultByHospital(order);
// // // labProvider.getPatientSpecialResult(order);
// // // Navigator.of(context).push(
// // // CustomPageRoute(page: LabResultByClinic(labOrder: order)),
// // // );
// // // }),
// // // )
// //
// // Expanded(
// // flex: 2,
// // child: CustomButton(
// // icon: AppAssets.view_report_icon,
// // iconColor: AppColors.primaryRedColor,
// // iconSize: 16.h,
// // text: LocaleKeys.viewResults.tr(context: context),
// // onPressed: () {
// // labViewModel.currentlySelectedPatientOrder = order;
// // labProvider.getPatientLabResultByHospital(order);
// // labProvider.getPatientSpecialResult(order);
// // Navigator.of(context).push(
// // CustomPageRoute(page: LabResultByClinic(labOrder: order)),
// // );
// // },
// // backgroundColor: AppColors.secondaryLightRedColor,
// // borderColor: AppColors.secondaryLightRedColor,
// // textColor: AppColors.primaryRedColor,
// // fontSize: 14,
// // fontWeight: FontWeight.w500,
// // borderRadius: 12,
// // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// // height: 40.h,
// // ),
// // )
// // ],
// // ),
// // SizedBox(height: 12.h),
// // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
// // SizedBox(height: 12.h),
// ],
// ).paddingOnly(top: 16, bottom: 16);
// },
// separatorBuilder: (cxt, index) => Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
// itemCount: 1),
// SizedBox(height: 16.h),
// CustomButton(
// text: LocaleKeys.viewReport.tr(),
// onPressed: () {
// model.navigationService.push(
// CustomPageRoute(
// page: RadiologyResultPage(patientRadiologyResponseModel: group),
// ),
// );
// },
// backgroundColor: AppColors.infoColor.withAlpha(20),
// borderColor: AppColors.infoColor.withAlpha(0),
// textColor: AppColors.infoColor,
// fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
// fontWeight: FontWeight.w500,
// borderRadius: 12.r,
// padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
// height: 40.h,
// iconSize: 14.h,
// icon: AppAssets.view_report_icon,
// iconColor: AppColors.infoColor,
// ),
// SizedBox(height: 16.h),
// ],
// ),
// )
// : SizedBox.shrink(),
// ),
], ],
), ),
), ),
), ),
), ),
), ));
); },
}, );
); }),
}), ],
], ),
), );
); },
},
),
), ),
), ),
),
); );
} }

@ -20,6 +20,7 @@ import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:open_filex/open_filex.dart'; import 'package:open_filex/open_filex.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'dart:ui' as ui;
class RadiologyResultPage extends StatefulWidget { class RadiologyResultPage extends StatefulWidget {
RadiologyResultPage({super.key, required this.patientRadiologyResponseModel}); RadiologyResultPage({super.key, required this.patientRadiologyResponseModel});
@ -52,6 +53,48 @@ class _RadiologyResultPageState extends State<RadiologyResultPage> {
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
title: LocaleKeys.radiologyResult.tr(context: context), title: LocaleKeys.radiologyResult.tr(context: context),
downloadReport: () async {
LoaderBottomSheet.showLoader();
await radiologyViewModel
.getRadiologyPDF(
patientRadiologyResponseModel: widget.patientRadiologyResponseModel,
authenticatedUser: _appState.getAuthenticatedUser()!,
onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
})
.then((val) async {
LoaderBottomSheet.hideLoader();
if (radiologyViewModel.patientRadiologyReportPDFBase64.isNotEmpty) {
String path = await Utils.createFileFromString(radiologyViewModel.patientRadiologyReportPDFBase64, "pdf");
try {
OpenFilex.open(path);
} catch (ex) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "Cannot open file"),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
}
});
},
// viewImage: () {
// if (radiologyViewModel.radiologyImageURL.isNotEmpty) {
// Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL);
// launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: "");
// } else {
// Utils.showToast("Radiology image not available");
// }
// },
child: SingleChildScrollView( child: SingleChildScrollView(
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.h), padding: EdgeInsets.symmetric(horizontal: 24.h),
@ -71,31 +114,34 @@ class _RadiologyResultPageState extends State<RadiologyResultPage> {
SizedBox(height: 16.h), SizedBox(height: 16.h),
// widget.patientRadiologyResponseModel.description!.toText16(isBold: true), // widget.patientRadiologyResponseModel.description!.toText16(isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
widget.patientRadiologyResponseModel.reportData!.trim().toText12(isBold: true, color: AppColors.textColorLight), Directionality(
SizedBox(height: 16.h), textDirection: ui.TextDirection.ltr,
CustomButton( child: widget.patientRadiologyResponseModel.reportData!.trim().toText12(isBold: true, color: AppColors.textColorLight, isEnglishOnly: true),
text: LocaleKeys.viewRadiologyImage.tr(context: context),
onPressed: () async {
if (radiologyViewModel.radiologyImageURL.isNotEmpty) {
Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL);
launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: "");
} else {
Utils.showToast("Radiology image not available");
}
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: Colors.white,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppAssets.download,
iconColor: Colors.white,
iconSize: 20.h,
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
// CustomButton(
// text: LocaleKeys.viewRadiologyImage.tr(context: context),
// onPressed: () async {
// if (radiologyViewModel.radiologyImageURL.isNotEmpty) {
// Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL);
// launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: "");
// } else {
// Utils.showToast("Radiology image not available");
// }
// },
// backgroundColor: AppColors.primaryRedColor,
// borderColor: AppColors.primaryRedColor,
// textColor: Colors.white,
// fontSize: 14,
// fontWeight: FontWeight.w500,
// borderRadius: 12,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 40.h,
// icon: AppAssets.download,
// iconColor: Colors.white,
// iconSize: 20.h,
// ),
// SizedBox(height: 16.h),
], ],
).paddingSymmetrical(16.h, 0.h), ).paddingSymmetrical(16.h, 0.h),
), ),
@ -112,49 +158,28 @@ class _RadiologyResultPageState extends State<RadiologyResultPage> {
borderRadius: 24.h, borderRadius: 24.h,
hasShadow: true, hasShadow: true,
), ),
child: CustomButton( child: widget.patientRadiologyResponseModel.dIAPACSURL != "" ? CustomButton(
text: LocaleKeys.downloadReport.tr(context: context), text: LocaleKeys.openRad.tr(context: context),
onPressed: () async { onPressed: () async {
LoaderBottomSheet.showLoader(); if (radiologyViewModel.radiologyImageURL.isNotEmpty) {
await radiologyViewModel.getRadiologyPDF(patientRadiologyResponseModel: widget.patientRadiologyResponseModel, authenticatedUser: _appState.getAuthenticatedUser()!, onError: (err) { Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL);
LoaderBottomSheet.hideLoader(); launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: "");
showCommonBottomSheetWithoutHeight( } else {
context, Utils.showToast("Radiology image not available");
child: Utils.getErrorWidget(loadingText: err), }
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}).then((val) async {
LoaderBottomSheet.hideLoader();
if (radiologyViewModel.patientRadiologyReportPDFBase64.isNotEmpty) {
String path = await Utils.createFileFromString(radiologyViewModel.patientRadiologyReportPDFBase64, "pdf");
try {
OpenFilex.open(path);
} catch (ex) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "Cannot open file"),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
}
});
}, },
backgroundColor: AppColors.successColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.successColor, borderColor: AppColors.primaryRedColor,
textColor: Colors.white, textColor: Colors.white,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderRadius: 12, borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 45.h, height: 45.h,
icon: AppAssets.download, icon: AppAssets.imageIcon,
iconColor: Colors.white, iconColor: Colors.white,
iconSize: 20.h, iconSize: 20.h,
).paddingSymmetrical(24.h, 24.h), ).paddingSymmetrical(24.h, 24.h) : SizedBox.shrink(),
), ),
], ],
), ),

@ -100,7 +100,7 @@ class _UserInfoSelectionPageState extends State<UserInfoSelectionPage> {
children: [ children: [
title.toText14(weight: FontWeight.w500), title.toText14(weight: FontWeight.w500),
subTitle subTitle
.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500) .toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500, isEnglishOnly: true)
.toShimmer2(isShow: (leadingIcon == AppAssets.rulerIcon || leadingIcon == AppAssets.weightScale) && hmgServicesVM.isVitalSignLoading), .toShimmer2(isShow: (leadingIcon == AppAssets.rulerIcon || leadingIcon == AppAssets.weightScale) && hmgServicesVM.isVitalSignLoading),
], ],
), ),

@ -168,7 +168,7 @@ class ConditionCard extends StatelessWidget {
crossAxisAlignment: WrapCrossAlignment.center, crossAxisAlignment: WrapCrossAlignment.center,
children: [ children: [
for (int i = 0; i < symptoms.length; i++) ...[ for (int i = 0; i < symptoms.length; i++) ...[
"${symptoms[i]}".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor), "${symptoms[i]}".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor, isEnglishOnly: true),
if (i != symptoms.length - 1) if (i != symptoms.length - 1)
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 2.w), padding: EdgeInsets.symmetric(horizontal: 2.w),
@ -228,7 +228,7 @@ class ConditionCard extends StatelessWidget {
backgroundColor: AppColors.scaffoldBgColor, backgroundColor: AppColors.scaffoldBgColor,
titleWidget: Row( titleWidget: Row(
children: [ children: [
"$percentage%".toText12(fontWeight: FontWeight.bold, color: getChipColorBySeverityEnum(severityEnum)), "$percentage%".toText12(fontWeight: FontWeight.bold, color: getChipColorBySeverityEnum(severityEnum), isEnglishOnly: true),
], ],
).paddingSymmetrical(0, 4.h), ).paddingSymmetrical(0, 4.h),
), ),

@ -166,7 +166,7 @@ class DialogServiceImp implements DialogService {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
if (message != null) (message).toText16(isBold: false, color: AppColors.textColor), if (message != null) (message).toText16(isBold: false, color: AppColors.textColor),
SizedBox(height: 24.h), // SizedBox(height: 24.h),
FamilyCards( FamilyCards(
profiles: profiles, profiles: profiles,
onSelect: (FamilyFileResponseModelLists profile) { onSelect: (FamilyFileResponseModelLists profile) {
@ -190,6 +190,7 @@ class DialogServiceImp implements DialogService {
}) })
], ],
), ),
useSafeArea: true,
callBackFunc: () {}); callBackFunc: () {});
} }

@ -8,7 +8,7 @@ class AppColors {
static const transparent = Colors.transparent; static const transparent = Colors.transparent;
// Scaffold / Background // Scaffold / Background
static Color get scaffoldBgColor => isDarkMode ? dark.scaffoldBgColor : const Color(0xFFF8F8F8); static Color get scaffoldBgColor => isDarkMode ? dark.scaffoldBgColor : const Color(0xFFF0F0F0);
static Color get bottomSheetBgColor => isDarkMode ? dark.bottomSheetBgColor : const Color(0xFFF8F8FA); static Color get bottomSheetBgColor => isDarkMode ? dark.bottomSheetBgColor : const Color(0xFFF8F8FA);
static Color get lightGreyEFColor => isDarkMode ? dark.lightGreyEFColor : const Color(0xffeaeaff); static Color get lightGreyEFColor => isDarkMode ? dark.lightGreyEFColor : const Color(0xffeaeaff);
static Color get greyF7Color => isDarkMode ? dark.greyF7Color : const Color(0xffF7F7F7); static Color get greyF7Color => isDarkMode ? dark.greyF7Color : const Color(0xffF7F7F7);

@ -26,6 +26,8 @@ class CollapsingListView extends StatelessWidget {
VoidCallback? sendEmail; VoidCallback? sendEmail;
VoidCallback? doctorResponse; VoidCallback? doctorResponse;
VoidCallback? downloadReport; VoidCallback? downloadReport;
VoidCallback? viewImage;
VoidCallback? location;
Widget? bottomChild; Widget? bottomChild;
Widget? trailing; Widget? trailing;
bool isClose; bool isClose;
@ -49,6 +51,8 @@ class CollapsingListView extends StatelessWidget {
this.sendEmail, this.sendEmail,
this.doctorResponse, this.doctorResponse,
this.downloadReport, this.downloadReport,
this.viewImage,
this.location,
this.isLeading = true, this.isLeading = true,
this.trailing, this.trailing,
this.leadingCallback, this.leadingCallback,
@ -92,6 +96,8 @@ class CollapsingListView extends StatelessWidget {
sendEmail: sendEmail, sendEmail: sendEmail,
doctorResponse: doctorResponse, doctorResponse: doctorResponse,
downloadReport: downloadReport, downloadReport: downloadReport,
viewImage: viewImage,
location: location,
bottomChild: bottomChild, bottomChild: bottomChild,
trailing: trailing, trailing: trailing,
aiOverview: aiOverview, aiOverview: aiOverview,
@ -204,6 +210,8 @@ class ScrollAnimatedTitle extends StatefulWidget implements PreferredSizeWidget
VoidCallback? sendEmail; VoidCallback? sendEmail;
VoidCallback? doctorResponse; VoidCallback? doctorResponse;
VoidCallback? downloadReport; VoidCallback? downloadReport;
VoidCallback? viewImage;
VoidCallback? location;
Widget? bottomChild; Widget? bottomChild;
Widget? trailing; Widget? trailing;
@ -222,6 +230,8 @@ class ScrollAnimatedTitle extends StatefulWidget implements PreferredSizeWidget
this.sendEmail, this.sendEmail,
this.doctorResponse, this.doctorResponse,
this.downloadReport, this.downloadReport,
this.viewImage,
this.location,
this.bottomChild, this.bottomChild,
this.trailing, this.trailing,
}); });
@ -254,7 +264,7 @@ class _ScrollAnimatedTitleState extends State<ScrollAnimatedTitle> {
super.dispose(); super.dispose();
} }
double t = 0; double t = 1.0;
void _onScroll() { void _onScroll() {
final double offset = widget.controller.offset; final double offset = widget.controller.offset;
@ -301,6 +311,8 @@ class _ScrollAnimatedTitleState extends State<ScrollAnimatedTitle> {
if (widget.search != null) Utils.buildSvgWithAssets(icon: AppAssets.search_icon).onPress(widget.search!), if (widget.search != null) Utils.buildSvgWithAssets(icon: AppAssets.search_icon).onPress(widget.search!),
if (widget.aiOverview != null) actionButton(context, t, title: LocaleKeys.aiOverView.tr(context: context), icon: AppAssets.aiOverView, isAiButton: true).onPress(widget.aiOverview!), if (widget.aiOverview != null) actionButton(context, t, title: LocaleKeys.aiOverView.tr(context: context), icon: AppAssets.aiOverView, isAiButton: true).onPress(widget.aiOverview!),
if (widget.downloadReport != null) actionButton(context, t, title: LocaleKeys.downloadReport.tr(context: context), icon: AppAssets.download).onPress(widget.downloadReport!), if (widget.downloadReport != null) actionButton(context, t, title: LocaleKeys.downloadReport.tr(context: context), icon: AppAssets.download).onPress(widget.downloadReport!),
if (widget.viewImage != null) actionButton(context, t, title: LocaleKeys.viewRadiologyImage.tr(context: context), icon: AppAssets.download).onPress(widget.viewImage!),
if (widget.location != null) actionButton(context, t, title: LocaleKeys.sortByLocation.tr(context: context), icon: AppAssets.location).onPress(widget.location!),
if (widget.trailing != null) widget.trailing!, if (widget.trailing != null) widget.trailing!,
] ]
], ],

@ -1,4 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -27,6 +29,7 @@ class AppCustomChipWidget extends StatelessWidget {
this.labelPadding, this.labelPadding,
this.onDeleteTap, this.onDeleteTap,
this.applyThemeColor = true, this.applyThemeColor = true,
this.isEnglishOnly = false
}); });
final String? labelText; final String? labelText;
@ -48,6 +51,7 @@ class AppCustomChipWidget extends StatelessWidget {
final void Function()? onChipTap; final void Function()? onChipTap;
final void Function()? onDeleteTap; final void Function()? onDeleteTap;
final bool applyThemeColor; final bool applyThemeColor;
final bool isEnglishOnly;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -85,7 +89,7 @@ class AppCustomChipWidget extends StatelessWidget {
applyThemeColor: applyThemeColor, applyThemeColor: applyThemeColor,
) )
: SizedBox.shrink(), : SizedBox.shrink(),
label: richText ?? (labelText?? "").toText10(weight: FontWeight.w500, letterSpacing: 0, color: resolvedTextColor), label: richText ?? (labelText?? "").toText10(weight: FontWeight.w500, letterSpacing: 0, color: resolvedTextColor, isEnglishOnly: isEnglishOnly),
padding: padding, padding: padding,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
labelPadding: labelPadding ?? EdgeInsetsDirectional.only(end: deleteIcon?.isNotEmpty == true ? 2.w : 8.w), labelPadding: labelPadding ?? EdgeInsetsDirectional.only(end: deleteIcon?.isNotEmpty == true ? 2.w : 8.w),
@ -99,12 +103,15 @@ class AppCustomChipWidget extends StatelessWidget {
deleteIcon: deleteIcon?.isNotEmpty == true deleteIcon: deleteIcon?.isNotEmpty == true
? InkWell( ? InkWell(
onTap: onDeleteTap, onTap: onDeleteTap,
child: Utils.buildSvgWithAssets( child: Transform.flip(
icon: deleteIcon!, flipX: getIt.get<AppState>().isArabic(),
width: iconS, child: Utils.buildSvgWithAssets(
height: iconS, icon: deleteIcon!,
iconColor: deleteIconHasColor ? resolvedDeleteIconColor : null, width: iconS,
applyThemeColor: applyThemeColor, height: iconS,
iconColor: deleteIconHasColor ? resolvedDeleteIconColor : null,
applyThemeColor: applyThemeColor,
),
), ),
) )
: null, : null,
@ -112,7 +119,7 @@ class AppCustomChipWidget extends StatelessWidget {
) )
: Chip( : Chip(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
label: richText ?? (labelText?? "").toText10(weight: FontWeight.w500, letterSpacing: 0, color: resolvedTextColor, isCenter: true), label: richText ?? (labelText?? "").toText10(weight: FontWeight.w500, letterSpacing: 0, color: resolvedTextColor, isCenter: true, isEnglishOnly: isEnglishOnly),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
backgroundColor: resolvedBackgroundColor, backgroundColor: resolvedBackgroundColor,
shape: shape ?? shape: shape ??

@ -2,6 +2,7 @@ import 'dart:io' show Platform;
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:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart'; import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart';
@ -10,6 +11,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_reminder_view.dart'; import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_reminder_view.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/services/permission_service.dart'; import 'package:hmg_patient_app_new/services/permission_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
@ -22,19 +24,66 @@ class BottomSheetUtils {
_showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, _showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted,
onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed);
} else { } else {
// Utils.showPermissionConsentDialog(context, TranslationBase.of(context).calendarPermission, () async { showCommonBottomSheetWithoutHeight(
// if (await Permission.calendarFullAccess.request().isGranted) { title: LocaleKeys.notice.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!),
// _showReminderDialog(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, GetIt.instance<NavigationService>().navigatorKey.currentContext!,
// onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); child: Utils.getWarningWidget(
// } loadingText: LocaleKeys.calendarPermissionAlert.tr(),
// }); isShowActionButtons: true,
onCancelTap: () {
GetIt.instance<NavigationService>().pop();
},
onConfirmTap: () async {
GetIt.instance<NavigationService>().pop();
openAppSettings();
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
} }
} else { } else {
if (await Permission.calendarWriteOnly.request().isGranted) { if (await Permission.calendarWriteOnly.request().isGranted) {
if (await Permission.calendarFullAccess.request().isGranted) { if (await Permission.calendarFullAccess.request().isGranted) {
_showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, _showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted,
onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed);
} else {
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!),
GetIt.instance<NavigationService>().navigatorKey.currentContext!,
child: Utils.getWarningWidget(
loadingText: LocaleKeys.calendarPermissionAlert.tr(),
isShowActionButtons: true,
onCancelTap: () {
GetIt.instance<NavigationService>().pop();
},
onConfirmTap: () async {
GetIt.instance<NavigationService>().pop();
openAppSettings();
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
} }
} else {
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!),
GetIt.instance<NavigationService>().navigatorKey.currentContext!,
child: Utils.getWarningWidget(
loadingText: LocaleKeys.calendarPermissionAlert.tr(),
isShowActionButtons: true,
onCancelTap: () {
GetIt.instance<NavigationService>().pop();
},
onConfirmTap: () async {
GetIt.instance<NavigationService>().pop();
openAppSettings();
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
} }
} }
} }

@ -2,7 +2,8 @@ name: hmg_patient_app_new
description: "New HMG Patient App" description: "New HMG Patient App"
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 0.0.11+8 version: 0.0.15+12
#version: 0.0.1+14
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.6.0 <4.0.0"

Loading…
Cancel
Save