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.
		
		
		
		
		
			
		
			
				
	
	
		
			267 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			267 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Dart
		
	
| import 'package:flutter/material.dart';
 | |
| import 'package:hijri_gregorian_calendar/hijri_gregorian_calendar.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/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/theme/colors.dart';
 | |
| import 'package:hmg_patient_app_new/widgets/dropdown/country_dropdown_widget.dart';
 | |
| import 'package:keyboard_actions/keyboard_actions.dart';
 | |
| 
 | |
| import '../core/dependencies.dart';
 | |
| 
 | |
| // TODO: Import AppColors if bgRedColor is defined there
 | |
| // import 'package:hmg_patient_app_new/core/ui_utils/app_colors.dart';
 | |
| 
 | |
| class TextInputWidget extends StatelessWidget {
 | |
|   final String labelText;
 | |
|   final String hintText;
 | |
|   final TextEditingController? controller;
 | |
|   final Function(String?)? onChange;
 | |
|   final Function(bool)? onCalendarTypeChanged;
 | |
|   final String? prefix;
 | |
|   final bool isEnable;
 | |
|   final bool isBorderAllowed;
 | |
|   final bool isAllowRadius;
 | |
|   final bool isReadOnly;
 | |
|   final TextInputType keyboardType;
 | |
|   final FocusNode? focusNode;
 | |
|   final bool autoFocus;
 | |
|   final EdgeInsetsGeometry? padding;
 | |
|   final bool isAllowLeadingIcon;
 | |
|   final String? leadingIcon;
 | |
|   final bool isCountryDropDown;
 | |
|   final bool hasError;
 | |
|   final String? errorMessage;
 | |
|   Function(CountryEnum)? onCountryChange;
 | |
|   final SelectionTypeEnum? selectionType;
 | |
|   final num? fontSize;
 | |
|   final bool? isWalletAmountInput;
 | |
|   final Widget? suffix;
 | |
| 
 | |
|   // final List<Country> countryList;
 | |
|   // final Function(Country)? onCountryChange;
 | |
| 
 | |
|   TextInputWidget({
 | |
|     super.key,
 | |
|     required this.labelText,
 | |
|     required this.hintText,
 | |
|     this.controller,
 | |
|     this.onChange,
 | |
|     this.onCalendarTypeChanged,
 | |
|     this.prefix,
 | |
|     this.isEnable = true,
 | |
|     this.isBorderAllowed = true,
 | |
|     this.isAllowRadius = true,
 | |
|     this.isReadOnly = false,
 | |
|     this.keyboardType = TextInputType.number,
 | |
|     this.focusNode,
 | |
|     this.autoFocus = false,
 | |
|     this.padding,
 | |
|     this.isAllowLeadingIcon = false,
 | |
|     this.leadingIcon,
 | |
|     this.isCountryDropDown = false,
 | |
|     this.hasError = false,
 | |
|     this.errorMessage,
 | |
|     this.onCountryChange,
 | |
|     this.selectionType,
 | |
|     this.fontSize = 14,
 | |
|     this.isWalletAmountInput = false,
 | |
|     this.suffix,
 | |
|     // this.countryList = const [],
 | |
|     // this.onCountryChange,
 | |
|   });
 | |
| 
 | |
|   final FocusNode _focusNode = FocusNode();
 | |
| 
 | |
|   // KeyboardActionsConfig get _keyboardActionsConfig {
 | |
|   //   return KeyboardActionsConfig(
 | |
|   //     keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
 | |
|   //     keyboardBarColor: const Color(0xFFCAD1D9), //Apple keyboard color
 | |
|   //     actions: [
 | |
|   //       KeyboardActionsItem(
 | |
|   //         focusNode: focusNode ?? _focusNode,
 | |
|   //         toolbarButtons: [
 | |
|   //           (node) {
 | |
|   //             return GestureDetector(
 | |
|   //               onTap: () => node.unfocus(),
 | |
|   //               child: Container(
 | |
|   //                 padding: const EdgeInsets.all(12.0),
 | |
|   //                 child: "Done".toText16(weight: FontWeight.w500, color: AppColors.infoColor),
 | |
|   //               ),
 | |
|   //             );
 | |
|   //           }
 | |
|   //         ],
 | |
|   //       ),
 | |
|   //     ],
 | |
|   //   );
 | |
|   // }
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     AppState appState = getIt.get<AppState>();
 | |
|     final errorColor = AppColors.primaryRedColor;
 | |
|     return Column(
 | |
|       mainAxisSize: MainAxisSize.min,
 | |
|       crossAxisAlignment: CrossAxisAlignment.start,
 | |
|       children: [
 | |
|         Container(
 | |
|           padding: padding,
 | |
|           alignment: Alignment.center,
 | |
|           decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
 | |
|             color: Colors.white,
 | |
|             borderRadius: isAllowRadius ? 12 : null,
 | |
|             side: isBorderAllowed ? BorderSide(color: hasError ? errorColor : const Color(0xffefefef), width: 1) : null,
 | |
|           ),
 | |
|           child: Row(
 | |
|             textDirection: Directionality.of(context),
 | |
|             children: [
 | |
|               if (isAllowLeadingIcon && leadingIcon != null && !isCountryDropDown) _buildLeadingIcon(context),
 | |
|               isCountryDropDown
 | |
|                   ? CustomCountryDropdown(
 | |
|                       countryList: CountryEnum.values,
 | |
|                       onCountryChange: onCountryChange,
 | |
|                       isRtl: Directionality.of(context) == TextDirection.rtl,
 | |
|                       isFromBottomSheet: isCountryDropDown,
 | |
|                       isEnableTextField: true,
 | |
|                       onPhoneNumberChanged: onChange,
 | |
|                       // textField: _buildTextField(context),
 | |
|                     )
 | |
|                   : Expanded(
 | |
|                       child: Column(
 | |
|                         mainAxisSize: MainAxisSize.min,
 | |
|                         crossAxisAlignment: CrossAxisAlignment.start,
 | |
|                         children: [
 | |
|                           _buildLabelText().paddingOnly(right: (appState.getLanguageCode() == "ar" ? 10 : 0)),
 | |
|                           _buildTextField(context),
 | |
|                         ],
 | |
|                       ),
 | |
|                     ),
 | |
|               if (selectionType == SelectionTypeEnum.calendar) _buildTrailingIcon(context),
 | |
|               if (selectionType == SelectionTypeEnum.search) _buildTrailingIconForSearch(context),
 | |
|             ],
 | |
|           ),
 | |
|         ),
 | |
|         if (hasError && errorMessage != null)
 | |
|           Padding(
 | |
|             padding: EdgeInsets.only(top: 4.h, left: 12.h), // Adjust padding as needed
 | |
|             child: Text(
 | |
|               errorMessage!,
 | |
|               style: TextStyle(
 | |
|                 color: errorColor,
 | |
|                 fontSize: 12.fSize,
 | |
|               ),
 | |
|             ),
 | |
|           ),
 | |
|       ],
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _buildLeadingIcon(BuildContext context) {
 | |
|     return Container(
 | |
|         height: 40.h,
 | |
|         width: 40.h,
 | |
|         margin: EdgeInsets.only(right: 10.h),
 | |
|         padding: EdgeInsets.all(8.h),
 | |
|         decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
 | |
|           borderRadius: 10.h,
 | |
|           color: AppColors.greyColor,
 | |
|         ),
 | |
|         child: Utils.buildSvgWithAssets(icon: leadingIcon!));
 | |
|   }
 | |
