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.
HMG_Patient_App/lib/widgets/mobile-no/mobile_no.dart

362 lines
13 KiB
Dart

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<PhoneNumberSelectorWidget> {
var _selectedType = '+966';
String countryCode = '966';
List<Countries> 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: (_) => <PopupMenuItem<String>>[
if (hasSelection)
for (var country in counties) PopupMenuItem<String>(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<MobileNo> {
var _selectedType = '+966';
String countryCode = '+966';
List<Countries> 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: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
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<DropdownMenuItem<String>>((Countries value) {
return DropdownMenuItem<String>(
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: <Widget>[
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: <TextInputFormatter>[
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});
// }