You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			220 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			220 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Dart
		
	
| import 'package:easy_localization/easy_localization.dart';
 | |
| import 'package:flutter/material.dart';
 | |
| import 'package:hmg_patient_app_new/core/app_assets.dart';
 | |
| import 'package:hmg_patient_app_new/core/app_state.dart';
 | |
| import 'package:hmg_patient_app_new/core/dependencies.dart';
 | |
| import 'package:hmg_patient_app_new/core/enums.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';
 | |
| 
 | |
| class CustomCountryDropdown extends StatefulWidget {
 | |
|   final List<CountryEnum> countryList;
 | |
|   final Function(CountryEnum)? onCountryChange;
 | |
|   final Function(String)? onPhoneNumberChanged;
 | |
|   final bool isRtl;
 | |
|   final bool isFromBottomSheet;
 | |
|   final bool isEnableTextField;
 | |
|   Widget? textField;
 | |
| 
 | |
|   CustomCountryDropdown({
 | |
|     Key? key,
 | |
|     required this.countryList,
 | |
|     this.onCountryChange,
 | |
|     this.onPhoneNumberChanged,
 | |
|     required this.isRtl,
 | |
|     this.isFromBottomSheet = false,
 | |
|     this.isEnableTextField = false,
 | |
|     this.textField,
 | |
|   }) : super(key: key);
 | |
| 
 | |
|   @override
 | |
|   _CustomCountryDropdownState createState() => _CustomCountryDropdownState();
 | |
| }
 | |
| 
 | |
