Appointment Queue implemented, Blood Donation implementation contd.

pull/110/head
haroon amjad 3 months ago
parent 634a138c7f
commit e72e67d9bf

@ -0,0 +1,3 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="mapbox_access_token" translatable="false" tools:ignore="UnusedResources">sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg</string>
</resources>

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

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -181,6 +181,7 @@ class AppAssets {
static const String call_for_vitals = '$svgBasePath/call_for_vitals.svg';
static const String call_for_doctor = '$svgBasePath/call_for_doctor.svg';
static const String bulb_icon = '$svgBasePath/bulb_icon.svg';
static const String select_city_icon = '$svgBasePath/select_city_icon.svg';
//bottom navigation//

@ -5,6 +5,8 @@ import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_repo.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/common/common_repo.dart';
@ -116,6 +118,7 @@ class AppDependencies {
getIt.registerLazySingleton<LocationRepo>(() => LocationRepoImpl(apiClient: getIt()));
getIt.registerLazySingleton<ContactUsRepo>(() => ContactUsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<HmgServicesRepo>(() => HmgServicesRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<BloodDonationRepo>(() => BloodDonationRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
// ViewModels
// Global/shared VMs LazySingleton
@ -224,6 +227,10 @@ class AppDependencies {
() => HmgServicesViewModel(bookAppointmentsRepo: getIt(), hmgServicesRepo: getIt(), errorHandlerService: getIt(), navigationService: getIt()),
);
getIt.registerLazySingleton<BloodDonationViewModel>(
() => BloodDonationViewModel(bloodDonationRepo: getIt(), errorHandlerService: getIt(), navigationService: getIt(), dialogService: getIt(), appState: getIt()),
);
// Screen-specific VMs Factory
// getIt.registerFactory<BookAppointmentsViewModel>(
// () => BookAppointmentsViewModel(

@ -875,4 +875,54 @@ class Utils {
Uri uri = Uri.parse(url);
launchUrl(uri, mode: LaunchMode.inAppBrowserView);
}
static Color getCardBorderColor(int currentQueueStatus) {
switch (currentQueueStatus) {
case 0:
return AppColors.ratingColorYellow;
case 1:
return AppColors.primaryRedColor;
case 2:
return AppColors.successColor;
}
return AppColors.textColor;
}
static Color getCardButtonColor(int currentQueueStatus) {
switch (currentQueueStatus) {
case 0:
return AppColors.textColor.withValues(alpha: 0.08);
case 1:
return AppColors.primaryRedColor;
case 2:
return AppColors.successColor;
}
return AppColors.primaryRedColor;
}
static Color getCardButtonTextColor(int currentQueueStatus) {
switch (currentQueueStatus) {
case 0:
return Color(0xFFA2A2A2);
case 1:
return AppColors.whiteColor;
case 2:
return AppColors.whiteColor;
}
return AppColors.primaryRedColor;
}
static String getCardButtonText(int currentQueueStatus) {
switch (currentQueueStatus) {
case 0:
return "Please wait! you will be called for vital signs".needTranslation;
case 1:
return "Please visit Room S5 for vital signs".needTranslation;
case 2:
return "Please visit Room S5 to the Doctor".needTranslation;
}
return "";
}
}

@ -0,0 +1,95 @@
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/blood_donation/models/blood_group_response_model.dart';
import 'package:hmg_patient_app_new/features/blood_donation/models/cities_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class BloodDonationRepo {
Future<Either<Failure, GenericApiModel<List<CitiesModel>>>> getAllCities();
Future<Either<Failure, GenericApiModel<List_BloodGroupDetailsModel>>> getPatientBloodGroupDetails();
}
class BloodDonationRepoImp implements BloodDonationRepo {
final ApiClient apiClient;
final LoggerService loggerService;
BloodDonationRepoImp({required this.loggerService, required this.apiClient});
@override
Future<Either<Failure, GenericApiModel<List<CitiesModel>>>> getAllCities() async {
Map<String, dynamic> mapDevice = {};
try {
GenericApiModel<List<CitiesModel>>? apiResponse;
Failure? failure;
await apiClient.post(
GET_CITIES_REQUEST,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['ListCities'];
final citiesList = list.map((item) => CitiesModel.fromJson(item as Map<String, dynamic>)).toList().cast<CitiesModel>();
apiResponse = GenericApiModel<List<CitiesModel>>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: citiesList,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<List_BloodGroupDetailsModel>>> getPatientBloodGroupDetails() async {
Map<String, dynamic> mapDevice = {};
try {
GenericApiModel<List_BloodGroupDetailsModel>? apiResponse;
Failure? failure;
await apiClient.post(
GET_BLOOD_REQUEST,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['List_BloodGroupDetails'][0];
final patientBloodGroup = List_BloodGroupDetailsModel.fromJson(list);
apiResponse = GenericApiModel<List_BloodGroupDetailsModel>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: patientBloodGroup,
);
} 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()));
}
}
}

@ -0,0 +1,133 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_repo.dart';
import 'package:hmg_patient_app_new/features/blood_donation/models/blood_group_list_model.dart';
import 'package:hmg_patient_app_new/features/blood_donation/models/blood_group_response_model.dart';
import 'package:hmg_patient_app_new/features/blood_donation/models/cities_model.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
class BloodDonationViewModel extends ChangeNotifier {
final DialogService dialogService;
BloodDonationRepo bloodDonationRepo;
ErrorHandlerService errorHandlerService;
final NavigationService navigationService;
final AppState appState;
List<CitiesModel> citiesList = [];
List<BloodGroupListModel> bloodGroupList = [
BloodGroupListModel("O+", 0),
BloodGroupListModel("O-", 1),
BloodGroupListModel("AB+", 2),
BloodGroupListModel("AB-", 3),
BloodGroupListModel("A+", 4),
BloodGroupListModel("A-", 5),
BloodGroupListModel("B+", 6),
BloodGroupListModel("B-", 7),
];
late CitiesModel selectedCity;
late BloodGroupListModel selectedBloodGroup;
int _selectedHospitalIndex = 0;
int _selectedBloodTypeIndex = 0;
String _selectedBloodType = '';
List_BloodGroupDetailsModel patientBloodGroupDetailsModel = List_BloodGroupDetailsModel();
BloodDonationViewModel({required this.bloodDonationRepo, required this.errorHandlerService, required this.navigationService, required this.dialogService, required this.appState});
setSelectedCity(CitiesModel city) {
selectedCity = city;
notifyListeners();
}
Future<void> getRegionSelectedClinics({Function(dynamic)? onSuccess, Function(String)? onError}) async {
citiesList.clear();
selectedCity = CitiesModel();
notifyListeners();
final result = await bloodDonationRepo.getAllCities();
result.fold(
(failure) async {
onError!(failure.message);
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
onError!(apiResponse.errorMessage ?? 'An unexpected error occurred');
} else if (apiResponse.messageStatus == 1) {
citiesList = apiResponse.data!;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> getPatientBloodGroupDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await bloodDonationRepo.getPatientBloodGroupDetails();
result.fold(
(failure) async {
onError!(failure.message);
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
onError!(apiResponse.errorMessage ?? 'An unexpected error occurred');
} else if (apiResponse.messageStatus == 1) {
patientBloodGroupDetailsModel = apiResponse.data!;
CitiesModel citiesModel = CitiesModel();
citiesModel.iD = getSelectedCityID();
_selectedHospitalIndex = (citiesModel.iD! - 1);
citiesModel.description = citiesList[_selectedHospitalIndex].description;
citiesModel.descriptionN = citiesList[_selectedHospitalIndex].descriptionN;
selectedCity = citiesModel;
_selectedBloodType = patientBloodGroupDetailsModel.bloodGroup!;
_selectedBloodTypeIndex = getBloodIndex(_selectedBloodType);
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
int getSelectedCityID() {
int cityID = 1;
citiesList.forEach((element) {
if (element.description == patientBloodGroupDetailsModel.city) {
cityID = element.iD!;
}
});
return cityID;
}
int getBloodIndex(String type) {
switch (type) {
case "O+":
return 0;
case "O-":
return 1;
case "AB+":
return 2;
case "AB-":
return 3;
case "A+":
return 4;
case "A-":
return 5;
case "B+":
return 6;
case "B-":
return 7;
default:
return 0;
}
}
}

@ -0,0 +1,6 @@
class BloodGroupListModel {
String name;
int value;
BloodGroupListModel(this.name, this.value);
}

@ -0,0 +1,61 @@
class List_BloodGroupDetailsModel {
int? iD;
int? patientID;
int? patientType;
bool? patientOutSA;
int? zipCode;
String? cellNumber;
String? cityCode;
String? city;
int? gender;
String? bloodGroup;
String? nationalID;
bool? isActive;
List_BloodGroupDetailsModel({
this.iD,
this.patientID,
this.patientType,
this.patientOutSA,
this.zipCode,
this.cellNumber,
this.cityCode,
this.city,
this.gender,
this.bloodGroup,
this.nationalID,
this.isActive,
});
List_BloodGroupDetailsModel.fromJson(Map<String, dynamic> json) {
iD = json['ID'];
patientID = json['PatientID'];
patientType = json['PatientType'];
patientOutSA = json['PatientOutSA'];
zipCode = json['ZipCode'];
cellNumber = json['CellNumber'];
cityCode = json['CityCode'];
city = json['City'];
gender = json['Gender'];
bloodGroup = json['BloodGroup'];
nationalID = json['NationalID'];
isActive = json['IsActive'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ID'] = this.iD;
data['PatientID'] = this.patientID;
data['PatientType'] = this.patientType;
data['PatientOutSA'] = this.patientOutSA;
data['ZipCode'] = this.zipCode;
data['CellNumber'] = this.cellNumber;
data['CityCode'] = this.cityCode;
data['City'] = this.city;
data['Gender'] = this.gender;
data['BloodGroup'] = this.bloodGroup;
data['NationalID'] = this.nationalID;
data['IsActive'] = this.isActive;
return data;
}
}

@ -0,0 +1,21 @@
class CitiesModel {
int? iD;
String? description;
String? descriptionN;
CitiesModel({this.iD, this.description, this.descriptionN});
CitiesModel.fromJson(Map<String, dynamic> json) {
iD = json['ID'];
description = json['Description'];
descriptionN = json['DescriptionN'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ID'] = this.iD;
data['Description'] = this.description;
data['DescriptionN'] = this.descriptionN;
return data;
}
}

@ -497,8 +497,8 @@ class BookAppointmentsViewModel extends ChangeNotifier {
}
initialSlotDuration = apiResponse.data["InitialSlotDuration"];
freeSlotsResponse = apiResponse.data['FreeTimeSlots'];
// isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"];
isWaitingAppointmentAvailable = true;
isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"];
// isWaitingAppointmentAvailable = true;
freeSlotsResponse.forEach((element) {
// date = (isLiveCareSchedule != null && isLiveCareSchedule)

@ -37,6 +37,9 @@ class MyAppointmentsViewModel extends ChangeNotifier {
DateTime? start = null;
DateTime? end = null;
bool isPatientHasQueueAppointment = false;
int currentQueueStatus = 0;
List<PatientAppointmentHistoryResponseModel> patientAppointmentsHistoryList = [];
List<PatientAppointmentHistoryResponseModel> filteredAppointmentList = [];
@ -85,6 +88,12 @@ class MyAppointmentsViewModel extends ChangeNotifier {
isTamaraDetailsLoading = true;
isAppointmentPatientShareLoading = true;
isEyeMeasurementsAppointmentsLoading = true;
isPatientHasQueueAppointment = false;
notifyListeners();
}
setCurrentQueueStatus(int currentQueueStatus) {
this.currentQueueStatus = currentQueueStatus;
notifyListeners();
}

@ -9,6 +9,7 @@ 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/utils.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart';
import 'package:hmg_patient_app_new/features/doctor_filter/doctor_filter_view_model.dart';
@ -145,6 +146,9 @@ void main() async {
),
ChangeNotifierProvider<HmgServicesViewModel>(
create: (_) => getIt.get<HmgServicesViewModel>(),
),
ChangeNotifierProvider<BloodDonationViewModel>(
create: (_) => getIt.get<BloodDonationViewModel>(),
)
], child: MyApp()),
),

@ -6,261 +6,215 @@ 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/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
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/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:provider/provider.dart';
class AppointmentQueuePage extends StatelessWidget {
AppointmentQueuePage({super.key});
AppState? appState;
int currentQueueStatus = 0;
@override
Widget build(BuildContext context) {
currentQueueStatus = 1;
appState = getIt.get<AppState>();
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
children: [
Expanded(
child: CollapsingListView(
title: "Queueing".needTranslation,
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
side: BorderSide(color: getCardBorderColor(), width: 2.w),
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AppCustomChipWidget(
labelText: currentQueueStatus == 0 ? "In Queue".needTranslation : "Your Turn".needTranslation,
backgroundColor: getCardBorderColor().withValues(alpha: 0.20),
textColor: getCardBorderColor(),
),
Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h),
],
),
SizedBox(height: 10.h),
"Hala ${appState!.getAuthenticatedUser()!.firstName}!!!".needTranslation.toText16(isBold: true),
SizedBox(height: 8.h),
"Thank you for your patience, here is your queue number.".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 8.h),
"IMD W-A-2".needTranslation.toText32(isBold: true),
SizedBox(height: 8.h),
CustomButton(
text: getCardButtonText(),
onPressed: () {},
backgroundColor: getCardButtonColor(),
borderColor: getCardButtonColor().withValues(alpha: 0.01),
textColor: getCardButtonTextColor(),
fontSize: 12.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
iconColor: AppColors.whiteColor,
iconSize: 18.h,
),
],
body: Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
return Column(
children: [
Expanded(
child: CollapsingListView(
title: "Queueing".needTranslation,
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
side: BorderSide(color: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus), width: 2.w),
),
),
),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Serving Now".needTranslation.toText16(isBold: true),
SizedBox(height: 18.h),
ListView.separated(
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: 3,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"IMD W-A-2".needTranslation.toText17(isBold: true),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
"Room: S2".toText12(fontWeight: FontWeight.w500),
SizedBox(width: 8.w),
AppCustomChipWidget(
deleteIcon: AppAssets.call_for_vitals,
labelText: "Call for vital signs".needTranslation,
iconColor: AppColors.primaryRedColor,
textColor: AppColors.primaryRedColor,
iconSize: 14.w,
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.1),
labelPadding: EdgeInsetsDirectional.only(start: 8.h, end: -2.h),
),
],
),
],
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 8.h),
),
],
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AppCustomChipWidget(
labelText: myAppointmentsVM.currentQueueStatus == 0 ? "In Queue".needTranslation : "Your Turn".needTranslation,
backgroundColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.20),
textColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus),
),
Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h),
],
),
SizedBox(height: 10.h),
"Hala ${appState!.getAuthenticatedUser()!.firstName}!!!".needTranslation.toText16(isBold: true),
SizedBox(height: 8.h),
"Thank you for your patience, here is your queue number.".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 8.h),
"IMD W-A-5".needTranslation.toText32(isBold: true),
SizedBox(height: 8.h),
CustomButton(
text: Utils.getCardButtonText(myAppointmentsVM.currentQueueStatus),
onPressed: () {},
backgroundColor: Utils.getCardButtonColor(myAppointmentsVM.currentQueueStatus),
borderColor: Utils.getCardButtonColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.01),
textColor: Utils.getCardButtonTextColor(myAppointmentsVM.currentQueueStatus),
fontSize: 12.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
iconColor: AppColors.whiteColor,
iconSize: 18.h,
),
],
),
),
),
),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Serving Now".needTranslation.toText16(isBold: true),
SizedBox(height: 18.h),
ListView.separated(
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: 3,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"IMD W-A-2".needTranslation.toText17(isBold: true),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
"Room: S2".toText12(fontWeight: FontWeight.w500),
SizedBox(width: 8.w),
AppCustomChipWidget(
deleteIcon: AppAssets.call_for_vitals,
labelText: "Call for vital signs".needTranslation,
iconColor: AppColors.primaryRedColor,
textColor: AppColors.primaryRedColor,
iconSize: 14.w,
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.1),
labelPadding: EdgeInsetsDirectional.only(start: 8.h, end: -2.h),
),
],
),
],
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 8.h),
),
],
),
),
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.bulb_icon, width: 24.w, height: 24.h),
SizedBox(width: 8.w),
"Things to ask your doctor today".needTranslation.toText16(isBold: true),
],
),
SizedBox(height: 8.h),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.bulb_icon, width: 24.w, height: 24.h),
SizedBox(width: 8.w),
"Things to ask your doctor today".needTranslation.toText16(isBold: true),
],
),
SizedBox(height: 8.h),
// What can I do to improve my overall health?
// Are there any routine screenings I should get?
// What is this medication for?
// Are there any side effects I should know about?
// When should I come back for a follow-up?
// What can I do to improve my overall health?
// Are there any routine screenings I should get?
// What is this medication for?
// Are there any side effects I should know about?
// When should I come back for a follow-up?
"${"What can I do to improve my overall health?"}".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 4.h),
"${"Are there any routine screenings I should get?"}".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 4.h),
"${"What is this medication for?"}".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 4.h),
"${"Are there any side effects I should know about?"}".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 4.h),
"${"When should I come back for a follow-up?"}".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
"${"What can I do to improve my overall health?"}".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 4.h),
"${"Are there any routine screenings I should get?"}".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 4.h),
"${"What is this medication for?"}".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 4.h),
"${"Are there any side effects I should know about?"}".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 4.h),
"${"When should I come back for a follow-up?"}".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 16.h),
],
SizedBox(height: 16.h),
],
),
),
),
),
],
],
),
),
),
),
),
),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: true,
),
child: CustomButton(
text: "Go to homepage".needTranslation,
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
CustomPageRoute(
page: LandingNavigation(),
),
(r) => false);
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 50.h,
icon: AppAssets.homeBottom,
iconColor: AppColors.whiteColor,
iconSize: 18.h,
).paddingSymmetrical(16.h, 24.h),
)
],
),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: true,
),
child: CustomButton(
text: "Go to homepage".needTranslation,
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
CustomPageRoute(
page: LandingNavigation(),
),
(r) => false);
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 50.h,
icon: AppAssets.homeBottom,
iconColor: AppColors.whiteColor,
iconSize: 18.h,
).paddingSymmetrical(16.h, 24.h),
)
],
);
}),
);
}
Color getCardBorderColor() {
switch (currentQueueStatus) {
case 0:
return AppColors.ratingColorYellow;
case 1:
return AppColors.primaryRedColor;
case 2:
return AppColors.successColor;
}
return AppColors.textColor;
}
Color getCardButtonColor() {
switch (currentQueueStatus) {
case 0:
return AppColors.textColor.withValues(alpha: 0.08);
case 1:
return AppColors.primaryRedColor;
case 2:
return AppColors.successColor;
}
return AppColors.primaryRedColor;
}
Color getCardButtonTextColor() {
switch (currentQueueStatus) {
case 0:
return Color(0xFFA2A2A2);
case 1:
return AppColors.whiteColor;
case 2:
return AppColors.whiteColor;
}
return AppColors.primaryRedColor;
}
String getCardButtonText() {
switch (currentQueueStatus) {
case 0:
return "Please wait! you will be called for vital signs".needTranslation;
case 1:
return "Please visit Room S5 for vital signs".needTranslation;
case 2:
return "Please visit Room S5 to the Doctor".needTranslation;
}
return "";
}
}

