diff --git a/assets/images/png/body_parts/female/abdomin.png b/assets/images/png/body_parts/female/abdomin.png new file mode 100644 index 0000000..f4918d7 Binary files /dev/null and b/assets/images/png/body_parts/female/abdomin.png differ diff --git a/assets/images/png/body_parts/female/anal.png b/assets/images/png/body_parts/female/anal.png new file mode 100644 index 0000000..d96ef28 Binary files /dev/null and b/assets/images/png/body_parts/female/anal.png differ diff --git a/assets/images/png/body_parts/female/axilla.png b/assets/images/png/body_parts/female/axilla.png new file mode 100644 index 0000000..f38be6b Binary files /dev/null and b/assets/images/png/body_parts/female/axilla.png differ diff --git a/assets/images/png/body_parts/female/back.png b/assets/images/png/body_parts/female/back.png new file mode 100644 index 0000000..65d9ef1 Binary files /dev/null and b/assets/images/png/body_parts/female/back.png differ diff --git a/assets/images/png/body_parts/female/bikini.png b/assets/images/png/body_parts/female/bikini.png new file mode 100644 index 0000000..a1a6842 Binary files /dev/null and b/assets/images/png/body_parts/female/bikini.png differ diff --git a/assets/images/png/body_parts/female/bikini_line.png b/assets/images/png/body_parts/female/bikini_line.png new file mode 100644 index 0000000..12fc0e6 Binary files /dev/null and b/assets/images/png/body_parts/female/bikini_line.png differ diff --git a/assets/images/png/body_parts/female/buttocks.png b/assets/images/png/body_parts/female/buttocks.png new file mode 100644 index 0000000..b83576f Binary files /dev/null and b/assets/images/png/body_parts/female/buttocks.png differ diff --git a/assets/images/png/body_parts/female/cheeks.svg b/assets/images/png/body_parts/female/cheeks.svg new file mode 100644 index 0000000..6305ce6 --- /dev/null +++ b/assets/images/png/body_parts/female/cheeks.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/female/chest.png b/assets/images/png/body_parts/female/chest.png new file mode 100644 index 0000000..727ebe7 Binary files /dev/null and b/assets/images/png/body_parts/female/chest.png differ diff --git a/assets/images/png/body_parts/female/chest_line.png b/assets/images/png/body_parts/female/chest_line.png new file mode 100644 index 0000000..0b4fecb Binary files /dev/null and b/assets/images/png/body_parts/female/chest_line.png differ diff --git a/assets/images/png/body_parts/female/chin.svg b/assets/images/png/body_parts/female/chin.svg new file mode 100644 index 0000000..37da45b --- /dev/null +++ b/assets/images/png/body_parts/female/chin.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/female/ears.svg b/assets/images/png/body_parts/female/ears.svg new file mode 100644 index 0000000..758a69e --- /dev/null +++ b/assets/images/png/body_parts/female/ears.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/female/eyebrows.svg b/assets/images/png/body_parts/female/eyebrows.svg new file mode 100644 index 0000000..9657daa --- /dev/null +++ b/assets/images/png/body_parts/female/eyebrows.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/female/full_body_female.png b/assets/images/png/body_parts/female/full_body_female.png new file mode 100644 index 0000000..fb6a375 Binary files /dev/null and b/assets/images/png/body_parts/female/full_body_female.png differ diff --git a/assets/images/png/body_parts/female/full_legs.png b/assets/images/png/body_parts/female/full_legs.png new file mode 100644 index 0000000..5a365a7 Binary files /dev/null and b/assets/images/png/body_parts/female/full_legs.png differ diff --git a/assets/images/png/body_parts/female/full_neck.svg b/assets/images/png/body_parts/female/full_neck.svg new file mode 100644 index 0000000..f73f07f --- /dev/null +++ b/assets/images/png/body_parts/female/full_neck.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/female/half_neck.svg b/assets/images/png/body_parts/female/half_neck.svg new file mode 100644 index 0000000..78e4cfa --- /dev/null +++ b/assets/images/png/body_parts/female/half_neck.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/female/hydra_facial.svg b/assets/images/png/body_parts/female/hydra_facial.svg new file mode 100644 index 0000000..6a46821 --- /dev/null +++ b/assets/images/png/body_parts/female/hydra_facial.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/female/lower_arm.png b/assets/images/png/body_parts/female/lower_arm.png new file mode 100644 index 0000000..717b2cd Binary files /dev/null and b/assets/images/png/body_parts/female/lower_arm.png differ diff --git a/assets/images/png/body_parts/female/lower_leg.png b/assets/images/png/body_parts/female/lower_leg.png new file mode 100644 index 0000000..88ccace Binary files /dev/null and b/assets/images/png/body_parts/female/lower_leg.png differ diff --git a/assets/images/png/body_parts/female/shoulders.png b/assets/images/png/body_parts/female/shoulders.png new file mode 100644 index 0000000..e1f253a Binary files /dev/null and b/assets/images/png/body_parts/female/shoulders.png differ diff --git a/assets/images/png/body_parts/female/side_burn.svg b/assets/images/png/body_parts/female/side_burn.svg new file mode 100644 index 0000000..123216e --- /dev/null +++ b/assets/images/png/body_parts/female/side_burn.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/female/upper_arm.png b/assets/images/png/body_parts/female/upper_arm.png new file mode 100644 index 0000000..1edb873 Binary files /dev/null and b/assets/images/png/body_parts/female/upper_arm.png differ diff --git a/assets/images/png/body_parts/female/upper_legs.png b/assets/images/png/body_parts/female/upper_legs.png new file mode 100644 index 0000000..a8aa2ec Binary files /dev/null and b/assets/images/png/body_parts/female/upper_legs.png differ diff --git a/assets/images/png/body_parts/female/upper_lips.svg b/assets/images/png/body_parts/female/upper_lips.svg new file mode 100644 index 0000000..7204337 --- /dev/null +++ b/assets/images/png/body_parts/female/upper_lips.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/male/abdomin.png b/assets/images/png/body_parts/male/abdomin.png new file mode 100644 index 0000000..1b180b4 Binary files /dev/null and b/assets/images/png/body_parts/male/abdomin.png differ diff --git a/assets/images/png/body_parts/male/axilla.png b/assets/images/png/body_parts/male/axilla.png new file mode 100644 index 0000000..61af949 Binary files /dev/null and b/assets/images/png/body_parts/male/axilla.png differ diff --git a/assets/images/png/body_parts/male/back.png b/assets/images/png/body_parts/male/back.png new file mode 100644 index 0000000..224147e Binary files /dev/null and b/assets/images/png/body_parts/male/back.png differ diff --git a/assets/images/png/body_parts/male/back.svg b/assets/images/png/body_parts/male/back.svg new file mode 100644 index 0000000..7d9aeb4 --- /dev/null +++ b/assets/images/png/body_parts/male/back.svg @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/male/bikini.png b/assets/images/png/body_parts/male/bikini.png new file mode 100644 index 0000000..aa98ea7 Binary files /dev/null and b/assets/images/png/body_parts/male/bikini.png differ diff --git a/assets/images/png/body_parts/male/bikini_line.png b/assets/images/png/body_parts/male/bikini_line.png new file mode 100644 index 0000000..60ed64e Binary files /dev/null and b/assets/images/png/body_parts/male/bikini_line.png differ diff --git a/assets/images/png/body_parts/male/cheek.svg b/assets/images/png/body_parts/male/cheek.svg new file mode 100644 index 0000000..984a59f --- /dev/null +++ b/assets/images/png/body_parts/male/cheek.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/male/chest.png b/assets/images/png/body_parts/male/chest.png new file mode 100644 index 0000000..b7cec07 Binary files /dev/null and b/assets/images/png/body_parts/male/chest.png differ diff --git a/assets/images/png/body_parts/male/chest_line.png b/assets/images/png/body_parts/male/chest_line.png new file mode 100644 index 0000000..41e779f Binary files /dev/null and b/assets/images/png/body_parts/male/chest_line.png differ diff --git a/assets/images/png/body_parts/male/chin.svg b/assets/images/png/body_parts/male/chin.svg new file mode 100644 index 0000000..9fdee93 --- /dev/null +++ b/assets/images/png/body_parts/male/chin.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/male/ears.svg b/assets/images/png/body_parts/male/ears.svg new file mode 100644 index 0000000..1c9600c --- /dev/null +++ b/assets/images/png/body_parts/male/ears.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/male/eyebrows.svg b/assets/images/png/body_parts/male/eyebrows.svg new file mode 100644 index 0000000..ea38523 --- /dev/null +++ b/assets/images/png/body_parts/male/eyebrows.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/male/full_body_male.png b/assets/images/png/body_parts/male/full_body_male.png new file mode 100644 index 0000000..df30472 Binary files /dev/null and b/assets/images/png/body_parts/male/full_body_male.png differ diff --git a/assets/images/png/body_parts/male/full_legs.png b/assets/images/png/body_parts/male/full_legs.png new file mode 100644 index 0000000..eee2fa0 Binary files /dev/null and b/assets/images/png/body_parts/male/full_legs.png differ diff --git a/assets/images/png/body_parts/male/full_neck.png b/assets/images/png/body_parts/male/full_neck.png new file mode 100644 index 0000000..a75159f Binary files /dev/null and b/assets/images/png/body_parts/male/full_neck.png differ diff --git a/assets/images/png/body_parts/male/full_neck.svg b/assets/images/png/body_parts/male/full_neck.svg new file mode 100644 index 0000000..33b755e --- /dev/null +++ b/assets/images/png/body_parts/male/full_neck.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/png/body_parts/male/half_neck.png b/assets/images/png/body_parts/male/half_neck.png new file mode 100644 index 0000000..5ee0249 Binary files /dev/null and b/assets/images/png/body_parts/male/half_neck.png differ diff --git a/assets/images/png/body_parts/male/half_neck.svg b/assets/images/png/body_parts/male/half_neck.svg new file mode 100644 index 0000000..26b6bc3 --- /dev/null +++ b/assets/images/png/body_parts/male/half_neck.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/png/body_parts/male/hydra_facial.svg b/assets/images/png/body_parts/male/hydra_facial.svg new file mode 100644 index 0000000..1051630 --- /dev/null +++ b/assets/images/png/body_parts/male/hydra_facial.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/male/lower_arm.png b/assets/images/png/body_parts/male/lower_arm.png new file mode 100644 index 0000000..120242e Binary files /dev/null and b/assets/images/png/body_parts/male/lower_arm.png differ diff --git a/assets/images/png/body_parts/male/lower_legs.png b/assets/images/png/body_parts/male/lower_legs.png new file mode 100644 index 0000000..8367aa8 Binary files /dev/null and b/assets/images/png/body_parts/male/lower_legs.png differ diff --git a/assets/images/png/body_parts/male/shoulders.png b/assets/images/png/body_parts/male/shoulders.png new file mode 100644 index 0000000..907f2dd Binary files /dev/null and b/assets/images/png/body_parts/male/shoulders.png differ diff --git a/assets/images/png/body_parts/male/side_burn.svg b/assets/images/png/body_parts/male/side_burn.svg new file mode 100644 index 0000000..156b30f --- /dev/null +++ b/assets/images/png/body_parts/male/side_burn.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/png/body_parts/male/upper_arm.png b/assets/images/png/body_parts/male/upper_arm.png new file mode 100644 index 0000000..f80a75d Binary files /dev/null and b/assets/images/png/body_parts/male/upper_arm.png differ diff --git a/assets/images/png/body_parts/male/upper_legs.png b/assets/images/png/body_parts/male/upper_legs.png new file mode 100644 index 0000000..e0c973b Binary files /dev/null and b/assets/images/png/body_parts/male/upper_legs.png differ diff --git a/assets/images/png/body_parts/male/upper_lips.svg b/assets/images/png/body_parts/male/upper_lips.svg new file mode 100644 index 0000000..b7ae6e0 --- /dev/null +++ b/assets/images/png/body_parts/male/upper_lips.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 811a1af..787a718 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -874,5 +874,7 @@ "to": "إلى", "startDate": "تاريخ البدء", "endDate": "تاريخ الانتهاء", - "walkin": "زيارة بدون موعد" + "walkin": "زيارة بدون موعد", + "laserClinic": "عيادة الليزر", + "continueString": "يكمل" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 336c06c..7b8c4b8 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -685,8 +685,8 @@ "body": "Body Mass", "bodyString": "Body", "face": "Face", - "retouch": "روتوش", - "bikini": "بيكيني", + "retouch": "Re-touch", + "bikini": "Bikini", "totalMinutes": "Total Minutes", "feedback": "Feedback", "send": "أرسل", @@ -870,6 +870,8 @@ "clearAllFilters": "Clear all filters", "filters": "Filters", "searchClinic": "Search Clinic", - "walkin": "Walk In" + "walkin": "Walk In", + "continueString": "Continue", + "laserClinic": "Laser Clinic" } \ No newline at end of file diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart index 42349ef..7337dfa 100644 --- a/lib/core/dependencies.dart +++ b/lib/core/dependencies.dart @@ -154,7 +154,7 @@ class AppDependencies { ); getIt.registerLazySingleton( - () => BookAppointmentsViewModel(bookAppointmentsRepo: getIt(), errorHandlerService: getIt(), navigationService: getIt(), myAppointmentsViewModel: getIt(), locationUtils: getIt()), + () => BookAppointmentsViewModel(bookAppointmentsRepo: getIt(), errorHandlerService: getIt(), navigationService: getIt(), myAppointmentsViewModel: getIt(), locationUtils: getIt(), dialogService: getIt()), ); getIt.registerLazySingleton( @@ -165,6 +165,12 @@ class AppDependencies { myAppointmentsViewModel: getIt(), ), ); + getIt.registerLazySingleton( + () => AppointmentViaRegionViewmodel( + navigationService: getIt(), + appState: getIt(), + ), + ); getIt.registerLazySingleton( () => AuthenticationViewModel( diff --git a/lib/features/book_appointments/book_appointments_repo.dart b/lib/features/book_appointments/book_appointments_repo.dart index 437d2c8..1783556 100644 --- a/lib/features/book_appointments/book_appointments_repo.dart +++ b/lib/features/book_appointments/book_appointments_repo.dart @@ -16,6 +16,8 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ 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/logger_service.dart'; +import 'models/resp_models/laser_body_parts.dart'; + abstract class BookAppointmentsRepo { Future>>> getClinics(); @@ -79,6 +81,9 @@ abstract class BookAppointmentsRepo { Future>>> getDentalChiefComplaintDoctorsList(int projectID, int chiefComplaintID, {Function(dynamic)? onSuccess, Function(String)? onError}); + + Future>>> getLaserClinics(int laserCategoryID, int projectID, int languageID, + {Function(dynamic)? onSuccess, Function(String)? onError}); } class BookAppointmentsRepoImp implements BookAppointmentsRepo { @@ -800,4 +805,47 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo { return Left(UnknownFailure(e.toString())); } } + + @override + Future>>> getLaserClinics(int laserCategoryID, int projectID, int languageID, {Function(dynamic p1)? onSuccess, Function(String p1)? onError}) async { + Map mapDevice = { + "LaserCategoryID": laserCategoryID, + "ProjectID": projectID, + "LanguageID": languageID, + }; + + try { + GenericApiModel>? apiResponse; + Failure? failure; + await apiClient.post( + LASER_BODY_PARTS, + body: mapDevice, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + onError!(error); + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + final list = response['Laser_GetBodyPartsByCategoryList']; + + final doctorsList = list.map((item) => LaserBodyPart.fromJson(item as Map)).toList().cast(); + + apiResponse = GenericApiModel>( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: doctorsList, + ); + } 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())); + } + } } diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index 26bfe4f..20b64fd 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; @@ -11,12 +13,14 @@ 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/book_appointments/book_appointments_repo.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/models/LaserCategoryType.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/free_slot.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/dental_chief_complaints_response_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctor_profile_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/book_appointments/models/resp_models/get_clinic_list_response_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_patient_dental_plan_response_model.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/laser_body_parts.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/timeslots.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart'; @@ -24,6 +28,7 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ 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/presentation/home/navigation_screen.dart'; +import 'package:hmg_patient_app_new/services/dialog_service.dart'; 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/widgets/common_bottom_sheet.dart'; @@ -32,6 +37,7 @@ import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'models/resp_models/get_livecare_clinics_response_model.dart'; class BookAppointmentsViewModel extends ChangeNotifier { + final DialogService dialogService; int selectedTabIndex = 0; bool isClinicsListLoading = false; @@ -108,8 +114,31 @@ class BookAppointmentsViewModel extends ChangeNotifier { String? selectedClinicForFilters; bool applyFilters = false; + + ///variables for laser clinic + List femaleLaserCategory = [ + LaserCategoryType(1, 'bodyString'), + LaserCategoryType(2, 'face'), + LaserCategoryType(10,'bikini'), + LaserCategoryType(11, 'retouch'), + ]; + List maleLaserCategory =[ + LaserCategoryType(1, 'body'), + LaserCategoryType(2, 'face'), + LaserCategoryType(11, 'retouch'), + ]; + List> bodyTypes = []; + + List laserBodyPartsList = []; + List selectedBodyPartList = []; + int selectedBodyTypeIndex = 0; + int selectedCategory = 0; + bool isBodyPartsLoading = false; + int duration = 0; + + BookAppointmentsViewModel( - {required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel, required this.locationUtils}) { + {required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel, required this.locationUtils, required this.dialogService }) { initBookAppointmentViewModel(); } @@ -141,6 +170,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { dentalChiefComplaintsList.clear(); isContinueDentalPlan = false; isChiefComplaintsListLoading = true; + bodyTypes = [maleLaserCategory, femaleLaserCategory]; // getLocation(); notifyListeners(); } @@ -310,7 +340,10 @@ class BookAppointmentsViewModel extends ChangeNotifier { result.fold( (failure) async { + isDoctorsListLoading = false; + onError!("No doctors found for the search criteria".needTranslation); + notifyListeners(); }, (apiResponse) { if (apiResponse.messageStatus == 2) { @@ -342,7 +375,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { result.fold( (failure) async { - onError!("No doctors found for the search criteria".needTranslation); + onError?.call("No doctors found for the search criteria".needTranslation); }, (apiResponse) async { if (apiResponse.messageStatus == 2) { @@ -1017,4 +1050,105 @@ class BookAppointmentsViewModel extends ChangeNotifier { }, ); } + + setBodyType(int bodyType){ + selectedBodyTypeIndex = bodyType; + selectedCategory = 0; + selectedBodyPartList = []; + duration = 0; + notifyListeners(); + } + + FutureOr getLaserClinic() async{ + isBodyPartsLoading = true; + int id = bodyTypes[selectedBodyTypeIndex][selectedCategory].laserCategoryID; + int projectID = currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : 0; + int languageID = _appState.isArabic() ? 1 : 0; + final result = await bookAppointmentsRepo.getLaserClinics(id, projectID, languageID); + result.fold( + (failure) { + isBodyPartsLoading = false; + notifyListeners(); + }, + (apiResponse) {isBodyPartsLoading = false; + if (apiResponse.messageStatus == 2) { + // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + } else if (apiResponse.messageStatus == 1) { + List response =apiResponse.data!; + if(response.first.category == 2 || response.first.category == 10 ) response.remove(response.first); + laserBodyPartsList = response; + } + notifyListeners(); + + }, + ); + } + + int getDuration() { + var duration = 0; + + var lowerUpperLegsList = selectedBodyPartList.where((element) => element.mappingCode == "47" || element.mappingCode == "48")?.toList() ?? []; + var upperLowerArmsList = selectedBodyPartList.where((element) => element.mappingCode == "40" || element.mappingCode == "41")?.toList() ?? []; + + if (selectedBodyPartList.isNotEmpty) { + duration = selectedBodyPartList.fold(0, (previousValue, element) => previousValue + int.parse(element.timeDuration!)); + } + if (lowerUpperLegsList.length == 2) { + duration -= 30; + } + if (upperLowerArmsList.length == 2) { + duration -= 15; + } + + return duration; + } + + void setSelectedCategory(category) { + selectedCategory = category; + notifyListeners(); + getLaserClinic(); + } + + void setSelectedBodyPart(LaserBodyPart part) { + if(selectedBodyPartList.contains(part)){ + selectedBodyPartList.remove(part); + this.duration = getDuration(); + + notifyListeners(); + } else { + if(this.duration == 90){ + dialogService.showErrorBottomSheet(message: "Duration can not exceed 90 min".needTranslation,); + return; + } + selectedBodyPartList.add(part); + var duration = getDuration(); + if(duration > 90){ + selectedBodyPartList.remove(part); + dialogService.showErrorBottomSheet(message: "Duration Exceeds 90 min".needTranslation,); + return; + } + this.duration = duration; + notifyListeners(); + } + } + + readCurrentLaserCategoryID() { + return bodyTypes[selectedBodyTypeIndex][selectedCategory].laserCategoryID; + } + + String getLaserProcedureNameWRTLanguage(LaserBodyPart part) { + if(_appState.isArabic()){ + return part.bodyPartN??""; + }else { + return part.bodyPart??""; + } + } + + void resetLaserData() { + selectedCategory = 0; + selectedBodyTypeIndex = 0; + selectedBodyPartList = []; + laserBodyPartsList = []; + duration = 0; + } } diff --git a/lib/features/book_appointments/models/LaserCategoryType.dart b/lib/features/book_appointments/models/LaserCategoryType.dart new file mode 100644 index 0000000..df85620 --- /dev/null +++ b/lib/features/book_appointments/models/LaserCategoryType.dart @@ -0,0 +1,6 @@ +class LaserCategoryType { + int laserCategoryID; + String title; + + LaserCategoryType(this.laserCategoryID, this.title); +} diff --git a/lib/features/book_appointments/models/laser_body_parts_data.dart b/lib/features/book_appointments/models/laser_body_parts_data.dart new file mode 100644 index 0000000..2f8b32d --- /dev/null +++ b/lib/features/book_appointments/models/laser_body_parts_data.dart @@ -0,0 +1,135 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class LaserBodyParts { + static final LaserBodyParts _instance = LaserBodyParts._internal(); + + LaserBodyParts._internal(); + + factory LaserBodyParts() => _instance; + + static Widget image(String assetUri) { + return new SvgPicture.asset(assetUri, fit: BoxFit.cover, width: 88, height: 88); + } + + static Widget imagePng(String assetUri) { + return Image.asset(assetUri, fit: BoxFit.cover, width: 88, height: 88); + } + + Map maleBodyMap = { + "1": imagePng("assets/images/png/body_parts/male/full_body_male.png"), + "40": imagePng("assets/images/png/body_parts/male/upper_arm.png"), + "41": imagePng("assets/images/png/body_parts/male/lower_arm.png"), + "42": imagePng("assets/images/png/body_parts/male/chest.png"), + "43": imagePng("assets/images/png/body_parts/male/chest_line.png"), + "44": imagePng("assets/images/png/body_parts/male/shoulders.png"), + "45": imagePng("assets/images/png/body_parts/male/back.png"), + "46": imagePng("assets/images/png/body_parts/male/abdomin.png"), + "47": imagePng("assets/images/png/body_parts/male/upper_legs.png"), + "48": imagePng("assets/images/png/body_parts/male/lower_legs.png"), + "49": imagePng("assets/images/png/body_parts/male/axilla.png") + }; + + Map maleFaceMap = { + "62": image("assets/images/png/body_parts/male/hydra_facial.svg"), + "5": image("assets/images/png/body_parts/male/upper_lips.svg"), + "6": image("assets/images/png/body_parts/male/chin.svg"), + "7": image("assets/images/png/body_parts/male/cheek.svg"), + "8": image("assets/images/png/body_parts/male/side_burn.svg"), + "9": image("assets/images/png/body_parts/male/ears.svg"), + "10": image("assets/images/png/body_parts/male/full_neck.svg"), + "11": image("assets/images/png/body_parts/male/half_neck.svg"), + "12": image("assets/images/png/body_parts/male/eyebrows.svg") + }; + + Map maleBodyRetouchMap = { + "50": imagePng("assets/images/png/body_parts/male/full_body_male.png"), + "51": imagePng("assets/images/png/body_parts/male/upper_arm.png"), + "52": imagePng("assets/images/png/body_parts/male/lower_arm.png"), + "53": imagePng("assets/images/png/body_parts/male/chest.png"), + "54": imagePng("assets/images/png/body_parts/male/shoulders.png"), + "55": imagePng("assets/images/png/body_parts/male/back.png"), + "56": imagePng("assets/images/png/body_parts/male/abdomin.png"), + "57": imagePng("assets/images/png/body_parts/male/full_legs.png"), + "58": imagePng("assets/images/png/body_parts/male/upper_legs.png"), + "59": imagePng("assets/images/png/body_parts/male/lower_legs.png"), + "60": imagePng("assets/images/png/body_parts/male/bikini.png"), + "61": imagePng("assets/images/png/body_parts/male/bikini_line.png") + }; + + Map femaleBodyMap = { + "1": imagePng("assets/images/png/body_parts/female/full_body_female.png"), + "40": imagePng("assets/images/png/body_parts/female/upper_arm.png"), + "41": imagePng("assets/images/png/body_parts/female/lower_arm.png"), + "42": imagePng("assets/images/png/body_parts/female/chest.png"), + "43": imagePng("assets/images/png/body_parts/female/chest_line.png"), + "44": imagePng("assets/images/png/body_parts/female/shoulders.png"), + "45": imagePng("assets/images/png/body_parts/female/back.png"), + "46": imagePng("assets/images/png/body_parts/female/abdomin.png"), + "47": imagePng("assets/images/png/body_parts/female/upper_legs.png"), + "48": imagePng("assets/images/png/body_parts/female/lower_leg.png"), + "49": imagePng("assets/images/png/body_parts/female/axilla.png") + }; + + Map femaleFaceMap = { + "62": image("assets/images/png/body_parts/female/hydra_facial.svg"), + "5": image("assets/images/png/body_parts/female/upper_lips.svg"), + "6": image("assets/images/png/body_parts/female/chin.svg"), + "7": image("assets/images/png/body_parts/female/cheeks.svg"), + "8": image("assets/images/png/body_parts/female/side_burn.svg"), + "9": image("assets/images/png/body_parts/female/ears.svg"), + "10": image("assets/images/png/body_parts/female/full_neck.svg"), + "11": image("assets/images/png/body_parts/female/half_neck.svg"), + "12": image("assets/images/png/body_parts/female/eyebrows.svg") + }; + + Map femaleBodyBikiniMap = { + "34": imagePng("assets/images/png/body_parts/female/bikini.png"), + "36": imagePng("assets/images/png/body_parts/female/bikini_line.png"), + "38": imagePng("assets/images/png/body_parts/female/buttocks.png"), + "39": imagePng("assets/images/png/body_parts/female/anal.png") + }; + + Map femaleBodyRetouchMap = { + "50": imagePng("assets/images/png/body_parts/female/full_body_female.png"), + "51": imagePng("assets/images/png/body_parts/female/upper_arm.png"), + "52": imagePng("assets/images/png/body_parts/female/lower_arm.png"), + "53": imagePng("assets/images/png/body_parts/female/chest.png"), + "54": imagePng("assets/images/png/body_parts/female/shoulders.png"), + "55": imagePng("assets/images/png/body_parts/female/back.png"), + "56": imagePng("assets/images/png/body_parts/female/abdomin.png"), + "57": imagePng("assets/images/png/body_parts/female/full_legs.png"), + "58": imagePng("assets/images/png/body_parts/female/upper_legs.png"), + "59": imagePng("assets/images/png/body_parts/female/lower_leg.png"), + "60": imagePng("assets/images/png/body_parts/female/bikini.png"), + "61": imagePng("assets/images/png/body_parts/female/bikini_line.png") + }; + + Widget? getCategoryImage(bool isMale, int category, String mappingCode) { + if (isMale) { + if (category == 1) { + return maleBodyMap![mappingCode]!; + } + if (category == 2) { + return maleFaceMap![mappingCode]!; + } + if (category == 11) { + return maleBodyRetouchMap![mappingCode]!; + } + } else { + if (category == 1) { + return femaleBodyMap![mappingCode]!; + } + if (category == 2) { + return femaleFaceMap![mappingCode]!; + } + if (category == 10) { + return femaleBodyBikiniMap![mappingCode]!; + } + if (category == 11) { + return femaleBodyRetouchMap![mappingCode]!; + } + } + return null; + } +} \ No newline at end of file diff --git a/lib/features/book_appointments/models/resp_models/laser_body_parts.dart b/lib/features/book_appointments/models/resp_models/laser_body_parts.dart new file mode 100644 index 0000000..d7d3fbd --- /dev/null +++ b/lib/features/book_appointments/models/resp_models/laser_body_parts.dart @@ -0,0 +1,64 @@ +class LaserBodyPart { + int? id; + int? category; + String? bodyPart; + bool? fullBoadyPart; + bool? isRetouch; + String? timeDuration; + String? bodyPartN; + bool? isActive; + String? mappingCode; + int? procedureID; + int? orderNum; + String? categoryName; + String? categoryNameN; + + LaserBodyPart( + {this.id, + this.category, + this.bodyPart, + this.fullBoadyPart, + this.isRetouch, + this.timeDuration, + this.bodyPartN, + this.isActive, + this.mappingCode, + this.procedureID, + this.orderNum, + this.categoryName, + this.categoryNameN}); + + LaserBodyPart.fromJson(Map json) { + id = json['Id']; + category = json['Category']; + bodyPart = json['BodyPart']; + fullBoadyPart = json['FullBoadyPart']; + isRetouch = json['IsRetouch']; + timeDuration = json['TimeDuration']; + bodyPartN = json['BodyPartN']; + isActive = json['IsActive']; + mappingCode = json['MappingCode']; + procedureID = json['ProcedureID']; + orderNum = json['OrderNum']; + categoryName = json['CategoryName']; + categoryNameN = json['CategoryNameN']; + } + + Map toJson() { + final Map data = new Map(); + data['Id'] = this.id; + data['Category'] = this.category; + data['BodyPart'] = this.bodyPart; + data['FullBoadyPart'] = this.fullBoadyPart; + data['IsRetouch'] = this.isRetouch; + data['TimeDuration'] = this.timeDuration; + data['BodyPartN'] = this.bodyPartN; + data['IsActive'] = this.isActive; + data['MappingCode'] = this.mappingCode; + data['ProcedureID'] = this.procedureID; + data['OrderNum'] = this.orderNum; + data['CategoryName'] = this.categoryName; + data['CategoryNameN'] = this.categoryNameN; + return data; + } +} diff --git a/lib/features/my_appointments/appointment_via_region_viewmodel.dart b/lib/features/my_appointments/appointment_via_region_viewmodel.dart index 9ffb544..3e3c3cd 100644 --- a/lib/features/my_appointments/appointment_via_region_viewmodel.dart +++ b/lib/features/my_appointments/appointment_via_region_viewmodel.dart @@ -1,6 +1,8 @@ import 'package:flutter/foundation.dart' show ChangeNotifier; import 'package:hmg_patient_app_new/core/app_state.dart' show AppState; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/dental_chief_complaints_page.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/laser/laser_appointment.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/select_doctor_page.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; @@ -96,9 +98,30 @@ class AppointmentViaRegionViewmodel extends ChangeNotifier { ),); } - void handleLastStepForClinicForDentalAndLaser() { - //todo handle the routing here + void handleLastStepForClinicForDentalAndLaser(int clinicId) { navigationService.pop(); + + if (clinicId == 17) { + if (!appState.isAuthenticated) { + navigationService.push( + CustomPageRoute( + page: DentalChiefComplaintsPage(), + ), + ); + } + } + + if (clinicId == 253) { + { + + + navigationService.push( + CustomPageRoute( + page: LaserAppointment(), + ), + ); + } + } } void handleLastStepForDentalAndLaser() { diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index d14a021..798f94d 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -189,6 +189,7 @@ abstract class LocaleKeys { static const firstName = 'firstName'; static const middleName = 'middleName'; static const lastName = 'lastName'; + static const female = 'female'; static const preferredLanguage = 'preferredLanguage'; static const locationsRegister = 'locationsRegister'; static const ksa = 'ksa'; @@ -863,7 +864,6 @@ abstract class LocaleKeys { static const clearAllFilters = 'clearAllFilters'; static const filters = 'filters'; static const searchClinic = 'searchClinic'; - static const walkin = 'walkin'; static const normal = 'normal'; static const attention = 'attention'; static const monitor = 'monitor'; @@ -873,5 +873,8 @@ abstract class LocaleKeys { static const to = 'to'; static const startDate = 'startDate'; static const endDate = 'endDate'; + static const walkin = 'walkin'; + static const laserClinic = 'laserClinic'; + static const continueString = 'continueString'; } diff --git a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart index 7a4d7e9..29a7b96 100644 --- a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart +++ b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart @@ -104,7 +104,7 @@ class HospitalBottomSheetBody extends StatelessWidget { regionalViewModel.handleLastStepForClinic(); } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) { regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); - regionalViewModel.handleLastStepForClinicForDentalAndLaser(); + regionalViewModel.handleLastStepForClinicForDentalAndLaser(appointmentsViewModel.selectedClinic.clinicID??-1); // regionalViewModel.handleLastStepForClinic(); } });}, diff --git a/lib/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart b/lib/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart index 174fe10..6bc8007 100644 --- a/lib/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart +++ b/lib/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart @@ -10,6 +10,8 @@ import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_vie import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bottomsheet/region_list_item.dart' show RegionListItem; import 'package:provider/provider.dart'; +import '../../../../widgets/common_bottom_sheet.dart'; + class RegionBottomSheetBody extends StatefulWidget { const RegionBottomSheetBody({super.key}); @@ -27,7 +29,16 @@ class _RegionBottomSheetBodyState extends State { if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION || regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER ) { myAppointmentsViewModel.getRegionMappedProjectList(); } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) { - myAppointmentsViewModel.getMappedDoctors(); + myAppointmentsViewModel.getMappedDoctors(onError: (err) { + Navigator.pop(context); + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: err), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }); } }); super.initState(); diff --git a/lib/presentation/book_appointment/laser/laser_appointment.dart b/lib/presentation/book_appointment/laser/laser_appointment.dart new file mode 100644 index 0000000..bad0591 --- /dev/null +++ b/lib/presentation/book_appointment/laser/laser_appointment.dart @@ -0,0 +1,129 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.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/widget_extensions.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/laser_body_parts.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/laser/widgets/body_part_listing.dart' show BodyPartsListing; +import 'package:hmg_patient_app_new/presentation/book_appointment/laser/widgets/body_type_listing.dart' + show BodyTypeListing; +import 'package:hmg_patient_app_new/presentation/book_appointment/select_doctor_page.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart' show AppColors; +import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; +import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; +import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; +import 'package:provider/provider.dart'; + +class LaserAppointment extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.bgScaffoldColor, + bottomNavigationBar: + DecoratedBox( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.h, + hasShadow: true, + ), + child: Selector(selector: (_, vm)=>vm.duration,builder: (_, duration, __)=> Row( + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + LocaleKeys.totalMinutes.tr(), + style: TextStyle( + fontSize: 12.fSize, + fontWeight: FontWeight.w600, + color: AppColors.textColor, + letterSpacing: -0.48, + ), + ), + Text( + "$duration / 90".tr(), + style: TextStyle( + fontSize: 16.fSize, + fontWeight: FontWeight.bold, + color: AppColors.textColor, + letterSpacing: -0.64, + ), + ), + ], + ), + ), + Expanded( + child: CustomButton( + isDisabled: duration==0, + text: LocaleKeys.continueString.tr(), onPressed: () { + Navigator.of(context).push( + CustomPageRoute( + page: SelectDoctorPage(), + ), + ); + }, + ), + ), + ], + )).paddingSymmetrical(24.h, 12.h), + ), + body: CollapsingListView( + title: LocaleKeys.laserClinic.tr(), + child: SingleChildScrollView( + child: Column( + children: [ + CustomTabBar( + activeTextColor: Color(0xffED1C2B), + activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), + tabs: [ + CustomTabBarModel(null,LocaleKeys.malE.tr()), + CustomTabBarModel(null,LocaleKeys.female.tr()), + ], + onTabChange: (index) { + var viewmodel = context.read(); + viewmodel.setBodyType(index); + viewmodel.setSelectedCategory(0); + viewmodel.getLaserClinic(); + }, + ), + Selector( + selector: (_, vm) => vm.selectedBodyTypeIndex, + builder: (_, bodyType, __) { + return BodyTypeListing( + availableBodyArea: context + .read() + .bodyTypes[bodyType], + selectedBodyAreaIndex: context + .read() + .selectedCategory, + onCategoryChanged: (category) { + context + .read() + .setSelectedCategory(category); + }); + }, + ), + Selector>(selector: (_, vm) => vm.laserBodyPartsList, builder:(_, parts,__){ + return BodyPartsListing( + parts: parts, + onPartSelected: (part){ + context.read().setSelectedBodyPart(part); + }, + selectedPart: context.watch().selectedBodyPartList, + isLoading: context.watch().isBodyPartsLoading, + isMale: context.watch().selectedBodyTypeIndex == 0, + laserCategoryID: context.watch().readCurrentLaserCategoryID(), + ); + }), + ], + ).paddingSymmetrical(24.h, 12.h), + ), + ), + ); + } +} diff --git a/lib/presentation/book_appointment/laser/widgets/body_part_listing.dart b/lib/presentation/book_appointment/laser/widgets/body_part_listing.dart new file mode 100644 index 0000000..564c013 --- /dev/null +++ b/lib/presentation/book_appointment/laser/widgets/body_part_listing.dart @@ -0,0 +1,129 @@ +import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/core/app_export.dart'; +import 'package:hmg_patient_app_new/extensions/widget_extensions.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/laser_body_parts_data.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/laser_body_parts.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:provider/provider.dart'; + +class BodyPartsListing extends StatelessWidget { + final List parts; + final Function(LaserBodyPart) onPartSelected; + final List selectedPart; + final int laserCategoryID; + final bool isMale; + final bool isLoading; + + const BodyPartsListing( + {super.key, + required this.parts, + required this.onPartSelected, + required this.selectedPart, + required this.laserCategoryID, + required this.isMale, required this.isLoading}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Visibility( + visible: isLoading, + child: GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + childAspectRatio: 85 / 107, + crossAxisSpacing: 4.h, + mainAxisSpacing: 21.h), + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: 20, + // padding: fullBody != null ? EdgeInsets.only(top: 16) : EdgeInsets.zero, + padding: EdgeInsets.zero, + itemBuilder: (BuildContext context, int index) { + return SizedBox( height: 80, width: 80,).toShimmer2(isShow: isLoading); + })), + GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + childAspectRatio: 85 / 107, + crossAxisSpacing: 4.h, + mainAxisSpacing: 21.h), + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: parts.length, + // padding: fullBody != null ? EdgeInsets.only(top: 16) : EdgeInsets.zero, + padding: EdgeInsets.zero, + itemBuilder: (BuildContext context, int index) { + bool _isSelected = + selectedPart.any((file) => file.id == parts[index].id); + return InkWell( + onTap: () { + onPartSelected(parts[index]); + }, + child: AnimatedOpacity( + opacity: 1.0, + duration: Duration(milliseconds: 200), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AspectRatio( + aspectRatio: 97 / 97, + child: FittedBox( + fit: BoxFit.fitWidth, + child: Stack( + alignment: Alignment.topRight, + children: [ + Container( + margin: EdgeInsets.only(top: 5.h, right: 5.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15.0), + border: Border.all( + color: _isSelected + ? AppColors.primaryRedColor + : AppColors.borderGrayColor, + width: 2.h), + ), + child: LaserBodyParts().getCategoryImage(isMale, + laserCategoryID, parts[index].mappingCode!), + ), + if (_isSelected) + Container( + width: 18.h, + height: 18.h, + child: Icon(Icons.done, + color: Colors.white, size: 12.h), + decoration: BoxDecoration( + color: AppColors.primaryRedColor, + borderRadius: BorderRadius.circular(30.h), + ), + ), + ], + ), + ), + ), + SizedBox(height: 6.h), + Expanded( + child: Text( + context + .read() + .getLaserProcedureNameWRTLanguage(parts[index]), + style: TextStyle( + fontSize: 12.fSize, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.48, + ), + maxLines: 1, + ), + ), + ], + ), + ), + ); + }, + ), + ], + ); + } +} diff --git a/lib/presentation/book_appointment/laser/widgets/body_type_listing.dart b/lib/presentation/book_appointment/laser/widgets/body_type_listing.dart new file mode 100644 index 0000000..d8fa736 --- /dev/null +++ b/lib/presentation/book_appointment/laser/widgets/body_type_listing.dart @@ -0,0 +1,66 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.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/widget_extensions.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/models/LaserCategoryType.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; +import 'package:smooth_corner/smooth_corner.dart' show SmoothRectangleBorder; + +class BodyTypeListing extends StatelessWidget { + final List availableBodyArea; + final Function(int) onCategoryChanged; + final int selectedBodyAreaIndex; + + const BodyTypeListing( + {super.key, + required this.availableBodyArea, + required this.onCategoryChanged, + required this.selectedBodyAreaIndex}); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 56.h, + child: Row( + children: [ + Expanded( + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: availableBodyArea.length, + separatorBuilder: (_, index) => SizedBox( + width: 8.h, + ), + itemBuilder: (_, index) => AppCustomChipWidget( + backgroundColor: index == selectedBodyAreaIndex + ? AppColors.chipSecondaryLightRedColor + : AppColors.whiteColor, + textColor: index == selectedBodyAreaIndex + ? AppColors.chipPrimaryRedBorderColor + : AppColors.blackColor, + labelText: availableBodyArea[index].title.tr(), + iconHasColor: false, + iconColor: index == selectedBodyAreaIndex + ? AppColors.chipPrimaryRedBorderColor + : AppColors.blackColor, + iconSize: 16, + labelPadding: + EdgeInsetsDirectional.only(start: 8.h, end: 0.h), + padding: + EdgeInsets.symmetric(vertical: 16.h, horizontal: 12.h), + deleteIconSize: Size(18.h, 18.h), + shape: SmoothRectangleBorder( + borderRadius: BorderRadius.circular(10), + smoothness: 10, + side: BorderSide( + color: index == selectedBodyAreaIndex + ? AppColors.chipPrimaryRedBorderColor + : AppColors.borderGrayColor, + width: 1), + )).onPress(() => onCategoryChanged(index)))) + ], + ), + ); + } +} diff --git a/lib/presentation/book_appointment/select_clinic_page.dart b/lib/presentation/book_appointment/select_clinic_page.dart index ada4809..f5e534e 100644 --- a/lib/presentation/book_appointment/select_clinic_page.dart +++ b/lib/presentation/book_appointment/select_clinic_page.dart @@ -19,6 +19,7 @@ import 'package:hmg_patient_app_new/presentation/appointments/widgets/faculity_s import 'package:hmg_patient_app_new/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/dental_chief_complaints_page.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/laser/laser_appointment.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/select_doctor_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/select_livecare_clinic_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/clinic_card.dart'; @@ -223,26 +224,51 @@ class _SelectClinicPageState extends State { void handleDoctorScreen(GetClinicsListResponseModel clinic) async { if (widget.isFromRegionFlow) { //Dental Clinic Flow - if (clinic.clinicID == 17 && appState.isAuthenticated) { - initDentalAppointmentBookingFlow(int.parse(bookAppointmentsViewModel.currentlySelectedHospitalFromRegionFlow ?? "0")); + if (clinic.clinicID == 17) { + if (appState.isAuthenticated) { + initDentalAppointmentBookingFlow(int.parse(bookAppointmentsViewModel + .currentlySelectedHospitalFromRegionFlow ?? + "0")); + return; + } else { + bookAppointmentsViewModel.setIsChiefComplaintsListLoading(true); + Navigator.of(context).push( + CustomPageRoute( + page: DentalChiefComplaintsPage(), + ), + ); + return; + } + } + else if (clinic.clinicID == 253) { + bookAppointmentsViewModel.resetLaserData(); + bookAppointmentsViewModel.getLaserClinic(); + Navigator.push( + context, + CustomPageRoute( + page: LaserAppointment(), + ), + ); + return; } else { - bookAppointmentsViewModel.setIsChiefComplaintsListLoading(true); - Navigator.of(context).push( + Navigator.push( + context, CustomPageRoute( - page: DentalChiefComplaintsPage(), + page: SelectDoctorPage(), ), ); } } else { var bottomSheetType = RegionBottomSheetType.FOR_CLINIIC; - if (clinic.clinicID == 17 || clinic.clinicID == 235) { + if (clinic.clinicID == 17 || clinic.clinicID == 253) { bottomSheetType = RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER; } openRegionListBottomSheet(context, bottomSheetType); } } - void openRegionListBottomSheet(BuildContext context, RegionBottomSheetType type) { + void openRegionListBottomSheet( + BuildContext context, RegionBottomSheetType type) { bookAppointmentsViewModel.setProjectID(null); regionalViewModel.flush(); @@ -252,16 +278,6 @@ class _SelectClinicPageState extends State { child: Consumer(builder: (_, data, __) { return getRegionalSelectionWidget(data); }), callBackFunc: () { - if (type == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER && appState.isAuthenticated) { - initDentalAppointmentBookingFlow(regionalViewModel.selectedHospital?.hospitalList.first.iD); - } else { - bookAppointmentsViewModel.setIsChiefComplaintsListLoading(true); - Navigator.of(context).push( - CustomPageRoute( - page: DentalChiefComplaintsPage(), - ), - ); - } }); } @@ -286,6 +302,18 @@ class _SelectClinicPageState extends State { } else { id = regionalViewModel.selectedHospital?.patientDoctorAppointmentList?.first.projectID?.toString() ?? ""; } + if (bookAppointmentsViewModel.selectedClinic.clinicID == 17) { + if (!appState.isAuthenticated) { + bookAppointmentsViewModel.setIsChiefComplaintsListLoading(true); + } + } + + if (bookAppointmentsViewModel.selectedClinic.clinicID == 253) { + { + bookAppointmentsViewModel.resetLaserData(); + bookAppointmentsViewModel.getLaserClinic(); + } + } bookAppointmentsViewModel.setProjectID(id); return SizedBox.shrink(); } diff --git a/lib/presentation/lab/lab_result_via_hospital/lab_order_result_item.dart b/lib/presentation/lab/lab_result_via_hospital/lab_order_result_item.dart index 87fd790..edfc65b 100644 --- a/lib/presentation/lab/lab_result_via_hospital/lab_order_result_item.dart +++ b/lib/presentation/lab/lab_result_via_hospital/lab_order_result_item.dart @@ -63,14 +63,13 @@ class LabOrderResultItem extends StatelessWidget { ), letterSpacing: -2, ), - overflow: TextOverflow.ellipsis, // prevent overflow - maxLines: 1, - softWrap: false, ), ), SizedBox(width: 4.h,), - Expanded( - flex: 2, + Visibility( + visible: tests?.checkIfGraphShouldBeDisplayed() == true, + child: Expanded( + flex: 2, child: Visibility( visible: tests?.referanceRange != null, child: Text( @@ -86,25 +85,31 @@ class LabOrderResultItem extends StatelessWidget { softWrap: true, ), ), - ), + ), + ) ], ), + SizedBox(height: 12.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Column( - spacing: 6.h, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - severityText.tr().toText10(weight: FontWeight.w500, color: AppColors.greyTextColor), - Utils.buildSvgWithAssets( - icon: AppAssets.lab_result_indicator, - width: 21, - height: 23, - iconColor: iconColor - ), - ], + Visibility( + visible: tests?.checkIfGraphShouldBeDisplayed() == true, + child: Column( + spacing: 6.h, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + severityText.tr().toText10( + weight: FontWeight.w500, + color: AppColors.greyTextColor), + Utils.buildSvgWithAssets( + icon: AppAssets.lab_result_indicator, + width: 21, + height: 23, + iconColor: iconColor), + ], + ), ), CustomButton( icon: AppAssets.view_report_icon, diff --git a/lib/presentation/lab/lab_results/lab_result_details.dart b/lib/presentation/lab/lab_results/lab_result_details.dart index 30c1910..ad108cc 100644 --- a/lib/presentation/lab/lab_results/lab_result_details.dart +++ b/lib/presentation/lab/lab_results/lab_result_details.dart @@ -6,7 +6,6 @@ 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/widget_extensions.dart'; -import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/lab_result.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; @@ -339,7 +338,6 @@ class LabResultDetails extends StatelessWidget { borderRadius: 24.h, hasShadow: true, ), - height: 98.h, padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/services/dialog_service.dart b/lib/services/dialog_service.dart index 6c232f5..68de687 100644 --- a/lib/services/dialog_service.dart +++ b/lib/services/dialog_service.dart @@ -62,6 +62,7 @@ class DialogServiceImp implements DialogService { } else { context.pop(); } + context.pop(); }, onCancelPressed: () { if (onCancelPressed != null) { diff --git a/lib/widgets/buttons/custom_button.dart b/lib/widgets/buttons/custom_button.dart index 05ec83f..73885b0 100644 --- a/lib/widgets/buttons/custom_button.dart +++ b/lib/widgets/buttons/custom_button.dart @@ -57,7 +57,7 @@ class CustomButton extends StatelessWidget { width: width, padding: padding, decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: isDisabled ? Colors.transparent : backgroundColor, + color: isDisabled ? backgroundColor.withOpacity(.5) : backgroundColor, borderRadius: borderRadius, customBorder: BorderRadius.circular(borderRadius), side: borderSide ?? BorderSide(width: borderWidth.h, color: isDisabled ? borderColor.withValues(alpha: 0.5) : borderColor)), diff --git a/pubspec.yaml b/pubspec.yaml index aad6de7..8265141 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -101,6 +101,8 @@ flutter: - assets/fonts/ - assets/langs/ - assets/images/ + - assets/images/png/body_parts/male/ + - assets/images/png/body_parts/female/ - assets/images/svg/ - assets/images/png/ - assets/animations/