import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hoshan/core/utils/strings.dart'; import 'package:hoshan/data/model/edittext_state_model.dart'; import 'package:hoshan/ui/theme/colors.dart'; import 'package:hoshan/ui/theme/text.dart'; import 'package:hoshan/ui/widgets/components/dropdown/hint_tooltip.dart'; import 'package:hoshan/ui/widgets/components/snackbar/snackbar_manager.dart'; class LabeledTextField extends StatefulWidget { final EdittextStateModel? stateController; final Function(String)? onChange; final String? Function(String?)? onValid; final int? maxLength; final TextInputAction textInputAction; final Widget? suffix; final Widget? error; final Widget? success; final bool isPassword; final bool enabled; final int? minLines; final int? maxLines; final TextStyle? hintStyle; final bool showLabel; final bool justEnglish; const LabeledTextField( {super.key, this.onChange, this.maxLength, this.suffix, this.error, this.success, this.isPassword = false, this.enabled = true, this.minLines, this.maxLines, this.onValid, this.stateController, this.hintStyle, this.textInputAction = TextInputAction.done, this.showLabel = true, this.justEnglish = false}); @override State createState() => _LabeledTextFieldState(); } class _LabeledTextFieldState extends State { String text = ''; bool resetError = false; bool isPassword = false; @override Widget build(BuildContext context) { return Directionality( textDirection: TextDirection.rtl, child: Form( key: widget.stateController?.formState, child: TextFormField( textInputAction: widget.minLines != null && widget.minLines! > 1 ? TextInputAction.newline : widget.textInputAction, controller: widget.stateController?.formController, onChanged: (value) { widget.onChange?.call(value); setState(() { text = value; resetError = true; widget.stateController?.formState.currentState?.validate(); }); }, validator: (value) { if (resetError) { resetError = false; return null; } return widget.onValid?.call(value); }, inputFormatters: widget.justEnglish ? [ TextInputFormatter.withFunction((oldValue, newValue) { if (!newValue.text.containsOnlyEnglish()) { SnackBarManager(context, id: 'justTypeEnglish').show( status: SnackBarStatus.info, message: 'نام کاربری باید فقط شامل حروف انگلیسی باشد', ); return oldValue; } return newValue; }), ] : null, maxLength: widget.maxLength, obscureText: widget.isPassword && isPassword, style: AppTextStyles.body4 .copyWith(color: Theme.of(context).colorScheme.onSurface), minLines: widget.minLines, maxLines: widget.maxLines, textDirection: text.startsWithEnglish() ? TextDirection.ltr : TextDirection.rtl, decoration: InputDecoration( labelStyle: AppTextStyles.body4 .copyWith(color: AppColors.primaryColor.defaultShade), errorStyle: AppTextStyles.body4.copyWith( color: AppColors.red.defaultShade, fontWeight: FontWeight.bold), hintText: widget.stateController?.hintText, hintStyle: widget.hintStyle ?? AppTextStyles.body5, contentPadding: const EdgeInsets.all(18), error: widget.error ?? widget.success, enabled: widget.enabled, floatingLabelBehavior: FloatingLabelBehavior.always, // Add this line label: widget.stateController?.label != null ? Opacity( opacity: widget.showLabel ? 1 : 0, child: Row( mainAxisSize: MainAxisSize.min, children: [ if (widget.stateController?.tooltipHint != null) Row( children: [ HintTooltip( hint: widget.stateController!.tooltipHint!), const SizedBox( width: 12, ), ], ), Text( widget.stateController?.label ?? '', style: AppTextStyles.body2.copyWith( color: Theme.of(context).colorScheme.primary), ), if (!widget.showLabel) const SizedBox( width: 16, ), ], ), ) : null, fillColor: AppColors.primaryColor.defaultShade, focusColor: AppColors.primaryColor.defaultShade, border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: AppColors.primaryColor.defaultShade)), focusedErrorBorder: OutlineInputBorder( borderSide: BorderSide( color: widget.success != null ? AppColors.green.defaultShade : AppColors.red.defaultShade, width: 2)), errorBorder: OutlineInputBorder( borderSide: BorderSide( color: widget.success != null ? AppColors.green.defaultShade : AppColors.red.defaultShade, width: 2)), focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: AppColors.primaryColor.defaultShade, width: 2)), ), ), ), ); } }