diff --git a/package-lock.json b/package-lock.json
index eb709eb..9e9436f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,6 +16,7 @@
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2",
"iconsax-reactjs": "^0.0.8",
+ "libphonenumber-js": "^1.12.10",
"react": "^19.1.0",
"react-country-flag": "^3.1.0",
"react-dom": "^19.1.0",
@@ -3306,6 +3307,12 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/libphonenumber-js": {
+ "version": "1.12.10",
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.10.tgz",
+ "integrity": "sha512-E91vHJD61jekHHR/RF/E83T/CMoaLXT7cwYA75T4gim4FZjnM6hbJjVIGg7chqlSqRsSvQ3izGmOjHy1SQzcGQ==",
+ "license": "MIT"
+ },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
diff --git a/package.json b/package.json
index 22e1fc7..91e1810 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2",
"iconsax-reactjs": "^0.0.8",
+ "libphonenumber-js": "^1.12.10",
"react": "^19.1.0",
"react-country-flag": "^3.1.0",
"react-dom": "^19.1.0",
diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index bc4b6ab..72b36d8 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -1,3 +1,250 @@
{
- "helloWorld": "hello world"
+ "helloWorld": "hello world",
+ "country": {
+ "afghanistan": "Afghanistan",
+ "aland_islands": "Aland islands",
+ "albania": "Albania",
+ "algeria": "Algeria",
+ "american_samoa": "American samoa",
+ "andorra": "Andorra",
+ "angola": "Angola",
+ "anguilla": "Anguilla",
+ "antarctica": "Antarctica",
+ "antigua_and_barbuda": "Antigua and barbuda",
+ "argentina": "Argentina",
+ "armenia": "Armenia",
+ "aruba": "Aruba",
+ "australia": "Australia",
+ "austria": "Austria",
+ "azerbaijan": "Azerbaijan",
+ "bahamas": "Bahamas",
+ "bahrain": "Bahrain",
+ "bangladesh": "Bangladesh",
+ "barbados": "Barbados",
+ "belarus": "Belarus",
+ "belgium": "Belgium",
+ "belize": "Belize",
+ "benin": "Benin",
+ "bermuda": "Bermuda",
+ "bhutan": "Bhutan",
+ "bolivia": "Bolivia",
+ "bosnia_and_herzegovina": "Bosnia and herzegovina",
+ "botswana": "Botswana",
+ "brazil": "Brazil",
+ "british_indian_ocean_territory": "British indian ocean territory",
+ "british_virgin_islands": "British virgin islands",
+ "brunei": "Brunei",
+ "bulgaria": "Bulgaria",
+ "burkina_faso": "Burkina faso",
+ "burundi": "Burundi",
+ "cambodia": "Cambodia",
+ "cameroon": "Cameroon",
+ "canada": "Canada",
+ "cape_verde": "Cape verde",
+ "cayman_islands": "Cayman islands",
+ "central_african_republic": "Central african republic",
+ "chad": "Chad",
+ "chile": "Chile",
+ "china": "China",
+ "christmas_island": "Christmas island",
+ "cocos_keeling_islands": "Cocos keeling islands",
+ "colombia": "Colombia",
+ "comoros": "Comoros",
+ "congo_brazzaville": "Congo brazzaville",
+ "congo_kinshasa": "Congo kinshasa",
+ "cook_islands": "Cook islands",
+ "costa_rica": "Costa rica",
+ "cote_divoire": "Cote divoire",
+ "croatia": "Croatia",
+ "cuba": "Cuba",
+ "curacao": "Curacao",
+ "cyprus": "Cyprus",
+ "czech_republic": "Czech republic",
+ "denmark": "Denmark",
+ "djibouti": "Djibouti",
+ "dominica": "Dominica",
+ "dominican_republic": "Dominican republic",
+ "ecuador": "Ecuador",
+ "egypt": "Egypt",
+ "el_salvador": "El salvador",
+ "equatorial_guinea": "Equatorial guinea",
+ "eritrea": "Eritrea",
+ "estonia": "Estonia",
+ "eswatini": "Eswatini",
+ "ethiopia": "Ethiopia",
+ "falkland_islands": "Falkland islands",
+ "faroe_islands": "Faroe islands",
+ "fiji": "Fiji",
+ "finland": "Finland",
+ "france": "France",
+ "french_guiana": "French guiana",
+ "french_polynesia": "French polynesia",
+ "gabon": "Gabon",
+ "gambia": "Gambia",
+ "georgia": "Georgia",
+ "germany": "Germany",
+ "ghana": "Ghana",
+ "gibraltar": "Gibraltar",
+ "greece": "Greece",
+ "greenland": "Greenland",
+ "grenada": "Grenada",
+ "guadeloupe": "Guadeloupe",
+ "guam": "Guam",
+ "guatemala": "Guatemala",
+ "guernsey": "Guernsey",
+ "guinea": "Guinea",
+ "guinea_bissau": "Guinea bissau",
+ "guyana": "Guyana",
+ "haiti": "Haiti",
+ "honduras": "Honduras",
+ "hong_kong": "Hong kong",
+ "hungary": "Hungary",
+ "iceland": "Iceland",
+ "india": "India",
+ "indonesia": "Indonesia",
+ "iran": "Iran",
+ "iraq": "Iraq",
+ "ireland": "Ireland",
+ "isle_of_man": "Isle of man",
+ "israel": "Israel",
+ "italy": "Italy",
+ "jamaica": "Jamaica",
+ "japan": "Japan",
+ "jersey": "Jersey",
+ "jordan": "Jordan",
+ "kazakhstan": "Kazakhstan",
+ "kenya": "Kenya",
+ "kiribati": "Kiribati",
+ "kosovo": "Kosovo",
+ "kuwait": "Kuwait",
+ "kyrgyzstan": "Kyrgyzstan",
+ "laos": "Laos",
+ "latvia": "Latvia",
+ "lebanon": "Lebanon",
+ "lesotho": "Lesotho",
+ "liberia": "Liberia",
+ "libya": "Libya",
+ "liechtenstein": "Liechtenstein",
+ "lithuania": "Lithuania",
+ "luxembourg": "Luxembourg",
+ "macau": "Macau",
+ "madagascar": "Madagascar",
+ "malawi": "Malawi",
+ "malaysia": "Malaysia",
+ "maldives": "Maldives",
+ "mali": "Mali",
+ "malta": "Malta",
+ "marshall_islands": "Marshall islands",
+ "martinique": "Martinique",
+ "mauritania": "Mauritania",
+ "mauritius": "Mauritius",
+ "mayotte": "Mayotte",
+ "mexico": "Mexico",
+ "micronesia": "Micronesia",
+ "moldova": "Moldova",
+ "monaco": "Monaco",
+ "mongolia": "Mongolia",
+ "montenegro": "Montenegro",
+ "montserrat": "Montserrat",
+ "morocco": "Morocco",
+ "mozambique": "Mozambique",
+ "myanmar": "Myanmar",
+ "namibia": "Namibia",
+ "nauru": "Nauru",
+ "nepal": "Nepal",
+ "netherlands": "Netherlands",
+ "new_caledonia": "New caledonia",
+ "new_zealand": "New zealand",
+ "nicaragua": "Nicaragua",
+ "niger": "Niger",
+ "nigeria": "Nigeria",
+ "niue": "Niue",
+ "norfolk_island": "Norfolk island",
+ "north_korea": "North korea",
+ "north_macedonia": "North macedonia",
+ "northern_mariana_islands": "Northern mariana islands",
+ "norway": "Norway",
+ "oman": "Oman",
+ "pakistan": "Pakistan",
+ "palau": "Palau",
+ "palestine": "Palestine",
+ "panama": "Panama",
+ "papua_new_guinea": "Papua new guinea",
+ "paraguay": "Paraguay",
+ "peru": "Peru",
+ "philippines": "Philippines",
+ "pitcairn_islands": "Pitcairn islands",
+ "poland": "Poland",
+ "portugal": "Portugal",
+ "puerto_rico": "Puerto rico",
+ "qatar": "Qatar",
+ "reunion": "Reunion",
+ "romania": "Romania",
+ "russia": "Russia",
+ "rwanda": "Rwanda",
+ "saint_barthelemy": "Saint barthelemy",
+ "saint_helena": "Saint helena",
+ "saint_kitts_and_nevis": "Saint kitts and nevis",
+ "saint_lucia": "Saint lucia",
+ "saint_martin": "Saint martin",
+ "saint_pierre_and_miquelon": "Saint pierre and miquelon",
+ "saint_vincent_and_the_grenadines": "Saint vincent and the grenadines",
+ "samoa": "Samoa",
+ "san_marino": "San marino",
+ "sao_tome_and_principe": "Sao tome and principe",
+ "saudi_arabia": "Saudi arabia",
+ "senegal": "Senegal",
+ "serbia": "Serbia",
+ "seychelles": "Seychelles",
+ "sierra_leone": "Sierra leone",
+ "singapore": "Singapore",
+ "sint_maarten": "Sint maarten",
+ "slovakia": "Slovakia",
+ "slovenia": "Slovenia",
+ "solomon_islands": "Solomon islands",
+ "somalia": "Somalia",
+ "south_africa": "South africa",
+ "south_georgia_and_south_sandwich_islands": "South georgia and south sandwich islands",
+ "south_korea": "South korea",
+ "south_sudan": "South sudan",
+ "spain": "Spain",
+ "sri_lanka": "Sri lanka",
+ "sudan": "Sudan",
+ "suriname": "Suriname",
+ "svalbard_and_jan_mayen": "Svalbard and jan mayen",
+ "sweden": "Sweden",
+ "switzerland": "Switzerland",
+ "syria": "Syria",
+ "taiwan": "Taiwan",
+ "tajikistan": "Tajikistan",
+ "tanzania": "Tanzania",
+ "thailand": "Thailand",
+ "timor_leste": "Timor leste",
+ "togo": "Togo",
+ "tokelau": "Tokelau",
+ "tonga": "Tonga",
+ "trinidad_and_tobago": "Trinidad and tobago",
+ "tunisia": "Tunisia",
+ "turkey": "Turkey",
+ "turkmenistan": "Turkmenistan",
+ "turks_and_caicos_islands": "Turks and caicos islands",
+ "tuvalu": "Tuvalu",
+ "us_virgin_islands": "Us virgin islands",
+ "uganda": "Uganda",
+ "ukraine": "Ukraine",
+ "united_arab_emirates": "United arab emirates",
+ "united_kingdom": "United kingdom",
+ "united_states": "United states",
+ "uruguay": "Uruguay",
+ "uzbekistan": "Uzbekistan",
+ "vanuatu": "Vanuatu",
+ "vatican_city": "Vatican city",
+ "venezuela": "Venezuela",
+ "vietnam": "Vietnam",
+ "wallis_and_futuna": "Wallis and futuna",
+ "western_sahara": "Western sahara",
+ "yemen": "Yemen",
+ "zambia": "Zambia",
+ "zimbabwe": "Zimbabwe"
+ }
}
diff --git a/public/locales/fa/common.json b/public/locales/fa/common.json
index eb50682..71ba38f 100644
--- a/public/locales/fa/common.json
+++ b/public/locales/fa/common.json
@@ -2,7 +2,188 @@
"labels": {
"search": "جست و جو"
},
- "country"
+ "country": {
+ "afghanistan": "افغانستان",
+ "aland_islands": "جزایر آلند",
+ "albania": "آلبانی",
+ "algeria": "الجزایر",
+ "american_samoa": "ساموای آمریکایی",
+ "andorra": "آندورا",
+ "angola": "آنگولا",
+ "anguilla": "آنگویلا",
+ "antarctica": "جنوبگان",
+ "antigua_and_barbuda": "آنتیگوا و باربودا",
+ "argentina": "آرژانتین",
+ "armenia": "ارمنستان",
+ "aruba": "آروبا",
+ "australia": "استرالیا",
+ "austria": "اتریش",
+ "azerbaijan": "آذربایجان",
+ "bahamas": "باهاما",
+ "bahrain": "بحرین",
+ "bangladesh": "بنگلادش",
+ "barbados": "باربادوس",
+ "belarus": "بلاروس",
+ "belgium": "بلژیک",
+ "belize": "بلیز",
+ "benin": "بنین",
+ "bermuda": "برمودا",
+ "bhutan": "بوتان",
+ "bolivia": "بولیوی",
+ "bosnia_and_herzegovina": "بوسنی و هرزگوین",
+ "botswana": "بوتسوانا",
+ "brazil": "برزیل",
+ "british_virgin_islands": "جزایر ویرجین بریتانیا",
+ "brunei": "برونئی",
+ "bulgaria": "بلغارستان",
+ "burkina_faso": "بورکینافاسو",
+ "burundi": "بوروندی",
+ "cambodia": "کامبوج",
+ "cameroon": "کامرون",
+ "canada": "کانادا",
+ "cape_verde": "کیپ ورد",
+ "cayman_islands": "جزایر کیمن",
+ "central_african_republic": "جمهوری آفریقای مرکزی",
+ "chad": "چاد",
+ "chile": "شیلی",
+ "china": "چین",
+ "colombia": "کلمبیا",
+ "comoros": "کومور",
+ "costa_rica": "کاستاریکا",
+ "cote_divoire": "ساحل عاج",
+ "croatia": "کرواسی",
+ "cuba": "کوبا",
+ "cyprus": "قبرس",
+ "czech_republic": "جمهوری چک",
+ "denmark": "دانمارک",
+ "djibouti": "جیبوتی",
+ "dominica": "دومینیکا",
+ "dominican_republic": "جمهوری دومینیکن",
+ "ecuador": "اکوادور",
+ "egypt": "مصر",
+ "el_salvador": "السالوادور",
+ "equatorial_guinea": "گینه استوایی",
+ "eritrea": "اریتره",
+ "estonia": "استونی",
+ "eswatini": "سوازیلند",
+ "ethiopia": "اتیوپی",
+ "fiji": "فیجی",
+ "finland": "فنلاند",
+ "france": "فرانسه",
+ "gabon": "گابن",
+ "gambia": "گامبیا",
+ "georgia": "گرجستان",
+ "germany": "آلمان",
+ "ghana": "غنا",
+ "greece": "یونان",
+ "guatemala": "گواتمالا",
+ "guinea": "گینه",
+ "guinea_bissau": "گینه بیسائو",
+ "guyana": "گویان",
+ "haiti": "هائیتی",
+ "honduras": "هندوراس",
+ "hungary": "مجارستان",
+ "iceland": "ایسلند",
+ "india": "هندوستان",
+ "indonesia": "اندونزی",
+ "iran": "ایران",
+ "iraq": "عراق",
+ "ireland": "ایرلند",
+ "israel": "اسرائیل",
+ "italy": "ایتالیا",
+ "jamaica": "جامائیکا",
+ "japan": "ژاپن",
+ "jordan": "اردن",
+ "kazakhstan": "قزاقستان",
+ "kenya": "کنیا",
+ "kuwait": "کویت",
+ "kyrgyzstan": "قرقیزستان",
+ "laos": "لائوس",
+ "latvia": "لتونی",
+ "lebanon": "لبنان",
+ "lesotho": "لسوتو",
+ "liberia": "لیبریا",
+ "libya": "لیبی",
+ "luxembourg": "لوکزامبورگ",
+ "malaysia": "مالزی",
+ "maldives": "مالدیو",
+ "mali": "مالی",
+ "malta": "مالت",
+ "mauritania": "موریتانی",
+ "mauritius": "موریس",
+ "mexico": "مکزیک",
+ "moldova": "مولداوی",
+ "monaco": "موناکو",
+ "mongolia": "مغولستان",
+ "morocco": "مراکش",
+ "mozambique": "موزامبیک",
+ "myanmar": "میانمار",
+ "namibia": "نامیبیا",
+ "nepal": "نپال",
+ "netherlands": "هلند",
+ "new_zealand": "نیوزیلند",
+ "nicaragua": "نیکاراگوئه",
+ "niger": "نیجر",
+ "nigeria": "نیجریه",
+ "north_korea": "کره شمالی",
+ "north_macedonia": "مقدونیه",
+ "norway": "نروژ",
+ "oman": "عمان",
+ "pakistan": "پاکستان",
+ "palau": "پالائو",
+ "panama": "پاناما",
+ "papua_new_guinea": "پاپوآ گینه نو",
+ "paraguay": "پاراگوئه",
+ "peru": "پرو",
+ "philippines": "فیلیپین",
+ "poland": "لهستان",
+ "portugal": "پرتغال",
+ "qatar": "قطر",
+ "romania": "رومانی",
+ "russia": "روسیه",
+ "rwanda": "رواندا",
+ "saudi_arabia": "عربستان سعودی",
+ "senegal": "سنگال",
+ "serbia": "صربستان",
+ "seychelles": "سیشل",
+ "sierra_leone": "سیرالئون",
+ "singapore": "سنگاپور",
+ "south_africa": "آفریقای جنوبی",
+ "south_korea": "کره جنوبی",
+ "south_sudan": "سودان جنوبی",
+ "spain": "اسپانیا",
+ "sri_lanka": "سریلانکا",
+ "sudan": "سودان",
+ "suriname": "سورینام",
+ "sweden": "سوئد",
+ "switzerland": "سوئیس",
+ "syria": "سوریه",
+ "taiwan": "تایوان",
+ "tajikistan": "تاجیکستان",
+ "tanzania": "تانزانیا",
+ "thailand": "تایلند",
+ "timor_leste": "تیمور شرقی",
+ "togo": "توگو",
+ "tonga": "تونگا",
+ "trinidad_and_tobago": "ترینیداد و توباگو",
+ "tunisia": "تونس",
+ "turkey": "ترکیه",
+ "turkmenistan": "ترکمنستان",
+ "tuvalu": "تووالو",
+ "uganda": "اوگاندا",
+ "ukraine": "اوکراین",
+ "united_arab_emirates": "امارات متحده عربی",
+ "united_kingdom": "انگلستان",
+ "united_states": "ایالات متحده آمریکا",
+ "uruguay": "اروگوئه",
+ "uzbekistan": "ازبکستان",
+ "vanuatu": "وانواتو",
+ "venezuela": "ونزوئلا",
+ "vietnam": "ویتنام",
+ "yemen": "یمن",
+ "zambia": "زامبیا",
+ "zimbabwe": "زیمبابوه"
+ },
"messages": {
"noResualtFound": "نتیجه ای یافت نشد."
}
diff --git a/src/features/authentication/components/CountryCodeSelector.tsx b/src/features/authentication/components/CountryCodeSelector.tsx
index ea4d89d..6028d6b 100644
--- a/src/features/authentication/components/CountryCodeSelector.tsx
+++ b/src/features/authentication/components/CountryCodeSelector.tsx
@@ -72,6 +72,7 @@ export function CountryCodeSelector({
() =>
countries.filter(
(country) =>
+ t(country.label).toLowerCase().includes(searchTerm.toLowerCase()) ||
country.label.toLowerCase().includes(searchTerm.toLowerCase()) ||
country.phone.includes(searchTerm),
),
@@ -205,7 +206,7 @@ export function CountryCodeSelector({
}}
/>
-
+
{country.phone}
diff --git a/src/features/authentication/components/LoginForm.tsx b/src/features/authentication/components/LoginForm.tsx
deleted file mode 100644
index 0584f23..0000000
--- a/src/features/authentication/components/LoginForm.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import { Box, Button, Stack, TextField, Typography } from '@mui/material';
-import { useRef, useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import { CountryCodeSelector } from './CountryCodeSelector';
-import { Google } from 'iconsax-reactjs';
-import { isNumeric } from '@/utils/regexes/isNumeric';
-
-export function LoginForm() {
- const { t, i18n } = useTranslation('authentication');
- const [value, setValue] = useState('');
- const [countryCode, setCountryCode] = useState('+41');
- const [inputType, setInputType] = useState<'phone' | 'email'>('phone');
- const textFieldRef = useRef(null);
- const inputRef = useRef(null);
- const dir = i18n.dir();
-
- const handleInputChange = (event: React.ChangeEvent) => {
- const newValue = event.target.value;
- setValue(newValue);
-
- // If the new value contains only digits (or is empty), it's a phone number
- if (isNumeric(newValue)) {
- setInputType('phone');
- } else {
- setInputType('email');
- }
- };
-
- const handleBlur = () => {
- // setTouched(true);
- // setError(validate(value, inputType));
- };
-
- const showAdornment = inputType === 'phone' && value.length > 0;
-
- return (
-
-
- {t('loginForm.title')}
-
- {t('loginForm.description')}
-
-
-
-
- ),
- endAdornment: dir === 'rtl' && (
-
- ),
- },
- }}
- sx={{ my: 4 }}
- />
-
-
-
- }>
- {t('loginForm.loginWithGoogle')}
-
-
-
- );
-}
diff --git a/src/features/authentication/components/LoginRegiserForm.tsx b/src/features/authentication/components/LoginRegiserForm.tsx
index c399826..233eb66 100644
--- a/src/features/authentication/components/LoginRegiserForm.tsx
+++ b/src/features/authentication/components/LoginRegiserForm.tsx
@@ -6,6 +6,7 @@ import { Google } from 'iconsax-reactjs';
import { isNumeric } from '@/utils/regexes/isNumeric';
import type { AuthMode, AuthType } from '../types/auth-types';
import { isEmail } from '@/utils/regexes/isEmail';
+import parsePhoneNumberFromString from 'libphonenumber-js';
export interface LoginRegisterFormProps {
authType: AuthType;
@@ -49,13 +50,19 @@ export function LoginRegisterForm({
setError(t('loginForm.thisFieldIsRequired'));
} else if (authType === 'email' && !isEmail(value)) {
setError(t('loginForm.emailIsInvalid'));
- } else if (authType === 'phone' && false /* TODO */) {
- setError(t('loginForm.emailIsInvalid'));
+ } else if (authType === 'phone' && !isPhoneValid(countryCode, value)) {
+ setError(t('loginForm.phoneNumberIsInvalid'));
} else {
setError(undefined);
}
};
+ const isPhoneValid = (code: string, phone: string) => {
+ const phoneNumber = parsePhoneNumberFromString(code + phone);
+
+ return phoneNumber && phoneNumber.isValid();
+ };
+
const isInputValid = (value: string, authType: AuthType): boolean => {
if (!value) {
return false;
@@ -65,7 +72,7 @@ export function LoginRegisterForm({
return false;
}
- if (authType === 'phone' && false /* TODO */) {
+ if (authType === 'phone' && !isPhoneValid(countryCode, value)) {
return false;
}
@@ -104,16 +111,7 @@ export function LoginRegisterForm({
slotProps={{
htmlInput: { dir: 'auto', sx: { lineHeight: 1.5, paddingX: 0 } },
input: {
- startAdornment: dir === 'ltr' && (
-
- ),
- endAdornment: dir === 'rtl' && (
+ endAdornment: (