import 'package:hmg_patient_app/core/viewModels/project_view_model.dart'; import 'package:hmg_patient_app/models/mobile_number.dart'; import 'package:hmg_patient_app/uitl/translations_delegate_base.dart'; import 'package:hmg_patient_app/uitl/utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import '../../Constants.dart'; class PhoneNumberSelectorWidget extends StatefulWidget { final Function? onNumberChange; final Function? onCountryChange; final String? mobileNo; bool isLiveCareTypeSelect; bool isEnable; PhoneNumberSelectorWidget({Key? key, this.onNumberChange, this.onCountryChange, this.mobileNo, this.isLiveCareTypeSelect = false, this.isEnable = true}) : super(key: key); @override _PhoneNumberSelectorWidgetState createState() { return _PhoneNumberSelectorWidgetState(); } } class _PhoneNumberSelectorWidgetState extends State { var _selectedType = '+966'; String countryCode = '966'; List counties = []; ProjectViewModel? projectProvider; TextEditingController textController = new TextEditingController(); String? validationError; // Regular expression to detect KSA (+966) or UAE (+971) phone numbers // Matches: +966, 966, 00966, +971, 971, 00971 at the start final RegExp ksaUaePattern = RegExp(r'^(\+|00)?(966|971)'); @override void initState() { for (var element in countriesData) counties.add(Countries.fromJson(element)); super.initState(); } // Validate phone number when "Others" is selected String? validatePhoneNumber(String value) { if (countryCode == "0" && value.isNotEmpty) { // Check if the number starts with KSA or UAE country code if (ksaUaePattern.hasMatch(value)) { return projectProvider?.isArabic == true ? "يرجى عدم إدخال أرقام السعودية أو الإمارات. استخدم الخيار المناسب من القائمة" : "Please do not enter KSA or UAE numbers. Use the appropriate option from the list"; } } return null; } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { projectProvider = Provider.of(context); String? countryName = ""; if (widget.isLiveCareTypeSelect) { textController.text = Utils.getPhoneNumberWithoutZero(widget.mobileNo!); } for (var element in counties) { if (element.code == countryCode) { countryName = projectProvider!.isArabic == true ? element.nameAr : element.name; } } // Check if "Others" is selected (code == "0") bool isOthersSelected = countryCode == "0"; return Column( children: [ inputWidget(TranslationBase.of(context).country, countryName!, isEnable: true, hasSelection: true), SizedBox(height: 12), Directionality( textDirection: TextDirection.ltr, child: inputWidget( TranslationBase.of(context).phoneNumber, isEnable: widget.isEnable, widget.mobileNo ?? (isOthersSelected ? "001xxxxxxxxx" : "5xxxxxxxx"), prefix: isOthersSelected ? null : countryCode ) ), if (validationError != null) Container( width: double.infinity, margin: EdgeInsets.only(top: 8), child: Text( validationError!, style: TextStyle( color: Colors.red, fontSize: 12, fontWeight: FontWeight.w500, ), ), ), ], ); } Widget inputWidget(String _labelText, String _hintText, {String? prefix, bool isEnable = true, bool hasSelection = false}) { // Check if "Others" is selected bool isOthersSelected = countryCode == "0"; return Container( padding: EdgeInsets.only(left: 16, right: 16, bottom: 15, top: 15), alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.white, border: Border.all( color: validationError != null ? Colors.red : Color(0xffefefef), width: validationError != null ? 1.5 : 1, ), ), child: PopupMenuButton( tooltip: "", child: Row( children: [ Expanded( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _labelText, style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.44, ), ), TextField( controller: hasSelection ? null : textController, enabled: isEnable, scrollPadding: EdgeInsets.zero, keyboardType: isOthersSelected ? TextInputType.phone : TextInputType.number, onChanged: (value) { // Validate the phone number setState(() { validationError = validatePhoneNumber(value); }); // Only call the callback if validation passes if (validationError == null) { widget.onNumberChange!(value); } else { // Call with empty value to invalidate the form widget.onNumberChange!(""); } }, style: TextStyle( fontSize: 14, height: 21 / 14, fontWeight: FontWeight.w400, color: Color(0xff2B353E), letterSpacing: -0.44, ), decoration: InputDecoration( isDense: true, hintText: _hintText, hintStyle: TextStyle( fontSize: 14, height: 21 / 14, fontWeight: FontWeight.w400, color: Color(0xff575757), letterSpacing: -0.56, ), prefixIconConstraints: BoxConstraints(minWidth: 50), prefixIcon: prefix == null ? null : Text( prefix, style: TextStyle( fontSize: 14, height: 21 / 14, fontWeight: FontWeight.w500, color: Color(0xff2E303A), letterSpacing: -0.56, ), ), contentPadding: EdgeInsets.zero, border: InputBorder.none, focusedBorder: InputBorder.none, enabledBorder: InputBorder.none, errorBorder: InputBorder.none, focusedErrorBorder: InputBorder.none, ), ), ], ), ), if (hasSelection) Icon(Icons.keyboard_arrow_down_outlined), ], ), itemBuilder: (_) => >[ if (hasSelection) for (var country in counties) PopupMenuItem(child: Text(projectProvider!.isArabic == true ? country.nameAr! : country.name!), value: country.code) ], onSelected: (countryCode) { setState(() { this.countryCode = countryCode; _selectedType = countryCode; // Clear the text field and validation error when switching to/from "Others" if (countryCode == "0" || this.countryCode == "0") { textController.clear(); validationError = null; } }); widget.onCountryChange!(countryCode); }, )); } } class MobileNo extends StatefulWidget { final bool disabled; final double margin; final double marginTop; final double marginRight; final double marginBottom; final double marginLeft; final TextEditingController? controller; final Function? onNumberChange; final Function? onCountryChange; MobileNo({this.disabled = false, this.marginTop = 0, this.marginRight = 0, this.marginBottom = 0, this.controller, this.marginLeft = 0, this.onNumberChange, this.onCountryChange, this.margin = 0}); @override _MobileNo createState() => _MobileNo(); } class _MobileNo extends State { var _selectedType = '+966'; String countryCode = '+966'; List counties = []; ProjectViewModel? projectProvider; @override void initState() { countriesData.forEach((element) { this.counties.add(Countries.fromJson(element)); }); super.initState(); } @override Widget build(BuildContext context) { projectProvider = Provider.of(context); return Visibility( child: Column(children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded( child: Container( margin: EdgeInsets.only(bottom: 10.0), height: 60.0, decoration: BoxDecoration( color: Colors.white, border: Border.all( color: Colors.grey[400]!, width: 1.0, ), borderRadius: BorderRadius.circular(10), ), width: MediaQuery.of(context).size.width * 0.89, child: Padding( padding: EdgeInsets.all(10), child: DropdownButtonHideUnderline( child: DropdownButton( isExpanded: true, value: _selectedType, iconSize: 40, elevation: 16, onChanged: (value) => { widget.onCountryChange!(value), setState(() { countryCode = value!; _selectedType = value!; }) }, items: counties.map>((Countries value) { return DropdownMenuItem( value: value.code, child: Text(projectProvider!.isArabic == true ? value.nameAr! : value.name!), ); }).toList()), ), ), ), ), ], ), Directionality( textDirection: TextDirection.ltr, child: Container( padding: EdgeInsets.all(5), decoration: BoxDecoration(color: Colors.white, border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(10)), child: Row(children: [ Expanded( flex: 1, child: Icon( Icons.phone, color: secondaryColor, ), ), Expanded( flex: 1, child: Text( countryCode, overflow: TextOverflow.clip, ), ), Expanded( flex: 4, child: Container( margin: widget.margin != null ? EdgeInsets.all(widget.margin) : EdgeInsets.only(top: widget.marginTop, right: widget.marginRight, bottom: widget.marginBottom, left: widget.marginLeft), child: TextField( controller: widget.controller, keyboardType: TextInputType.number, maxLength: 10, inputFormatters: [ FilteringTextInputFormatter.allow(RegExp("[0-9]")), ], // maxLengthEnforced: true, // onChanged: (value) { // widget.controller.text = countryCode; // }, onChanged: (value) => widget.onNumberChange!(value), decoration: InputDecoration(counterText: "", border: InputBorder.none, hintText: '5xxxxxxxx'), ), ), ) ]), ), ) ]), ); } } // class Countries { // final String name; // final String name_ar; // final String code; // Countries({this.name, this.name_ar, this.code}); // }