Files
worker/lib/features/auth/presentation/widgets/phone_input_field.dart
2025-11-07 11:52:06 +07:00

134 lines
4.1 KiB
Dart

/// Phone Input Field Widget
///
/// Custom text field for Vietnamese phone number input.
/// Supports formats: 0xxx xxx xxx, +84xxx xxx xxx, 84xxx xxx xxx
library;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/theme/colors.dart';
/// Phone Input Field
///
/// A custom text field widget specifically designed for Vietnamese phone number input.
/// Features:
/// - Phone icon prefix
/// - Numeric keyboard
/// - Phone number formatting
/// - Vietnamese phone validation support
///
/// Usage:
/// ```dart
/// PhoneInputField(
/// controller: phoneController,
/// validator: Validators.phone,
/// onChanged: (value) {
/// // Handle phone number change
/// },
/// )
/// ```
class PhoneInputField extends StatelessWidget {
/// Creates a phone input field
const PhoneInputField({
super.key,
required this.controller,
this.focusNode,
this.validator,
this.onChanged,
this.onFieldSubmitted,
this.enabled = true,
this.autofocus = false,
});
/// Text editing controller
final TextEditingController controller;
/// Focus node for keyboard focus management
final FocusNode? focusNode;
/// Form field validator
final String? Function(String?)? validator;
/// Callback when text changes
final void Function(String)? onChanged;
/// Callback when field is submitted
final void Function(String)? onFieldSubmitted;
/// Whether the field is enabled
final bool enabled;
/// Whether the field should auto-focus
final bool autofocus;
@override
Widget build(BuildContext context) {
return TextFormField(
controller: controller,
focusNode: focusNode,
autofocus: autofocus,
enabled: enabled,
keyboardType: TextInputType.phone,
textInputAction: TextInputAction.next,
inputFormatters: [
// Allow digits, spaces, +, and parentheses
FilteringTextInputFormatter.allow(RegExp(r'[0-9+\s()]')),
// Limit to reasonable phone length
LengthLimitingTextInputFormatter(15),
],
style: const TextStyle(
fontSize: InputFieldSpecs.fontSize,
color: AppColors.grey900,
),
decoration: InputDecoration(
labelText: 'Số điện thoại',
labelStyle: const TextStyle(
fontSize: InputFieldSpecs.labelFontSize,
color: AppColors.grey500,
),
hintText: 'Nhập số điện thoại',
hintStyle: const TextStyle(
fontSize: InputFieldSpecs.hintFontSize,
color: AppColors.grey500,
),
prefixIcon: const Icon(
Icons.phone,
color: AppColors.primaryBlue,
size: AppIconSize.md,
),
filled: true,
fillColor: AppColors.white,
contentPadding: InputFieldSpecs.contentPadding,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius),
borderSide: const BorderSide(color: AppColors.grey100, width: 1.0),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius),
borderSide: const BorderSide(color: AppColors.grey100, width: 1.0),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius),
borderSide: const BorderSide(
color: AppColors.primaryBlue,
width: 2.0,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius),
borderSide: const BorderSide(color: AppColors.danger, width: 1.0),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(InputFieldSpecs.borderRadius),
borderSide: const BorderSide(color: AppColors.danger, width: 2.0),
),
errorStyle: const TextStyle(fontSize: 12.0, color: AppColors.danger),
),
validator: validator,
onChanged: onChanged,
onFieldSubmitted: onFieldSubmitted,
);
}
}