Skip to content

Commit

Permalink
Merge pull request #1 from UdaySagar-Git/Fix-#7248
Browse files Browse the repository at this point in the history
  • Loading branch information
UdaySagar-Git authored Feb 22, 2024
2 parents 68cb138 + 5dacde2 commit 0ae9c4c
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 51 deletions.
12 changes: 2 additions & 10 deletions src/Common/static/countryPhoneAndFlags.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,7 @@
"DJ": { "flag": "🇩🇯", "name": "Djibouti", "code": "253" },
"DK": { "flag": "🇩🇰", "name": "Denmark", "code": "45" },
"DM": { "flag": "🇩🇲", "name": "Dominica", "code": "1-767" },
"DO": {
"flag": "🇩🇴",
"name": "Dominican Republic",
"code": "1"
},
"DO": { "flag": "🇩🇴", "name": "Dominican Republic", "code": "1" },
"DZ": { "flag": "🇩🇿", "name": "Algeria", "code": "213" },
"EC": { "flag": "🇪🇨", "name": "Ecuador", "code": "593" },
"EE": { "flag": "🇪🇪", "name": "Estonia", "code": "372" },
Expand Down Expand Up @@ -105,11 +101,7 @@
"IL": { "flag": "🇮🇱", "name": "Israel", "code": "972" },
"IM": { "flag": "🇮🇲", "name": "Isle of Man", "code": "44-1624" },
"IN": { "flag": "🇮🇳", "name": "India", "code": "91" },
"IO": {
"flag": "🇮🇴",
"name": "British Indian Ocean Territory",
"code": "246"
},
"IO": { "flag": "🇮🇴", "name": "British Indian Ocean Territory", "code": "246" },
"IQ": { "flag": "🇮🇶", "name": "Iraq", "code": "964" },
"IR": { "flag": "🇮🇷", "name": "Iran", "code": "98" },
"IS": { "flag": "🇮🇸", "name": "Iceland", "code": "354" },
Expand Down
176 changes: 135 additions & 41 deletions src/Components/Form/FormFields/PhoneNumberFormField.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FormFieldBaseProps, useFormFieldPropsResolver } from "./Utils";
import FormField from "./FormField";
import { useEffect, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import {
classNames,
parsePhoneNumber,
Expand All @@ -27,7 +27,13 @@ interface Props extends FormFieldBaseProps<string> {

export default function PhoneNumberFormField(props: Props) {
const field = useFormFieldPropsResolver(props as any);
const [error, setError] = useState<FieldError>();
const [error, setError] = useState<FieldError | undefined>();
const [country, setCountry] = useState<CountryData>({
flag: "🇮🇳",
name: "India",
code: "91",
});
const [isOpen, setIsOpen] = useState<boolean>(false);

const validator = useMemo(
() => PhoneNumberValidator(props.types),
Expand All @@ -51,19 +57,44 @@ export default function PhoneNumberFormField(props: Props) {
[props.disableValidation]
);

const setValue = (value: string) => {
value = value.replaceAll(/[^0-9+]/g, "");
if (value.length > 12 && value.startsWith("+910")) {
value = "+91" + value.slice(4);
}
const setValue = useCallback(
(value: string) => {
value = value.replaceAll(/[^0-9+]/g, "");
if (value.length > 12 && value.startsWith("+910")) {
value = "+91" + value.slice(4);
}

const error = validate(value, "change");
field.handleChange(value);
const error = validate(value, "change");
field.handleChange(value);

setError(error);
setError(error);
},
[field, validate]
);

const handleCountryChange = (value: CountryData): void => {
setCountry(value);
setValue(conditionPhoneCode(value.code));
setIsOpen(false);
};

useEffect(() => setValue(field.value || "+91"), []);
useEffect(() => {
if (field.value && field.value.length > 0) {
if (field.value.startsWith("1800")) {
setCountry({ flag: "📞", name: "Support", code: "1800" });
return;
}
if (field.value === "+") {
setCountry({ flag: "🌍", name: "Other", code: "+" });
return;
}
setCountry(phoneCodes[getCountryCode(field.value)!]);
}
}, [setValue]);

useEffect(() => {
setValue(field.value || "+91");
}, []);

return (
<FormField
Expand All @@ -76,13 +107,27 @@ export default function PhoneNumberFormField(props: Props) {
}}
>
<div className="relative rounded-md shadow-sm">
<div
className="absolute inset-y-0 left-0 w-24 cursor-pointer p-0.5"
onClick={() => setIsOpen(!isOpen)}
>
<span className="flex h-full items-center justify-center rounded-md bg-slate-100 ">
{country?.flag ?? "🇮🇳"}
</span>
{isOpen ? (
<CareIcon className="care-l-angle-up absolute right-1 top-1/2 -translate-y-1/2 text-2xl font-bold " />
) : (
<CareIcon className="care-l-angle-down absolute right-1 top-1/2 -translate-y-1/2 text-2xl font-bold " />
)}
</div>

<input
type="tel"
id={field.id}
name={field.name}
autoComplete={props.autoComplete ?? "tel"}
className={classNames(
"cui-input-base pr-24 tracking-widest sm:leading-6 md:pr-28",
"cui-input-base h-full pl-28 tracking-widest sm:leading-6 ",
field.error && "border-danger-500",
field.className
)}
Expand All @@ -93,35 +138,9 @@ export default function PhoneNumberFormField(props: Props) {
disabled={field.disabled}
onBlur={() => setError(validate(field.value, "blur"))}
/>
<div className="absolute inset-y-0 right-0 flex items-center">
<label htmlFor={field.id + "__country"} className="sr-only">
Country
</label>
<select
disabled={field.disabled}
id={field.id + "__country"}
name="country"
autoComplete="country"
className="cui-input-base h-full border-0 bg-transparent pl-2 pr-8 text-end font-medium tracking-wider text-gray-700 focus:ring-2 focus:ring-inset"
value={
getCountryCode(field.value) ??
(field.value?.startsWith("1800") ? "1800" : "Other")
}
onChange={(e) => {
if (e.target.value === "1800") return setValue("1800");
if (e.target.value === "Other") return setValue("");
setValue(conditionPhoneCode(phoneCodes[e.target.value].code));
}}
>
{Object.entries(phoneCodes).map(([country, { flag }]) => (
<option key={country} value={country}>
{flag} {country}
</option>
))}
<option value="Other">Other</option>
<option value="1800">Support</option>
</select>
</div>
{isOpen && (
<CountryCodesList handleCountryChange={handleCountryChange} />
)}
</div>
</FormField>
);
Expand Down Expand Up @@ -170,3 +189,78 @@ const formatPhoneNumber = (value: string, types: PhoneNumberType[]) => {
const phoneNumber = parsePhoneNumber(value);
return phoneNumber ? formatPhoneNumberUtil(phoneNumber) : value;
};

const CountryCodesList = ({ handleCountryChange }: any) => {
const [searchValue, setSearchValue] = useState<string>("");

return (
<div className="absolute z-10 w-full rounded-md border border-gray-300 bg-white shadow-lg transition-all duration-300">
<div className="relative m-2">
<CareIcon
icon="l-search"
className="absolute left-3 top-3 mr-1 text-base"
/>
<input
type="search"
placeholder="Search"
className="w-full border-b border-gray-400 p-2 pl-10 focus:outline-none focus:ring-0"
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
/>
</div>

<ul className="max-h-[200px] overflow-x-hidden overflow-y-scroll px-2">
{Object.entries(phoneCodes)
.filter(([country, { flag, name, code }]) => {
if (searchValue === "") {
return true;
}
return (
name.toLowerCase().includes(searchValue.toLowerCase()) ||
code.includes(searchValue) ||
country.toLowerCase().includes(searchValue.toLowerCase()) ||
flag.includes(searchValue)
);
})
.map(([country, { flag, name, code }]) => (
<li
key={country}
className="flex cursor-pointer items-center gap-2 rounded-md p-2 hover:bg-primary-100 hover:text-primary-600"
onClick={() => {
handleCountryChange({ flag, name, code });
}}
>
<span>{flag}</span>
<span>{name}</span>
<span className="text-gray-600">
{" "}
({conditionPhoneCode(code)})
</span>
</li>
))}
<li
key={"support"}
className="flex cursor-pointer items-center gap-2 rounded-md p-2 hover:bg-primary-100 hover:text-primary-600"
onClick={() => {
handleCountryChange({ flag: "📞", name: "Support", code: "1800" });
}}
>
<span>📞</span>
<span>Support</span>
<span className="text-gray-600"> (1800)</span>
</li>
<li
key={"other"}
className="flex cursor-pointer items-center gap-2 rounded-md p-2 hover:bg-primary-100 hover:text-primary-600"
onClick={() => {
handleCountryChange({ flag: "🌍", name: "Other", code: "+" });
}}
>
<span>🌍</span>
<span>Other</span>
<span className="text-gray-600"> (+)</span>
</li>
</ul>
</div>
);
};

0 comments on commit 0ae9c4c

Please sign in to comment.