@ -17,7 +17,6 @@ import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_vie
import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/appointment_details_page.dart';
import 'package:hmg_patient_app_new/presentation/appointments/appointment_queue_page.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/ask_doctor_request_type_select.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/eye_measurement_details_page.dart';
@ -27,7 +26,6 @@ import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.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:smooth_corner/smooth_corner.dart';
class AppointmentCard extends StatelessWidget {
final PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
@ -133,7 +131,7 @@ class AppointmentCard extends StatelessWidget {
width: 63.w,
height: 63.h,
fit: BoxFit.cover,
).circle(100).toShimmer2(isShow: isLoading),
).circle(100.r).toShimmer2(isShow: isLoading),
Transform.translate(
offset: Offset(0.0, -20.h),
child: Container(
@ -149,7 +147,11 @@ class AppointmentCard extends StatelessWidget {
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h), SizedBox(height: 2.h), "4.7".toText11(isBold: true, color: AppColors.textColor)],
children: [
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h),
SizedBox(height: 2.h),
"${patientAppointmentHistoryResponseModel.decimalDoctorRate}".toText11(isBold: true, color: AppColors.textColor),
],
),
).circle(100).toShimmer2(isShow: isLoading),
),
@ -169,10 +171,14 @@ class AppointmentCard extends StatelessWidget {
spacing: 3.h,
runSpacing: 4.h,
children: [
AppCustomChipWidget(labelText: isLoading ? 'Cardiology' : patientAppointmentHistoryResponseModel.clinicName!)
.toShimmer2(isShow: isLoading),
AppCustomChipWidget(labelText: isLoading ? 'Olaya' : patientAppointmentHistoryResponseModel.projectName!)
.toShimmer2(isShow: isLoading),
AppCustomChipWidget(
labelText: isLoading
? 'Cardiology'
: (patientAppointmentHistoryResponseModel.clinicName!.length > 15
? '${patientAppointmentHistoryResponseModel.clinicName!.substring(0, 12)}...'
: patientAppointmentHistoryResponseModel.clinicName!),
).toShimmer2(isShow: isLoading),
AppCustomChipWidget(labelText: isLoading ? 'Olaya' : patientAppointmentHistoryResponseModel.projectName!).toShimmer2(isShow: isLoading),
AppCustomChipWidget(
icon: AppAssets.appointment_calendar_icon,
labelText: isLoading
@ -292,41 +298,34 @@ class AppointmentCard extends StatelessWidget {
if (isRecent) {
return CustomButton(
text: LocaleKeys.askDoctor.tr(context: context),
onPressed: () {
Navigator.of(context).push(
CustomPageRoute(
page: AppointmentQueuePage(),
),
);
onPressed: () async {
LoaderBottomSheet.showLoader(loadingText: "Checking doctor availability...".needTranslation);
await myAppointmentsViewModel.isDoctorAvailable(
projectID: patientAppointmentHistoryResponseModel.projectID,
doctorId: patientAppointmentHistoryResponseModel.doctorID,
clinicId: patientAppointmentHistoryResponseModel.clinicID,
onSuccess: (value) async {
if (value) {
await myAppointmentsViewModel.getAskDoctorRequestTypes(onSuccess: (val) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
title: LocaleKeys.askDoctor.tr(context: context),
child: AskDoctorRequestTypeSelect(
askDoctorRequestTypeList: myAppointmentsViewModel.askDoctorRequestTypeList,
myAppointmentsViewModel: myAppointmentsViewModel,
patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
} else {
print("Doctor is not available");
}
});
},
// onPressed: () async {
// LoaderBottomSheet.showLoader(loadingText: "Checking doctor availability...".needTranslation);
// await myAppointmentsViewModel.isDoctorAvailable(
// projectID: patientAppointmentHistoryResponseModel.projectID,
// doctorId: patientAppointmentHistoryResponseModel.doctorID,
// clinicId: patientAppointmentHistoryResponseModel.clinicID,
// onSuccess: (value) async {
// if (value) {
// await myAppointmentsViewModel.getAskDoctorRequestTypes(onSuccess: (val) {
// LoaderBottomSheet.hideLoader();
// showCommonBottomSheetWithoutHeight(
// context,
// title: LocaleKeys.askDoctor.tr(context: context),
// child: AskDoctorRequestTypeSelect(
// askDoctorRequestTypeList: myAppointmentsViewModel.askDoctorRequestTypeList,
// myAppointmentsViewModel: myAppointmentsViewModel,
// patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
// ),
// callBackFunc: () {},
// isFullScreen: false,
// isCloseButtonVisible: true,
// );
// });
// } else {
// print("Doctor is not available");
// }
// });
// },
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,

@ -13,6 +13,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/appointment_queue_page.dart';
import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
@ -156,7 +157,9 @@ class AppointmentCheckinBottomSheet extends StatelessWidget {
),
(r) => false);
Navigator.of(context).push(
CustomPageRoute(page: MyAppointmentsPage()),
CustomPageRoute(
page: AppointmentQueuePage(),
),
);
}, isFullScreen: false);
},

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.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/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
@ -50,8 +51,29 @@ class AppointmentDoctorCard extends StatelessWidget {
height: 63.h,
fit: BoxFit.cover,
).circle(100.r),
SizedBox(height: 12.h),
AppCustomChipWidget(icon: AppAssets.rating_icon, iconColor: AppColors.ratingColorYellow, labelText: "Rating: ${patientAppointmentHistoryResponseModel.decimalDoctorRate}"),
Transform.translate(
offset: Offset(0.0, -20.h),
child: Container(
width: 40.w,
height: 40.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
shape: BoxShape.circle, // Makes the container circular
border: Border.all(
color: AppColors.scaffoldBgColor, // Color of the border
width: 1.5.w, // Width of the border
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h),
SizedBox(height: 2.h),
"${patientAppointmentHistoryResponseModel.decimalDoctorRate}".toText11(isBold: true, color: AppColors.textColor),
],
),
).circle(100),
),
],
),
SizedBox(width: 16.w),
@ -60,13 +82,16 @@ class AppointmentDoctorCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
patientAppointmentHistoryResponseModel.doctorNameObj!.toText16(isBold: true),
SizedBox(height: 8.h),
Wrap(
direction: Axis.horizontal,
spacing: 6.w,
runSpacing: 6.h,
children: [
AppCustomChipWidget(
labelText: patientAppointmentHistoryResponseModel.clinicName!,
labelText: (patientAppointmentHistoryResponseModel.clinicName!.length > 15
? '${patientAppointmentHistoryResponseModel.clinicName!.substring(0, 12)}...'
: patientAppointmentHistoryResponseModel.clinicName!),
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w),
),
AppCustomChipWidget(
@ -75,8 +100,7 @@ class AppointmentDoctorCard extends StatelessWidget {
),
AppCustomChipWidget(
icon: AppAssets.doctor_calendar_icon,
labelText:
"${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)}, ${DateUtil.formatDateToTimeLang(
labelText: "${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)} ${DateUtil.formatDateToTimeLang(
DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate),
false,
)}",
@ -100,8 +124,7 @@ class AppointmentDoctorCard extends StatelessWidget {
),
],
),
SizedBox(height: 16.h),
SizedBox(height: 8.h),
Visibility(
visible: renderWidgetForERDisplay == false,
child: getAppointmentActionButtons(

@ -0,0 +1,172 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/blood_donation/widgets/select_city_widget.dart';
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/loader/bottomsheet_loader.dart';
import 'package:provider/provider.dart';
class BloodDonationPage extends StatelessWidget {
BloodDonationPage({super.key});
late AppState appState;
@override
Widget build(BuildContext context) {
appState = getIt.get<AppState>();
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Consumer<BloodDonationViewModel>(builder: (context, bloodDonationVM, child) {
return Column(
children: [
Expanded(
child: CollapsingListView(
title: LocaleKeys.bloodDonation.tr(),
child: Padding(
padding: EdgeInsets.all(24.w),
child: SingleChildScrollView(
child: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
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.select_city_icon, width: 40.h, height: 40.h),
SizedBox(width: 12.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.city.tr().toText16(color: AppColors.textColor, weight: FontWeight.w500),
(appState.isArabic()
? (bloodDonationVM.selectedCity.descriptionN ?? LocaleKeys.select.tr())
: bloodDonationVM.selectedCity.description ?? LocaleKeys.select.tr(context: context))
.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
],
),
],
),
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h),
],
).onPress(() async {
LoaderBottomSheet.showLoader(loadingText: "Fetching Cities...");
await bloodDonationVM.getRegionSelectedClinics(onSuccess: (val) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(context,
title: LocaleKeys.selectCity.tr(context: context),
isDismissible: true,
child: SelectCityWidget(
bloodDonationViewModel: bloodDonationVM,
),
callBackFunc: () {});
}, onError: (err) {
LoaderBottomSheet.hideLoader();
});
}),
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.my_account_icon, width: 40.h, height: 40.h),
SizedBox(width: 12.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.gender.tr().toText16(color: AppColors.textColor, weight: FontWeight.w500),
"Male".toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
],
),
],
),
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h),
],
),
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.my_account_icon, width: 40.h, height: 40.h),
SizedBox(width: 12.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.bloodType.tr().toText16(color: AppColors.textColor, weight: FontWeight.w500),
"AB+".toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
],
),
],
),
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h),
],
),
],
),
),
),
),
),
),
),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: true,
),
child: SizedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CustomButton(
text: LocaleKeys.save.tr(),
onPressed: () {
// openDoctorScheduleCalendar();
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 50.h,
iconSize: 18.h,
).paddingSymmetrical(16.h, 24.h),
],
),
),
),
],
);
}),
);
}
}

