diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index fbd8465f..2c312334 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1888,10 +1888,15 @@ "pharmacy": "الصيدلية", "visitsOrders": "الزيارات/الطلبات", "cannotOpenThisFile": "لا يمكن فتح هذا الملف", + "thisInvoiceIsNotEligibleForRefund": "هذه الفاتورة غير مؤهلة للاسترداد", "refundDetails": "تفاصيل الاسترداد", + "refund": "استرداد", "requestNo": "رقم الطلب.", "referenceNo": "رقم المرجع", "advanceNumber": "رقم الدفعة المقدمة", "amountOnly": "المبلغ", - "invoiceHistory": "سجل الفواتير" + "invoiceHistory": "سجل الفواتير", + "selectAdvance": "اختر الدفعة المقدمة", + "advanceNo": "رقم الدفعة", + "noAdvancesAvailable": "لا توجد دفعات متاحة للاسترداد" } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index bfba9725..2fe76d05 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1886,7 +1886,10 @@ "refund": "Refund", "advanceNumber": "Advance Number", "amountOnly": "Amount", - "invoiceHistory": "Invoice History" + "invoiceHistory": "Invoice History", + "selectAdvance": "Select Advance", + "advanceNo": "Advance No", + "noAdvancesAvailable": "No advances available for refund" } diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index f8919251..b1fc0e5b 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -208,8 +208,8 @@ class ApiClientImp implements ApiClient { body['TokenID'] = "@dm!n"; } - // body['TokenID'] = "@dm!n"; - // body['PatientID'] = 4774167; + body['TokenID'] = "@dm!n"; + body['PatientID'] = 4774167; // body['PatientID'] = 89754444; // body['PatientTypeID'] = 1; // body['PatientOutSA'] = 0; diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index 4a71fa9b..24872c32 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -290,30 +290,31 @@ class ApiConsts { static String googleCloudStorageENTranslationFileBaseURL = "https://storage.googleapis.com/hmg-patientapp-translations"; // ************ static values for Api **************** - static final double appVersionID = 21.2; + // static final double appVersionID = 21.2; - // static final double appVersionID = 50.7; + static final double appVersionID = 50.7; static final int appChannelId = 3; static final String appIpAddress = "10.20.10.20"; static final String appGeneralId = "Cs2020@2016\$2958"; static final String sessionID = 'TMRhVmkGhOsvamErw'; -} // PACKAGES and OFFERS -var EXA_CART_API_BASE_URL = 'https://mdlaboratories.com/offersdiscounts'; + static String exaCartApiBaseUrl = 'https://mdlaboratories.com/offersdiscounts'; + // var EXA_CART_API_BASE_URL = 'http://10.200.101.75:9000'; -var PACKAGES_CATEGORIES = '/api/categories'; -var PACKAGES_STORES = '/api/stores'; -var PACKAGES_TOKEN = '/api/token'; -var PACKAGES_PRODUCTS = '/api/products'; -var PACKAGES_CUSTOMER = '/api/customers'; -var PACKAGES_SHOPPING_CART = '/api/shopping_cart_items'; -var PACKAGES_ORDERS = '/api/orders'; -var PACKAGES_ORDER_HISTORY = '/api/orders/items'; -var PACKAGES_TAMARA_OPT = '/api/orders/paymentoptions/tamara'; + static String packagesCategories = '/api/categories'; + static String packagesStores = '/api/stores'; + static String packagesToken = '/api/token'; + static String packagesProducts = '/api/products'; + static String packagesCustomer = '/api/customers'; + static String packagesShoppingCart = '/api/shopping_cart_items'; + static String packagesOrders = '/api/orders'; + static String packagesOrderHistory = '/api/orders/items'; + static String packagesTamaraOpt = '/api/orders/paymentoptions/tamara'; + // var BASE_URL = 'http://10.50.100.198:2018/'; // var BASE_URL = 'https://uat.hmgwebservices.com/'; -var BASE_URL = 'https://hmgwebservices.com/'; + // var BASE_URL = 'http://10.201.204.103/'; // var BASE_URL = 'https://orash.cloudsolutions.com.sa/'; // var BASE_URL = 'https://vidauat.cloudsolutions.com.sa/'; @@ -328,10 +329,8 @@ var BASE_URL = 'https://hmgwebservices.com/'; // var PHARMACY_BASE_URL = 'https://uat.hmgwebservices.com/epharmacy/api/'; // // Pharmacy Production URLs -var BASE_PHARMACY_URL = 'https://mdlaboratories.com/exacartapi/api/'; -var PHARMACY_BASE_URL = 'https://mdlaboratories.com/exacartapi/api/'; - -var PHARMACY_REDIRECT_URL = 'https://bit.ly/AlhabibPharmacy'; + static String pharmacyBaseUrl = 'https://mdlaboratories.com/exacartapi/api/'; + static String pharmacyRedirectUrl = 'https://bit.ly/AlhabibPharmacy'; // Pharmacy VidaPlus URLs // var BASE_PHARMACY_URL = 'https://mdlaboratories.com/exacartapitest/api/'; @@ -346,28 +345,30 @@ var PHARMACY_REDIRECT_URL = 'https://bit.ly/AlhabibPharmacy'; // var RC_BASE_URL = 'https://ms.hmg.com/rc/'; -var PING_SERVICE = 'Services/Weather.svc/REST/CheckConnectivity'; + static String pingService = 'Services/Weather.svc/REST/CheckConnectivity'; -var GET_PROJECT_LIST = 'Services/Lists.svc/REST/GetProject'; + static String getProjectsList = 'Services/Lists.svc/REST/GetProject'; -///Geofencing -var GET_GEO_ZONES = 'Services/Patients.svc/REST/GeoF_GetAllPoints'; -var LOG_GEO_ZONES = 'Services/Patients.svc/REST/GeoF_InsertPatientFileInfo'; + ///Geofencing + static String getGeoZones = 'Services/Patients.svc/REST/GeoF_GetAllPoints'; + static String logGeoZones = 'Services/Patients.svc/REST/GeoF_InsertPatientFileInfo'; // Delivery Driver -var DRIVER_LOCATION = 'Services/Patients.svc/REST/PatientER_GetDriverLocation'; + static String driverLocation = 'Services/Patients.svc/REST/PatientER_GetDriverLocation'; //weather -var WEATHER_INDICATOR = 'Services/Weather.svc/REST/GetCityInfo'; + static String weatherIndicator = 'Services/Weather.svc/REST/GetCityInfo'; -var GET_PRIVILEGE = 'Services/Patients.svc/REST/Service_Privilege'; + static String getPrivilege = 'Services/Patients.svc/REST/Service_Privilege'; // Wifi Credentials -var WIFI_CREDENTIALS = "Services/Patients.svc/Hmg_SMS_Get_By_ProjectID_And_PatientID"; + static String wifiCredentials = "Services/Patients.svc/Hmg_SMS_Get_By_ProjectID_And_PatientID"; + + ///Doctor + static String getMyDoctor = 'Services/Doctors.svc/REST/GetPatientDoctorAppointmentResult'; + static String getDoctorProfiles = 'Services/Doctors.svc/REST/GetDocProfiles'; +} -///Doctor -var GET_MY_DOCTOR = 'Services/Doctors.svc/REST/GetPatientDoctorAppointmentResult'; -var GET_DOCTOR_PROFILE = 'Services/Doctors.svc/REST/GetDocProfiles'; var GET_DOCTOR_PRE_POST_IMAGES = 'Services/Doctors.svc/REST/GetDoctorPrePostImages'; var GET_DOCTOR_RATING_NOTES = 'Services/Doctors.svc/REST/dr_GetNotesDoctorRating'; var GET_DOCTOR_RATING_DETAILS = 'Services/Doctors.svc/REST/dr_GetDoctorRatingDetails'; @@ -1001,43 +1002,12 @@ const SAVE_SETTING = 'Services/Patients.svc/REST/UpdatePateintInfo'; const GET_PROFILE_IMAGE = 'Services/Patients.svc/REST/Patient_GetProfileImageData'; -const UPLOAD_PROFILE_IMAGE = 'Services/Patients.svc/REST/Patient_InsertProfileImageData'; +const uploadProfileImageData = 'Services/Patients.svc/REST/Patient_InsertProfileImageData'; -const DOWNLOAD_INVOICE_PDF = 'Services/Notifications.svc/REST/DownloadInvoiceReport'; +const downloadInvoicePdf = 'Services/Notifications.svc/REST/DownloadInvoiceReport'; -const DOWNLOAD_PHARMACY_INVOICE_PDF = 'Services/Notifications.svc/REST/DownloadInvoiceReport'; +const downloadPharmacyInvoicePdf = 'Services/Notifications.svc/REST/DownloadInvoiceReport'; class ApiKeyConstants { static final String googleMapsApiKey = 'AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng'; } - -//flutter: URL : https://hmgwebservices.com/Services/H2ORemainder.svc/REST/H2O_InsertUserActivity -// flutter: {"IdentificationNo":"2530976584","MobileNumber":"504278212","QuantityIntake":200,"VersionID":20.0,"Channel":3,"LanguageID":2,"IPAdress":"10.20.10.20","generalid":"Cs2020@2016$2958","PatientOutSA":0,"SessionID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNS0xMi0yOFQwODozNjo0My45MTY0MzRaIiwiUGF0aWVudElEIjoiNDUxNTY5NyIsIlBhdGllbnRNZXJnZWRJRHMiOiI0NTE1Njk3IiwiUGF0aWVudE91dFNBIjpmYWxzZX0sImV4cCI6MTc2Njk2NjQwMH0.l1rCcs2OAU5u2J-iZMiO7NX6shGzLJV0hlYtVh2JeqY","isDentalAllowedBackend":false,"DeviceTypeID":1,"PatientID":4515697,"TokenID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNS0xMi0yOFQwODozNjo0My45MTY0MzRaIiwiUGF0aWVudElEIjoiNDUxNTY5NyIsIlBhdGllbnRNZXJnZWRJRHMiOiI0NTE1Njk3IiwiUGF0aWVudE91dFNBIjpmYWxzZX0sImV4cCI6MTc2Njk2NjQwMH0.l1rCcs2OAU5u2J-iZMiO7NX6shGzLJV0hlYtVh2JeqY","PatientTypeID":1,"PatientType":1,"Latitude":37.785834,"Longitude":-122.406417} -// flutter: response.body: -// flutter: {"Date":null,"LanguageID":0,"ServiceName":0,"Time":null,"AndroidLink":null,"AuthenticationTokenID":null,"Data":null,"Dataw":false,"DietType":0,"DietTypeID":0,"ErrorCode":null,"ErrorEndUserMessage":null,"ErrorEndUserMessageN":null,"ErrorMessage":null,"ErrorStatusCode":0,"ErrorType":0,"FoodCategory":0,"IOSLink":null,"IsAuthenticated":true,"MealOrderStatus":0,"MealType":0,"MessageStatus":1,"NumberOfResultRecords":0,"PatientBlodType":null,"SuccessMsg":null,"SuccessMsgN":null,"VidaUpdatedResponse":null,"IsHMGPatient":false,"LogInTokenID":null,"PhysicalActivityData":null,"RowExists":0,"UserDetailData":null,"UserDetailData_New":null,"UserProgressForMonthData":null,"UserProgressForTodayData":[{"QuantityConsumed":200.00,"PercentageConsumed":9.41,"PercentageLeft":90.59,"QuantityLimit":2125.00}],"UserProgressForWeekData":null,"UserProgressHistoryData":[{"Quantity":200.000,"CreatedDate":"\/Date(1766911222217+0300)\/"}],"VerificationCode":null,"isSMSSent":false} - -// URL : https://hmgwebservices.com/Services/H2ORemainder.svc/REST/H2o_UndoUserActivity -// flutter: {"Progress":1,"MobileNumber":"504278212","IdentificationNo":"2530976584","VersionID":20.0,"Channel":3,"LanguageID":2,"IPAdress":"10.20.10.20","generalid":"Cs2020@2016$2958","PatientOutSA":0,"SessionID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNS0xMi0yOFQwODozNjo0My45MTY0MzRaIiwiUGF0aWVudElEIjoiNDUxNTY5NyIsIlBhdGllbnRNZXJnZWRJRHMiOiI0NTE1Njk3IiwiUGF0aWVudE91dFNBIjpmYWxzZX0sImV4cCI6MTc2Njk2NjQwMH0.l1rCcs2OAU5u2J-iZMiO7NX6shGzLJV0hlYtVh2JeqY","isDentalAllowedBackend":false,"DeviceTypeID":1,"PatientID":4515697,"TokenID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNS0xMi0yOFQwODozNjo0My45MTY0MzRaIiwiUGF0aWVudElEIjoiNDUxNTY5NyIsIlBhdGllbnRNZXJnZWRJRHMiOiI0NTE1Njk3IiwiUGF0aWVudE91dFNBIjpmYWxzZX0sImV4cCI6MTc2Njk2NjQwMH0.l1rCcs2OAU5u2J-iZMiO7NX6shGzLJV0hlYtVh2JeqY","PatientTypeID":1,"PatientType":1,"Latitude":37.785834,"Longitude":-122.406417} -// flutter: response.body: -// flutter: {"Date":null,"LanguageID":0,"ServiceName":0,"Time":null,"AndroidLink":null,"AuthenticationTokenID":null,"Data":null,"Dataw":false,"DietType":0,"DietTypeID":0,"ErrorCode":null,"ErrorEndUserMessage":null,"ErrorEndUserMessageN":null,"ErrorMessage":null,"ErrorStatusCode":0,"ErrorType":0,"FoodCategory":0,"IOSLink":null,"IsAuthenticated":false,"MealOrderStatus":0,"MealType":0,"MessageStatus":1,"NumberOfResultRecords":0,"PatientBlodType":null,"SuccessMsg":null,"SuccessMsgN":null,"VidaUpdatedResponse":null,"IsHMGPatient":false,"LogInTokenID":null,"PhysicalActivityData":null,"RowExists":0,"UserDetailData":null,"UserDetailData_New":null,"UserProgressForMonthData":null,"UserProgressForTodayData":[{"QuantityConsumed":0.00,"PercentageConsumed":0.00,"PercentageLeft":100.00,"QuantityLimit":2125.00}],"UserProgressForWeekData":null,"UserProgressHistoryData":[],"VerificationCode":null,"isSMSSent":false} - -// Progress":2 means weekly data - -// flutter: URL : https://hmgwebservices.com/Services/H2ORemainder.svc/REST/H2O_GetUserProgress -// flutter: {"Progress":2,"MobileNumber":"504278212","IdentificationNo":"2530976584","VersionID":20.0,"Channel":3,"LanguageID":2,"IPAdress":"10.20.10.20","generalid":"Cs2020@2016$2958","PatientOutSA":0,"SessionID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNS0xMi0yOFQwODozNjo0My45MTY0MzRaIiwiUGF0aWVudElEIjoiNDUxNTY5NyIsIlBhdGllbnRNZXJnZWRJRHMiOiI0NTE1Njk3IiwiUGF0aWVudE91dFNBIjpmYWxzZX0sImV4cCI6MTc2Njk2NjQwMH0.l1rCcs2OAU5u2J-iZMiO7NX6shGzLJV0hlYtVh2JeqY","isDentalAllowedBackend":false,"DeviceTypeID":1,"PatientID":4515697,"TokenID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNS0xMi0yOFQwODozNjo0My45MTY0MzRaIiwiUGF0aWVudElEIjoiNDUxNTY5NyIsIlBhdGllbnRNZXJnZWRJRHMiOiI0NTE1Njk3IiwiUGF0aWVudE91dFNBIjpmYWxzZX0sImV4cCI6MTc2Njk2NjQwMH0.l1rCcs2OAU5u2J-iZMiO7NX6shGzLJV0hlYtVh2JeqY","PatientTypeID":1,"PatientType":1,"Latitude":37.785834,"Longitude":-122.406417} -// flutter: response.body: -// [log] {"Date":null,"LanguageID":0,"ServiceName":0,"Time":null,"AndroidLink":null,"AuthenticationTokenID":null,"Data":null,"Dataw":false,"DietType":0,"DietTypeID":0,"ErrorCode":null,"ErrorEndUserMessage":null,"ErrorEndUserMessageN":null,"ErrorMessage":null,"ErrorStatusCode":0,"ErrorType":0,"FoodCategory":0,"IOSLink":null,"IsAuthenticated":false,"MealOrderStatus":0,"MealType":0,"MessageStatus":1,"NumberOfResultRecords":0,"PatientBlodType":null,"SuccessMsg":null,"SuccessMsgN":null,"VidaUpdatedResponse":null,"IsHMGPatient":false,"LogInTokenID":null,"PhysicalActivityData":null,"RowExists":0,"UserDetailData":null,"UserDetailData_New":null,"UserProgressForMonthData":null,"UserProgressForTodayData":null,"UserProgressForWeekData":[{"DayNumber":1,"DayDate":null,"DayName":"Sunday","PercentageConsumed":0},{"DayNumber":7,"DayDate":null,"DayName":"Saturday","PercentageConsumed":0},{"DayNumber":6,"DayDate":null,"DayName":"Friday","PercentageConsumed":0},{"DayNumber":5,"DayDate":null,"DayName":"Thursday","PercentageConsumed":0},{"DayNumber":4,"DayDate":null,"DayName":"Wednesday","PercentageConsumed":0},{"DayNumber":3,"DayDate":null,"DayName":"Tuesday","PercentageConsumed":0},{"DayNumber":2,"DayDate":null,"DayName":"Monday","PercentageConsumed":0}],"UserProgressHistoryData":[],"VerificationCode":null,"isSMSSent":false} - -// Progress":1 means daily data - -//URL : https://hmgwebservices.com/Services/H2ORemainder.svc/REST/H2O_GetUserProgress -// flutter: {"Progress":1,"MobileNumber":"504278212","IdentificationNo":"2530976584","VersionID":20.0,"Channel":3,"LanguageID":2,"IPAdress":"10.20.10.20","generalid":"Cs2020@2016$2958","PatientOutSA":0,"SessionID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNS0xMi0yOFQwODozNjo0My45MTY0MzRaIiwiUGF0aWVudElEIjoiNDUxNTY5NyIsIlBhdGllbnRNZXJnZWRJRHMiOiI0NTE1Njk3IiwiUGF0aWVudE91dFNBIjpmYWxzZX0sImV4cCI6MTc2Njk2NjQwMH0.l1rCcs2OAU5u2J-iZMiO7NX6shGzLJV0hlYtVh2JeqY","isDentalAllowedBackend":false,"DeviceTypeID":1,"PatientID":4515697,"TokenID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNS0xMi0yOFQwODozNjo0My45MTY0MzRaIiwiUGF0aWVudElEIjoiNDUxNTY5NyIsIlBhdGllbnRNZXJnZWRJRHMiOiI0NTE1Njk3IiwiUGF0aWVudE91dFNBIjpmYWxzZX0sImV4cCI6MTc2Njk2NjQwMH0.l1rCcs2OAU5u2J-iZMiO7NX6shGzLJV0hlYtVh2JeqY","PatientTypeID":1,"PatientType":1,"Latitude":37.785834,"Longitude":-122.406417} -// flutter: response.body: -// flutter: {"Date":null,"LanguageID":0,"ServiceName":0,"Time":null,"AndroidLink":null,"AuthenticationTokenID":null,"Data":null,"Dataw":false,"DietType":0,"DietTypeID":0,"ErrorCode":null,"ErrorEndUserMessage":null,"ErrorEndUserMessageN":null,"ErrorMessage":null,"ErrorStatusCode":0,"ErrorType":0,"FoodCategory":0,"IOSLink":null,"IsAuthenticated":false,"MealOrderStatus":0,"MealType":0,"MessageStatus":1,"NumberOfResultRecords":0,"PatientBlodType":null,"SuccessMsg":null,"SuccessMsgN":null,"VidaUpdatedResponse":null,"IsHMGPatient":false,"LogInTokenID":null,"PhysicalActivityData":null,"RowExists":0,"UserDetailData":null,"UserDetailData_New":null,"UserProgressForMonthData":null,"UserProgressForTodayData":[{"QuantityConsumed":0.00,"PercentageConsumed":0.00,"PercentageLeft":100.00,"QuantityLimit":2125.00}],"UserProgressForWeekData":null,"UserProgressHistoryData":[],"VerificationCode":null,"isSMSSent":false} - -// Progress":1 means monthly data - -// flutter: URL : https://hmgwebservices.com/Services/H2ORemainder.svc/REST/H2O_GetUserProgress -// flutter: {"Progress":3,"MobileNumber":"504278212","IdentificationNo":"2530976584","VersionID":20.0,"Channel":3,"LanguageID":2,"IPAdress":"10.20.10.20","generalid":"Cs2020@2016$2958","PatientOutSA":0,"SessionID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNS0xMi0yOFQwODozNjo0My45MTY0MzRaIiwiUGF0aWVudElEIjoiNDUxNTY5NyIsIlBhdGllbnRNZXJnZWRJRHMiOiI0NTE1Njk3IiwiUGF0aWVudE91dFNBIjpmYWxzZX0sImV4cCI6MTc2Njk2NjQwMH0.l1rCcs2OAU5u2J-iZMiO7NX6shGzLJV0hlYtVh2JeqY","isDentalAllowedBackend":false,"DeviceTypeID":1,"PatientID":4515697,"TokenID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNS0xMi0yOFQwODozNjo0My45MTY0MzRaIiwiUGF0aWVudElEIjoiNDUxNTY5NyIsIlBhdGllbnRNZXJnZWRJRHMiOiI0NTE1Njk3IiwiUGF0aWVudE91dFNBIjpmYWxzZX0sImV4cCI6MTc2Njk2NjQwMH0.l1rCcs2OAU5u2J-iZMiO7NX6shGzLJV0hlYtVh2JeqY","PatientTypeID":1,"PatientType":1,"Latitude":37.785834,"Longitude":-122.406417} -// flutter: response.body: -// [log] {"Date":null,"LanguageID":0,"ServiceName":0,"Time":null,"AndroidLink":null,"AuthenticationTokenID":null,"Data":null,"Dataw":false,"DietType":0,"DietTypeID":0,"ErrorCode":null,"ErrorEndUserMessage":null,"ErrorEndUserMessageN":null,"ErrorMessage":null,"ErrorStatusCode":0,"ErrorType":0,"FoodCategory":0,"IOSLink":null,"IsAuthenticated":false,"MealOrderStatus":0,"MealType":0,"MessageStatus":1,"NumberOfResultRecords":0,"PatientBlodType":null,"SuccessMsg":null,"SuccessMsgN":null,"VidaUpdatedResponse":null,"IsHMGPatient":false,"LogInTokenID":null,"PhysicalActivityData":null,"RowExists":0,"UserDetailData":null,"UserDetailData_New":null,"UserProgressForMonthData":[{"MonthNumber":1,"MonthName":"January","PercentageConsumed":0},{"MonthNumber":2,"MonthName":"February","PercentageConsumed":0},{"MonthNumber":3,"MonthName":"March","PercentageConsumed":0},{"MonthNumber":4,"MonthName":"April","PercentageConsumed":0},{"MonthNumber":5,"MonthName":"May","PercentageConsumed":0},{"MonthNumber":6,"MonthName":"June","PercentageConsumed":0},{"MonthNumber":7,"MonthName":"July","PercentageConsumed":0},{"MonthNumber":8,"MonthName":"August","PercentageConsumed":0},{"MonthNumber":9,"MonthName":"September","PercentageConsumed":0},{"MonthNumber":10,"MonthName":"October","PercentageConsumed":0},{"MonthNumber":11,"MonthName":"November","PercentageConsumed":0},{"MonthNumber":12,"MonthName":"December","PercentageConsumed":0}],"UserProgressForTodayData":null,"UserProgressForWeekData":null,"UserProgressHistoryData":[],"VerificationCode":null,"isSMSSent":false} diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart index 9a4826b0..81742148 100644 --- a/lib/core/app_state.dart +++ b/lib/core/app_state.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:developer'; import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; @@ -9,8 +10,8 @@ import 'package:hmg_patient_app_new/core/common_models/privilege/VidaPlusProject import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_user_staus_nhic_response_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart'; -import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/cache_service.dart'; +import 'package:hmg_patient_app_new/services/navigation_service.dart'; import '../features/authentication/models/request_models/registration_payload_model.dart'; @@ -20,7 +21,7 @@ class AppState { static const String _profileImageKey = 'profile_image_data'; - AppState({required this.navigationService, required this.cacheService}){ + AppState({required this.navigationService, required this.cacheService}) { checkIfGMSAvailableOrNot(); _loadProfileImageFromCache(); } @@ -52,7 +53,8 @@ class AppState { bool isChildLoggedIn = false; bool isGMSAvailable = true; bool isAndroid = true; - bool isRatedVisible =false; + bool isRatedVisible = false; + void setAuthenticatedUser(AuthenticatedUser? authenticatedUser, {bool isFamily = false}) { if (isFamily) { _authenticatedChildUser = authenticatedUser; @@ -64,10 +66,10 @@ class AppState { FutureOr checkIfGMSAvailableOrNot() async { isGMSAvailable = (await GmsCheck().checkGmsAvailability()) ?? true; - if(Platform.isIOS) { - isGMSAvailable = true; - isAndroid = false; - return; + if (Platform.isIOS) { + isGMSAvailable = true; + isAndroid = false; + return; } } @@ -100,16 +102,16 @@ class AppState { set setProfileImageData(String? value) { // Clear old data first if (_profileImageData != null && _profileImageData != value) { - print('🔄 Replacing profile image: old data length=${_profileImageData!.length}, new data length=${value?.length ?? 0}'); + log('🔄 Replacing profile image: old data length=${_profileImageData!.length}, new data length=${value?.length ?? 0}'); } // Set new value directly WITHOUT caching _profileImageData = value; if (value != null && value.isNotEmpty) { - print('✅ Profile image set (length: ${value.length}) - NO CACHE'); + log('✅ Profile image set (length: ${value.length}) - NO CACHE'); } else { - print('🗑️ Profile image cleared - NO CACHE'); + log('🗑️ Profile image cleared - NO CACHE'); } } @@ -117,14 +119,14 @@ class AppState { void _loadProfileImageFromCache() { // DO NOT LOAD FROM CACHE - always fetch fresh from API _profileImageData = null; - print('📂 Profile image cache disabled - will fetch from API'); + log('📂 Profile image cache disabled - will fetch from API'); } /// Clear profile image data (e.g., on logout or user switch) void clearProfileImageCache() { - print('🧹 Clearing profile image data (was: ${_profileImageData != null ? "${_profileImageData!.length} chars" : "null"})'); + log('🧹 Clearing profile image data (was: ${_profileImageData != null ? "${_profileImageData!.length} chars" : "null"})'); _profileImageData = null; - print('✅ Profile image data cleared - NO CACHE'); + log('✅ Profile image data cleared - NO CACHE'); } SelectDeviceByImeiRespModelElement? _selectDeviceByImeiRespModelElement; @@ -159,7 +161,6 @@ class AppState { set setIsAuthenticated(v) => isAuthenticated = v; - String deviceTypeID = ""; set setDeviceTypeID(v) => deviceTypeID = v; @@ -215,7 +216,7 @@ class AppState { userLat = 0.0; } - setRatedVisible(bool value) { + setRatedVisible(bool value) { isRatedVisible = value; } @@ -270,7 +271,6 @@ class AppState { } } - dynamic getUserSwitchPayload({required String userType}) { return _userSwitchPayloads[userType]; } @@ -296,11 +296,11 @@ class AppState { void clearChildUsersKeepSuperUser() { // Keep the super user payload final superUserPayload = _userSwitchPayloads['superUser']; - + // Clear all payloads _userSwitchPayloads.clear(); _childSwitchCounter = 0; - + // Restore super user if it existed if (superUserPayload != null) { _userSwitchPayloads['superUser'] = superUserPayload; diff --git a/lib/features/blood_donation/blood_donation_repo.dart b/lib/features/blood_donation/blood_donation_repo.dart index c709b038..2cbcd916 100644 --- a/lib/features/blood_donation/blood_donation_repo.dart +++ b/lib/features/blood_donation/blood_donation_repo.dart @@ -116,7 +116,7 @@ class BloodDonationRepoImp implements BloodDonationRepo { GenericApiModel>? apiResponse; Failure? failure; await apiClient.post( - GET_PROJECT_LIST, + ApiConsts.getProjectsList, body: request, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; diff --git a/lib/features/book_appointments/book_appointments_repo.dart b/lib/features/book_appointments/book_appointments_repo.dart index 9afa113e..8bbb596c 100644 --- a/lib/features/book_appointments/book_appointments_repo.dart +++ b/lib/features/book_appointments/book_appointments_repo.dart @@ -271,7 +271,7 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo { GenericApiModel? apiResponse; Failure? failure; await apiClient.post( - GET_DOCTOR_PROFILE, + ApiConsts.getDoctorProfiles, body: mapDevice, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; @@ -527,7 +527,7 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo { GenericApiModel>? apiResponse; Failure? failure; await apiClient.post( - GET_PROJECT_LIST, + ApiConsts.getProjectsList, body: request, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; diff --git a/lib/features/contact_us/contact_us_view_model.dart b/lib/features/contact_us/contact_us_view_model.dart index 648fab6b..1b460a03 100644 --- a/lib/features/contact_us/contact_us_view_model.dart +++ b/lib/features/contact_us/contact_us_view_model.dart @@ -299,7 +299,7 @@ class ContactUsViewModel extends ChangeNotifier { requestInsertCOCItem.projectID = 0; requestInsertCOCItem.tokenID = "C0c@@dm!n?T&A&A@Barcha202029582948"; requestInsertCOCItem.identificationNo = int.parse(appState.getAuthenticatedUser()!.patientIdentificationNo!); - if (BASE_URL.contains('uat')) { + if (ApiConsts.baseUrl.contains('uat')) { requestInsertCOCItem.forDemo = true; } else { requestInsertCOCItem.forDemo = false; diff --git a/lib/features/emergency_services/emergency_services_repo.dart b/lib/features/emergency_services/emergency_services_repo.dart index 582c4a58..5fca01a8 100644 --- a/lib/features/emergency_services/emergency_services_repo.dart +++ b/lib/features/emergency_services/emergency_services_repo.dart @@ -189,7 +189,7 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo { GenericApiModel>? apiResponse; Failure? failure; await apiClient.post( - GET_PROJECT_LIST, + ApiConsts.getProjectsList, body: request, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; diff --git a/lib/features/habib_wallet/habib_wallet_repo.dart b/lib/features/habib_wallet/habib_wallet_repo.dart index 57d5af20..ff255092 100644 --- a/lib/features/habib_wallet/habib_wallet_repo.dart +++ b/lib/features/habib_wallet/habib_wallet_repo.dart @@ -83,7 +83,7 @@ class HabibWalletRepoImp implements HabibWalletRepo { GenericApiModel>? apiResponse; Failure? failure; await apiClient.post( - GET_PROJECT_LIST, + ApiConsts.getProjectsList, body: request, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; diff --git a/lib/features/habib_wallet/habib_wallet_view_model.dart b/lib/features/habib_wallet/habib_wallet_view_model.dart index 00ba55cc..ce18bf09 100644 --- a/lib/features/habib_wallet/habib_wallet_view_model.dart +++ b/lib/features/habib_wallet/habib_wallet_view_model.dart @@ -39,6 +39,31 @@ class HabibWalletViewModel extends ChangeNotifier { List refundableAdvancesList = []; bool isSubmittingWithdrawal = false; + // ── Wallet Withdrawal Step Management ───────────────────────────────────── + int currentWithdrawStep = 0; + RefundableAdvancesItem? selectedAdvance; + + void nextWithdrawStep() { + if (currentWithdrawStep < 1) { + currentWithdrawStep++; + notifyListeners(); + } + } + + void previousWithdrawStep() { + if (currentWithdrawStep > 0) { + currentWithdrawStep--; + notifyListeners(); + } + } + + void setSelectedAdvance(RefundableAdvancesItem? advance) { + selectedAdvance = advance; + notifyListeners(); + } + + double get selectedAdvanceBalance => selectedAdvance?.balanceAmount ?? 0.0; + bool isSearchedFileNumberDataShown = false; int currentIndex = 0; @@ -261,15 +286,17 @@ class HabibWalletViewModel extends ChangeNotifier { isSubmittingWithdrawal = true; notifyListeners(); - final advances = refundableAdvancesList - .map((a) => SubmitRefundAdvanceItem( - advanceNo: (a.advanceNo ?? 0).toString(), - paidAmount: a.paidAmount ?? 0.0, - balanceAmount: a.balanceAmount ?? 0.0, - advanceDate: a.advanceDate ?? "", - // advanceDate: _formatAdvanceDate(a.advanceDate), - )) - .toList(); + // Only send the selected advance (not all advances) + final advances = selectedAdvance != null + ? [ + SubmitRefundAdvanceItem( + advanceNo: (selectedAdvance!.advanceNo ?? 0).toString(), + paidAmount: selectedAdvance!.paidAmount ?? 0.0, + balanceAmount: selectedAdvance!.balanceAmount ?? 0.0, + advanceDate: selectedAdvance!.advanceDate ?? "", + ) + ] + : []; final request = SubmitRefundRequestModel( projectId: projectId, @@ -293,7 +320,7 @@ class HabibWalletViewModel extends ChangeNotifier { // only bank transfer refundIban: iban, refundRemarks: remarks, - refundTotalAmount: totalAdvancesBalance, + refundTotalAmount: selectedAdvanceBalance, refundProceduresList: const [], refundAdvancesList: advances, ); @@ -362,6 +389,8 @@ class HabibWalletViewModel extends ChangeNotifier { isSubmittingWithdrawal = false; _ibanError = null; _withdrawDescriptionError = null; + currentWithdrawStep = 0; + selectedAdvance = null; if (!silent) notifyListeners(); } diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart index 553491e1..f05edc6f 100644 --- a/lib/features/my_appointments/my_appointments_repo.dart +++ b/lib/features/my_appointments/my_appointments_repo.dart @@ -522,7 +522,7 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo { GenericApiModel>? apiResponse; Failure? failure; await apiClient.post( - GET_MY_DOCTOR, + ApiConsts.getMyDoctor, body: mapDevice, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; diff --git a/lib/features/my_invoices/my_invoices_repo.dart b/lib/features/my_invoices/my_invoices_repo.dart index 23f5d06a..c0f60049 100644 --- a/lib/features/my_invoices/my_invoices_repo.dart +++ b/lib/features/my_invoices/my_invoices_repo.dart @@ -199,7 +199,7 @@ class MyInvoicesRepoImp implements MyInvoicesRepo { GenericApiModel? apiResponse; Failure? failure; await apiClient.post( - DOWNLOAD_INVOICE_PDF, + downloadInvoicePdf, body: mapDevice, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; @@ -238,7 +238,7 @@ class MyInvoicesRepoImp implements MyInvoicesRepo { GenericApiModel? apiResponse; Failure? failure; await apiClient.post( - DOWNLOAD_PHARMACY_INVOICE_PDF, + downloadPharmacyInvoicePdf, body: mapDevice, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; diff --git a/lib/features/profile_settings/profile_settings_repo.dart b/lib/features/profile_settings/profile_settings_repo.dart index 113a52c0..5c16e646 100644 --- a/lib/features/profile_settings/profile_settings_repo.dart +++ b/lib/features/profile_settings/profile_settings_repo.dart @@ -207,7 +207,7 @@ class ProfileSettingsRepoImp implements ProfileSettingsRepo { Failure? failure; await apiClient.post( - UPLOAD_PROFILE_IMAGE, + uploadProfileImageData, body: body, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; diff --git a/lib/features/weather/weather_repo.dart b/lib/features/weather/weather_repo.dart index 26bf0a32..4777713f 100644 --- a/lib/features/weather/weather_repo.dart +++ b/lib/features/weather/weather_repo.dart @@ -25,7 +25,7 @@ class WeatherRepoImp implements WeatherRepo { GenericApiModel>? apiResponse; Failure? failure; await apiClient.post( - WEATHER_INDICATOR, + ApiConsts.weatherIndicator, body: request, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 07afd569..1cf39e81 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -2,7 +2,7 @@ // ignore_for_file: constant_identifier_names -abstract class LocaleKeys { +abstract class LocaleKeys { static const english = 'english'; static const arabic = 'arabic'; static const login = 'login'; @@ -1851,7 +1851,7 @@ abstract class LocaleKeys { static const invalidIbanFormat = 'invalidIbanFormat'; static const refundHistory = 'refundHistory'; static const noRefundHistoryFound = 'noRefundHistoryFound'; - static const selectProcedures = 'selectProcedures'; + static const selectProcedure = 'selectProcedure'; static const noProceduresAvailableForRefund = 'noProceduresAvailableForRefund'; static const selectAll = 'selectAll'; static const selectRefundMethod = 'selectRefundMethod'; @@ -1866,6 +1866,7 @@ abstract class LocaleKeys { static const refundReason5 = 'refundReason5'; static const refundReason6 = 'refundReason6'; static const refundReason7 = 'refundReason7'; + static const selectProcedures = 'selectProcedures'; static const redeem = 'redeem'; static const points = 'points'; static const transactions = 'transactions'; @@ -1876,8 +1877,12 @@ abstract class LocaleKeys { static const refundDetails = 'refundDetails'; static const requestNo = 'requestNo'; static const referenceNo = 'referenceNo'; - static const refund = 'refund'; static const advanceNumber = 'advanceNumber'; static const amountOnly = 'amountOnly'; static const invoiceHistory = 'invoiceHistory'; + static const selectAdvance = 'selectAdvance'; + static const advanceNo = 'advanceNo'; + static const noAdvancesAvailable = 'noAdvancesAvailable'; + static const refund = 'refund'; + } diff --git a/lib/presentation/habib_wallet/withdraw_request_create_page.dart b/lib/presentation/habib_wallet/withdraw_request_create_page.dart index cc0c9731..a5909e3a 100644 --- a/lib/presentation/habib_wallet/withdraw_request_create_page.dart +++ b/lib/presentation/habib_wallet/withdraw_request_create_page.dart @@ -1,15 +1,17 @@ -import 'dart:io'; - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart'; +import 'package:hmg_patient_app_new/features/refund_request/models/resp_models/refundable_invoices_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/widgets/select_hospital_bottom_sheet.dart'; import 'package:hmg_patient_app_new/presentation/refund_request/refund_history_screen.dart'; @@ -17,10 +19,10 @@ import 'package:hmg_patient_app_new/theme/colors.dart'; 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/common_bottom_sheet.dart'; -import 'package:hmg_patient_app_new/widgets/image_picker.dart'; import 'package:hmg_patient_app_new/widgets/input_widget.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; +import 'package:hmg_patient_app_new/widgets/stepper/stepper_widget.dart'; import 'package:provider/provider.dart'; class WithdrawRequestCreatePage extends StatefulWidget { @@ -45,6 +47,8 @@ class _WithdrawRequestCreatePageState extends State { _appState = getIt.get(); _habibWalletViewModel = context.read(); WidgetsBinding.instance.addPostFrameCallback((_) { + _habibWalletViewModel.currentWithdrawStep = 0; + _habibWalletViewModel.selectedAdvance = null; _habibWalletViewModel.getProjectsList(); }); } @@ -59,6 +63,170 @@ class _WithdrawRequestCreatePageState extends State { super.dispose(); } + // ── Stepper ─────────────────────────────────────────────────────────────── + + Widget _buildStepper(HabibWalletViewModel vm) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 24.w), + child: LayoutBuilder( + builder: (context, constraints) { + final itemWidth = (constraints.maxWidth - 2 * 8.h) / 2; + return Row( + children: List.generate(2, (index) { + final isActive = index <= vm.currentWithdrawStep; + final isThumb = index == vm.currentWithdrawStep; + return StepperWidget( + itemWidth, + isActive ? AppColors.primaryRedColor : AppColors.greyColor, + isThumb, + 6.h, + ); + }), + ); + }, + ), + ); + } + + // ── Step 1 — Select Advance ────────────────────────────────────────────── + + Widget _buildStep1Content(HabibWalletViewModel vm) { + return Consumer( + builder: (context, walletVM, _) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.selectAdvance.tr(context: context).toText20(isBold: true), + SizedBox(height: 24.h), + if (vm.isAdvancesLoading) + ListView.separated( + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (context, index) => SizedBox(height: 16.h), + itemCount: 4, + itemBuilder: (_, index) => Container( + height: 80.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 16.h, + ), + ).toShimmer2(isShow: true, radius: 16.r), + ) + else if (vm.refundableAdvancesList.isEmpty) + Center( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 24.h), + child: LocaleKeys.noAdvancesAvailable.tr().toText14(color: AppColors.greyTextColor), + ), + ) + else + AnimationLimiter( + child: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.h, + hasShadow: false, + ), + child: ListView.separated( + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (context, index) => Divider( + color: AppColors.bottomNAVBorder, + height: 1, + thickness: 1, + ).paddingSymmetrical(16.w, 0.w), + itemCount: vm.refundableAdvancesList.length, + itemBuilder: (context, index) { + final advance = vm.refundableAdvancesList[index]; + return _buildAdvanceCard(advance, index); + }, + ), + ), + ), + ], + ); + }, + ); + } + + Widget _buildAdvanceCard(RefundableAdvancesItem advance, int index) { + return AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 400), + child: SlideAnimation( + verticalOffset: 50.0, + child: FadeInAnimation( + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () => _habibWalletViewModel.setSelectedAdvance(advance), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: 24.w, + height: 24.w, + child: Radio( + value: advance.advanceNo ?? 0, + groupValue: _habibWalletViewModel.selectedAdvance?.advanceNo ?? -1, + onChanged: (_) => _habibWalletViewModel.setSelectedAdvance(advance), + activeColor: AppColors.primaryRedColor, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + visualDensity: VisualDensity.compact, + ), + ), + SizedBox(width: 12.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "${LocaleKeys.advanceNo.tr()}: ${advance.advanceNo ?? 0}".toText16(isBold: true), + SizedBox(height: 4.h), + _buildAdvanceDate(advance.advanceDate), + ], + ), + ), + SizedBox(width: 8.w), + Utils.getPaymentAmountWithSymbol( + (advance.balanceAmount ?? 0.0).toStringAsFixed(2).toText20( + isBold: true, + isEnglishOnly: true, + color: AppColors.textColor, + ), + AppColors.textColor, + 10.f, + isSaudiCurrency: true, + ), + ], + ), + ), + ), + ), + ), + ), + ); + } + + Widget _buildAdvanceDate(String? dateString) { + if (dateString == null || dateString.isEmpty) { + return const SizedBox.shrink(); + } + + try { + final date = DateUtil.convertStringToDate(dateString); + final formattedDate = DateUtil.formatDateToDate(date, false); + return formattedDate.toText12(color: AppColors.greyTextColor); + } catch (e) { + return const SizedBox.shrink(); + } + } + + // ── Step 2 — Bank Details ──────────────────────────────────────────────── + bool get _isFormValid { final vm = _habibWalletViewModel; return vm.selectedHospital != null && @@ -72,9 +240,13 @@ class _WithdrawRequestCreatePageState extends State { Widget _buildBottomBar() { return Consumer( builder: (context, vm, _) { - final isValid = vm.selectedHospital != null && - !vm.isAdvancesLoading && - _bankDetailsController.text.trim().isNotEmpty && + final isStep2 = vm.currentWithdrawStep == 1; + + // Step 1 validation: advance selected + final isStep1Valid = vm.selectedAdvance != null; + + // Step 2 validation: bank details filled + final isStep2Valid = _bankDetailsController.text.trim().isNotEmpty && _descriptionController.text.trim().isNotEmpty; return Container( @@ -86,16 +258,47 @@ class _WithdrawRequestCreatePageState extends State { child: Column( mainAxisSize: MainAxisSize.min, children: [ + if (isStep2 && vm.selectedAdvance != null) ...[ + Padding( + padding: EdgeInsets.fromLTRB(24.w, 16.h, 24.w, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + LocaleKeys.totalAmount.tr().toText18(color: AppColors.textColor, isBold: true), + Utils.getPaymentAmountWithSymbol( + vm.selectedAdvanceBalance.toStringAsFixed(2).toText24( + isBold: true, + isEnglishOnly: true, + color: AppColors.textColor, + ), + AppColors.textColorLight, + 14, + isSaudiCurrency: true, + ), + ], + ), + ), + ], CustomButton( - text: LocaleKeys.submitRequest.tr(context: context), - isDisabled: !isValid, + text: isStep2 + ? LocaleKeys.submitRequest.tr(context: context) + : LocaleKeys.next.tr(context: context), + isDisabled: isStep2 ? !isStep2Valid : !isStep1Valid, onPressed: () { - final isFormValid = vm.validateWithdrawForm( - iban: _bankDetailsController.text, - description: _descriptionController.text, - ); - if (isFormValid) { - _handleWalletWithdrawalSubmit(vm); + if (!isStep2) { + // Move to step 2 + if (vm.selectedAdvance != null) { + vm.nextWithdrawStep(); + } + } else { + // Submit + final isFormValid = vm.validateWithdrawForm( + iban: _bankDetailsController.text, + description: _descriptionController.text, + ); + if (isFormValid) { + _handleWalletWithdrawalSubmit(vm); + } } }, ).paddingSymmetrical(24.h, 24.h), @@ -108,6 +311,9 @@ class _WithdrawRequestCreatePageState extends State { Widget _buildProjectSelectionAndBalance(HabibWalletViewModel habibWalletViewModel) { final isArabic = _appState.isArabic(); + final showAmount = habibWalletViewModel.currentWithdrawStep == 1 && + habibWalletViewModel.selectedAdvance != null; + return Container( padding: EdgeInsets.all(16.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r), @@ -137,45 +343,40 @@ class _WithdrawRequestCreatePageState extends State { ]), ], ), - Utils.buildSvgWithAssets( - icon: AppAssets.arrow_down, - width: 25.h, - height: 25.h, - ), + if (habibWalletViewModel.currentWithdrawStep == 0) + Utils.buildSvgWithAssets( + icon: AppAssets.arrow_down, + width: 25.h, + height: 25.h, + ), ], - ).onPress(() { - showCommonBottomSheetWithoutHeight( - context, - title: LocaleKeys.selectHospital.tr(context: context), - isDismissible: false, - child: SelectHospitalBottomSheet( - onHospitalSelected: (hospital) { - habibWalletViewModel.setSelectedHospital(hospital); - habibWalletViewModel.fetchAdvancesForHospital(); - }, - ), - callBackFunc: () {}, - ); - }), - // Only show divider + amount once hospital is selected - if (habibWalletViewModel.selectedHospital != null) ...[ + ).onPress( + habibWalletViewModel.currentWithdrawStep == 0 + ? () { + showCommonBottomSheetWithoutHeight( + context, + title: LocaleKeys.selectHospital.tr(context: context), + isDismissible: false, + child: SelectHospitalBottomSheet( + onHospitalSelected: (hospital) { + habibWalletViewModel.setSelectedHospital(hospital); + habibWalletViewModel.fetchAdvancesForHospital(); + }, + ), + callBackFunc: () {}, + ); + } + : () {}, // Empty callback for step 2 + ), + if (showAmount) ...[ Divider(color: AppColors.bottomNAVBorder, thickness: 1).paddingOnly(top: 16.h), - habibWalletViewModel.isAdvancesLoading - ? Container( - height: 60.h, - // width: 160.w, - decoration: BoxDecoration( - color: AppColors.whiteColor, - borderRadius: BorderRadius.circular(12.r), - ), - ).toShimmer2(isShow: true, radius: 12.r) - : Utils.getPaymentAmountWithSymbol( - habibWalletViewModel.totalAdvancesBalance.toStringAsFixed(2).toText44(isBold: true), - AppColors.blackColor, - 18.w, - isSaudiCurrency: true, - isExpanded: false, - ), + Utils.getPaymentAmountWithSymbol( + habibWalletViewModel.selectedAdvanceBalance.toStringAsFixed(2).toText44(isBold: true), + AppColors.blackColor, + 18.w, + isSaudiCurrency: true, + isExpanded: false, + ), ], ], ), @@ -254,45 +455,6 @@ class _WithdrawRequestCreatePageState extends State { ); } - Widget _buildImagePickerDropDown() { - return Container( - padding: EdgeInsets.all(16.h), - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Utils.buildSvgWithAssets( - icon: AppAssets.selectImageIcon, - width: 40.h, - height: 40.h, - applyThemeColor: false, - ), - SizedBox(width: 8.h), - Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - LocaleKeys.uploadImage.tr(context: context).toText12(color: AppColors.greyTextColor, isBold: true), - LocaleKeys.selectImage.tr(context: context).toText14(color: AppColors.textColor, isBold: true), - ]), - ], - ), - Utils.buildSvgWithAssets( - icon: AppAssets.arrow_down, - width: 25.h, - height: 25.h, - ), - ], - ).onPress(() { - ImageOptions.showImageOptionsNew( - context, - false, - title: LocaleKeys.selectOptions.tr(context: context), - (String image, File file) {}, - ); - }), - ); - } - // ── Submit ──────────────────────────────────────────────────────────────── void _handleWalletWithdrawalSubmit(HabibWalletViewModel vm) { @@ -407,6 +569,13 @@ class _WithdrawRequestCreatePageState extends State { Expanded( child: CollapsingListView( title: LocaleKeys.requestRefund.tr(context: context), + leadingCallback: () { + if (habibWalletViewModel.currentWithdrawStep > 0) { + habibWalletViewModel.previousWithdrawStep(); + } else { + context.pop(); + } + }, requests: () => Navigator.of(context).push( CustomPageRoute( page: RefundHistoryScreen( @@ -415,17 +584,53 @@ class _WithdrawRequestCreatePageState extends State { ), ), child: SingleChildScrollView( - padding: EdgeInsets.only(bottom: 32.h, left: 24.w, right: 24.w), + padding: EdgeInsets.only(bottom: 32.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildProjectSelectionAndBalance(habibWalletViewModel), + // Hospital selection card - always visible + Padding( + padding: EdgeInsets.symmetric(horizontal: 24.w), + child: _buildProjectSelectionAndBalance(habibWalletViewModel), + ), + + // Stepper - show only after hospital selected if (habibWalletViewModel.selectedHospital != null) ...[ SizedBox(height: 16.h), - _buildBankInputDetails(), - // SizedBox(height: 16.h), - // _buildImagePickerDropDown(), + _buildStepper(habibWalletViewModel), + SizedBox(height: 16.h), ], + + // Step content - show only after hospital selected + if (habibWalletViewModel.selectedHospital != null) + AnimatedSwitcher( + duration: const Duration(milliseconds: 350), + transitionBuilder: (child, animation) => FadeTransition( + opacity: animation, + child: SlideTransition( + position: Tween( + begin: const Offset(0.05, 0), + end: Offset.zero, + ).animate(animation), + child: child, + ), + ), + child: habibWalletViewModel.currentWithdrawStep == 0 + ? KeyedSubtree( + key: const ValueKey('step1'), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 24.w), + child: _buildStep1Content(habibWalletViewModel), + ), + ) + : KeyedSubtree( + key: const ValueKey('step2'), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 24.w), + child: _buildBankInputDetails(), + ), + ), + ), ], ), ), @@ -440,6 +645,3 @@ class _WithdrawRequestCreatePageState extends State { } } -// I/flutter (13750): uri: https://uat.hmgwebservices.com/Services/COCWS.svc/REST/SubmitRefund -// [log] body: {"ProjectID":15,"Refund_RefundType":"2","Refund_Project":"مستشفى الريان","Refund_ProjectId":15,"Refund_PatientId":"4770714","PatientMobileNumber":"0504278212","Refund_PatientName":"FAIZ UR REHMAN REHMAN","Refund_NationalId":"2530976584","Refund_DoctorId":0,"Refund_DoctorName":"","Refund_RefundDestination":"2","Refund_IBAN":"SA0380000000608010167519","Refund_Remarks":"teskchjvs","Refund_TotalRefundAmount":1714.75,"Refund_AdvancesList":[{"AdvanceNo":"2026000444","PaidAmount":362.25,"BalanceAmount":362.25,"AdvanceDate":"/Date(1775682000000+0300)/"},{"AdvanceNo":"2026000392","PaidAmount":362.25,"BalanceAmount":362.25,"AdvanceDate":"/Date(1774645200000+0300)/"},{"AdvanceNo":"2026000066","PaidAmount":362.25,"BalanceAmount":362.25,"AdvanceDate":"/Date(1770152400000+0300)/"},{"AdvanceNo":"2026000047","PaidAmount":30.0,"BalanceAmount":30.0,"AdvanceDate":"/Date(1769547600000+0300)/"},{"AdvanceNo":"2025000751","PaidAmount":362.25,"BalanceAmount":362.25,"AdvanceDate":"/Date(1765746000000+0300)/"},{"AdvanceNo":"2025000414","PaidAmount":115.0,"BalanceAmount":115.0,"AdvanceDate":"/Date(1747083600000+0300)/"},{"AdvanceNo":"2025000210","PaidAmount":120.75,"BalanceAmount":120.75,"AdvanceDate":"/Date(1741726800000+0300)/"}],"PatientType":1,"PatientTypeID":1,"TokenID":"@dm!n","PatientID":4770714,"PatientOutSA":0,"SessionID":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlblR5cGUiOjIsIm9iaiI6eyJUaW1lIjoiMjAyNi0wNS0xOFQwNzo1MzoyMS4wMjQ5MDM2WiIsIlBhdGllbnRJRCI6IjQ3NzIxNjMiLCJQYXRpZW50TWVyZ2VkSURzIjoiNDc3MjE2MyIsIlBhdGllbnRPdXRTQSI6ZmFsc2UsIlNoYXJlZElkcyI6IiJ9LCJleHAiOjE3NzkxMzgwMDB9.VHd_kCya33GfK-DywTHwSU1PMewbQB7UhQD1zXS7X5w","VersionID":"21.2","Channel":"3","IPAdress":"10.20.10.20","generalid":"Cs2020@2016$2958","LanguageID":"1","Latitude":"0.0","Longitude":"0.0","DeviceTypeID":"2","IsNewFlutterApp":true} -// [log] response: {"Date":null,"LanguageID":0,"ServiceName":0,"Time":null,"AndroidLink":null,"AuthenticationTokenID":null,"Data":null,"Dataw":false,"DietType":0,"DietTypeID":0,"ErrorCode":null,"ErrorEndUserMessage":"Internal server error occurred.","ErrorEndUserMessageN":null,"ErrorMessage":null,"ErrorStatusCode":0,"ErrorType":0,"FoodCategory":0,"IOSLink":null,"IsAuthenticated":true,"MealOrderStatus":0,"MealType":0,"MessageStatus":2,"NumberOfResultRecords":0,"PatientBlodType":null,"RequestId":null,"SuccessMsg":null,"SuccessMsgN":null,"VidaUpdatedResponse":null,"ENSAT_GetPatientRequestListResponse":null,"ENSAT_Patient_External_Response":null,"ETQAN_CreateIncident_Response":null,"ETQAN_GetEmployeeOVRRequests_Response":null,"ETQAN_GetIncidentRequest_Response":null,"ETQAN_GetProjects_Response":null,"ITGRequest":null,"Itg_FormAttachmentsList":null,"ListCOCItems":null,"Message":"Refunds API returned status 500. Body: {\"message\":\"Internal server error occurred.\"}","Mohemm_ENSAT_GetItgToken_Response":null,"Mohemm_ITG_DepartmentSectionsList":null,"Mohemm_ITG_Pending_Task_ResponseItem":null,"Mohemm_ITG_ProjectDepartmentsList":null,"Mohemm_ITG_ResponseItem":null,"Mohemm_ITG_SectionTopicsList":null,"Mohemm_ITG_TicketDetailsList":null,"Mohemm_ITG_TicketTransactionsList":null,"Mohemm_ITG_TicketsByEmployeeList":null,"Mohemm_Itg_ProjectsList":null,"Mohemm_Itg_TicketTypesList":null,"ReferenceNumber":null,"Refund_InvoicesList":null,"Refund_PatientIdDisplay":null,"Refund_RefNo":null,"Refund_RefundTypeDisplay":null,"Refund_StatusItem":null,"Refund_TotalInvoices":0,"Refund_VerifyResult":null,"RequestType":null,"TotalCount":0,"statuseCode":500} diff --git a/lib/presentation/home/lakum_wallet_details.dart b/lib/presentation/home/lakum_wallet_details.dart index 79b71ec0..83f7009d 100644 --- a/lib/presentation/home/lakum_wallet_details.dart +++ b/lib/presentation/home/lakum_wallet_details.dart @@ -250,7 +250,7 @@ class LakumWalletDetails extends StatelessWidget { padding: EdgeInsets.fromLTRB(4, 0, 12, 0), fontSize: 14.f, onPressed: () { - Uri uri = Uri.parse(PHARMACY_REDIRECT_URL); + Uri uri = Uri.parse(ApiConsts.pharmacyRedirectUrl); launchUrl(uri, mode: LaunchMode.externalApplication); }, ); diff --git a/lib/presentation/home/widgets/lakum_wallet_card.dart b/lib/presentation/home/widgets/lakum_wallet_card.dart index 3645a2d3..f2ee7a26 100644 --- a/lib/presentation/home/widgets/lakum_wallet_card.dart +++ b/lib/presentation/home/widgets/lakum_wallet_card.dart @@ -137,7 +137,7 @@ class LakumWalletCard extends StatelessWidget { padding: EdgeInsets.fromLTRB(4, 0, 12, 0), fontSize: 14.f, onPressed: () { - Uri uri = Uri.parse(PHARMACY_REDIRECT_URL); + Uri uri = Uri.parse(ApiConsts.pharmacyRedirectUrl); launchUrl(uri, mode: LaunchMode.externalApplication); // Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); }, diff --git a/lib/presentation/home/widgets/large_service_card.dart b/lib/presentation/home/widgets/large_service_card.dart index 72b11ef3..7c4948c4 100644 --- a/lib/presentation/home/widgets/large_service_card.dart +++ b/lib/presentation/home/widgets/large_service_card.dart @@ -165,7 +165,7 @@ class LargeServiceCard extends StatelessWidget { } case "pharmacy": { - Uri uri = Uri.parse(PHARMACY_REDIRECT_URL); + Uri uri = Uri.parse(ApiConsts.pharmacyRedirectUrl); launchUrl(uri, mode: LaunchMode.externalApplication); } } @@ -312,7 +312,7 @@ class FadedLargeServiceCard extends StatelessWidget { } case "pharmacy": { - Uri uri = Uri.parse(PHARMACY_REDIRECT_URL); + Uri uri = Uri.parse(ApiConsts.pharmacyRedirectUrl); launchUrl(uri, mode: LaunchMode.externalApplication); } }