Merge branch 'refs/heads/master' into dev_sikander
| After Width: | Height: | Size: 137 KiB | 
| After Width: | Height: | Size: 127 KiB | 
| Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 130 KiB | 
| Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 161 KiB | 
| @ -0,0 +1,3 @@ | |||||||
|  | <svg width="14" height="15" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||||
|  | <path fill-rule="evenodd" clip-rule="evenodd" d="M11.5525 2.46209C9.79631 1.38751 8.20843 1.81413 7.24747 2.53374L7.24696 2.53412L6.99967 2.71856L6.75249 2.53412C5.79154 1.81445 4.20322 1.38747 2.44697 2.46209C1.21445 3.21625 0.537796 4.77917 0.775779 6.54921C1.01526 8.33035 2.16771 10.3232 4.57364 12.0996L4.64687 12.1537C5.46216 12.7562 6.04566 13.1875 6.99985 13.1875C7.95405 13.1875 8.53754 12.7562 9.35283 12.1537L9.42606 12.0996C10.3581 11.4114 11.1012 10.6918 11.6765 9.96419C11.6797 9.96013 11.6828 9.95603 11.6859 9.95191C14.0531 6.94717 13.5653 3.69371 11.5525 2.46209ZM7.74698 6.53198L10.4778 9.62245C10.0168 10.1444 9.44544 10.6701 8.74767 11.1853C7.83876 11.8564 7.54669 12.05 6.99985 12.05C6.45302 12.05 6.16095 11.8564 5.25204 11.1853C3.02962 9.54441 2.09491 7.80338 1.90596 6.39801C1.71551 4.98153 2.26916 3.90531 3.0432 3.43169C4.33507 2.64121 5.40954 2.95773 6.05358 3.43314L4.70267 4.46071C3.88293 5.08424 3.8086 6.28812 4.54542 7.00729C4.86355 7.31779 5.27961 7.48142 5.70118 7.48816C5.71901 7.48845 5.73685 7.48845 5.75469 7.48818C6.05478 7.48357 6.3557 7.39938 6.62418 7.232L7.74698 6.53198Z" fill="#2E3039"/> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.2 KiB | 
| @ -0,0 +1,14 @@ | |||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ///class used to provide value for the [DynamicResultChart] to plot the values | ||||||
|  | class DataPoint { | ||||||
|  |   ///values that is displayed on the graph and dot is plotted on this | ||||||
|  |   final double value; | ||||||
|  |   ///label shown on the bottom of the graph | ||||||
|  |   String label; | ||||||
|  | 
 | ||||||
|  |   DataPoint( | ||||||
|  |       {required this.value, | ||||||
|  |         required this.label, | ||||||
|  |       }); | ||||||
|  | } | ||||||
| @ -0,0 +1,21 @@ | |||||||
|  | import 'dart:ui' show Color; | ||||||
|  | 
 | ||||||
