import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:mobile_monitoring/core/constants/colors.dart'; import 'package:mobile_monitoring/core/constants/app_settings.dart'; /// Custom TextField - Text input field yang reusable class CustomTextField extends StatefulWidget { final TextEditingController? controller; final String? labelText; final String? hintText; final String? helperText; final String? errorText; final IconData? prefixIcon; final IconData? suffixIcon; final VoidCallback? onSuffixIconTap; final bool obscureText; final bool enabled; final bool readOnly; final TextInputType? keyboardType; final TextInputAction? textInputAction; final int? maxLines; final int? minLines; final int? maxLength; final List? inputFormatters; final String? Function(String?)? validator; final void Function(String)? onChanged; final void Function(String)? onSubmitted; final void Function()? onTap; final FocusNode? focusNode; final TextCapitalization textCapitalization; final bool autofocus; final bool showPasswordToggle; const CustomTextField({ super.key, this.controller, this.labelText, this.hintText, this.helperText, this.errorText, this.prefixIcon, this.suffixIcon, this.onSuffixIconTap, this.obscureText = false, this.enabled = true, this.readOnly = false, this.keyboardType, this.textInputAction, this.maxLines = 1, this.minLines, this.maxLength, this.inputFormatters, this.validator, this.onChanged, this.onSubmitted, this.onTap, this.focusNode, this.textCapitalization = TextCapitalization.none, this.autofocus = false, this.showPasswordToggle = false, }); @override State createState() => _CustomTextFieldState(); } class _CustomTextFieldState extends State { late bool _obscureText; @override void initState() { super.initState(); _obscureText = widget.obscureText; } @override void didUpdateWidget(CustomTextField oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.obscureText != widget.obscureText) { _obscureText = widget.obscureText; } } @override Widget build(BuildContext context) { return TextFormField( controller: widget.controller, obscureText: _obscureText, enabled: widget.enabled, readOnly: widget.readOnly, keyboardType: widget.keyboardType, textInputAction: widget.textInputAction, maxLines: _obscureText ? 1 : widget.maxLines, minLines: widget.minLines, maxLength: widget.maxLength, inputFormatters: widget.inputFormatters, validator: widget.validator, onChanged: widget.onChanged, onFieldSubmitted: widget.onSubmitted, onTap: widget.onTap, focusNode: widget.focusNode, textCapitalization: widget.textCapitalization, autofocus: widget.autofocus, style: TextStyle( color: widget.enabled ? AppColors.textPrimary : AppColors.textSecondary, fontSize: 16, ), decoration: InputDecoration( labelText: widget.labelText, hintText: widget.hintText, helperText: widget.helperText, errorText: widget.errorText, prefixIcon: widget.prefixIcon != null ? Icon( widget.prefixIcon, color: AppColors.textSecondary, ) : null, suffixIcon: _buildSuffixIcon(), filled: true, fillColor: widget.enabled ? AppColors.white : AppColors.lightGray, contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), border: OutlineInputBorder( borderRadius: BorderRadius.circular(AppSettings.defaultBorderRadius), borderSide: const BorderSide(color: AppColors.borderLight), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppSettings.defaultBorderRadius), borderSide: const BorderSide(color: AppColors.borderLight), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppSettings.defaultBorderRadius), borderSide: const BorderSide(color: AppColors.primary, width: 2), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppSettings.defaultBorderRadius), borderSide: const BorderSide(color: AppColors.error), ), focusedErrorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppSettings.defaultBorderRadius), borderSide: const BorderSide(color: AppColors.error, width: 2), ), disabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppSettings.defaultBorderRadius), borderSide: const BorderSide(color: AppColors.borderLight), ), ), ); } Widget? _buildSuffixIcon() { if (widget.showPasswordToggle && widget.obscureText) { return IconButton( icon: Icon( _obscureText ? Icons.visibility_off : Icons.visibility, color: AppColors.textSecondary, ), onPressed: () { setState(() { _obscureText = !_obscureText; }); }, ); } if (widget.suffixIcon != null) { return IconButton( icon: Icon( widget.suffixIcon, color: AppColors.textSecondary, ), onPressed: widget.onSuffixIconTap, ); } return null; } }