diff --git a/assets/images/svg/search_icon.svg b/assets/images/svg/search_icon.svg new file mode 100644 index 0000000..1a64ce5 --- /dev/null +++ b/assets/images/svg/search_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index 92a7e6c..53bd522 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -179,7 +179,7 @@ class ApiClientImp implements ApiClient { // TODO : we will use all these from appState body['LanguageID'] = body['LanguageID'] ?? "2"; - body['VersionID'] = body['VersionID'] ?? "18.7"; + body['VersionID'] = body['VersionID'] ?? "50.0"; body['Channel'] = body['Channel'] ?? "3"; body['IPAdress'] = body['IPAdress'] ?? "10.20.10.20"; body['generalid'] = body['generalid'] ?? "Cs2020@2016\$2958"; diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index cba90a1..2032f56 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -60,6 +60,7 @@ class AppAssets { static const String show_icon = '$svgBasePath/show_icon.svg'; static const String recharge_icon = '$svgBasePath/recharge_icon.svg'; static const String eye_result_icon = '$svgBasePath/eye_results_icon.svg'; + static const String search_icon = '$svgBasePath/search_icon.svg'; // PNGS // static const String hmg_logo = '$pngBasePath/hmg_logo.png'; diff --git a/lib/features/lab/lab_repo.dart b/lib/features/lab/lab_repo.dart new file mode 100644 index 0000000..f651a71 --- /dev/null +++ b/lib/features/lab/lab_repo.dart @@ -0,0 +1,9 @@ +import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; +import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; +import 'package:dartz/dartz.dart'; + +abstract class AuthenticationRepo { + Future>> getPatientLabOrders({ + required String firebaseToken, + }); +} diff --git a/lib/features/lab/lab_view_model.dart b/lib/features/lab/lab_view_model.dart new file mode 100644 index 0000000..f0ebad3 --- /dev/null +++ b/lib/features/lab/lab_view_model.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; + +class LabViewModel extends ChangeNotifier { + + bool isLabOrdersLoading = false; + bool isLabResultsLoading = false; + + initLabProvider() { + isLabOrdersLoading = true; + isLabResultsLoading = true; + notifyListeners(); + } +} diff --git a/lib/main.dart b/lib/main.dart index bb4332b..1ea5d84 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,6 +8,7 @@ import 'package:flutter/services.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/providers/bottom_navigation_provider.dart'; +import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/routes/app_routes.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; @@ -54,6 +55,9 @@ void main() async { ChangeNotifierProvider( create: (_) => BottomNavigationProvider(), ), + ChangeNotifierProvider( + create: (_) => LabViewModel(), + ), ChangeNotifierProvider( create: (_) => AuthenticationViewModel( authenticationRepo: getIt(), diff --git a/lib/presentation/home/data/landing_page_data.dart b/lib/presentation/home/data/landing_page_data.dart index af43b9f..8474422 100644 --- a/lib/presentation/home/data/landing_page_data.dart +++ b/lib/presentation/home/data/landing_page_data.dart @@ -8,6 +8,7 @@ import 'package:hmg_patient_app_new/theme/colors.dart'; class LandingPageData { static List getNotLoggedInServiceCardsList = [ ServiceCardData( + serviceName: "emergency", icon: AppAssets.emergency_services_icon, title: "Emergency", subtitle: "Services", @@ -17,6 +18,7 @@ class LandingPageData { isBold: true, ), ServiceCardData( + serviceName: "indoor_navigation", icon: AppAssets.indoor_nav_icon, title: "Indoor", subtitle: "Navigation", @@ -26,6 +28,7 @@ class LandingPageData { isBold: false, ), ServiceCardData( + serviceName: "search_doctor", icon: AppAssets.search_doctor_icon, title: "Search", subtitle: "Doctor", @@ -35,6 +38,7 @@ class LandingPageData { isBold: false, ), ServiceCardData( + serviceName: "health_calculators", icon: AppAssets.health_calculators_icon, title: "Health", subtitle: "Calculators", @@ -44,6 +48,7 @@ class LandingPageData { isBold: false, ), ServiceCardData( + serviceName: "health_converters", icon: AppAssets.health_calculators_icon, title: "Health", subtitle: "Converters", @@ -53,6 +58,7 @@ class LandingPageData { isBold: false, ), ServiceCardData( + serviceName: "parking_guide", icon: AppAssets.health_calculators_icon, title: "Parking", subtitle: "Guide", @@ -65,6 +71,7 @@ class LandingPageData { static List getLoggedInServiceCardsList = [ ServiceCardData( + serviceName: "emergency", icon: AppAssets.emergency_services_icon, title: "Emergency", subtitle: "Services", @@ -74,6 +81,7 @@ class LandingPageData { isBold: true, ), ServiceCardData( + serviceName: "lab_results", icon: AppAssets.lab_result_icon, title: "My Lab", subtitle: "Results", @@ -83,6 +91,17 @@ class LandingPageData { isBold: false, ), ServiceCardData( + serviceName: "radiology_results", + icon: AppAssets.lab_result_icon, + title: "My Radiology", + subtitle: "Results", + backgroundColor: AppColors.whiteColor, + iconColor: AppColors.blackColor, + textColor: AppColors.blackColor, + isBold: false, + ), + ServiceCardData( + serviceName: "prescriptions", icon: AppAssets.my_prescription_icon, title: "My", subtitle: "Prescriptions", @@ -92,6 +111,7 @@ class LandingPageData { isBold: false, ), ServiceCardData( + serviceName: "insurance_update", icon: AppAssets.insurance_update_icon, title: "Insurance", subtitle: "Update", @@ -101,6 +121,7 @@ class LandingPageData { isBold: false, ), ServiceCardData( + serviceName: "my_doctors", icon: AppAssets.insurance_update_icon, title: "My", subtitle: "Doctors", @@ -110,6 +131,7 @@ class LandingPageData { isBold: false, ), ServiceCardData( + serviceName: "sick_leaves", icon: AppAssets.insurance_update_icon, title: "My Sick", subtitle: "Leaves", diff --git a/lib/presentation/home/data/service_card_data.dart b/lib/presentation/home/data/service_card_data.dart index 856a15e..49e7e3d 100644 --- a/lib/presentation/home/data/service_card_data.dart +++ b/lib/presentation/home/data/service_card_data.dart @@ -3,6 +3,7 @@ import 'dart:ui'; import 'package:hmg_patient_app_new/theme/colors.dart'; class ServiceCardData { + final String serviceName; final String icon; final String title; final String subtitle; @@ -13,6 +14,7 @@ class ServiceCardData { final String largeCardIcon; ServiceCardData({ + this.serviceName = "", this.icon = "", this.title = "", this.subtitle = "", diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 8421856..a1707fa 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -155,6 +155,7 @@ class _LandingPageState extends State { horizontalOffset: 100.0, child: FadeInAnimation( child: SmallServiceCard( + serviceName: LandingPageData.getLoggedInServiceCardsList[index].serviceName, icon: LandingPageData.getLoggedInServiceCardsList[index].icon, title: LandingPageData.getLoggedInServiceCardsList[index].title, subtitle: LandingPageData.getLoggedInServiceCardsList[index].subtitle, diff --git a/lib/presentation/home/widgets/small_service_card.dart b/lib/presentation/home/widgets/small_service_card.dart index a138db6..0983a06 100644 --- a/lib/presentation/home/widgets/small_service_card.dart +++ b/lib/presentation/home/widgets/small_service_card.dart @@ -2,11 +2,14 @@ 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/presentation/lab/lab_orders_page.dart'; +import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import '../../../core/utils/utils.dart'; import '../../../theme/colors.dart'; class SmallServiceCard extends StatelessWidget { + final String serviceName; final String icon; final String title; final String subtitle; @@ -18,6 +21,7 @@ class SmallServiceCard extends StatelessWidget { SmallServiceCard({ super.key, this.icon = "", + this.serviceName = "", this.title = "", this.subtitle = "", this.backgroundColor = AppColors.whiteColor, @@ -48,6 +52,25 @@ class SmallServiceCard extends StatelessWidget { ), ), ), - ); + ).onPress(() { + switch (serviceName) { + case "lab_results": + Navigator.of(context).push( + FadePage( + page: LabOrdersPage(), + ), + ); + break; + case "radiology_results": + break; + case "prescriptions": + break; + case "insurance_update": + break; + default: + // Handle unknown service + break; + } + }); } } diff --git a/lib/presentation/lab/lab_orders_page.dart b/lib/presentation/lab/lab_orders_page.dart new file mode 100644 index 0000000..bc7ff61 --- /dev/null +++ b/lib/presentation/lab/lab_orders_page.dart @@ -0,0 +1,173 @@ +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/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/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/features/lab/lab_view_model.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/shimmer/movies_shimmer_widget.dart'; +import 'package:provider/provider.dart'; + +class LabOrdersPage extends StatefulWidget { + const LabOrdersPage({super.key}); + + @override + State createState() => _LabOrdersPageState(); +} + +class _LabOrdersPageState extends State { + late LabViewModel labProvider; + + int? expandedIndex; + + // Sample data for demonstration + final List labOrders = [ + 'Blood Test', + 'Urine Test', + 'X-Ray', + 'MRI', + ]; + + @override + void initState() { + scheduleMicrotask(() { + labProvider.initLabProvider(); + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + labProvider = Provider.of(context); + return Scaffold( + backgroundColor: AppColors.bgScaffoldColor, + appBar: AppBar( + title: const Text('Lab Results'), + backgroundColor: AppColors.bgScaffoldColor, + ), + body: Padding( + padding: EdgeInsets.all(24.h), + child: SingleChildScrollView( + child: Consumer( + builder: (context, model, child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + LocaleKeys.labResults.tr(context: context).toText24(isBold: true), + Utils.buildSvgWithAssets(icon: AppAssets.search_icon), + ], + ), + SizedBox(height: 16.h), + // Build Tab Bar + SizedBox(height: 16.h), + // Expandable list + ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: model.isLabOrdersLoading ? 5 : labOrders.length, + itemBuilder: (context, index) { + final isExpanded = expandedIndex == index; + return model.isLabOrdersLoading + ? const MoviesShimmerWidget() + : AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 500), + child: SlideAnimation( + verticalOffset: 100.0, + child: FadeInAnimation( + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + margin: EdgeInsets.symmetric(vertical: 8.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.h, + ), + child: InkWell( + onTap: () { + setState(() { + expandedIndex = isExpanded ? null : index; + }); + }, + child: Column( + children: [ + Padding( + padding: EdgeInsets.all(16.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomButton( + text: LocaleKeys.pending.tr(context: context), + onPressed: () {}, + backgroundColor: getLabOrderStatusColor(44).withOpacity(0.15), + borderColor: getLabOrderStatusColor(44).withOpacity(0.01), + textColor: getLabOrderStatusColor(44), + fontSize: 10, + fontWeight: FontWeight.normal, + borderRadius: 8, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + Icon(isExpanded ? Icons.expand_less : Icons.expand_more), + ], + ), + SizedBox(height: 8.h), + Text(labOrders[index], style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + ], + ), + ), + AnimatedCrossFade( + firstChild: SizedBox.shrink(), + secondChild: Padding( + padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h), + child: Text('Details for ${labOrders[index]}'), + ), + crossFadeState: isExpanded ? CrossFadeState.showSecond : CrossFadeState.showFirst, + duration: Duration(milliseconds: 300), + ), + ], + ), + ), + ), + ), + ), + ); + }, + ), + ], + ); + }, + ), + ), + ), + ); + } + + Color getLabOrderStatusColor(num status) { + switch (status) { + case 44: + return AppColors.warningColorYellow; + case 45: + return AppColors.warningColorYellow; + case 16: + return AppColors.successColor; + case 17: + return AppColors.successColor; + default: + return AppColors.greyColor; + } + } +} diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index 6635ef5..7fa4fe9 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -87,9 +87,6 @@ class MedicalFilePage extends StatelessWidget { ), SizedBox(width: 4.h), CustomButton( - icon: AppAssets.checkmark_icon, - iconColor: AppColors.successColor, - iconSize: 13.h, text: LocaleKeys.verified.tr(context: context), onPressed: () {}, backgroundColor: AppColors.greyColor, diff --git a/lib/theme/colors.dart b/lib/theme/colors.dart index a6b3362..8b388f1 100644 --- a/lib/theme/colors.dart +++ b/lib/theme/colors.dart @@ -31,6 +31,7 @@ class AppColors { static const Color textColor = Color(0xFF2E3039); static const Color borderOnlyColor = Color(0xFF2E3039); static const Color dividerColor = Color(0xFFD2D2D2); + static const Color warningColorYellow = Color(0xFFF4A308); //Chips static const Color successColor = Color(0xff18C273);