|  | class ThresholdRange { | ||||||
|  |   final String label; | ||||||
|  |   final double value; | ||||||
|  |   final Color color; | ||||||
|  |   final Color lineColor; | ||||||
|  |   final String? actualValue; | ||||||
|  | 
 | ||||||
|  |   ThresholdRange( | ||||||
|  |       {required this.label, | ||||||
|  |       required this.value, | ||||||
|  |       required this.color, | ||||||
|  |       required this.lineColor, | ||||||
|  |       this.actualValue}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   String toString() { | ||||||
|  |     return 'ThresholdRange(label: $label, value: $value, color: ${color.value.toRadixString(16)}, lineColor: ${lineColor.value.toRadixString(16)})'; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,105 @@ | |||||||
|  | import 'dart:convert'; | ||||||
|  | 
 | ||||||
|  | class FamilyFileResponseModelLists { | ||||||
|  |   int? id; | ||||||
|  |   int? patientId; | ||||||
|  |   int? responseId; | ||||||
|  |   dynamic relationshipId; | ||||||
|  |   dynamic relationship; | ||||||
|  |   dynamic relationshipN; | ||||||
|  |   int? regionId; | ||||||
|  |   int? familyRegionId; | ||||||
|  |   int? status; | ||||||
|  |   dynamic isActive; | ||||||
|  |   String? editedOn; | ||||||
|  |   String? createdOn; | ||||||
|  |   int? age; | ||||||
|  |   String? emaiLAddress; | ||||||
|  |   int? gender; | ||||||
|  |   String? genderDescription; | ||||||
|  |   String? genderImage; | ||||||
|  |   String? mobileNumber; | ||||||
|  |   int? patientDataVerified; | ||||||
|  |   String? patientIdenficationNumber; | ||||||
|  |   String? patientName; | ||||||
|  |   String? statusDescription; | ||||||
|  | 
 | ||||||
|  |   FamilyFileResponseModelLists({ | ||||||
|  |     this.id, | ||||||
|  |     this.patientId, | ||||||
|  |     this.responseId, | ||||||
|  |     this.relationshipId, | ||||||
|  |     this.relationship, | ||||||
|  |     this.relationshipN, | ||||||
|  |     this.regionId, | ||||||
|  |     this.familyRegionId, | ||||||
|  |     this.status, | ||||||
|  |     this.isActive, | ||||||
|  |     this.editedOn, | ||||||
|  |     this.createdOn, | ||||||
|  |     this.age, | ||||||
|  |     this.emaiLAddress, | ||||||
|  |     this.gender, | ||||||
|  |     this.genderDescription, | ||||||
|  |     this.genderImage, | ||||||
|  |     this.mobileNumber, | ||||||
|  |     this.patientDataVerified, | ||||||
|  |     this.patientIdenficationNumber, | ||||||
|  |     this.patientName, | ||||||
|  |     this.statusDescription, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   factory FamilyFileResponseModelLists.fromRawJson(String str) => FamilyFileResponseModelLists.fromJson(json.decode(str)); | ||||||
|  | 
 | ||||||
|  |   String toRawJson() => json.encode(toJson()); | ||||||
|  | 
 | ||||||
|  |   factory FamilyFileResponseModelLists.fromJson(Map<String, dynamic> json) => FamilyFileResponseModelLists( | ||||||
|  |     id: json["ID"], | ||||||
|  |     patientId: json["PatientID"], | ||||||
|  |     responseId: json["ResponseID"], | ||||||
|  |     relationshipId: json["RelationshipID"], | ||||||
|  |     relationship: json["Relationship"], | ||||||
|  |     relationshipN: json["RelationshipN"], | ||||||
|  |     regionId: json["RegionID"], | ||||||
|  |     familyRegionId: json["FamilyRegionID"], | ||||||
|  |     status: json["Status"], | ||||||
|  |     isActive: json["IsActive"], | ||||||
|  |     editedOn: json["EditedOn"], | ||||||
|  |     createdOn: json["CreatedOn"], | ||||||
|  |     age: json["Age"], | ||||||
|  |     emaiLAddress: json["EmaiLAddress"], | ||||||
|  |     gender: json["Gender"], | ||||||
|  |     genderDescription: json["GenderDescription"], | ||||||
|  |     genderImage: json["GenderImage"], | ||||||
|  |     mobileNumber: json["MobileNumber"], | ||||||
|  |     patientDataVerified: json["PatientDataVerified"], | ||||||
|  |     patientIdenficationNumber: json["PatientIdenficationNumber"], | ||||||
|  |     patientName: json["PatientName"], | ||||||
|  |     statusDescription: json["StatusDescription"], | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   Map<String, dynamic> toJson() => { | ||||||
|  |     "ID": id, | ||||||
|  |     "PatientID": patientId, | ||||||
|  |     "ResponseID": responseId, | ||||||
|  |     "RelationshipID": relationshipId, | ||||||
|  |     "Relationship": relationship, | ||||||
|  |     "RelationshipN": relationshipN, | ||||||
|  |     "RegionID": regionId, | ||||||
|  |     "FamilyRegionID": familyRegionId, | ||||||
|  |     "Status": status, | ||||||
|  |     "IsActive": isActive, | ||||||
|  |     "EditedOn": editedOn, | ||||||
|  |     "CreatedOn": createdOn, | ||||||
|  |     "Age": age, | ||||||
|  |     "EmaiLAddress": emaiLAddress, | ||||||
|  |     "Gender": gender, | ||||||
|  |     "GenderDescription": genderDescription, | ||||||
|  |     "GenderImage": genderImage, | ||||||
|  |     "MobileNumber": mobileNumber, | ||||||
|  |     "PatientDataVerified": patientDataVerified, | ||||||
|  |     "PatientIdenficationNumber": patientIdenficationNumber, | ||||||
|  |     "PatientName": patientName, | ||||||
|  |     "StatusDescription": statusDescription, | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @ -0,0 +1,84 @@ | |||||||
|  | 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_export.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/enums.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/utils/date_util.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/lab/models/resp_models/patient_lab_orders_response_model.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/generated/locale_keys.g.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/chip/app_custom_chip_widget.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; | ||||||
|  | 
 | ||||||
|  | class LabOrderByTest extends StatelessWidget { | ||||||
|  |   final VoidCallback onTap; | ||||||
|  |   final int index; | ||||||
|  |   final TestDetails? tests; | ||||||
|  |   final bool isLoading; | ||||||
|  |   final bool isExpanded; | ||||||
|  | 
 | ||||||
|  |   const LabOrderByTest({super.key, required this.onTap, this.tests, required this.index, this.isLoading = false, this.isExpanded = false}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   build(BuildContext context) { | ||||||
|  |     return AnimatedContainer( | ||||||
|  |         duration: Duration(milliseconds: 300), | ||||||
|  |         curve: Curves.easeInOut, | ||||||
|  |         margin: EdgeInsets.symmetric(vertical: 8.h), | ||||||
|  |         decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), | ||||||
|  |         child: InkWell( | ||||||
|  |             onTap: () { | ||||||
|  |               if (!isLoading) { | ||||||
|  |                 onTap(); | ||||||
|  |               } | ||||||
|  |             }, | ||||||
|  |             child: Container( | ||||||
|  |               key: ValueKey<int>(index), | ||||||
|  |               padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h), | ||||||
|  |               child: Column( | ||||||
|  |                 crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |                 children: [ | ||||||
|  |                   // ...labOrder!.testDetails!.map((detail) { | ||||||
|  |                   Padding( | ||||||
|  |                     padding: EdgeInsets.only(bottom: 8.h), | ||||||
|  |                     child: '${tests!.description}'.toText14(weight: FontWeight.w500), | ||||||
|  |                   ), | ||||||
|  | 
 | ||||||
|  |                   SizedBox(height: 12.h), | ||||||
|  | 
 | ||||||
|  |                   Row( | ||||||
|  |                     mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||||
|  |                     children: [ | ||||||
|  |                       AppCustomChipWidget( | ||||||
|  |                         richText: '${"Last Tested:".needTranslation} ${ DateUtil.formatDateToDate(DateUtil.convertStringToDate(tests!.createdOn), false)}'.toText12(isBold: true), | ||||||
|  |                         // chipType: ChipTypeEnum.lightBg, | ||||||
|  |                         backgroundColor: AppColors.greyLightColor, | ||||||
|  |                         textColor: AppColors.textColor, | ||||||
|  |                         // borderRadius: 5, | ||||||
|  | 
 | ||||||
|  |                       ), | ||||||
|  |                       CustomButton( | ||||||
|  |                         icon: AppAssets.view_report_icon, | ||||||
|  |                         iconColor: AppColors.primaryRedColor, | ||||||
|  |                         iconSize: 16.h, | ||||||
|  |                         text: LocaleKeys.viewReport.tr(context: context), | ||||||
|  |                         onPressed: () {}, | ||||||
|  |                         backgroundColor: AppColors.secondaryLightRedColor, | ||||||
|  |                         borderColor: AppColors.secondaryLightRedColor, | ||||||
|  |                         textColor: AppColors.primaryRedColor, | ||||||
|  |                         fontSize: 14, | ||||||
|  |                         fontWeight: FontWeight.bold, | ||||||
|  |                         borderRadius: 12, | ||||||
|  |                         padding: EdgeInsets.fromLTRB(10, 0, 10, 0), | ||||||
|  |                         height: 40.h, | ||||||
|  |                       ), | ||||||
|  |                     ], | ||||||
|  |                   ), | ||||||
|  |                 ], | ||||||
|  |               ), | ||||||
|  |             ))); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,197 @@ | |||||||
|  | import 'package:easy_localization/easy_localization.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:flutter_svg/flutter_svg.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/dependencies.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/enums.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/utils/utils.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/utils/validation_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/authentication/authentication_view_model.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/presentation/my_family/widget/family_cards.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/services/dialog_service.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/theme/colors.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.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/custom_tab_bar.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/widgets/dropdown/country_dropdown_widget.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/widgets/input_widget.dart'; | ||||||
|  | 
 | ||||||
|  | class FamilyMedicalScreen extends StatefulWidget { | ||||||
|  |   final List<FamilyFileResponseModelLists> profiles; | ||||||
|  |   final Function(FamilyFileResponseModelLists) onSelect; | ||||||
|  | 
 | ||||||
|  |   const FamilyMedicalScreen({ | ||||||
|  |     Key? key, | ||||||
|  |     required this.profiles, | ||||||
|  |     required this.onSelect, | ||||||
|  |   }) : super(key: key); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   State<FamilyMedicalScreen> createState() => _FamilyMedicalScreenState(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _FamilyMedicalScreenState extends State<FamilyMedicalScreen> { | ||||||
|  |   List<CustomTabBarModel> tabs = [CustomTabBarModel("", LocaleKeys.medicalFile.tr()), CustomTabBarModel("", LocaleKeys.request.tr())]; | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Scaffold( | ||||||
|  |       backgroundColor: AppColors.scaffoldBgColor, | ||||||
|  |       appBar: CustomAppBar( | ||||||
|  |         onBackPressed: () { | ||||||
|  |           Navigator.of(context).pop(); | ||||||
|  |         }, | ||||||
|  |         onLanguageChanged: (lang) {}, | ||||||
|  |         hideLogoAndLang: true, | ||||||
|  |       ), | ||||||
|  |       body: SingleChildScrollView( | ||||||
|  |         child: Column( | ||||||
|  |           mainAxisSize: MainAxisSize.min, | ||||||
|  |           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |           children: [ | ||||||
|  |             LocaleKeys.myMedicalFile.tr().toText26(color: AppColors.textColor, weight: FontWeight.w600, letterSpacing: -2), | ||||||
|  |             SizedBox(height: 25.h), | ||||||
|  |             CustomTabBar( | ||||||
|  |               tabs: tabs, | ||||||
|  |               onTabChange: (int index) {}, | ||||||
|  |             ), | ||||||
|  |             SizedBox(height: 25.h), | ||||||
|  |             FamilyCards(profiles: widget.profiles, onSelect: widget.onSelect, isShowDetails: true), | ||||||
|  |             SizedBox(height: 20.h), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ).paddingSymmetrical(20, 0), | ||||||
|  |       bottomSheet: Container( | ||||||
|  |           decoration: RoundedRectangleBorder().toSmoothCornerDecoration( | ||||||
|  |             color: AppColors.whiteColor, | ||||||
|  |             customBorder: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)), | ||||||
|  |           ), | ||||||
|  |           padding: EdgeInsets.symmetric(vertical: 10.h, horizontal: 20.h), | ||||||
|  |           child: CustomButton( | ||||||
|  |             text: "Add a new family member", | ||||||
|  |             onPressed: () { | ||||||
|  |               showModelSheet(); | ||||||
|  |             }, | ||||||
|  |             icon: AppAssets.add_icon, | ||||||
|  |             height: 56.h, | ||||||
|  |             fontWeight: FontWeight.w600, | ||||||
|  |           )), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void showModelSheet() { | ||||||
|  |     AuthenticationViewModel authVm = getIt.get<AuthenticationViewModel>(); | ||||||
|  |     return showCommonBottomSheetWithoutHeight(context, | ||||||
|  |         title: "Add Family Member", | ||||||
|  |         child: Column( | ||||||
|  |           crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |           mainAxisAlignment: MainAxisAlignment.start, | ||||||
|  |           children: [ | ||||||
|  |             "Please fill the below field to add a new family member to your profile".toText16(color: AppColors.textColor, weight: FontWeight.w500), | ||||||
|  |             SizedBox(height: 20.h), | ||||||
|  |             Container( | ||||||
|  |               decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(24)), | ||||||
|  |               padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h), | ||||||
|  |               child: Column( | ||||||
|  |                 children: [ | ||||||
|  |                   CustomCountryDropdown( | ||||||
|  |                     countryList: CountryEnum.values, | ||||||
|  |                     onCountryChange: authVm.onCountryChange, | ||||||
|  |                   ).paddingOnly(top: 8.h, bottom: 16.h), | ||||||
|  |                   Divider( | ||||||
|  |                     height: 1.h, | ||||||
|  |                     color: AppColors.spacerLineColor, | ||||||
|  |                   ), | ||||||
|  |                   TextInputWidget( | ||||||
|  |                     labelText: LocaleKeys.nationalIdNumber.tr(), | ||||||
|  |                     hintText: "xxxxxxxxx", | ||||||
|  |                     controller: authVm.nationalIdController, | ||||||
|  |                     // focusNode: _nationalIdFocusNode, | ||||||
|  |                     isEnable: true, | ||||||
|  |                     prefix: null, | ||||||
|  |                     isAllowRadius: true, | ||||||
|  |                     isBorderAllowed: false, | ||||||
|  |                     isAllowLeadingIcon: true, | ||||||
|  |                     autoFocus: true, | ||||||
|  |                     keyboardType: TextInputType.number, | ||||||
|  |                     padding: EdgeInsets.symmetric(vertical: 8.h), | ||||||
|  |                     leadingIcon: AppAssets.student_card, | ||||||
|  |                   ).paddingOnly(top: 8.h, bottom: 8.h), | ||||||
|  |                   Divider( | ||||||
|  |                     height: 1.h, | ||||||
|  |                     color: AppColors.spacerLineColor, | ||||||
|  |                   ), | ||||||
|  |                   TextInputWidget( | ||||||
|  |                     labelText: LocaleKeys.phoneNumber.tr(), | ||||||
|  |                     hintText: "574345434", | ||||||
|  |                     controller: authVm.phoneNumberController, | ||||||
|  |                     isEnable: true, | ||||||
|  |                     prefix: authVm.selectedCountrySignup.countryCode, | ||||||
|  |                     isAllowRadius: true, | ||||||
|  |                     isBorderAllowed: false, | ||||||
|  |                     isAllowLeadingIcon: true, | ||||||
|  |                     autoFocus: true, | ||||||
|  |                     keyboardType: TextInputType.number, | ||||||
|  |                     padding: EdgeInsets.symmetric(vertical: 8.h), | ||||||
|  |                     leadingIcon: AppAssets.smart_phone, | ||||||
|  |                   ).paddingOnly(top: 8.h, bottom: 4), | ||||||
|  | 
 | ||||||
|  |                   //TextInputWidget( | ||||||
|  |                   //                           labelText: widget.isForEmail ? LocaleKeys.email.tr() : LocaleKeys.phoneNumber.tr(), | ||||||
|  |                   //                           hintText: widget.isForEmail ? "demo@gmail.com" : "5xxxxxxxx", | ||||||
|  |                   //                           controller: widget.textController!, | ||||||
|  |                   //                           focusNode: _textFieldFocusNode, | ||||||
|  |                   //                           autoFocus: widget.autoFocus, | ||||||
|  |                   //                           padding: EdgeInsets.all(8.h), | ||||||
|  |                   //                           keyboardType: widget.isForEmail ? TextInputType.emailAddress : TextInputType.number, | ||||||
|  |                   //                           onChange: (value) { | ||||||
|  |                   //                             if (widget.onChange != null) { | ||||||
|  |                   //                               widget.onChange!(value); | ||||||
|  |                   //                             } | ||||||
|  |                   //                           }, | ||||||
|  |                   //                           onCountryChange: (value) { | ||||||
|  |                   //                             if (widget.onCountryChange != null) { | ||||||
|  |                   //                               widget.onCountryChange!(value); | ||||||
|  |                   //                             } | ||||||
|  |                   //                           }, | ||||||
|  |                   //                           isEnable: true, | ||||||
|  |                   //                           isReadOnly: widget.isFromSavedLogin, | ||||||
|  |                   //                           prefix: widget.isForEmail ? null : widget.countryCode, | ||||||
|  |                   //                           isBorderAllowed: false, | ||||||
|  |                   //                           isAllowLeadingIcon: true, | ||||||
|  |                   //                           fontSize: 13.h, | ||||||
|  |                   //                           isCountryDropDown: widget.isEnableCountryDropdown, | ||||||
|  |                   //                           leadingIcon: widget.isForEmail ? AppAssets.email : AppAssets.smart_phone, | ||||||
|  |                   //                         ) | ||||||
|  |                 ], | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             SizedBox(height: 20.h), | ||||||
|  |             CustomButton( | ||||||
|  |                 text: "Verify the member", | ||||||
|  |                 onPressed: () { | ||||||
|  |                   FocusScope.of(context).unfocus(); | ||||||
|  |                   if (ValidationUtils.isValidatedIdAndPhoneWithCountryValidation( | ||||||
|  |                     nationalId: authVm.nationalIdController.text, | ||||||
|  |                     selectedCountry: authVm.selectedCountrySignup, | ||||||
|  |                     phoneNumber: authVm.phoneNumberController.text, | ||||||
|  |                     onOkPress: () { | ||||||
|  |                       Navigator.of(context).pop(); | ||||||
|  |                     }, | ||||||
|  |                   )) {} | ||||||
|  |                 }, | ||||||
|  |                 icon: AppAssets.add_icon, | ||||||
|  |                 height: 56.h, | ||||||
|  |                 fontWeight: FontWeight.w600), | ||||||
|  |             SizedBox(height: 20.h), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |         callBackFunc: () {}); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,116 @@ | |||||||
|  | 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_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/enums.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/medical_file/models/family_file_response_model.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/generated/locale_keys.g.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/chip/custom_chip_widget.dart'; | ||||||
|  | 
 | ||||||
|  | class FamilyCards extends StatefulWidget { | ||||||
|  |   final List<FamilyFileResponseModelLists> profiles; | ||||||
|  |   final Function(FamilyFileResponseModelLists) onSelect; | ||||||
|  |   final bool isShowDetails; | ||||||
|  |   final bool isBottomSheet; | ||||||
|  | 
 | ||||||
|  |   const FamilyCards({super.key, required this.profiles, required this.onSelect, this.isShowDetails = false, this.isBottomSheet = false}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   State<FamilyCards> createState() => _FamilyCardsState(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _FamilyCardsState extends State<FamilyCards> { | ||||||
|  |   AppState appState = getIt<AppState>(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return GridView.builder( | ||||||
|  |       shrinkWrap: true, | ||||||
|  |       physics: const NeverScrollableScrollPhysics(), | ||||||
|  |       itemCount: widget.profiles.length, | ||||||
|  |       gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( | ||||||
|  |         crossAxisCount: 2, | ||||||
|  |         crossAxisSpacing: 10.h, | ||||||
|  |         mainAxisSpacing: 10.h, | ||||||
|  |         childAspectRatio: widget.isShowDetails ? 0.56.h : 0.74.h, | ||||||
|  |       ), | ||||||
|  |       itemBuilder: (context, index) { | ||||||
|  |         final profile = widget.profiles[index]; | ||||||
|  |         final isActive = (profile.responseId == appState | ||||||
|  |             .getAuthenticatedUser() | ||||||
|  |             ?.patientId); | ||||||
|  |         return Container( | ||||||
|  |           padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 15.h), | ||||||
|  |           decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24), | ||||||
|  |           child: Opacity( | ||||||
|  |             opacity: isActive ? 0.4 : 1.0, // Fade all content if active | ||||||
|  |             child: Column( | ||||||
|  |               mainAxisSize: MainAxisSize.min, | ||||||
|  |               children: [ | ||||||
|  |                 SizedBox(height: 5.h), | ||||||
|  |                 Utils.buildImgWithAssets( | ||||||
|  |                     icon: profile.gender == 1 ? ((profile.age ?? 0) < 7 ? AppAssets.babyBoyImg : AppAssets.male_img) : (profile.age! < 7 ? AppAssets.babyGirlImg : AppAssets.femaleImg), | ||||||
|  |                     width: 80.h, | ||||||
|  |                     height: 78.h), | ||||||
|  |                 SizedBox(height: 8.h), | ||||||
|  |                 (profile.patientName ?? "Unknown").toText16(isBold: false, isCenter: true, maxlines: 1, weight: FontWeight.w600), | ||||||
|  |                 SizedBox(height: 4.h), | ||||||
|  |                 CustomChipWidget( | ||||||
|  |                     chipType: ChipTypeEnum.alert, | ||||||
|  |                     backgroundColor: AppColors.lightGrayBGColor, | ||||||
|  |                     chipText: "Relation: ${profile.relationship ?? "N/A"}", | ||||||
|  |                     iconAsset: AppAssets.heart, | ||||||
|  |                     isShowBorder: false, | ||||||
|  |                     borderRadius: 8.h, | ||||||
|  |                     textColor: AppColors.textColor), | ||||||
|  |                 widget.isShowDetails ? SizedBox(height: 4.h) : SizedBox(), | ||||||
|  |                 widget.isShowDetails | ||||||
|  |                     ? CustomChipWidget( | ||||||
|  |                   chipType: ChipTypeEnum.alert, | ||||||
|  |                   backgroundColor: AppColors.lightGrayBGColor, | ||||||
|  |                   chipText: "Age: ${profile.age ?? "N/A"} Years", | ||||||
|  |                   isShowBorder: false, | ||||||
|  |                   borderRadius: 8.h, | ||||||
|  |                   textColor: AppColors.textColor, | ||||||
|  |                 ) | ||||||
|  |                     : SizedBox(), | ||||||
|  |                 widget.isShowDetails ? SizedBox(height: 8.h) : SizedBox(), | ||||||
|  |                 Spacer(), | ||||||
|  |                 if (isActive) | ||||||
|  |                   CustomButton( | ||||||
|  |                     height: 40.h, | ||||||
|  |                     onPressed: () {}, | ||||||
|  |                     text: LocaleKeys.active.tr(), | ||||||
|  |                     backgroundColor: Colors.grey.shade200, | ||||||
|  |                     borderColor: Colors.grey.shade200, | ||||||
|  |                     textColor: AppColors.greyTextColor, | ||||||
|  |                     fontSize: 13.h, | ||||||
|  |                   ).paddingOnly(top: 0, bottom: 0) | ||||||
|  |                 else | ||||||
|  |                   CustomButton( | ||||||
|  |                     height: 40.h, | ||||||
|  |                     onPressed: () => widget.onSelect(profile), | ||||||
|  |                     text: LocaleKeys.select.tr(), | ||||||
|  |                     backgroundColor: AppColors.secondaryLightRedColor, | ||||||
|  |                     borderColor: AppColors.secondaryLightRedColor, | ||||||
|  |                     textColor: AppColors.primaryRedColor, | ||||||
|  |                     fontSize: 13.h, | ||||||
|  |                     icon: widget.isBottomSheet ? null :  AppAssets.heart, | ||||||
|  |                     iconColor: AppColors.primaryRedColor, | ||||||
|  |                     padding: EdgeInsets.symmetric(vertical: 0, horizontal: 0), | ||||||
|  |                   ).paddingOnly(top: 0, bottom: 0), | ||||||
|  |               ], | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |         ); | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,31 @@ | |||||||
|  | import 'package:flutter/material.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/features/medical_file/models/family_file_response_model.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/presentation/my_family/my_Family.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/presentation/my_family/widget/family_cards.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/theme/colors.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; | ||||||
|  | 
 | ||||||
|  | class MyFamilySheet { | ||||||
|  |   static void show(BuildContext context, List<FamilyFileResponseModelLists> familyLists, Function(FamilyFileResponseModelLists) onSelect) { | ||||||
|  |     return showCommonBottomSheetWithoutHeight( | ||||||
|  |       context, | ||||||
|  |       titleWidget: Column( | ||||||
|  |         crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |         children: [ | ||||||
|  |           'Please select a profile'.toText21(isBold: true), | ||||||
|  |           'switch from the below list of medical file'.toText16(weight: FontWeight.w100, color: AppColors.greyTextColor), | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |       child: FamilyCards( | ||||||
|  |           profiles: familyLists, | ||||||
|  |           onSelect: (profile) { | ||||||
|  |             Navigator.of(context).pop(); // Close the bottom sheet | ||||||
|  |             onSelect(profile); // Call the onSelect callback | ||||||
|  |           }, | ||||||
|  |           isBottomSheet: true), | ||||||
|  |       callBackFunc: () {}, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,287 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:fl_chart/fl_chart.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/common_models/data_points.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/theme/colors.dart'; | ||||||
|  | /// | ||||||
|  | /// CustomGraph(dataPoints: sampleData, scrollDirection: Axis.horizontal,height: 200,maxY: 100, maxX:2.5, | ||||||
|  | ///               leftLabelFormatter: (value){ | ||||||
|  | ///                 Widget buildLabel(String label) { | ||||||
|  | ///                   return Padding( | ||||||
|  | ///                     padding: const EdgeInsets.only(right: 8), | ||||||
|  | ///                     child: Text( | ||||||
|  | ///                       label, | ||||||
|  | ///                       style: TextStyle( | ||||||
|  | ///                           fontSize: 8.fSize, color: AppColors.textColor, | ||||||
|  | ///                       fontFamily: | ||||||
|  | ///                       FontUtils.getFontFamilyForLanguage(false) | ||||||
|  | ///                       ), | ||||||
|  | ///                       textAlign: TextAlign.right, | ||||||
|  | ///                     ), | ||||||
|  | ///                   ); | ||||||
|  | ///                 } | ||||||
|  | ///                 switch (value.toInt()) { | ||||||
|  | /// | ||||||
|  | ///                   case 20: | ||||||
|  | ///                     return buildLabel("Critical Low"); | ||||||
|  | ///                   case 40: | ||||||
|  | ///                     return buildLabel("Low"); | ||||||
|  | ///                   case 60: | ||||||
|  | ///                     return buildLabel("Normal"); | ||||||
|  | ///                   case 80: | ||||||
|  | ///                     return buildLabel("High"); | ||||||
|  | ///                   case 100: | ||||||
|  | ///                     return buildLabel("Critical High"); | ||||||
|  | ///                 } | ||||||
|  | ///                 return const SizedBox.shrink(); | ||||||
|  | ///               }, | ||||||
|  | /// | ||||||
|  | ///             ), | ||||||
|  | class CustomGraph extends StatelessWidget { | ||||||
|  |   final List<DataPoint> dataPoints; | ||||||
|  |   final double? width; | ||||||
|  |   final double height; | ||||||
|  |   final double? maxY; | ||||||
|  |   final double? maxX; | ||||||
|  |   final Color spotColor; | ||||||
|  |   final Color graphColor; | ||||||
|  |   final Color graphShadowColor; | ||||||
|  |   final Color graphGridColor; | ||||||
|  |   final Color bottomLabelColor; | ||||||
|  |   final double? bottomLabelSize; | ||||||
|  |   final FontWeight? bottomLabelFontWeight; | ||||||
|  | 
 | ||||||
|  |   ///creates the left label and provide it to the chart as it will be used  by other part of the application so the label will be different for every chart | ||||||
|  |   final Widget Function(double value) leftLabelFormatter; | ||||||
|  | 
 | ||||||
|  |   final Axis scrollDirection; | ||||||
|  |   final bool showBottomTitleDates; | ||||||
|  |   final bool isFullScreeGraph; | ||||||
|  | 
 | ||||||
|  |   const CustomGraph({ | ||||||
|  |     super.key, | ||||||
|  |     required this.dataPoints, | ||||||
|  |     required this.leftLabelFormatter, | ||||||
|  |     this.width, | ||||||
|  |     required this.scrollDirection, | ||||||
|  |     required this.height, | ||||||
|  |     this.maxY, | ||||||
|  |     this.maxX, | ||||||
|  |     this.showBottomTitleDates = true, | ||||||
|  |     this.isFullScreeGraph = false, | ||||||
|  |     this.spotColor = AppColors.bgGreenColor, | ||||||
|  |     this.graphColor = AppColors.bgGreenColor, | ||||||
|  |     this.graphShadowColor = AppColors.graphGridColor, | ||||||
|  |     this.graphGridColor = AppColors.graphGridColor, | ||||||
|  |     this.bottomLabelColor = AppColors.textColor, | ||||||
|  |     this.bottomLabelFontWeight = FontWeight.w500, | ||||||
|  |     this.bottomLabelSize, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     // var maxY = 0.0; | ||||||
|  |     double interval = 20; | ||||||
|  |     if ((maxY ?? 0) > 10 && (maxY ?? 0) <= 20) { | ||||||
|  |       interval = 2; | ||||||
|  |     } else if ((maxY ?? 0) > 5 && (maxY ?? 0) <= 10) { | ||||||
|  |       interval = 1; | ||||||
|  |     } else if ((maxY ?? 0) >= 0 && (maxY ?? 0) <= 5) { | ||||||
|  |       interval = .4; | ||||||
|  |     } | ||||||
|  |     return Material( | ||||||
|  |         color: Colors.white, | ||||||
|  |         child: SizedBox( | ||||||
|  |           width: width, | ||||||
|  |           height: height, | ||||||
|  |           child: Padding( | ||||||
|  |             padding: const EdgeInsets.only(top: 8.0, bottom: 8), | ||||||
|  |             child: LineChart( | ||||||
|  |               LineChartData( | ||||||
|  |                 minY: 0, | ||||||
|  |                 maxY: | ||||||
|  |                     ((maxY?.ceilToDouble() ?? 0.0) + interval).floorToDouble(), | ||||||
|  |                 // minX: dataPoints.first.labelValue - 1, | ||||||
|  |                 maxX: maxX, | ||||||
|  |                 minX: -0.2, | ||||||
|  |                 lineTouchData: LineTouchData( | ||||||
|  |                   getTouchLineEnd: (_, __) => 0, | ||||||
|  |                   getTouchedSpotIndicator: (barData, indicators) { | ||||||
|  |                     // Only show custom marker for touched spot | ||||||
|  |                     return indicators.map((int index) { | ||||||
|  |                       return TouchedSpotIndicatorData( | ||||||
|  |                         FlLine(color: Colors.transparent), | ||||||
|  |                         FlDotData( | ||||||
|  |                           show: true, | ||||||
|  |                           getDotPainter: (spot, percent, barData, idx) { | ||||||
|  |                             return FlDotCirclePainter( | ||||||
|  |                               radius: 8, | ||||||
|  |                               color: spotColor, | ||||||
|  |                               strokeWidth: 2, | ||||||
|  |                               strokeColor: Colors.white, | ||||||
|  |                             ); | ||||||
|  |                           }, | ||||||
|  |                         ), | ||||||
|  |                       ); | ||||||
|  |                     }).toList(); | ||||||
|  |                   }, | ||||||
|  |                   enabled: true, | ||||||
|  |                   touchTooltipData: LineTouchTooltipData( | ||||||
|  |                     getTooltipColor: (_) => Colors.white, | ||||||
|  |                     getTooltipItems: (touchedSpots) { | ||||||
|  |                       if (touchedSpots.isEmpty) return []; | ||||||
|  |                       // Only show tooltip for the first touched spot, hide others | ||||||
|  |                       return touchedSpots.map((spot) { | ||||||
|  |                         if (spot == touchedSpots.first) { | ||||||
|  |                           final dataPoint = dataPoints[spot.x.toInt()]; | ||||||
|  | 
 | ||||||
|  |                           return LineTooltipItem( | ||||||
|  |                             // '${dataPoint.label} ${spot.y.toStringAsFixed(2)}', | ||||||
|  |                             '${dataPoint.value} ', | ||||||
|  |                             TextStyle( | ||||||
|  |                                 color: Colors.black, | ||||||
|  |                                 fontSize: 12.fSize, | ||||||
|  |                                 fontWeight: FontWeight.w500), | ||||||
|  |                           ); | ||||||
|  |                         } | ||||||
|  |                         return null; // hides the rest | ||||||
|  |                       }).toList(); | ||||||
|  |                     }, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |                 titlesData: FlTitlesData( | ||||||
|  |                   leftTitles: AxisTitles( | ||||||
|  |                     sideTitles: SideTitles( | ||||||
|  |                       showTitles: true, | ||||||
|  |                       reservedSize: 77, | ||||||
|  |                       interval: .1, // Let fl_chart handle it | ||||||
|  |                       getTitlesWidget: (value, _) { | ||||||
|  |                         return leftLabelFormatter(value); | ||||||
|  |                       }, | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|  |                   bottomTitles: AxisTitles( | ||||||
|  |                     axisNameSize: 60, | ||||||
|  |                     sideTitles: SideTitles( | ||||||
|  |                       showTitles: showBottomTitleDates, | ||||||
|  |                       reservedSize: 50, | ||||||
|  |                       getTitlesWidget: (value, _) { | ||||||
|  |                         if ((value.toDouble() >= 0) && | ||||||
|  |                             (value.toDouble() < (maxX ?? dataPoints.length))) { | ||||||
|  |                           var label = dataPoints[value.toInt()].label; | ||||||
|  | 
 | ||||||
|  |                           return buildBottomLabel(label); | ||||||
|  |                         } | ||||||
|  |                         return const SizedBox.shrink(); | ||||||
|  |                       }, | ||||||
|  |                       interval: 1, // ensures 1:1 mapping with spots | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|  |                   topTitles: AxisTitles(), | ||||||
|  |                   rightTitles: AxisTitles(), | ||||||
|  |                 ), | ||||||
|  |                 borderData: FlBorderData( | ||||||
|  |                   show: true, | ||||||
|  |                   border: const Border( | ||||||
|  |                     bottom: BorderSide.none, | ||||||
|  |                     left: BorderSide(color: Colors.grey, width: .5), | ||||||
|  |                     right: BorderSide.none, | ||||||
|  |                     top: BorderSide.none, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |                 lineBarsData: _buildColoredLineSegments(dataPoints), | ||||||
|  |                 gridData: FlGridData( | ||||||
|  |                   show: true, | ||||||
|  |                   drawVerticalLine: false, | ||||||
|  |                   horizontalInterval: 20, | ||||||
|  |                   checkToShowHorizontalLine: (value) => | ||||||
|  |                       value >= 0 && value <= 100, | ||||||
|  |                   getDrawingHorizontalLine: (value) { | ||||||
|  |                     return FlLine( | ||||||
|  |                       color: AppColors.graphGridColor, | ||||||
|  |                       strokeWidth: 1, | ||||||
|  |                       dashArray: [5, 5], | ||||||
|  |                     ); | ||||||
|  |                   }, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |         )); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   List<LineChartBarData> _buildColoredLineSegments(List<DataPoint> dataPoints) { | ||||||
|  |     final List<FlSpot> allSpots = dataPoints.asMap().entries.map((entry) { | ||||||
|  |       return FlSpot(entry.key.toDouble(), entry.value.value); | ||||||
|  |     }).toList(); | ||||||
|  | 
 | ||||||
|  |     var data = [ | ||||||
|  |       LineChartBarData( | ||||||
|  |         spots: allSpots, | ||||||
|  |         isCurved: true, | ||||||
|  |         isStrokeCapRound: true, | ||||||
|  |         isStrokeJoinRound: true, | ||||||
|  |         barWidth: 4, | ||||||
|  |         gradient: LinearGradient( | ||||||
|  |           colors: [graphColor, graphColor], | ||||||
|  |           begin: Alignment.centerLeft, | ||||||
|  |           end: Alignment.centerRight, | ||||||
|  |         ), | ||||||
|  |         dotData: FlDotData( | ||||||
|  |           show: false, | ||||||
|  |         ), | ||||||
|  |         belowBarData: BarAreaData( | ||||||
|  |           show: true, | ||||||
|  |           gradient: LinearGradient( | ||||||
|  |             colors: [ | ||||||
|  |               graphShadowColor, | ||||||
|  |               Colors.transparent, | ||||||
|  |             ], | ||||||
|  |             begin: Alignment.topCenter, | ||||||
|  |             end: Alignment.bottomCenter, | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |       ) | ||||||
|  |     ]; | ||||||
|  | 
 | ||||||
|  |     return data; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Widget buildLabel(String label) { | ||||||
|  |   //   return Padding( | ||||||
|  |   //     padding: const EdgeInsets.only(right: 8), | ||||||
|  |   //     child: Text( | ||||||
|  |   //       label, | ||||||
|  |   //       style: TextStyle( | ||||||
|  |   //           fontSize: leftLabelSize ?? 8.fSize, color: leftLabelColor), | ||||||
|  |   //       textAlign: TextAlign.right, | ||||||
|  |   //     ), | ||||||
|  |   //   ); | ||||||
|  |   // } | ||||||
|  | 
 | ||||||
|  |   Widget buildBottomLabel(String label) { | ||||||
|  |     return Padding( | ||||||
|  |       padding: const EdgeInsets.all(8.0), | ||||||
|  |       child: Text( | ||||||
|  |         label, | ||||||
|  |         style: TextStyle( | ||||||
|  |             fontSize: bottomLabelSize ?? 8.fSize, color: bottomLabelColor), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | final List<DataPoint> sampleData = [ | ||||||
|  |   DataPoint( | ||||||
|  |     value: 20, | ||||||
|  |     label: 'Jan 2024', | ||||||
|  |   ), | ||||||
|  |   DataPoint( | ||||||
|  |     value: 36, | ||||||
|  |     label: 'Feb 2024', | ||||||
|  |   ), | ||||||
|  |   DataPoint( | ||||||
|  |     value: 80, | ||||||
|  |     label: 'This result', | ||||||
|  |   ), | ||||||
|  | ]; | ||||||
| @ -1,44 +0,0 @@ | |||||||
| import 'package:flutter/material.dart'; |  | ||||||
| 
 |  | ||||||
| class ProfileSelector extends StatelessWidget { |  | ||||||
|   final List<Map<String, dynamic>> profiles; |  | ||||||
|   final Function(Map<String, dynamic>) onSelect; |  | ||||||
| 
 |  | ||||||
|   const ProfileSelector({ |  | ||||||
|     Key? key, |  | ||||||
|     required this.profiles, |  | ||||||
|     required this.onSelect, |  | ||||||
|   }) : super(key: key); |  | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   Widget build(BuildContext context) { |  | ||||||
|     return Column( |  | ||||||
|       mainAxisSize: MainAxisSize.min, |  | ||||||
|       children: profiles.map((profile) { |  | ||||||
|         return ListTile( |  | ||||||
|           leading: CircleAvatar( |  | ||||||
|             radius: 22, |  | ||||||
|             backgroundImage: profile["GenderImage"] != null && |  | ||||||
|                 profile["GenderImage"].toString().isNotEmpty |  | ||||||
|                 ? NetworkImage(profile["GenderImage"]) |  | ||||||
|                 : AssetImage( |  | ||||||
|                 profile["Gender"] == 1 |  | ||||||
|                     ? "assets/images/male.png" |  | ||||||
|                     : "assets/images/female.png") |  | ||||||
|             as ImageProvider, |  | ||||||
|           ), |  | ||||||
|           title: Text( |  | ||||||
|             profile["PatientName"] ?? "Unknown", |  | ||||||
|             style: const TextStyle(fontWeight: FontWeight.w600), |  | ||||||
|           ), |  | ||||||
|           subtitle: Text( |  | ||||||
|             profile["Relationship"] ?? "Self", |  | ||||||
|             style: const TextStyle(color: Colors.grey), |  | ||||||
|           ), |  | ||||||
|           trailing: const Icon(Icons.arrow_forward_ios, size: 16), |  | ||||||
|           onTap: () => onSelect(profile), |  | ||||||
|         ); |  | ||||||
|       }).toList(), |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @ -1,15 +0,0 @@ | |||||||
| import 'package:flutter/material.dart'; |  | ||||||
| import '../common_bottom_sheet.dart'; |  | ||||||
| import 'my_Family.dart'; |  | ||||||
|  class MyFamilySheet { |  | ||||||
|    static void show(BuildContext context, List<Map<String, dynamic>> profiles, Function(Map<String, dynamic>) onSelect) { |  | ||||||
|      showCommonBottomSheetWithoutHeight( |  | ||||||
|        context, |  | ||||||
|        title: 'Select Profile', |  | ||||||
|        child: ProfileSelector(profiles: profiles, onSelect: (profile) { |  | ||||||
|          Navigator.of(context).pop(); // Close the bottom sheet |  | ||||||
|          onSelect(profile); // Call the onSelect callback |  | ||||||
|        }), callBackFunc: () {}, |  | ||||||
|      ); |  | ||||||
|    } |  | ||||||
|  } |  | ||||||