| 
 | |
|   Widget _buildTrailingIcon(BuildContext context) {
 | |
|     final AppState appState = getIt.get<AppState>();
 | |
|     return Container(
 | |
|       height: 40.h,
 | |
|       width: 40.h,
 | |
|       margin: EdgeInsets.zero,
 | |
|       padding: EdgeInsets.all(8.h),
 | |
|       decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 10.h, color: AppColors.whiteColor),
 | |
|       child: GestureDetector(
 | |
|         onTap: () async {
 | |
|           bool isGregorian = true;
 | |
|           final picked = await showHijriGregBottomSheet(context,
 | |
|               isShowTimeSlots: true,
 | |
|               switcherIcon: Utils.buildSvgWithAssets(icon: AppAssets.language, width: 24.h, height: 24.h),
 | |
|               language: appState.getLanguageCode()!,
 | |
|               initialDate: DateTime.now(),
 | |
|               okWidget: Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.confirm, width: 24.h, height: 24.h)),
 | |
|               cancelWidget: Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.cancel, iconColor: Colors.white, width: 24.h, height: 24.h)),
 | |
|               onCalendarTypeChanged: (bool value) {
 | |
|             isGregorian = value;
 | |
|           });
 | |
|           if (picked != null && onChange != null) {
 | |
|             if (onCalendarTypeChanged != null) {
 | |
|               onCalendarTypeChanged!.call(isGregorian);
 | |
|             }
 | |
|             onChange!(picked.toString());
 | |
|           }
 | |