| class _CustomCountryDropdownState extends State<CustomCountryDropdown> {
 | |
|   CountryEnum? selectedCountry;
 | |
|   late OverlayEntry _overlayEntry;
 | |
|   bool _isDropdownOpen = false;
 | |
|   FocusNode textFocusNode = new FocusNode();
 | |
| 
 | |
|   @override
 | |
|   void initState() {
 | |
|     super.initState();
 | |
|     selectedCountry = CountryEnum.saudiArabia;
 | |
| 
 | |
|     if (widget.isEnableTextField && widget.isFromBottomSheet) {
 | |
|       WidgetsBinding.instance.addPostFrameCallback((_) {
 | |
|         if (mounted && textFocusNode.canRequestFocus) {
 | |
|           FocusScope.of(context).requestFocus(textFocusNode);
 | |
|         }
 | |
|       });
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void dispose() {
 | |
|     textFocusNode.dispose();
 | |
|     super.dispose();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     AppState appState = getIt.get<AppState>();
 | |
|     return Container(
 | |
|       height: 40.h,
 | |
|       decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 10.h),
 | |
|       child: Row(
 | |
|         children: [
 | |
|           GestureDetector(
 | |
|               onTap: () {
 | |
|                 if (_isDropdownOpen) {
 | |
|                   _closeDropdown();
 | |
|                 } else {
 | |
|                   _openDropdown();
 | |
|                 }
 | |
|               },
 | |
|               child: Utils.buildSvgWithAssets(icon: selectedCountry != null ? selectedCountry!.iconPath : AppAssets.ksa, width: 40.h, height: 40.h)),
 | |
|           SizedBox(width: 8.h),
 | |
|           Utils.buildSvgWithAssets(icon: _isDropdownOpen ? AppAssets.dropdow_icon : AppAssets.dropdow_icon),
 | |
|           SizedBox(width: 4.h),
 | |
|           if (widget.isFromBottomSheet)
 | |
|             GestureDetector(
 | |
|               onTap: () {
 | |
|                 if (widget.isEnableTextField && textFocusNode.canRequestFocus) {
 | |
|                   FocusScope.of(context).requestFocus(textFocusNode);
 | |
|                 }
 | |
|               },
 | |
|               child: Column(
 | |
|                 crossAxisAlignment: CrossAxisAlignment.start,
 | |
|                 mainAxisAlignment: MainAxisAlignment.start,
 | |
|                 children: [
 | |
|                   Row(
 | |
|                     children: [
 | |
|                       Text(
 | |
|                         LocaleKeys.phoneNumber.tr(),
 | |
|                         style: TextStyle(fontSize: 12.fSize, height: 21 / 12, fontWeight: FontWeight.w500, letterSpacing: -1),
 | |
|                       ),
 | |
|                     ],
 | |
|                   ),
 | |
|                   Row(
 | |
|                     children: [
 | |
|                       Text(
 | |
|                         selectedCountry!.countryCode,
 | |
|                         style: TextStyle(fontSize: 12.fSize, height: 21 / 18, fontWeight: FontWeight.w600, letterSpacing: -0.2),
 | |
|                       ),
 | |
|                       SizedBox(width: 4.h),
 | |
|                       if (widget.isEnableTextField)
 | |
|                         SizedBox(
 | |
|                           height: 18,
 | |
|                           width: 200,
 | |
|                           child: TextField(
 | |
|                               focusNode: textFocusNode,
 | |
|                               decoration: InputDecoration(hintText: "", isDense: true, border: InputBorder.none),
 | |
|                               keyboardType: TextInputType.phone,
 | |
|                               onChanged: widget.onPhoneNumberChanged),
 | |
|                         ),
 | |
|                     ],
 | |
|                   )
 | |
|                 ],
 | |
|               ),
 | |
|             ),
 | |
|           if (!widget.isFromBottomSheet)
 | |
|             Text(
 | |
|               selectedCountry != null
 | |
|                   ? appState.getLanguageCode() == "ar"
 | |
|                       ? selectedCountry!.nameArabic
 | |
|                       : selectedCountry!.displayName
 | |
|                   : "Select Country",
 | |
|               style: TextStyle(fontSize: 14.fSize, height: 21 / 14, fontWeight: FontWeight.w500, letterSpacing: -0.2),
 | |
|             ),
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   void _openDropdown() {
 | |
|     if (textFocusNode.hasFocus) {
 | |
|       textFocusNode.unfocus();
 | |
|     }
 | |
|     AppState appState = getIt.get<AppState>();
 | |
|     RenderBox renderBox = context.findRenderObject() as RenderBox;
 | |
|     Offset offset = renderBox.localToGlobal(Offset.zero);
 | |
| 
 | |
|     _overlayEntry = OverlayEntry(
 | |
|       builder: (context) => Stack(
 | |
|         children: [
 | |
|           // Dismiss dropdown when tapping outside
 | |
|           Positioned.fill(
 | |
|             child: GestureDetector(
 | |
|               onTap: _closeDropdown,
 | |
|               behavior: HitTestBehavior.translucent,
 | |
|               child: Container(),
 | |
|             ),
 | |
|           ),
 | |
|           Positioned(
 | |
|             top: offset.dy + renderBox.size.height,
 | |
|             left: widget.isRtl ? offset.dx + 6.h : offset.dx - 6.h,
 | |
|             width: renderBox.size.width,
 | |
|             child: Material(
 | |
|               child: Container(
 | |
|                 decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: Colors.white, borderRadius: 12),
 | |
|                 child: Column(
 | |
|                   children: widget.countryList
 | |
|                       .map(
 | |
|                         (country) => GestureDetector(
 | |
|                           onTap: () {
 | |
|                             setState(() {
 | |
|                               selectedCountry = country;
 | |
|                             });
 | |
|                             widget.onCountryChange?.call(country);
 | |
|                             _closeDropdown();
 | |
|                           },
 | |
|                           child: Container(
 | |
|                             padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h),
 | |
|                             decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 16.h),
 | |
|                             child: Row(
 | |
|                               children: [
 | |
|                                 Utils.buildSvgWithAssets(icon: country.iconPath, width: 38.h, height: 38.h),
 | |
|                                 if (!widget.isFromBottomSheet) SizedBox(width: 12.h),
 | |
|                                 if (!widget.isFromBottomSheet)
 | |
|                                   Text(appState.getLanguageCode() == "ar" ? country.nameArabic : country.displayName,
 | |
|                                       style: TextStyle(fontSize: 14.fSize, height: 21 / 14, fontWeight: FontWeight.w500, letterSpacing: -0.2)),
 | |
|                               ],
 | |
|                             ),
 | |
|                           ),
 | |
|                         ),
 | |
|                       )
 | |
|                       .toList(),
 | |
|                 ),
 | |
|               ),
 | |
|             ),
 | |
|           ),
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
| 
 | |
|     Overlay.of(context)?.insert(_overlayEntry);
 | |
|     setState(() {
 | |
|       _isDropdownOpen = true;
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   void _closeDropdown() {
 | |
|     _overlayEntry.remove();
 | |
|     setState(() {
 | |
|       _isDropdownOpen = false;
 | |
|     });
 | |
| 
 | |
|     if (widget.isEnableTextField && widget.isFromBottomSheet) {
 | |
|       Future.delayed(Duration(milliseconds: 100), () {
 | |
|         if (mounted && textFocusNode.canRequestFocus) {
 | |
|           FocusScope.of(context).requestFocus(textFocusNode);
 | |
|         }
 | |
|       });
 | |
|     }
 | |
|   }
 | |
| }
 |