@ -0,0 +1,60 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.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/blood_donation/models/cities_model.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class CityListItem extends StatelessWidget {
final CitiesModel cityModel;
late AppState appState;
CityListItem({super.key, required this.cityModel});
@override
Widget build(BuildContext context) {
appState = getIt.get<AppState>();
return DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8.h,
children: [hospitalName],
),
),
Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 40.h,
height: 40.h,
fit: BoxFit.contain,
),
),
],
).paddingSymmetrical(16.h, 16.h),
);
}
Widget get hospitalName => Row(
children: [
Expanded(
child: (appState.isArabic() ? cityModel.descriptionN : cityModel.description)!.toText16(color: AppColors.textColor, isBold: true),
)
],
);
}

@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart';
import 'package:hmg_patient_app_new/presentation/blood_donation/widgets/city_list_item.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class SelectCityWidget extends StatelessWidget {
SelectCityWidget({super.key, required this.bloodDonationViewModel});
BloodDonationViewModel bloodDonationViewModel;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 8.h),
SizedBox(
height: MediaQuery.sizeOf(context).height * .4,
child: ListView.separated(
itemBuilder: (_, index) {
return CityListItem(
cityModel: bloodDonationViewModel.citiesList[index],
).onPress(() {
bloodDonationViewModel.setSelectedCity(bloodDonationViewModel.citiesList[index]);
Navigator.of(context).pop();
});
},
separatorBuilder: (_, __) => SizedBox(
height: 8.h,
),
itemCount: bloodDonationViewModel.citiesList.length),
)
],
);
}
}