|         },
 | |
|         child: Utils.buildSvgWithAssets(icon: AppAssets.calendar),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _buildLabelText() {
 | |
|     return Text(
 | |
|       labelText,
 | |
|       style: TextStyle(
 | |
|         fontSize: 12.fSize,
 | |
|         fontWeight: FontWeight.w500,
 | |
|         color: AppColors.inputLabelTextColor,
 | |
|         letterSpacing: -0.2,
 | |
|         height: 18 / 12,
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _buildTextField(BuildContext context) {
 | |
|     return TextField(
 | |
|       enabled: isEnable,
 | |
|       scrollPadding: EdgeInsets.zero,
 | |
|       keyboardType: keyboardType,
 | |
|       controller: controller,
 | |
|       readOnly: isReadOnly,
 | |
|       textAlignVertical: TextAlignVertical.top,
 | |
|       textAlign: TextAlign.left,
 | |
|       textDirection: TextDirection.ltr,
 | |
|       onChanged: onChange,
 | |
|       focusNode: focusNode ?? _focusNode,
 | |
|       autofocus: autoFocus,
 | |
|       textInputAction: TextInputAction.done,
 | |
|       cursorHeight: isWalletAmountInput! ? 40.h : 20.h,
 | |
|       onTapOutside: (event) {
 | |
|         FocusManager.instance.primaryFocus?.unfocus();
 | |
|       },
 | |
|       style: TextStyle(fontSize: fontSize!.fSize, height: isWalletAmountInput! ? 1 / 4 : 21 / 14, fontWeight: FontWeight.w500, color: AppColors.textColor, letterSpacing: -0.2),
 | |
|       decoration: InputDecoration(
 | |
|         isDense: true,
 | |
|         hintText: hintText,
 | |
|         hintStyle: TextStyle(fontSize: 14.fSize, height: 21 / 16, fontWeight: FontWeight.w500, color: Color(0xff898A8D), letterSpacing: -1),
 | |
|         prefixIconConstraints: BoxConstraints(minWidth: 30.h),
 | |
|         prefixIcon: prefix == null ? null : "+${prefix!}".toText14(letterSpacing: -1, color: AppColors.textColor, weight: FontWeight.w500),
 | |
|         contentPadding: EdgeInsets.zero,
 | |
|         border: InputBorder.none,
 | |
|         focusedBorder: InputBorder.none,
 | |
|         enabledBorder: InputBorder.none,
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   _buildTrailingIconForSearch(BuildContext context) {
 | |
|     final AppState appState = getIt.get<AppState>();
 | |
|     return Container(
 | |
|       height: 40.h,
 | |
|       width: 40.h,
 | |
|       margin: EdgeInsets.zero,
 | |
|       padding: EdgeInsets.all(8.h),
 | |
|       decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 10.h, color: AppColors.whiteColor),
 | |
|       child: Utils.buildSvgWithAssets(icon: AppAssets.search_icon),
 | |
|     );
 | |
|   }
 | |
| }
 |