From a711d3a6dd43b35e1b8c537df7cfe04fdb74f314 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 24 Sep 2025 14:33:00 +0300 Subject: [PATCH] LiveCare shcedule implementation contd. --- lib/core/api/api_client.dart | 4 +- lib/core/api_consts.dart | 2 +- lib/extensions/string_extensions.dart | 2 +- .../book_appointments_repo.dart | 137 ++++++++++++++ .../book_appointments_view_model.dart | 172 ++++++++++++++---- .../get_clinic_list_response_model.dart | 4 +- .../get_livecare_clinics_response_model.dart | 33 ++++ .../book_appointment_page.dart | 137 ++++++++++++-- .../book_appointment/select_clinic_page.dart | 124 +++++++++---- .../book_appointment/select_doctor_page.dart | 14 +- .../book_appointment/widgets/clinic_card.dart | 11 +- .../book_appointment/widgets/doctor_card.dart | 70 ++++--- lib/presentation/home/navigation_screen.dart | 1 + .../bottom_navigation/bottom_navigation.dart | 42 ++--- lib/widgets/buttons/custom_button.dart | 2 +- 15 files changed, 613 insertions(+), 142 deletions(-) create mode 100644 lib/features/book_appointments/models/resp_models/get_livecare_clinics_response_model.dart diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index 62339bf..deb107d 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -176,8 +176,8 @@ class ApiClientImp implements ApiClient { body[_appState.isAuthenticated ? 'TokenID' : 'LogInTokenID'] = _appState.appAuthToken; } - // body['TokenID'] = "@dm!n"; - // body['PatientID'] = 3628599; + body['TokenID'] = "@dm!n"; + body['PatientID'] = 4767477; } body.removeWhere((key, value) => value == null); diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index 5886dfa..fa02b2e 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -727,7 +727,7 @@ const FAMILY_FILES= 'Services/Authentication.svc/REST/GetAllSharedRecordsByStatu class ApiConsts { static const maxSmallScreen = 660; - static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod; + static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat; // static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 5465ce3..059e553 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -365,7 +365,7 @@ extension DynamicTextStyleExtension on BuildContext { TextBaseline? textBaseline, FontStyle? fontStyle, bool isLanguageSwitcher = false}) { - final family = FontUtils.getFontFamilyForLanguage(true); + final family = FontUtils.getFontFamilyForLanguage(false); // TODO: @Aamir make it dynamic based on app language return TextStyle( fontFamily: family, fontSize: fontSize, diff --git a/lib/features/book_appointments/book_appointments_repo.dart b/lib/features/book_appointments/book_appointments_repo.dart index 81faf91..c3cc9cf 100644 --- a/lib/features/book_appointments/book_appointments_repo.dart +++ b/lib/features/book_appointments/book_appointments_repo.dart @@ -7,6 +7,7 @@ import 'package:hmg_patient_app_new/core/utils/date_util.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_livecare_clinics_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/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; @@ -45,6 +46,13 @@ abstract class BookAppointmentsRepo { Future>>> getProjectList(); Future>>> getClinicsWithRespectToClinicId(String projectID); + + Future>>> getLiveCareScheduleClinics(int age, int genderID); + + Future>>> getLiveCareDoctorsList(int serviceID, int age, int genderID, {Function(dynamic)? onSuccess, Function(String)? onError}); + + Future>> getLiveCareDoctorFreeSlots(int clinicID, int serviceID, int projectID, int doctorId, bool isBookingForLiveCare, + {Function(dynamic)? onSuccess, Function(String)? onError}); } class BookAppointmentsRepoImp implements BookAppointmentsRepo { @@ -443,4 +451,133 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo { return Left(UnknownFailure(e.toString())); } } + + @override + Future>>> getLiveCareScheduleClinics(int age, int genderID) async { + Map mapDevice = {"Age": age, "Gender": genderID}; + + try { + GenericApiModel>? apiResponse; + Failure? failure; + await apiClient.post( + GET_LIVECARE_SCHEDULE_CLINICS, + body: mapDevice, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + final list = response['ClinicsHaveScheduleList']; + // if (list == null || list.isEmpty) { + // throw Exception("lab list is empty"); + // } + + final clinicsList = list.map((item) => GetLiveCareClinicsResponseModel.fromJson(item as Map)).toList().cast(); + + apiResponse = GenericApiModel>( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: clinicsList, + ); + } 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>>> getLiveCareDoctorsList(int serviceID, int age, int genderID, + {Function(dynamic)? onSuccess, Function(String)? onError}) async { + Map mapDevice = { + "ServiceID": serviceID, + "Age": age, + "Gender": genderID, + }; + + try { + GenericApiModel>? apiResponse; + Failure? failure; + await apiClient.post( + GET_LIVECARE_SCHEDULE_CLINIC_DOCTOR_LIST, + body: mapDevice, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + onError!(error); + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + final list = response['DoctorByClinicIDList']; + + final doctorsList = list.map((item) => DoctorsListResponseModel.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())); + } + } + + @override + Future> getLiveCareDoctorFreeSlots(int clinicID, int serviceID, int projectID, int doctorId, bool isBookingForLiveCare, + {Function(dynamic)? onSuccess, Function(String)? onError}) async { + Map mapDevice = { + "DoctorID": doctorId, + "IsBookingForLiveCare": true, + "ClinicID": clinicID, + "ServiceID": serviceID, + "ProjectID": projectID, + "OriginalClinicID": clinicID, + "days": 50, + "isReschadual": false, + }; + + try { + GenericApiModel? apiResponse; + Failure? failure; + await apiClient.post( + GET_LIVECARE_SCHEDULE_DOCTOR_TIME_SLOTS, + body: mapDevice, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + apiResponse = GenericApiModel( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + 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())); + } + } } diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index 6488dd8..e8d02b9 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -29,6 +29,8 @@ import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:location/location.dart' show Location; +import 'models/resp_models/get_livecare_clinics_response_model.dart'; + class BookAppointmentsViewModel extends ChangeNotifier { int selectedTabIndex = 0; @@ -37,6 +39,8 @@ class BookAppointmentsViewModel extends ChangeNotifier { bool isDoctorProfileLoading = false; bool isDoctorSearchByNameStarted = false; + bool isLiveCareSchedule = false; + int initialSlotDuration = 0; LocationUtils locationUtils; @@ -44,12 +48,17 @@ class BookAppointmentsViewModel extends ChangeNotifier { List clinicsList = []; List _filteredClinicsList = []; + List liveCareClinicsList = []; + List get filteredClinicsList => _filteredClinicsList; List doctorsList = []; + List liveCareDoctorsList = []; + GetClinicsListResponseModel selectedClinic = GetClinicsListResponseModel(); DoctorsListResponseModel selectedDoctor = DoctorsListResponseModel(); + GetLiveCareClinicsResponseModel selectedLiveCareClinic = GetLiveCareClinicsResponseModel(); late DoctorsProfileResponseModel doctorsProfileResponseModel; @@ -78,7 +87,9 @@ class BookAppointmentsViewModel extends ChangeNotifier { bool shouldLoadSpecificClinic = false; String? currentlySelectedHospitalFromRegionFlow; - BookAppointmentsViewModel({required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel, required this.locationUtils}) {; + BookAppointmentsViewModel( + {required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel, required this.locationUtils}) { + ; initBookAppointmentViewModel(); } @@ -101,8 +112,10 @@ class BookAppointmentsViewModel extends ChangeNotifier { isClinicsListLoading = true; isDoctorsListLoading = true; isDoctorProfileLoading = true; + isLiveCareSchedule = false; clinicsList.clear(); doctorsList.clear(); + liveCareClinicsList.clear(); // getLocation(); notifyListeners(); } @@ -154,6 +167,16 @@ class BookAppointmentsViewModel extends ChangeNotifier { notifyListeners(); } + setIsLiveCareSchedule(bool value) { + isLiveCareSchedule = value; + notifyListeners(); + } + + setLiveCareSelectedClinic(GetLiveCareClinicsResponseModel clinic) { + selectedLiveCareClinic = clinic; + notifyListeners(); + } + void onTabChanged(int index) { selectedTabIndex = index; notifyListeners(); @@ -161,10 +184,11 @@ class BookAppointmentsViewModel extends ChangeNotifier { /// this function will decide which clinic api to be called /// either api for region flow or the select clinic api - Future getClinics() async - { - if(shouldLoadSpecificClinic) { + Future getClinics() async { + if (shouldLoadSpecificClinic) { getRegionSelectedClinics(); + } else if (isLiveCareSchedule) { + getLiveCareScheduleClinics(); } else { getAllClinics(); } @@ -191,11 +215,58 @@ class BookAppointmentsViewModel extends ChangeNotifier { ); } + Future getLiveCareScheduleClinics({Function(dynamic)? onSuccess, Function(String)? onError}) async { + liveCareClinicsList.clear(); + final result = await bookAppointmentsRepo.getLiveCareScheduleClinics(_appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!); + + result.fold( + (failure) async => await errorHandlerService.handleError(failure: failure), + (apiResponse) { + if (apiResponse.messageStatus == 2) { + // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + } else if (apiResponse.messageStatus == 1) { + liveCareClinicsList = apiResponse.data!; + isClinicsListLoading = false; + initializeFilteredList(); + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } + + Future getLiveCareDoctorsList({Function(dynamic)? onSuccess, Function(String)? onError}) async { + doctorsList.clear(); + final result = + await bookAppointmentsRepo.getLiveCareDoctorsList(selectedLiveCareClinic.serviceID!, _appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!, onError: onError); + + result.fold( + (failure) async { + onError!("No doctors found for the search criteria".needTranslation); + }, + (apiResponse) { + if (apiResponse.messageStatus == 2) { + // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + } else if (apiResponse.messageStatus == 1) { + liveCareDoctorsList = apiResponse.data!; + isDoctorsListLoading = false; + // initializeFilteredList(); + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } + //TODO: Make the API dynamic with parameters for ProjectID, isNearest, languageID, doctorId, doctorName Future getDoctorsList( {int projectID = 0, bool isNearest = false, int doctorId = 0, String doctorName = "", isContinueDentalPlan = false, Function(dynamic)? onSuccess, Function(String)? onError}) async { doctorsList.clear(); - projectID = currentlySelectedHospitalFromRegionFlow != null?int.parse(currentlySelectedHospitalFromRegionFlow!):projectID; + projectID = currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : projectID; final result = await bookAppointmentsRepo.getDoctorsList(selectedClinic.clinicID ?? 0, projectID, isNearest, doctorId, doctorName); result.fold( @@ -238,7 +309,6 @@ class BookAppointmentsViewModel extends ChangeNotifier { ); } - //TODO: Handle the cases for LiveCare Schedule Future getDoctorFreeSlots({bool isBookingForLiveCare = false, Function(dynamic)? onSuccess, Function(String)? onError}) async { docFreeSlots.clear(); DateTime date; @@ -281,6 +351,50 @@ class BookAppointmentsViewModel extends ChangeNotifier { ); } + Future getLiveCareDoctorFreeSlots({bool isBookingForLiveCare = false, Function(dynamic)? onSuccess, Function(String)? onError}) async { + docFreeSlots.clear(); + DateTime date; + final DateFormat formatter = DateFormat('HH:mm'); + final DateFormat dateFormatter = DateFormat('yyyy-MM-dd'); + Map _eventsParsed; + + final result = await bookAppointmentsRepo.getLiveCareDoctorFreeSlots( + selectedDoctor.clinicID ?? 0, selectedLiveCareClinic.serviceID ?? 0, selectedDoctor.projectID ?? 0, selectedDoctor.doctorID ?? 0, isBookingForLiveCare, + onError: onError); + + result.fold( + (failure) async { + print(failure); + }, + (apiResponse) { + if (apiResponse.messageStatus == 2) { + onError!(apiResponse.errorMessage ?? "Unknown error occurred"); + // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + } else if (apiResponse.messageStatus == 1) { + if (apiResponse.data['PatientER_DoctorFreeSlots'] == null || apiResponse.data['PatientER_DoctorFreeSlots'].isEmpty) { + onError!("No free slots available".tr()); + return; + } + initialSlotDuration = apiResponse.data["InitialSlotDuration"]; + freeSlotsResponse = apiResponse.data['PatientER_DoctorFreeSlots']; + freeSlotsResponse.forEach((element) { + // date = (isLiveCareSchedule != null && isLiveCareSchedule) + // ? DateUtil.convertStringToDate(element) + // : + date = DateUtil.convertStringToDateSaudiTimezone(element, int.parse(selectedDoctor.projectID.toString())); + slotsList.add(FreeSlot(date, ['slot'])); + docFreeSlots.add(TimeSlot(isoTime: formatter.format(date), start: new DateTime(date.year, date.month, date.day, 0, 0, 0, 0), end: date, vidaDate: element)); + }); + + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } + Future cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async { final result = await bookAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel); @@ -419,22 +533,21 @@ class BookAppointmentsViewModel extends ChangeNotifier { final result = await bookAppointmentsRepo.getProjectList(); result.fold( - (failure) async => - await errorHandlerService.handleError(failure: failure), - (apiResponse) async { + (failure) async => await errorHandlerService.handleError(failure: failure), + (apiResponse) async { if (apiResponse.messageStatus == 2) { // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); } else if (apiResponse.messageStatus == 1) { var projectList = apiResponse.data!; - hospitalList = await DoctorMapper.getMappedHospitals(projectList, + hospitalList = await DoctorMapper.getMappedHospitals( + projectList, isArabic: _appState.isArabic(), lat: _appState.userLat, lng: _appState.userLong, ); var isLocationEnabled = (_appState.userLat != 0) && (_appState.userLong != 0); - hospitalList = - await DoctorMapper.sortList(isLocationEnabled, hospitalList!); + hospitalList = await DoctorMapper.sortList(isLocationEnabled, hospitalList!); isRegionListLoading = false; filteredHospitalList = hospitalList; @@ -450,22 +563,21 @@ class BookAppointmentsViewModel extends ChangeNotifier { } void filterHospitalListByString(String? value, String? selectedRegionId, bool isHMG) { - if(value ==null || value.isEmpty){ + if (value == null || value.isEmpty) { filteredHospitalList = hospitalList; } else { filteredHospitalList = RegionList(); - var list = isHMG - ? hospitalList?.registeredDoctorMap![selectedRegionId]!.hmgDoctorList - : hospitalList?.registeredDoctorMap![selectedRegionId]!.hmcDoctorList; + var list = isHMG ? hospitalList?.registeredDoctorMap![selectedRegionId]!.hmgDoctorList : hospitalList?.registeredDoctorMap![selectedRegionId]!.hmcDoctorList; - if(list != null && list.isEmpty){ notifyListeners(); return;} + if (list != null && list.isEmpty) { + notifyListeners(); + return; + } - var filteredList = list!.where((element) => - element.filterName!.toLowerCase().contains(value.toLowerCase()) - ).toList(); + var filteredList = list!.where((element) => element.filterName!.toLowerCase().contains(value.toLowerCase())).toList(); var regionData = PatientDoctorAppointmentListByRegion(); - if(isHMG){ + if (isHMG) { regionData.hmgDoctorList = filteredList; regionData.hmgSize = filteredList.length; } else { @@ -473,9 +585,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { regionData.hmcSize = filteredList.length; } - filteredHospitalList?.registeredDoctorMap = { - selectedRegionId! : regionData - }; + filteredHospitalList?.registeredDoctorMap = {selectedRegionId!: regionData}; } notifyListeners(); } @@ -498,12 +608,12 @@ class BookAppointmentsViewModel extends ChangeNotifier { currentlySelectedHospitalFromRegionFlow = mainProjectID; } - Future getRegionSelectedClinics() async{ - final result = await bookAppointmentsRepo.getClinicsWithRespectToClinicId(currentlySelectedHospitalFromRegionFlow??""); + Future getRegionSelectedClinics() async { + final result = await bookAppointmentsRepo.getClinicsWithRespectToClinicId(currentlySelectedHospitalFromRegionFlow ?? ""); result.fold( - (failure) async => await errorHandlerService.handleError(failure: failure), - (apiResponse) { + (failure) async => await errorHandlerService.handleError(failure: failure), + (apiResponse) { if (apiResponse.messageStatus == 2) { // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); } else if (apiResponse.messageStatus == 1) { @@ -515,12 +625,12 @@ class BookAppointmentsViewModel extends ChangeNotifier { }, ); } - void resetFilterList(){ + + void resetFilterList() { filteredHospitalList = hospitalList; } - - void getLocation(){ + void getLocation() { locationUtils.getLocation(); } } diff --git a/lib/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart b/lib/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart index 0b0fa13..24d1c70 100644 --- a/lib/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart +++ b/lib/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart @@ -12,8 +12,8 @@ class GetClinicsListResponseModel { GetClinicsListResponseModel.fromJson(Map json) { clinicID = json['ClinicID']; - clinicDescription = json['ClinicDescription']; - clinicDescriptionN = json['ClinicDescriptionN']; + clinicDescription = json['ClinicDescription'] ?? "LiveCare Clinic"; + clinicDescriptionN = json['ClinicDescriptionN'] ?? "LiveCare Clinic"; age = json['Age']; gender = json['Gender']; isLiveCareClinicAndOnline = json['IsLiveCareClinicAndOnline']; diff --git a/lib/features/book_appointments/models/resp_models/get_livecare_clinics_response_model.dart b/lib/features/book_appointments/models/resp_models/get_livecare_clinics_response_model.dart new file mode 100644 index 0000000..2b66cfc --- /dev/null +++ b/lib/features/book_appointments/models/resp_models/get_livecare_clinics_response_model.dart @@ -0,0 +1,33 @@ +class GetLiveCareClinicsResponseModel { + int? clinicID; + int? serviceID; + int? projectID; + String? clinicDesc; + String? clinicDescN; + String? projectDesc; + String? projectDescN; + + GetLiveCareClinicsResponseModel({this.clinicID, this.serviceID, this.projectID, this.clinicDesc, this.clinicDescN, this.projectDesc, this.projectDescN}); + + GetLiveCareClinicsResponseModel.fromJson(Map json) { + clinicID = json['ClinicID']; + serviceID = json['ServiceID']; + projectID = json['ProjectID']; + clinicDesc = json['ClinicDesc'] ?? "LiveCare Clinic"; + clinicDescN = json['ClinicDescN']; + projectDesc = json['ProjectDesc']; + projectDescN = json['ProjectDescN']; + } + + Map toJson() { + final Map data = new Map(); + data['ClinicID'] = this.clinicID; + data['ServiceID'] = this.serviceID; + data['ProjectID'] = this.projectID; + data['ClinicDesc'] = this.clinicDesc; + data['ClinicDescN'] = this.clinicDescN; + data['ProjectDesc'] = this.projectDesc; + data['ProjectDescN'] = this.projectDescN; + return data; + } +} diff --git a/lib/presentation/book_appointment/book_appointment_page.dart b/lib/presentation/book_appointment/book_appointment_page.dart index 140b593..78f1540 100644 --- a/lib/presentation/book_appointment/book_appointment_page.dart +++ b/lib/presentation/book_appointment/book_appointment_page.dart @@ -42,6 +42,7 @@ class _BookAppointmentPageState extends State { @override void initState() { scheduleMicrotask(() { + bookAppointmentsViewModel.selectedTabIndex = 0; bookAppointmentsViewModel.initBookAppointmentViewModel(); bookAppointmentsViewModel.getLocation(); }); @@ -123,6 +124,7 @@ class _BookAppointmentPageState extends State { ).onPress(() { bookAppointmentsViewModel.setIsClinicsListLoading(true); bookAppointmentsViewModel.setLoadSpecificClinic(false); + bookAppointmentsViewModel.setIsLiveCareSchedule(false); bookAppointmentsViewModel.setProjectID(null); Navigator.of(context).push( CustomPageRoute( @@ -191,6 +193,112 @@ class _BookAppointmentPageState extends State { ), ], ).paddingSymmetrical(24.h, 0.h); + case 1: + //TODO: Get LiveCare type Select UI from Hussain + return Column( + children: [ + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.h, + hasShadow: false, + ), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.search_by_clinic_icon, width: 40.h, height: 40.h), + SizedBox(width: 12.h), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Immediate Consultation".needTranslation.toText14(color: AppColors.textColor, weight: FontWeight.w500), + "Tap to select clinic".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), + ], + ), + ], + ), + Transform.flip( + flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h)), + ], + ).onPress(() { + // bookAppointmentsViewModel.setIsClinicsListLoading(true); + // bookAppointmentsViewModel.setLoadSpecificClinic(false); + // bookAppointmentsViewModel.setProjectID(null); + // Navigator.of(context).push( + // CustomPageRoute( + // page: SelectClinicPage(), + // ), + // ); + }), + SizedBox(height: 16.h), + Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h), + SizedBox(height: 16.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.search_by_doctor_icon, width: 40.h, height: 40.h), + SizedBox(width: 12.h), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Scheduled Consultation".needTranslation.toText14(color: AppColors.textColor, weight: FontWeight.w500), + "Tap to select clinic".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), + ], + ), + ], + ), + Transform.flip( + flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h)), + ], + ).onPress(() { + bookAppointmentsViewModel.setIsClinicsListLoading(true); + bookAppointmentsViewModel.setIsLiveCareSchedule(true); + Navigator.of(context).push( + CustomPageRoute( + page: SelectClinicPage(), + ), + ); + }), + SizedBox(height: 16.h), + Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h), + SizedBox(height: 16.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.search_by_region_icon, width: 40.h, height: 40.h), + SizedBox(width: 12.h), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Pharma LiveCare".needTranslation.toText14(color: AppColors.textColor, weight: FontWeight.w500), + "".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), + ], + ), + ], + ), + Transform.flip( + flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h)), + ], + ).onPress(() { + openRegionListBottomSheet(context); + }), + ], + ), + ), + ), + ], + ).paddingSymmetrical(24.h, 0.h); default: SizedBox.shrink(); } @@ -200,11 +308,7 @@ class _BookAppointmentPageState extends State { void openRegionListBottomSheet(BuildContext context) { regionalViewModel.flush(); // AppointmentViaRegionViewmodel? viewmodel = null; - showCommonBottomSheetWithoutHeight(context, - title: "", - titleWidget: Consumer( - builder: (_, data, __) => getTitle(data)), - isDismissible: false, + showCommonBottomSheetWithoutHeight(context, title: "", titleWidget: Consumer(builder: (_, data, __) => getTitle(data)), isDismissible: false, child: Consumer(builder: (_, data, __) { return getRegionalSelectionWidget(data); }), callBackFunc: () {}); @@ -238,19 +342,16 @@ class _BookAppointmentPageState extends State { if (data.selectedRegionId == null) { return LocaleKeys.selectRegion.tr().toText20(weight: FontWeight.w600); } else { - return - Transform.flip( - flipX: data.isArabic ? true : false, - child: Utils.buildSvgWithAssets( - icon: AppAssets.arrow_back, - iconColor: Color(0xff2B353E), - - fit: BoxFit.contain, - ), - ).onPress(() { - data.handleBackPress(); - }); - + return Transform.flip( + flipX: data.isArabic ? true : false, + child: Utils.buildSvgWithAssets( + icon: AppAssets.arrow_back, + iconColor: Color(0xff2B353E), + fit: BoxFit.contain, + ), + ).onPress(() { + data.handleBackPress(); + }); } } } diff --git a/lib/presentation/book_appointment/select_clinic_page.dart b/lib/presentation/book_appointment/select_clinic_page.dart index 0580480..ba5c2ee 100644 --- a/lib/presentation/book_appointment/select_clinic_page.dart +++ b/lib/presentation/book_appointment/select_clinic_page.dart @@ -12,6 +12,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/features/book_appointments/book_appointments_view_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_livecare_clinics_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.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'; @@ -58,7 +59,7 @@ class _SelectClinicPageState extends State { return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: CollapsingListView( - title: LocaleKeys.selectClinic.tr(context: context), + title: bookAppointmentsViewModel.isLiveCareSchedule ? "Select LiveCare Clinic".needTranslation : LocaleKeys.selectClinic.tr(context: context), child: SingleChildScrollView( child: Padding( padding: EdgeInsets.symmetric(horizontal: 24.h), @@ -94,40 +95,83 @@ class _SelectClinicPageState extends State { horizontal: ResponsiveExtension(15).h, ), ), - ListView.separated( - padding: EdgeInsets.only(top: 24.h), - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - itemCount: bookAppointmentsVM.isClinicsListLoading ? 5 : bookAppointmentsVM.filteredClinicsList.length, - itemBuilder: (context, index) { - return bookAppointmentsVM.isClinicsListLoading - ? ClinicCard( - clinicsListResponseModel: GetClinicsListResponseModel(), - isLoading: bookAppointmentsVM.isClinicsListLoading, - ) - : AnimationConfiguration.staggeredList( - position: index, - duration: const Duration(milliseconds: 500), - child: SlideAnimation( - verticalOffset: 100.0, - child: FadeInAnimation( - child: AnimatedContainer( - duration: Duration(milliseconds: 300), - curve: Curves.easeInOut, - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), - child: ClinicCard( - clinicsListResponseModel: bookAppointmentsVM.filteredClinicsList[index], - isLoading: bookAppointmentsVM.isClinicsListLoading, - ).onPress(() { - onClinicSelected(bookAppointmentsVM.filteredClinicsList[index]); - }), - ), - ), - ), - ); - }, - separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), - ), + bookAppointmentsVM.isLiveCareSchedule + ? ListView.separated( + padding: EdgeInsets.only(top: 24.h), + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: bookAppointmentsVM.isClinicsListLoading ? 5 : bookAppointmentsVM.liveCareClinicsList.length, + itemBuilder: (context, index) { + return bookAppointmentsVM.isClinicsListLoading + ? ClinicCard( + bookAppointmentsVM: bookAppointmentsVM, + liveCareClinicsResponseModel: GetLiveCareClinicsResponseModel(), + clinicsListResponseModel: GetClinicsListResponseModel(), + isLoading: bookAppointmentsVM.isClinicsListLoading, + ) + : AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 500), + child: SlideAnimation( + verticalOffset: 100.0, + child: FadeInAnimation( + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), + child: ClinicCard( + bookAppointmentsVM: bookAppointmentsVM, + liveCareClinicsResponseModel: bookAppointmentsVM.liveCareClinicsList[index], + clinicsListResponseModel: GetClinicsListResponseModel(), + isLoading: bookAppointmentsVM.isClinicsListLoading, + ).onPress(() { + onLiveCareClinicSelected(bookAppointmentsVM.liveCareClinicsList[index]); + }), + ), + ), + ), + ); + }, + separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), + ) + : ListView.separated( + padding: EdgeInsets.only(top: 24.h), + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: bookAppointmentsVM.isClinicsListLoading ? 5 : bookAppointmentsVM.filteredClinicsList.length, + itemBuilder: (context, index) { + return bookAppointmentsVM.isClinicsListLoading + ? ClinicCard( + bookAppointmentsVM: bookAppointmentsVM, + liveCareClinicsResponseModel: GetLiveCareClinicsResponseModel(), + clinicsListResponseModel: GetClinicsListResponseModel(), + isLoading: bookAppointmentsVM.isClinicsListLoading, + ) + : AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 500), + child: SlideAnimation( + verticalOffset: 100.0, + child: FadeInAnimation( + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), + child: ClinicCard( + bookAppointmentsVM: bookAppointmentsVM, + liveCareClinicsResponseModel: GetLiveCareClinicsResponseModel(), + clinicsListResponseModel: bookAppointmentsVM.filteredClinicsList[index], + isLoading: bookAppointmentsVM.isClinicsListLoading, + ).onPress(() { + onClinicSelected(bookAppointmentsVM.filteredClinicsList[index]); + }), + ), + ), + ), + ); + }, + separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), + ), ], ); }), @@ -137,6 +181,16 @@ class _SelectClinicPageState extends State { ); } + void onLiveCareClinicSelected(GetLiveCareClinicsResponseModel clinic) { + bookAppointmentsViewModel.setLiveCareSelectedClinic(clinic); + bookAppointmentsViewModel.setIsDoctorsListLoading(true); + Navigator.of(context).push( + CustomPageRoute( + page: SelectDoctorPage(), + ), + ); + } + void onClinicSelected(GetClinicsListResponseModel clinic) { bookAppointmentsViewModel.setSelectedClinic(clinic); bookAppointmentsViewModel.setIsDoctorsListLoading(true); diff --git a/lib/presentation/book_appointment/select_doctor_page.dart b/lib/presentation/book_appointment/select_doctor_page.dart index 27a60f6..25a6618 100644 --- a/lib/presentation/book_appointment/select_doctor_page.dart +++ b/lib/presentation/book_appointment/select_doctor_page.dart @@ -42,7 +42,11 @@ class _SelectDoctorPageState extends State { @override void initState() { scheduleMicrotask(() { - bookAppointmentsViewModel.getDoctorsList(); + if (bookAppointmentsViewModel.isLiveCareSchedule) { + bookAppointmentsViewModel.getLiveCareDoctorsList(); + } else { + bookAppointmentsViewModel.getDoctorsList(); + } }); super.initState(); } @@ -96,7 +100,8 @@ class _SelectDoctorPageState extends State { padding: EdgeInsets.only(top: 24.h), shrinkWrap: true, physics: NeverScrollableScrollPhysics(), - itemCount: bookAppointmentsVM.isDoctorsListLoading ? 5 : bookAppointmentsVM.doctorsList.length, + itemCount: + bookAppointmentsVM.isDoctorsListLoading ? 5 : (bookAppointmentsVM.isLiveCareSchedule ? bookAppointmentsVM.liveCareDoctorsList.length : bookAppointmentsVM.doctorsList.length), itemBuilder: (context, index) { return bookAppointmentsVM.isDoctorsListLoading ? DoctorCard( @@ -115,11 +120,12 @@ class _SelectDoctorPageState extends State { curve: Curves.easeInOut, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), child: DoctorCard( - doctorsListResponseModel: bookAppointmentsVM.doctorsList[index], + doctorsListResponseModel: bookAppointmentsVM.isLiveCareSchedule ? bookAppointmentsVM.liveCareDoctorsList[index] : bookAppointmentsVM.doctorsList[index], isLoading: false, bookAppointmentsViewModel: bookAppointmentsViewModel, ).onPress(() async { - bookAppointmentsVM.setSelectedDoctor(bookAppointmentsVM.doctorsList[index]); + bookAppointmentsVM + .setSelectedDoctor(bookAppointmentsVM.isLiveCareSchedule ? bookAppointmentsVM.liveCareDoctorsList[index] : bookAppointmentsVM.doctorsList[index]); // bookAppointmentsVM.setSelectedDoctor(DoctorsListResponseModel()); LoaderBottomSheet.showLoader(); await bookAppointmentsVM.getDoctorProfile(onSuccess: (dynamic respData) { diff --git a/lib/presentation/book_appointment/widgets/clinic_card.dart b/lib/presentation/book_appointment/widgets/clinic_card.dart index 57315e6..c9c0555 100644 --- a/lib/presentation/book_appointment/widgets/clinic_card.dart +++ b/lib/presentation/book_appointment/widgets/clinic_card.dart @@ -6,14 +6,18 @@ 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/features/book_appointments/book_appointments_view_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_livecare_clinics_response_model.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; class ClinicCard extends StatelessWidget { - ClinicCard({super.key, required this.clinicsListResponseModel, required this.isLoading}); + ClinicCard({super.key, required this.clinicsListResponseModel, required this.liveCareClinicsResponseModel, required this.isLoading, required this.bookAppointmentsVM}); GetClinicsListResponseModel clinicsListResponseModel; + GetLiveCareClinicsResponseModel liveCareClinicsResponseModel; bool isLoading; + BookAppointmentsViewModel bookAppointmentsVM; @override Widget build(BuildContext context) { @@ -35,7 +39,10 @@ class ClinicCard extends StatelessWidget { ]), SizedBox(height: 16.h), Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded(child: (isLoading ? "Cardiology" : clinicsListResponseModel.clinicDescription!).toText16(isBold: true).toShimmer2(isShow: isLoading)), + Expanded( + child: (isLoading ? "Cardiology" : (bookAppointmentsVM.isLiveCareSchedule ? liveCareClinicsResponseModel.clinicDesc! : clinicsListResponseModel.clinicDescription!)) + .toText16(isBold: true) + .toShimmer2(isShow: isLoading)), Transform.flip( flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor).toShimmer2(isShow: isLoading)), diff --git a/lib/presentation/book_appointment/widgets/doctor_card.dart b/lib/presentation/book_appointment/widgets/doctor_card.dart index 1e1e0ae..3f3d51c 100644 --- a/lib/presentation/book_appointment/widgets/doctor_card.dart +++ b/lib/presentation/book_appointment/widgets/doctor_card.dart @@ -108,29 +108,53 @@ class DoctorCard extends StatelessWidget { onPressed: () async { bookAppointmentsViewModel.setSelectedDoctor(doctorsListResponseModel); LoaderBottomSheet.showLoader(); - await bookAppointmentsViewModel.getDoctorFreeSlots( - isBookingForLiveCare: false, - onSuccess: (dynamic respData) async { - LoaderBottomSheet.hideLoader(); - showCommonBottomSheetWithoutHeight( - title: "Pick a Date".needTranslation, - context, - child: AppointmentCalendar(), - isFullScreen: false, - isCloseButtonVisible: true, - callBackFunc: () {}, - ); - }, - onError: (err) { - LoaderBottomSheet.hideLoader(); - showCommonBottomSheetWithoutHeight( - context, - child: Utils.getErrorWidget(loadingText: err), - callBackFunc: () {}, - isFullScreen: false, - isCloseButtonVisible: true, - ); - }); + bookAppointmentsViewModel.isLiveCareSchedule + ? await bookAppointmentsViewModel.getLiveCareDoctorFreeSlots( + isBookingForLiveCare: true, + onSuccess: (dynamic respData) async { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + title: "Pick a Date".needTranslation, + context, + child: AppointmentCalendar(), + isFullScreen: false, + isCloseButtonVisible: true, + callBackFunc: () {}, + ); + }, + onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: err), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }) + : await bookAppointmentsViewModel.getDoctorFreeSlots( + isBookingForLiveCare: false, + onSuccess: (dynamic respData) async { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + title: "Pick a Date".needTranslation, + context, + child: AppointmentCalendar(), + isFullScreen: false, + isCloseButtonVisible: true, + callBackFunc: () {}, + ); + }, + onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: err), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }); }, backgroundColor: Color(0xffFEE9EA), borderColor: Color(0xffFEE9EA), diff --git a/lib/presentation/home/navigation_screen.dart b/lib/presentation/home/navigation_screen.dart index 8feeb5f..6b33b2f 100644 --- a/lib/presentation/home/navigation_screen.dart +++ b/lib/presentation/home/navigation_screen.dart @@ -34,6 +34,7 @@ class _LandingNavigationState extends State { ], ), bottomNavigationBar: BottomNavigation( + context: context, currentIndex: _currentIndex, onTap: (index) { setState(() => _currentIndex = index); diff --git a/lib/widgets/bottom_navigation/bottom_navigation.dart b/lib/widgets/bottom_navigation/bottom_navigation.dart index da289c1..1163c66 100644 --- a/lib/widgets/bottom_navigation/bottom_navigation.dart +++ b/lib/widgets/bottom_navigation/bottom_navigation.dart @@ -12,27 +12,26 @@ import 'package:hmg_patient_app_new/theme/colors.dart'; class BottomNavigation extends StatelessWidget { final int currentIndex; final ValueChanged onTap; + BuildContext? context; - const BottomNavigation({ - super.key, - required this.currentIndex, - required this.onTap, - }); + BottomNavigation({super.key, required this.currentIndex, required this.onTap, this.context}); @override Widget build(BuildContext context) { - AppState appState = getIt.get(); + AppState appState = getIt.get(); final items = [ - BottomNavItem(icon: AppAssets.homeBottom, label: LocaleKeys.home.tr()), - appState.isAuthenticated ? BottomNavItem(icon: AppAssets.myFilesBottom, label: LocaleKeys.myFiles.tr()) : BottomNavItem(icon: AppAssets.feedback, label: LocaleKeys.feedback.tr()), + BottomNavItem(icon: AppAssets.homeBottom, label: LocaleKeys.home.tr(context: context)), + appState.isAuthenticated + ? BottomNavItem(icon: AppAssets.myFilesBottom, label: LocaleKeys.myFiles.tr(context: context)) + : BottomNavItem(icon: AppAssets.feedback, label: LocaleKeys.feedback.tr()), BottomNavItem( icon: AppAssets.bookAppoBottom, - label: LocaleKeys.appointment.tr(), + label: LocaleKeys.appointment.tr(context: context), iconSize: 27, isSpecial: true, ), - appState.isAuthenticated ? BottomNavItem(icon: AppAssets.toDoBottom, label: LocaleKeys.todoList.tr()) : BottomNavItem(icon: AppAssets.news, label: LocaleKeys.news.tr()) , - BottomNavItem(icon: AppAssets.servicesBottom, label: LocaleKeys.services2.tr()), + appState.isAuthenticated ? BottomNavItem(icon: AppAssets.toDoBottom, label: LocaleKeys.todoList.tr(context: context)) : BottomNavItem(icon: AppAssets.news, label: LocaleKeys.news.tr()), + BottomNavItem(icon: AppAssets.servicesBottom, label: LocaleKeys.services2.tr(context: context)), ]; return Container( @@ -42,7 +41,7 @@ class BottomNavigation extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceAround, children: List.generate( items.length, - (index) => _buildNavItem(items[index], index), + (index) => _buildNavItem(items[index], index), ), ), ); @@ -57,23 +56,22 @@ class BottomNavigation extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Center( - child: Utils.buildSvgWithAssets( - icon: item.icon, - height: item.iconSize.h, - width: item.iconSize.h, - // iconColor: isSelected ? Colors.black87 : Colors.black87, - ), + Center( + child: Utils.buildSvgWithAssets( + icon: item.icon, + height: item.iconSize.h, + width: item.iconSize.h, + // iconColor: isSelected ? Colors.black87 : Colors.black87, ), + ), const SizedBox(height: 10), item.label.toText12( - fontWeight:FontWeight.w500, + fontWeight: FontWeight.w500, // color: Colors.black87, // textAlign: TextAlign.center, ), - SizedBox(height: item.isSpecial ? 5:0 ) + SizedBox(height: item.isSpecial ? 5 : 0) ], - ), ); } diff --git a/lib/widgets/buttons/custom_button.dart b/lib/widgets/buttons/custom_button.dart index d0b4a6c..954877f 100644 --- a/lib/widgets/buttons/custom_button.dart +++ b/lib/widgets/buttons/custom_button.dart @@ -66,7 +66,7 @@ class CustomButton extends StatelessWidget { child: Utils.buildSvgWithAssets(icon: icon!, iconColor: iconColor, isDisabled: isDisabled, width: iconSize, height: iconSize), ), Padding( - padding: EdgeInsets.only(top: 2.5), + padding: EdgeInsets.only(top: 0), child: Text( text, style: context.dynamicTextStyle(