From 028e03a97b62769abb18939ec659a1a4e865562f Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Thu, 6 Nov 2025 11:52:57 +0300 Subject: [PATCH] filter radiology --- .../radiology/radiology_view_model.dart | 30 +++- .../call_ambulance/tracking_screen.dart | 12 +- .../profile_settings/profile_settings.dart | 2 +- .../radiology/radiology_orders_page.dart | 38 ++++- .../radiology/search_radiology.dart | 154 ++++++++++++++++++ 5 files changed, 226 insertions(+), 10 deletions(-) create mode 100644 lib/presentation/radiology/search_radiology.dart diff --git a/lib/features/radiology/radiology_view_model.dart b/lib/features/radiology/radiology_view_model.dart index 3441881..d37d1ea 100644 --- a/lib/features/radiology/radiology_view_model.dart +++ b/lib/features/radiology/radiology_view_model.dart @@ -13,14 +13,20 @@ class RadiologyViewModel extends ChangeNotifier { ErrorHandlerService errorHandlerService; List patientRadiologyOrders = []; - + List filteredRadiologyOrders = []; + List tempRadiologyOrders = []; String radiologyImageURL = ""; String patientRadiologyReportPDFBase64 = ""; + late List _radiologySuggestionsList = []; + + List get radiologySuggestions => _radiologySuggestionsList; + RadiologyViewModel({required this.radiologyRepo, required this.errorHandlerService}); initRadiologyProvider() { patientRadiologyOrders.clear(); + filteredRadiologyOrders.clear(); isRadiologyOrdersLoading = true; isRadiologyPDFReportLoading = true; radiologyImageURL = ""; @@ -38,7 +44,10 @@ class RadiologyViewModel extends ChangeNotifier { // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); } else if (apiResponse.messageStatus == 1) { patientRadiologyOrders = apiResponse.data!; + filteredRadiologyOrders = List.from(patientRadiologyOrders); + tempRadiologyOrders = [...patientRadiologyOrders]; isRadiologyOrdersLoading = false; + filterSuggestions(); notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); @@ -93,4 +102,23 @@ class RadiologyViewModel extends ChangeNotifier { }, ); } + filterSuggestions() { + final List labels = patientRadiologyOrders + .map((detail) => detail.description) + .whereType() + .toList(); + _radiologySuggestionsList = labels.toSet().toList(); + notifyListeners(); + } + filterRadiologyReports(String query) { + if (query.isEmpty) { + patientRadiologyOrders =tempRadiologyOrders;// reset + } else { + filteredRadiologyOrders = + filteredRadiologyOrders.where((desc) => desc.description!.toLowerCase().contains(query.toLowerCase())).toList(); + patientRadiologyOrders = filteredRadiologyOrders; + } + notifyListeners(); + } + } diff --git a/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart b/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart index a48ca10..999d382 100644 --- a/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart +++ b/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart @@ -119,7 +119,7 @@ class TrackingScreen extends StatelessWidget { backgroundColor: AppColors.lightRedButtonColor, borderColor: Colors.transparent, text: "Share Your Live Locatin on Whatsapp".needTranslation, - fontSize: 12.fSize, + fontSize: 12.f, textColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor, onPressed: () {}, @@ -244,7 +244,7 @@ class TrackingScreen extends StatelessWidget { TextSpan( text: "Please wait for the call".needTranslation, style: TextStyle( - fontSize: 21.fSize, + fontSize: 21.f, fontWeight: FontWeight.w600, color: AppColors.textColor, ), @@ -252,7 +252,7 @@ class TrackingScreen extends StatelessWidget { TextSpan( text: "...".needTranslation, style: TextStyle( - fontSize: 21.fSize, + fontSize: 21.f, fontWeight: FontWeight.w600, color: AppColors.errorColor, ), @@ -265,7 +265,7 @@ class TrackingScreen extends StatelessWidget { TextSpan( text: "15:30".needTranslation, style: TextStyle( - fontSize: 21.fSize, + fontSize: 21.f, fontWeight: FontWeight.w600, color: AppColors.textColor, ), @@ -273,7 +273,7 @@ class TrackingScreen extends StatelessWidget { TextSpan( text: " mins ".needTranslation, style: TextStyle( - fontSize: 21.fSize, + fontSize: 21.f, fontWeight: FontWeight.w600, color: AppColors.errorColor, ), @@ -281,7 +281,7 @@ class TrackingScreen extends StatelessWidget { TextSpan( text: "to hospital".needTranslation, style: TextStyle( - fontSize: 21.fSize, + fontSize: 21.f, fontWeight: FontWeight.w600, color: AppColors.textColor, ), diff --git a/lib/presentation/profile_settings/profile_settings.dart b/lib/presentation/profile_settings/profile_settings.dart index f5e2ef8..34e6988 100644 --- a/lib/presentation/profile_settings/profile_settings.dart +++ b/lib/presentation/profile_settings/profile_settings.dart @@ -277,7 +277,7 @@ class _ProfileSettingsState extends State { ? Switch( value: switchValue, onChanged: (value) {}, - activeThumbColor: AppColors.successColor, + // activeThumbColor: AppColors.successColor, activeTrackColor: AppColors.successColor.withValues(alpha: .15), ) : Transform.scale( diff --git a/lib/presentation/radiology/radiology_orders_page.dart b/lib/presentation/radiology/radiology_orders_page.dart index 6662a8e..bc55f10 100644 --- a/lib/presentation/radiology/radiology_orders_page.dart +++ b/lib/presentation/radiology/radiology_orders_page.dart @@ -4,6 +4,7 @@ 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/enums.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'; @@ -12,11 +13,13 @@ 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/presentation/lab/lab_result_item_view.dart'; +import 'package:hmg_patient_app_new/presentation/radiology/search_radiology.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/presentation/radiology/radiology_result_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/chip/app_custom_chip_widget.dart'; +import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart'; import 'package:provider/provider.dart'; @@ -32,7 +35,7 @@ class RadiologyOrdersPage extends StatefulWidget { class _RadiologyOrdersPageState extends State { late RadiologyViewModel radiologyViewModel; - + String selectedFilterText =''; int? expandedIndex; @override @@ -50,6 +53,24 @@ class _RadiologyOrdersPageState extends State { backgroundColor: AppColors.bgScaffoldColor, body: CollapsingListView( title: LocaleKeys.radiology.tr(context: context), + search: () async { + final lavVM = Provider.of(context, listen: false); + if (lavVM.isLabOrdersLoading) { + return; + } else { + String? value = await Navigator.of(context).push( + CustomPageRoute( + page: SearchRadiologyContent(radiologySuggestionsList: radiologyViewModel.radiologySuggestions), + fullScreenDialog: true, + direction: AxisDirection.down, + ), + ); + if (value != null) { + selectedFilterText = value; + radiologyViewModel.filterRadiologyReports(value); + } + } + }, child: SingleChildScrollView( child: Consumer( builder: (context, model, child) { @@ -58,7 +79,20 @@ class _RadiologyOrdersPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Expandable list + selectedFilterText!.isNotEmpty + ? AppCustomChipWidget( + labelText: selectedFilterText!, + deleteIcon:'assets/images/svg/cross_circle.svg', + onChipTap: (){ + setState(() { + selectedFilterText =''; + model.filterRadiologyReports(''); + }); + }, + // chipType: ChipTypeEnum.alert, + // isSelected: true, + ) + : SizedBox(), ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), diff --git a/lib/presentation/radiology/search_radiology.dart b/lib/presentation/radiology/search_radiology.dart new file mode 100644 index 0000000..98f5c90 --- /dev/null +++ b/lib/presentation/radiology/search_radiology.dart @@ -0,0 +1,154 @@ +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/extensions/string_extensions.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.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/input_widget.dart'; +import 'package:sizer/sizer.dart'; + +class SearchRadiologyContent extends StatefulWidget { + final List radiologySuggestionsList; + + const SearchRadiologyContent({super.key, required this.radiologySuggestionsList}); + + @override + State createState() => _SearchRadiologyContentContentState(); +} + +class _SearchRadiologyContentContentState extends State { + TextEditingController searchEditingController = TextEditingController(); + List filteredSuggestions = []; + + @override + void initState() { + super.initState(); + filteredSuggestions = List.from(widget.radiologySuggestionsList); + + // Listen for changes in the search field + searchEditingController.addListener(() { + filterSuggestions(); + }); + } + + @override + void dispose() { + searchEditingController.dispose(); + super.dispose(); + } + + void filterSuggestions() { + final query = searchEditingController.text.toLowerCase(); + + if (query.isEmpty) { + setState(() { + filteredSuggestions = List.from(widget.radiologySuggestionsList); + }); + } else { + setState(() { + filteredSuggestions = widget.radiologySuggestionsList.where((suggestion) => suggestion.toLowerCase().contains(query)).toList(); + }); + } + } + + @override + Widget build(BuildContext context) { + return CollapsingListView( + title: LocaleKeys.radiology.tr(), + isClose: true, + bottomChild: Container( + color: Colors.white, + padding: EdgeInsets.all(ResponsiveExtension(20).h), + child: CustomButton( + text: LocaleKeys.search.tr(), + icon: AppAssets.search_icon, + iconColor: Colors.white, + onPressed: () => Navigator.pop(context, searchEditingController.text), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 24, right: 24, top: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextInputWidget( + labelText: "Search radiology results", + hintText: "Type test description", + controller: searchEditingController, + isEnable: true, + prefix: null, + autoFocus: false, + isBorderAllowed: false, + keyboardType: TextInputType.text, + padding: EdgeInsets.symmetric( + vertical: ResponsiveExtension(9).h, + horizontal: ResponsiveExtension(15).h, + ), + ), + SizedBox(height: ResponsiveExtension(20).h), + if (filteredSuggestions.isNotEmpty) ...[ + "Suggestions".toText16(isBold: true), + ], + ], + ), + ), + SingleChildScrollView( + physics: NeverScrollableScrollPhysics(), + padding: const EdgeInsets.only(left: 24, right: 24, bottom: 24, top: 16), + child: Wrap( + alignment: WrapAlignment.start, + spacing: 10, + runSpacing: 10, + children: filteredSuggestions + .map((label) => SuggestionChip( + label: label, + onTap: () { + searchEditingController.text = label; + }, + )) + .toList(), + ), + ), + ], + ), + ); + } +} + +class SuggestionChip extends StatelessWidget { + final String label; + final bool isSelected; + final VoidCallback? onTap; + + const SuggestionChip({ + super.key, + required this.label, + this.isSelected = false, + this.onTap, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8), + decoration: BoxDecoration( + color: isSelected ? AppColors.primaryRedColor : AppColors.whiteColor, + borderRadius: BorderRadius.circular(8), + ), + child: label.toText12( + color: isSelected ? Colors.white : Colors.black87, + fontWeight: FontWeight.w500, + ), + ), + ); + } +}