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.
		
		
		
		
		
			
		
			
				
	
	
		
			305 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			305 lines
		
	
	
		
			12 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 isFromBottomSheet;
 | |
|   final bool isEnableTextField;
 | |
|   Widget? textField;
 | |
| 
 | |
|   CustomCountryDropdown({
 | |
|     Key? key,
 | |
|     required this.countryList,
 | |
|     this.onCountryChange,
 | |
|     this.onPhoneNumberChanged,
 | |
|     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: Row(
 | |
|               children: [
 | |
|                 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: 1.2.h, fontWeight: FontWeight.w500, letterSpacing: -1),
 | |
|                       ),
 | |
|                     ],
 | |
|                   ),
 | |
|                   Row(
 | |
|                     crossAxisAlignment: CrossAxisAlignment.center,
 | |
|                     mainAxisAlignment: MainAxisAlignment.start,
 | |
|                     children: [
 | |
|                       Text(
 | |
|                         selectedCountry!.countryCode,
 | |
|                         style: TextStyle(fontSize: 12.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5),
 | |
|                       ),
 | |
|                       SizedBox(width: 4.h),
 | |
|                       if (widget.isEnableTextField)
 | |
|                         SizedBox(
 | |
|                           height: 20.h,
 | |
|                           width: 200.h,
 | |
|                           child: Align(
 | |
|                             alignment: Alignment.centerLeft,
 | |
|                             child: TextField(
 | |
|                               focusNode: textFocusNode,
 | |
|                               style: TextStyle(fontSize: 12.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5),
 | |
|                               decoration: InputDecoration(hintText: "", isDense: true, border: InputBorder.none, contentPadding: EdgeInsets.zero),
 | |
|                               keyboardType: TextInputType.phone,
 | |
|                               onChanged: widget.onPhoneNumberChanged,
 | |
|                             ),
 | |
|                           ),
 | |
|                         ),
 | |
|                     ],
 | |
|                   )
 | |
|                 ],
 | |
|               ),
 | |
|             ),
 | |
|           if (!widget.isFromBottomSheet)
 | |
|             Text(
 | |
|               selectedCountry != null
 | |
|                   ? appState.getLanguageCode() == "ar"
 | |
|                       ? selectedCountry!.nameArabic
 | |
|                       : selectedCountry!.displayName
 | |
|                   : LocaleKeys.selectCountry.tr(),
 | |
|               style: TextStyle(fontSize: 14.fSize, height: 21 / 14, fontWeight: FontWeight.w500, letterSpacing: -0.2),
 | |
|             ),
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   void _openDropdown() {
 | |
|     if (textFocusNode.hasFocus) {
 | |
|       textFocusNode.unfocus();
 | |
|       // Wait for keyboard to close before calculating position
 | |
|       Future.delayed(Duration(milliseconds: 300), () {
 | |
|         _showDropdown();
 | |
|       });
 | |
|     } else {
 | |
|       _showDropdown();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void _showDropdown() {
 | |
|     AppState appState = getIt.get<AppState>();
 | |
|     RenderBox renderBox = context.findRenderObject() as RenderBox;
 | |
|     Offset offset = renderBox.localToGlobal(Offset.zero);
 | |
| 
 | |
|     bool isRtl = appState.getLanguageCode() == "ar";
 | |
|     double leftPosition = isRtl ? offset.dx + 8 + renderBox.size.width - (!widget.isFromBottomSheet ? renderBox.size.width : 60.h) : offset.dx;
 | |
| 
 | |
|     _overlayEntry = OverlayEntry(
 | |
|       builder: (context) => Stack(
 | |
|         children: [
 | |
|           Positioned.fill(
 | |
|             child: GestureDetector(
 | |
|               onTap: _closeDropdown,
 | |
|               behavior: HitTestBehavior.translucent,
 | |
|               child: Container(),
 | |
|             ),
 | |
|           ),
 | |
|           Positioned(
 | |
|             top: offset.dy + renderBox.size.height,
 | |
|             left: leftPosition,
 | |
|             width: !widget.isFromBottomSheet ? renderBox.size.width : 60.h,
 | |
|             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 _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: [
 | |
|   //         Positioned.fill(
 | |
|   //           child: GestureDetector(
 | |
|   //             onTap: _closeDropdown,
 | |
|   //             behavior: HitTestBehavior.translucent,
 | |
|   //             child: Container(),
 | |
|   //           ),
 | |
|   //         ),
 | |
|   //         Positioned(
 | |
|   //           top: offset.dy + renderBox.size.height,
 | |
|   //           left: offset.dx,
 | |
|   //           width: !widget.isFromBottomSheet ? renderBox.size.width : 60.h,
 | |
|   //           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);
 | |
|         }
 | |
|       });
 | |
|     }
 | |
|   }
 | |
| }
 |