@ -67,40 +67,4 @@ class HospitalListItemAdvancePayment extends StatelessWidget {
)
],
);
// Widget get distanceInfo => Row(
// children: [
// Visibility(
// visible: (hospitalModel.distanceInKMs != "0"),
// child: AppCustomChipWidget(
// labelText: "${hospitalData?.distanceInKMs ?? ""} km".needTranslation,
// deleteIcon: AppAssets.location_red,
// deleteIconSize: Size(9, 12),
// backgroundColor: AppColors.secondaryLightRedColor,
// textColor: AppColors.errorColor,
// ),
// ),
// Visibility(
// visible: (hospitalData?.distanceInKMs == "0"),
// child: Row(
// children: [
// AppCustomChipWidget(
// labelText: "Distance not available".needTranslation,
// textColor: AppColors.blackColor,
// ),
// SizedBox(
// width: 8.h,
// )
// ],
// )),
// Visibility(
// visible: !isLocationEnabled,
// child: AppCustomChipWidget(
// labelText: "Location turned off".needTranslation,
// deleteIcon: AppAssets.location_unavailable,
// deleteIconSize: Size(9, 12),
// textColor: AppColors.blackColor,
// )),
// ],
// );
}

@ -42,6 +42,16 @@ class ServicesPage extends StatelessWidget {
textColor: AppColors.blackColor,
route: AppRoutes.homeHealthCarePage,
),
HmgServicesComponentModel(
3,
"Blood Donation".needTranslation,
"".needTranslation,
AppAssets.emergency_services_icon,
true,
bgColor: AppColors.bgGreenColor,
textColor: AppColors.blackColor,
route: AppRoutes.bloodDonationPage,
),
HmgServicesComponentModel(
11,
"Virtual Tour".needTranslation,

@ -266,11 +266,86 @@ class _LandingPageState extends State<LandingPage> {
builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor),
),
itemBuilder: (BuildContext context, int index) {
return (immediateLiveCareVM.patientHasPendingLiveCareRequest && index == 0)
? Column(
children: [
SizedBox(height: 12.h),
Container(
return (myAppointmentsVM.isPatientHasQueueAppointment && index == 0)
? Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
side: BorderSide(color: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus), width: 2.w),
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AppCustomChipWidget(
labelText: myAppointmentsVM.currentQueueStatus == 0 ? "In Queue".needTranslation : "Your Turn".needTranslation,
backgroundColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.20),
textColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus),
),
Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h),
],
),
SizedBox(height: 10.h),
"Hala ${appState!.getAuthenticatedUser()!.firstName}!!!".needTranslation.toText16(isBold: true),
SizedBox(height: 8.h),
"Thank you for your patience, here is your queue number."
.needTranslation
.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
SizedBox(height: 8.h),
"IMD W-A-5".needTranslation.toText28(isBold: true),
SizedBox(height: 12.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
"Serving Now: ".needTranslation.toText14(isBold: true),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
"IMD W-A-2".needTranslation.toText12(isBold: true),
SizedBox(width: 8.w),
AppCustomChipWidget(
deleteIcon: AppAssets.call_for_vitals,
labelText: "Call for vital signs".needTranslation,
iconColor: AppColors.primaryRedColor,
textColor: AppColors.primaryRedColor,
iconSize: 14.w,
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.1),
labelPadding: EdgeInsetsDirectional.only(start: 8.h, end: -2.h),
),
],
),
],
),
SizedBox(height: 8.h),
CustomButton(
text: Utils.getCardButtonText(myAppointmentsVM.currentQueueStatus),
onPressed: () {},
backgroundColor: Utils.getCardButtonColor(myAppointmentsVM.currentQueueStatus),
borderColor: Utils.getCardButtonColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.01),
textColor: Utils.getCardButtonTextColor(myAppointmentsVM.currentQueueStatus),
fontSize: 12.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
iconColor: AppColors.whiteColor,
iconSize: 18.h,
),
],
),
),
)
: (immediateLiveCareVM.patientHasPendingLiveCareRequest && index == 0)
? Column(
children: [
SizedBox(height: 12.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.r,

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/presentation/authentication/login.dart';
import 'package:hmg_patient_app_new/presentation/authentication/register.dart';
import 'package:hmg_patient_app_new/presentation/authentication/register_step2.dart';
import 'package:hmg_patient_app_new/presentation/blood_donation/blood_donation_page.dart';
import 'package:hmg_patient_app_new/presentation/comprehensive_checkup/comprehensive_checkup_page.dart';
import 'package:hmg_patient_app_new/presentation/e_referral/new_e_referral.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
@ -21,6 +22,7 @@ class AppRoutes {
static const String comprehensiveCheckupPage = '/comprehensiveCheckupPage';
static const String homeHealthCarePage = '/homeHealthCarePage';
static const String zoomCallPage = '/zoomCallPage';
static const String bloodDonationPage = '/bloodDonationPage';
static Map<String, WidgetBuilder> get routes => {
initialRoute: (context) => SplashPage(),
@ -32,6 +34,7 @@ class AppRoutes {
eReferralPage: (context) => NewReferralPage(),
comprehensiveCheckupPage: (context) => ComprehensiveCheckupPage(),
homeHealthCarePage: (context) => HhcProceduresPage(),
zoomCallPage: (context) => CallScreen()
zoomCallPage: (context) => CallScreen(),
bloodDonationPage: (context) => BloodDonationPage()
};
}

Loading…
Cancel
Save