diff --git a/assets/images/svg/alarm_clock_icon.svg b/assets/images/svg/alarm_clock_icon.svg
new file mode 100644
index 0000000..50b64bd
--- /dev/null
+++ b/assets/images/svg/alarm_clock_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index 02160a2..23945d0 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -99,6 +99,7 @@ class AppAssets {
static const String notes_icon = '$svgBasePath/notes_icon.svg';
static const String forward_chevron_icon = '$svgBasePath/forward_chevron_icon.svg';
static const String logout = '$svgBasePath/logout.svg';
+ static const String alarm_clock_icon = '$svgBasePath/alarm_clock_icon.svg';
//bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg';
diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart
index 804f9f9..a5528cf 100644
--- a/lib/features/my_appointments/my_appointments_repo.dart
+++ b/lib/features/my_appointments/my_appointments_repo.dart
@@ -32,6 +32,8 @@ abstract class MyAppointmentsRepo {
Future>> sendCheckInNfcRequest(
{required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, required String scannedCode, required int checkInType});
+
+ Future>>> getPatientAppointmentsForTimeLine();
}
class MyAppointmentsRepoImp implements MyAppointmentsRepo {
@@ -395,4 +397,51 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future>>> getPatientAppointmentsForTimeLine() async {
+ Map mapDevice = {
+ "isDentalAllowedBackend": false,
+ "PatientTypeID": 1,
+ "IsComingFromCOC": false,
+ "PatientType": 1,
+ "IsForTimeLine": true,
+ };
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_PATIENT_APPOINTMENT_HISTORY,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['AppoimentAllHistoryResultList'];
+ // if (list == null || list.isEmpty) {
+ // throw Exception("Appointments list is empty");
+ // }
+
+ final appointmentsList = list.map((item) => PatientAppointmentHistoryResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: appointmentsList,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
}
diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart
index 4a921da..d3121af 100644
--- a/lib/features/my_appointments/my_appointments_view_model.dart
+++ b/lib/features/my_appointments/my_appointments_view_model.dart
@@ -12,12 +12,15 @@ class MyAppointmentsViewModel extends ChangeNotifier {
bool isMyAppointmentsLoading = false;
bool isAppointmentPatientShareLoading = false;
+ bool isTimeLineAppointmentsLoading = false;
List patientAppointmentsHistoryList = [];
List patientUpcomingAppointmentsHistoryList = [];
List patientArrivedAppointmentsHistoryList = [];
+ List patientTimelineAppointmentsList = [];
+
PatientAppointmentShareResponseModel? patientAppointmentShareResponseModel;
MyAppointmentsViewModel({required this.myAppointmentsRepo, required this.errorHandlerService});
@@ -31,8 +34,10 @@ class MyAppointmentsViewModel extends ChangeNotifier {
patientAppointmentsHistoryList.clear();
patientUpcomingAppointmentsHistoryList.clear();
patientArrivedAppointmentsHistoryList.clear();
+ patientTimelineAppointmentsList.clear();
isMyAppointmentsLoading = true;
isAppointmentPatientShareLoading = true;
+ isTimeLineAppointmentsLoading = true;
notifyListeners();
}
@@ -46,6 +51,11 @@ class MyAppointmentsViewModel extends ChangeNotifier {
notifyListeners();
}
+ setIsPatientTimeLineAppointmentLoading(bool val) {
+ isTimeLineAppointmentsLoading = val;
+ notifyListeners();
+ }
+
setAppointmentReminder(bool value, PatientAppointmentHistoryResponseModel item) {
int index = patientAppointmentsHistoryList.indexOf(item);
if (index != -1) {
diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart
index 18b778a..ee2a042 100644
--- a/lib/presentation/appointments/appointment_details_page.dart
+++ b/lib/presentation/appointments/appointment_details_page.dart
@@ -57,8 +57,8 @@ class _AppointmentDetailsPageState extends State {
@override
Widget build(BuildContext context) {
- myAppointmentsViewModel = Provider.of(context);
- prescriptionsViewModel = Provider.of(context);
+ myAppointmentsViewModel = Provider.of(context, listen: false);
+ prescriptionsViewModel = Provider.of(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
diff --git a/lib/presentation/appointments/my_appointments_page.dart b/lib/presentation/appointments/my_appointments_page.dart
index 333c8b1..5a3205d 100644
--- a/lib/presentation/appointments/my_appointments_page.dart
+++ b/lib/presentation/appointments/my_appointments_page.dart
@@ -35,7 +35,7 @@ class _MyAppointmentsPageState extends State {
@override
Widget build(BuildContext context) {
- myAppointmentsViewModel = Provider.of(context);
+ myAppointmentsViewModel = Provider.of(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView(
diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart
index d148b83..b63b404 100644
--- a/lib/presentation/home/landing_page.dart
+++ b/lib/presentation/home/landing_page.dart
@@ -13,6 +13,8 @@ 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/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/models/habib_wallet_view_model.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
+import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/authentication/quick_login.dart';
import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart';
@@ -43,6 +45,8 @@ class _LandingPageState extends State {
late final HabibWalletViewModel habibWalletVM;
late AppState appState;
+ late MyAppointmentsViewModel myAppointmentsViewModel;
+ late PrescriptionsViewModel prescriptionsViewModel;
@override
void initState() {
@@ -51,13 +55,16 @@ class _LandingPageState extends State {
authVM.savePushTokenToAppState();
if (mounted) {
authVM.checkLastLoginStatus(() {
- showQuickLogin(context);
+ showQuickLogin(context);
});
}
scheduleMicrotask(() {
if (appState.isAuthenticated) {
habibWalletVM.initHabibWalletProvider();
habibWalletVM.getPatientBalanceAmount();
+ myAppointmentsViewModel.initAppointmentsViewModel();
+ myAppointmentsViewModel.getPatientAppointments(true, false);
+ prescriptionsViewModel.initPrescriptionsViewModel();
}
});
super.initState();
@@ -67,7 +74,8 @@ class _LandingPageState extends State {
Widget build(BuildContext context) {
appState = getIt.get();
NavigationService navigationService = getIt.get();
-
+ myAppointmentsViewModel = Provider.of(context, listen: false);
+ prescriptionsViewModel = Provider.of(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: SingleChildScrollView(
@@ -338,29 +346,22 @@ class _LandingPageState extends State {
void showQuickLogin(BuildContext context) {
showCommonBottomSheetWithoutHeight(
-
context,
title: "",
isCloseButtonVisible: false,
- child:
- StatefulBuilder(
- builder: (context, setState) {
- return QuickLogin(
- isDone: isDone,
- onPressed: () {
- // sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true);
- authVM.loginWithFingerPrintFace((){
-
- isDone = true;
- setState(() {
-
+ child: StatefulBuilder(builder: (context, setState) {
+ return QuickLogin(
+ isDone: isDone,
+ onPressed: () {
+ // sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true);
+ authVM.loginWithFingerPrintFace(() {
+ isDone = true;
+ setState(() {});
});
- });
-
- },
- );
+ },
+ );
}),
- // height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3,
+ // height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3,
isFullScreen: false,
callBackFunc: () {
isDone = true;
diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart
index 47951c4..4860bb1 100644
--- a/lib/presentation/medical_file/medical_file_page.dart
+++ b/lib/presentation/medical_file/medical_file_page.dart
@@ -2,18 +2,25 @@ import 'dart:async';
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/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
+import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
+import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
+import 'package:hmg_patient_app_new/presentation/medical_file/widgets/lab_rad_card.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/medical_file_card.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@@ -23,6 +30,8 @@ import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart';
+import 'widgets/medical_file_appointment_card.dart';
+
class MedicalFilePage extends StatefulWidget {
MedicalFilePage({super.key});
@@ -33,6 +42,7 @@ class MedicalFilePage extends StatefulWidget {
class _MedicalFilePageState extends State {
late InsuranceViewModel insuranceViewModel;
late AppState appState;
+ late MyAppointmentsViewModel myAppointmentsViewModel;
int currentIndex = 0;
@@ -46,174 +56,174 @@ class _MedicalFilePageState extends State {
@override
Widget build(BuildContext context) {
- insuranceViewModel = Provider.of(context);
+ insuranceViewModel = Provider.of(context, listen: false);
+ myAppointmentsViewModel = Provider.of(context, listen: false);
appState = getIt.get();
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
- appBar: AppBar(
- title: const Text('Appointments'),
- backgroundColor: AppColors.bgScaffoldColor,
- ),
body: SingleChildScrollView(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- LocaleKeys.medicalFile.tr(context: context).toText22(isBold: true).paddingSymmetrical(24.h, 0.0),
- SizedBox(height: 16.h),
- TextInputWidget(
- labelText: LocaleKeys.search.tr(context: context),
- hintText: "Type any record",
- controller: TextEditingController(),
- keyboardType: TextInputType.number,
- isEnable: true,
- prefix: null,
- autoFocus: false,
- isBorderAllowed: false,
- isAllowLeadingIcon: true,
- padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h),
- leadingIcon: AppAssets.student_card,
- ).paddingSymmetrical(24.h, 0.0),
- SizedBox(height: 16.h),
- Container(
- width: double.infinity,
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 24,
- ),
- child: Padding(
- padding: EdgeInsets.all(16.h),
- child: Column(
+ child: Padding(
+ padding: EdgeInsets.only(top: 80.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ LocaleKeys.medicalFile.tr(context: context).toText22(isBold: true).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 16.h),
+ TextInputWidget(
+ labelText: LocaleKeys.search.tr(context: context),
+ hintText: "Type any record",
+ controller: TextEditingController(),
+ keyboardType: TextInputType.number,
+ isEnable: true,
+ prefix: null,
+ autoFocus: false,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h),
+ leadingIcon: AppAssets.student_card,
+ ).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 16.h),
+ Container(
+ width: double.infinity,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.asset(
+ appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg,
+ width: 56.h,
+ height: 56.h,
+ ),
+ SizedBox(width: 8.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText18(isBold: true),
+ SizedBox(height: 4.h),
+ Row(
+ children: [
+ CustomButton(
+ icon: AppAssets.file_icon,
+ iconColor: AppColors.blackColor,
+ iconSize: 12.h,
+ text: "File no: ${appState.getAuthenticatedUser()!.patientId}",
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.normal,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ SizedBox(width: 4.h),
+ CustomButton(
+ text: LocaleKeys.verified.tr(context: context),
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.normal,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ ],
+ ),
+ ],
+ )
+ ],
+ ),
+ SizedBox(height: 16.h),
+ Divider(color: AppColors.dividerColor, height: 1.h),
+ SizedBox(height: 16.h),
+ Row(
+ children: [
+ CustomButton(
+ text: "${appState.getAuthenticatedUser()!.age} Years Old",
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.normal,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ SizedBox(width: 4.h),
+ CustomButton(
+ icon: AppAssets.blood_icon,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 13.h,
+ text: "Blood: ${appState.getUserBloodGroup}",
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.normal,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ // SizedBox(width: 4.h),
+ // CustomButton(
+ // icon: AppAssets.insurance_active_icon,
+ // iconColor: AppColors.successColor,
+ // iconSize: 13.h,
+ // text: "Insurance Active",
+ // onPressed: () {},
+ // backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
+ // borderColor: AppColors.bgGreenColor.withOpacity(0.0),
+ // textColor: AppColors.blackColor,
+ // fontSize: 10,
+ // fontWeight: FontWeight.normal,
+ // borderRadius: 12,
+ // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ // height: 30.h,
+ // ),
+ ],
+ ),
+ SizedBox(height: 8.h),
+ ],
+ ),
+ ),
+ ).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 16.h),
+ Consumer(builder: (context, medicalFileVM, child) {
+ return Column(
children: [
- Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Image.asset(
- appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg,
- width: 56.h,
- height: 56.h,
- ),
- SizedBox(width: 8.h),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText18(isBold: true),
- SizedBox(height: 4.h),
- Row(
- children: [
- CustomButton(
- icon: AppAssets.file_icon,
- iconColor: AppColors.blackColor,
- iconSize: 12.h,
- text: "File no: ${appState.getAuthenticatedUser()!.patientId}",
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 10,
- fontWeight: FontWeight.normal,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- SizedBox(width: 4.h),
- CustomButton(
- text: LocaleKeys.verified.tr(context: context),
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 10,
- fontWeight: FontWeight.normal,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- ],
- )
+ CustomTabBar(
+ activeTextColor: Color(0xffED1C2B),
+ activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
+ tabs: [
+ CustomTabBarModel(AppAssets.myFilesBottom, LocaleKeys.general.tr(context: context).needTranslation),
+ CustomTabBarModel(AppAssets.insurance, LocaleKeys.insurance.tr(context: context)),
+ CustomTabBarModel(AppAssets.requests, LocaleKeys.request.tr(context: context).needTranslation),
+ CustomTabBarModel(AppAssets.more, "More".needTranslation),
],
- ),
- SizedBox(height: 16.h),
- Divider(color: AppColors.dividerColor, height: 1.h),
- SizedBox(height: 16.h),
- Row(
- children: [
- CustomButton(
- text: "${appState.getAuthenticatedUser()!.age} Years Old",
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 10,
- fontWeight: FontWeight.normal,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- SizedBox(width: 4.h),
- CustomButton(
- icon: AppAssets.blood_icon,
- iconColor: AppColors.primaryRedColor,
- iconSize: 13.h,
- text: "Blood: ${appState.getUserBloodGroup}",
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 10,
- fontWeight: FontWeight.normal,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- // SizedBox(width: 4.h),
- // CustomButton(
- // icon: AppAssets.insurance_active_icon,
- // iconColor: AppColors.successColor,
- // iconSize: 13.h,
- // text: "Insurance Active",
- // onPressed: () {},
- // backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
- // borderColor: AppColors.bgGreenColor.withOpacity(0.0),
- // textColor: AppColors.blackColor,
- // fontSize: 10,
- // fontWeight: FontWeight.normal,
- // borderRadius: 12,
- // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- // height: 30.h,
- // ),
- ],
- ),
- SizedBox(height: 8.h),
+ onTabChange: (index) {
+ print(index);
+ medicalFileVM.onTabChanged(index);
+ },
+ ).paddingSymmetrical(24.h, 0.0),
+ SizedBox(height: 24.h),
+ getSelectedTabData(medicalFileVM.selectedTabIndex),
],
- ),
- ),
- ).paddingSymmetrical(24.h, 0.0),
- SizedBox(height: 16.h),
- Consumer(builder: (context, medicalFileVM, child) {
- return Column(
- children: [
- CustomTabBar(
- activeTextColor: Color(0xffED1C2B),
- activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
- tabs: [
- CustomTabBarModel(AppAssets.myFilesBottom, LocaleKeys.general.tr(context: context).needTranslation),
- CustomTabBarModel(AppAssets.insurance, LocaleKeys.insurance.tr(context: context)),
- CustomTabBarModel(AppAssets.requests, LocaleKeys.request.tr(context: context).needTranslation),
- CustomTabBarModel(AppAssets.more, "More".needTranslation),
- ],
- onTabChange: (index) {
- print(index);
- medicalFileVM.onTabChanged(index);
- },
- ).paddingSymmetrical(24.h, 0.0),
- SizedBox(height: 24.h),
- getSelectedTabData(medicalFileVM.selectedTabIndex),
- ],
- );
- }),
- ],
+ );
+ }),
+ ],
+ ),
),
),
);
@@ -224,6 +234,7 @@ class _MedicalFilePageState extends State {
case 0:
//General Tab Data
return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -244,6 +255,179 @@ class _MedicalFilePageState extends State {
),
);
}),
+ Consumer(builder: (context, myAppointmentsVM, child) {
+ return SizedBox(
+ height: 200.h,
+ child: ListView.separated(
+ scrollDirection: Axis.horizontal,
+ padding: EdgeInsets.only(top: 16.h, left: 24.h, right: 24.h, bottom: 0.h),
+ shrinkWrap: true,
+ itemCount: myAppointmentsVM.isMyAppointmentsLoading ? 5 : myAppointmentsVM.patientAppointmentsHistoryList.length,
+ itemBuilder: (context, index) {
+ return AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ horizontalOffset: 100.0,
+ child: FadeInAnimation(
+ child: AnimatedContainer(
+ duration: Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ child: myAppointmentsVM.isMyAppointmentsLoading
+ ? MedicalFileAppointmentCard(
+ patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(),
+ myAppointmentsViewModel: myAppointmentsVM,
+ )
+ : MedicalFileAppointmentCard(
+ patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
+ myAppointmentsViewModel: myAppointmentsViewModel,
+ ),
+ ),
+ ),
+ ),
+ );
+ },
+ separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 12.h),
+ ),
+ );
+ }),
+ SizedBox(height: 24.h),
+ "Lab & Radiology".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 16.h),
+ Row(
+ children: [
+ Expanded(
+ child: LabRadCard(
+ icon: AppAssets.lab_result_icon,
+ labelText: LocaleKeys.labResults.tr(context: context),
+ labOrderTests: ["Complete blood count", "Creatinine", "Blood Sugar"],
+ ),
+ ),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: LabRadCard(
+ icon: AppAssets.radiology_icon,
+ labelText: LocaleKeys.radiology.tr(context: context),
+ labOrderTests: ["Chest X-ray", "Abdominal Ultrasound", "Dental X-ray"],
+ ),
+ ),
+ ],
+ ).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 24.h),
+ "Active Medications & Prescriptions".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 16.h),
+ Consumer(builder: (context, prescriptionVM, child) {
+ return prescriptionVM.isPrescriptionsOrdersLoading
+ ? const MoviesShimmerWidget()
+ : Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: Colors.white,
+ borderRadius: 20.h,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ children: [
+ ListView.separated(
+ itemCount: prescriptionVM.patientPrescriptionOrders.length,
+ shrinkWrap: true,
+ padding: const EdgeInsets.only(left: 0, right: 8),
+ physics: NeverScrollableScrollPhysics(),
+ itemBuilder: (context, index) {
+ return AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: Row(
+ children: [
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.prescription_item_icon,
+ width: 40.h,
+ height: 40.h,
+ ),
+ SizedBox(width: 8.h),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Column(
+ children: [
+ // SizedBox(width: 150.h, child: prescriptionVM.prescriptionDetailsList[index].itemDescription!.toText12(isBold: true, maxLine: 1)),
+ // SizedBox(
+ // width: 150.h,
+ // child:
+ // "Prescribed By: ${widget.patientAppointmentHistoryResponseModel.doctorTitle} ${widget.patientAppointmentHistoryResponseModel.doctorNameObj}"
+ // .needTranslation
+ // .toText10(weight: FontWeight.w500, color: AppColors.greyTextColor, letterSpacing: -0.4),
+ // ),
+ ],
+ ),
+ SizedBox(width: 68.h),
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ iconColor: AppColors.blackColor,
+ width: 18.h,
+ height: 13.h,
+ fit: BoxFit.contain,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ },
+ separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
+ ).onPress(() {
+ prescriptionVM.setPrescriptionsDetailsLoading();
+ // Navigator.of(context).push(
+ // FadePage(
+ // page: PrescriptionDetailPage(prescriptionsResponseModel: getPrescriptionRequestModel()),
+ // ),
+ // );
+ }),
+ SizedBox(height: 16.h),
+ const Divider(color: AppColors.dividerColor),
+ SizedBox(height: 16.h),
+ Row(
+ children: [
+ Expanded(
+ child: CustomButton(
+ text: "All Prescriptions".needTranslation,
+ onPressed: () {
+ // Navigator.of(context)
+ // .push(
+ // FadePage(
+ // page: PrescriptionsListPage(),
+ // ),
+ // )
+ // .then((val) {
+ // prescriptionsViewModel.setPrescriptionsDetailsLoading();
+ // prescriptionsViewModel.getPrescriptionDetails(getPrescriptionRequestModel());
+ // });
+ },
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ height: 40.h,
+ icon: AppAssets.requests,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 16.h,
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ).paddingSymmetrical(24.h, 0.h);
+ }),
+ SizedBox(height: 24.h),
],
);
case 1:
diff --git a/lib/presentation/medical_file/widgets/lab_rad_card.dart b/lib/presentation/medical_file/widgets/lab_rad_card.dart
new file mode 100644
index 0000000..aa53b2f
--- /dev/null
+++ b/lib/presentation/medical_file/widgets/lab_rad_card.dart
@@ -0,0 +1,65 @@
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/app_assets.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/theme/colors.dart';
+
+class LabRadCard extends StatelessWidget {
+ LabRadCard({super.key, required this.icon, required this.labelText, required this.labOrderTests});
+
+ String icon;
+ String labelText;
+ List labOrderTests = [];
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: false),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(
+ icon: icon,
+ width: 40.h,
+ height: 40.h,
+ fit: BoxFit.contain,
+ ).toShimmer2(isShow: false, radius: 12.h),
+ SizedBox(width: 8.h),
+ labelText.toText14(isBold: true).toShimmer2(isShow: false, radius: 6.h, height: 32.h),
+ ],
+ ),
+ SizedBox(height: 16.h),
+ ListView.separated(
+ scrollDirection: Axis.vertical,
+ padding: EdgeInsets.zero,
+ physics: NeverScrollableScrollPhysics(),
+ shrinkWrap: true,
+ itemBuilder: (cxt, index) {
+ return labOrderTests[index].toText12(isBold: true, maxLine: 1).toShimmer2(isShow: false, radius: 6.h, height: 24.h, width: 120.h);
+ },
+ separatorBuilder: (cxt, index) => SizedBox(height: 8.h),
+ itemCount: labOrderTests.length,
+ ),
+ SizedBox(height: 16.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ SizedBox.shrink(),
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ width: 15.h,
+ height: 15.h,
+ fit: BoxFit.contain,
+ iconColor: AppColors.textColor
+ ).toShimmer2(isShow: false, radius: 12.h),
+ ],
+ )
+ ],
+ ).paddingAll(16.h),
+ );
+ }
+}
diff --git a/lib/presentation/medical_file/widgets/medical_file_appointment_card.dart b/lib/presentation/medical_file/widgets/medical_file_appointment_card.dart
new file mode 100644
index 0000000..48cc328
--- /dev/null
+++ b/lib/presentation/medical_file/widgets/medical_file_appointment_card.dart
@@ -0,0 +1,181 @@
+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/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';
+import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
+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/theme/colors.dart';
+import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
+import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
+
+class MedicalFileAppointmentCard extends StatelessWidget {
+ MedicalFileAppointmentCard({super.key, required this.patientAppointmentHistoryResponseModel, required this.myAppointmentsViewModel});
+
+ PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
+ MyAppointmentsViewModel myAppointmentsViewModel;
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ CustomButton(
+ text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false),
+ onPressed: () {},
+ backgroundColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.greyColor : AppColors.secondaryLightRedColor,
+ borderColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.greyLightColor : AppColors.secondaryLightRedColor,
+ textColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
+ fontSize: 12,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppAssets.appointment_calendar_icon : AppAssets.alarm_clock_icon,
+ iconColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
+ iconSize: 16.h,
+ ).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
+ width: 200.h,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ Image.network(
+ patientAppointmentHistoryResponseModel.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
+ width: 25.h,
+ height: 27.h,
+ fit: BoxFit.fill,
+ ).circle(100).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
+ SizedBox(width: 8.h),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ (patientAppointmentHistoryResponseModel.doctorNameObj ?? "").toText14(isBold: true, maxlines: 1).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
+ (patientAppointmentHistoryResponseModel.clinicName ?? "")
+ .toText12(maxLine: 1, fontWeight: FontWeight.w500, color: AppColors.greyTextColor)
+ .toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
+ ],
+ ),
+ ),
+ ],
+ ),
+ SizedBox(height: 12.h),
+ Row(
+ children: [
+ myAppointmentsViewModel.isMyAppointmentsLoading
+ ? Container().toShimmer2(isShow: true, height: 40.h, width: 100.h, radius: 12.h)
+ : Expanded(
+ flex: 6,
+ child: AppointmentType.isArrived(patientAppointmentHistoryResponseModel)
+ ? getArrivedAppointmentButton(context).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading)
+ : CustomButton(
+ text: AppointmentType.getNextActionText(patientAppointmentHistoryResponseModel.nextAction),
+ onPressed: () {
+ Navigator.of(context)
+ .push(FadePage(
+ page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel),
+ ))
+ .then((val) {
+ // widget.myAppointmentsViewModel.initAppointmentsViewModel();
+ // widget.myAppointmentsViewModel.getPatientAppointments(true, false);
+ });
+ },
+ backgroundColor: AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.15),
+ borderColor: AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
+ textColor: AppointmentType.getNextActionTextColor(patientAppointmentHistoryResponseModel.nextAction),
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppointmentType.getNextActionIcon(patientAppointmentHistoryResponseModel.nextAction),
+ iconColor: AppointmentType.getNextActionTextColor(patientAppointmentHistoryResponseModel.nextAction),
+ iconSize: 14.h,
+ ).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
+ ),
+ SizedBox(width: 8.h),
+ Expanded(
+ flex: 2,
+ child: Container(
+ height: 40.h,
+ width: 40.h,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.textColor,
+ borderRadius: 10.h,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(10.h),
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ width: 10.h,
+ height: 10.h,
+ fit: BoxFit.contain,
+ ),
+ ),
+ ).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading).onPress(() {
+ Navigator.of(context)
+ .push(
+ FadePage(
+ page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel),
+ ),
+ )
+ .then((val) {
+ // widget.myAppointmentsViewModel.initAppointmentsViewModel();
+ // widget.myAppointmentsViewModel.getPatientAppointments(true, false);
+ });
+ }),
+ ),
+ ],
+ ),
+ ],
+ ).paddingAll(16.h),
+ ),
+ ],
+ );
+ }
+
+ Widget getArrivedAppointmentButton(BuildContext context) {
+ return DateTime.now().difference(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate)).inDays <= 15
+ ? CustomButton(
+ text: LocaleKeys.askDoctor.tr(context: context),
+ onPressed: () {},
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppAssets.ask_doctor_icon,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 16.h,
+ )
+ : CustomButton(
+ text: "Rebook".needTranslation,
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppAssets.rebook_appointment_icon,
+ iconColor: AppColors.blackColor,
+ iconSize: 16.h,
+ );
+ }
+}