chore: LoginRegisterForm and AuthenticationContainer created

This commit is contained in:
مهرزاد قدرتی
2025-07-26 13:26:33 +03:30
parent d2efafa5a9
commit 2e10a5496c
14 changed files with 628 additions and 17 deletions

View File

@@ -34,8 +34,12 @@ export default tseslint.config(
...tseslint.configs.recommended.rules,
...reactHooks.configs.recommended.rules,
...prettierConfig.rules,
'prettier/prettier': 'error',
'linebreak-style': ['error', 'unix'],
'prettier/prettier': [
'error',
{
"endOfLine": "auto"
}
],
'react-refresh/only-export-components': 'warn',
'@typescript-eslint/no-explicit-any': 'warn',
},

View File

@@ -0,0 +1,12 @@
{
"loginForm": {
"title": "Login/Register",
"description": "Please enter your email/password to start",
"emailOrPhoneLabel": "Email/Password",
"submitButton": "Login/Register",
"loginWithGoogle": "Login with google",
"emailIsInvalid": "Email is invalid",
"phoneNumberIsInvalid": "Phone number is invalid",
"thisFieldIsRequired": "This field is requried"
}
}

View File

@@ -0,0 +1,247 @@
{
"country.afghanistan": "Afghanistan",
"country.aland_islands": "Aland islands",
"country.albania": "Albania",
"country.algeria": "Algeria",
"country.american_samoa": "American samoa",
"country.andorra": "Andorra",
"country.angola": "Angola",
"country.anguilla": "Anguilla",
"country.antarctica": "Antarctica",
"country.antigua_and_barbuda": "Antigua and barbuda",
"country.argentina": "Argentina",
"country.armenia": "Armenia",
"country.aruba": "Aruba",
"country.australia": "Australia",
"country.austria": "Austria",
"country.azerbaijan": "Azerbaijan",
"country.bahamas": "Bahamas",
"country.bahrain": "Bahrain",
"country.bangladesh": "Bangladesh",
"country.barbados": "Barbados",
"country.belarus": "Belarus",
"country.belgium": "Belgium",
"country.belize": "Belize",
"country.benin": "Benin",
"country.bermuda": "Bermuda",
"country.bhutan": "Bhutan",
"country.bolivia": "Bolivia",
"country.bosnia_and_herzegovina": "Bosnia and herzegovina",
"country.botswana": "Botswana",
"country.brazil": "Brazil",
"country.british_indian_ocean_territory": "British indian ocean territory",
"country.british_virgin_islands": "British virgin islands",
"country.brunei": "Brunei",
"country.bulgaria": "Bulgaria",
"country.burkina_faso": "Burkina faso",
"country.burundi": "Burundi",
"country.cambodia": "Cambodia",
"country.cameroon": "Cameroon",
"country.canada": "Canada",
"country.cape_verde": "Cape verde",
"country.cayman_islands": "Cayman islands",
"country.central_african_republic": "Central african republic",
"country.chad": "Chad",
"country.chile": "Chile",
"country.china": "China",
"country.christmas_island": "Christmas island",
"country.cocos_keeling_islands": "Cocos keeling islands",
"country.colombia": "Colombia",
"country.comoros": "Comoros",
"country.congo_brazzaville": "Congo brazzaville",
"country.congo_kinshasa": "Congo kinshasa",
"country.cook_islands": "Cook islands",
"country.costa_rica": "Costa rica",
"country.cote_divoire": "Cote divoire",
"country.croatia": "Croatia",
"country.cuba": "Cuba",
"country.curacao": "Curacao",
"country.cyprus": "Cyprus",
"country.czech_republic": "Czech republic",
"country.denmark": "Denmark",
"country.djibouti": "Djibouti",
"country.dominica": "Dominica",
"country.dominican_republic": "Dominican republic",
"country.ecuador": "Ecuador",
"country.egypt": "Egypt",
"country.el_salvador": "El salvador",
"country.equatorial_guinea": "Equatorial guinea",
"country.eritrea": "Eritrea",
"country.estonia": "Estonia",
"country.eswatini": "Eswatini",
"country.ethiopia": "Ethiopia",
"country.falkland_islands": "Falkland islands",
"country.faroe_islands": "Faroe islands",
"country.fiji": "Fiji",
"country.finland": "Finland",
"country.france": "France",
"country.french_guiana": "French guiana",
"country.french_polynesia": "French polynesia",
"country.gabon": "Gabon",
"country.gambia": "Gambia",
"country.georgia": "Georgia",
"country.germany": "Germany",
"country.ghana": "Ghana",
"country.gibraltar": "Gibraltar",
"country.greece": "Greece",
"country.greenland": "Greenland",
"country.grenada": "Grenada",
"country.guadeloupe": "Guadeloupe",
"country.guam": "Guam",
"country.guatemala": "Guatemala",
"country.guernsey": "Guernsey",
"country.guinea": "Guinea",
"country.guinea_bissau": "Guinea bissau",
"country.guyana": "Guyana",
"country.haiti": "Haiti",
"country.honduras": "Honduras",
"country.hong_kong": "Hong kong",
"country.hungary": "Hungary",
"country.iceland": "Iceland",
"country.india": "India",
"country.indonesia": "Indonesia",
"country.iran": "Iran",
"country.iraq": "Iraq",
"country.ireland": "Ireland",
"country.isle_of_man": "Isle of man",
"country.israel": "Israel",
"country.italy": "Italy",
"country.jamaica": "Jamaica",
"country.japan": "Japan",
"country.jersey": "Jersey",
"country.jordan": "Jordan",
"country.kazakhstan": "Kazakhstan",
"country.kenya": "Kenya",
"country.kiribati": "Kiribati",
"country.kosovo": "Kosovo",
"country.kuwait": "Kuwait",
"country.kyrgyzstan": "Kyrgyzstan",
"country.laos": "Laos",
"country.latvia": "Latvia",
"country.lebanon": "Lebanon",
"country.lesotho": "Lesotho",
"country.liberia": "Liberia",
"country.libya": "Libya",
"country.liechtenstein": "Liechtenstein",
"country.lithuania": "Lithuania",
"country.luxembourg": "Luxembourg",
"country.macau": "Macau",
"country.madagascar": "Madagascar",
"country.malawi": "Malawi",
"country.malaysia": "Malaysia",
"country.maldives": "Maldives",
"country.mali": "Mali",
"country.malta": "Malta",
"country.marshall_islands": "Marshall islands",
"country.martinique": "Martinique",
"country.mauritania": "Mauritania",
"country.mauritius": "Mauritius",
"country.mayotte": "Mayotte",
"country.mexico": "Mexico",
"country.micronesia": "Micronesia",
"country.moldova": "Moldova",
"country.monaco": "Monaco",
"country.mongolia": "Mongolia",
"country.montenegro": "Montenegro",
"country.montserrat": "Montserrat",
"country.morocco": "Morocco",
"country.mozambique": "Mozambique",
"country.myanmar": "Myanmar",
"country.namibia": "Namibia",
"country.nauru": "Nauru",
"country.nepal": "Nepal",
"country.netherlands": "Netherlands",
"country.new_caledonia": "New caledonia",
"country.new_zealand": "New zealand",
"country.nicaragua": "Nicaragua",
"country.niger": "Niger",
"country.nigeria": "Nigeria",
"country.niue": "Niue",
"country.norfolk_island": "Norfolk island",
"country.north_korea": "North korea",
"country.north_macedonia": "North macedonia",
"country.northern_mariana_islands": "Northern mariana islands",
"country.norway": "Norway",
"country.oman": "Oman",
"country.pakistan": "Pakistan",
"country.palau": "Palau",
"country.palestine": "Palestine",
"country.panama": "Panama",
"country.papua_new_guinea": "Papua new guinea",
"country.paraguay": "Paraguay",
"country.peru": "Peru",
"country.philippines": "Philippines",
"country.pitcairn_islands": "Pitcairn islands",
"country.poland": "Poland",
"country.portugal": "Portugal",
"country.puerto_rico": "Puerto rico",
"country.qatar": "Qatar",
"country.reunion": "Reunion",
"country.romania": "Romania",
"country.russia": "Russia",
"country.rwanda": "Rwanda",
"country.saint_barthelemy": "Saint barthelemy",
"country.saint_helena": "Saint helena",
"country.saint_kitts_and_nevis": "Saint kitts and nevis",
"country.saint_lucia": "Saint lucia",
"country.saint_martin": "Saint martin",
"country.saint_pierre_and_miquelon": "Saint pierre and miquelon",
"country.saint_vincent_and_the_grenadines": "Saint vincent and the grenadines",
"country.samoa": "Samoa",
"country.san_marino": "San marino",
"country.sao_tome_and_principe": "Sao tome and principe",
"country.saudi_arabia": "Saudi arabia",
"country.senegal": "Senegal",
"country.serbia": "Serbia",
"country.seychelles": "Seychelles",
"country.sierra_leone": "Sierra leone",
"country.singapore": "Singapore",
"country.sint_maarten": "Sint maarten",
"country.slovakia": "Slovakia",
"country.slovenia": "Slovenia",
"country.solomon_islands": "Solomon islands",
"country.somalia": "Somalia",
"country.south_africa": "South africa",
"country.south_georgia_and_south_sandwich_islands": "South georgia and south sandwich islands",
"country.south_korea": "South korea",
"country.south_sudan": "South sudan",
"country.spain": "Spain",
"country.sri_lanka": "Sri lanka",
"country.sudan": "Sudan",
"country.suriname": "Suriname",
"country.svalbard_and_jan_mayen": "Svalbard and jan mayen",
"country.sweden": "Sweden",
"country.switzerland": "Switzerland",
"country.syria": "Syria",
"country.taiwan": "Taiwan",
"country.tajikistan": "Tajikistan",
"country.tanzania": "Tanzania",
"country.thailand": "Thailand",
"country.timor_leste": "Timor leste",
"country.togo": "Togo",
"country.tokelau": "Tokelau",
"country.tonga": "Tonga",
"country.trinidad_and_tobago": "Trinidad and tobago",
"country.tunisia": "Tunisia",
"country.turkey": "Turkey",
"country.turkmenistan": "Turkmenistan",
"country.turks_and_caicos_islands": "Turks and caicos islands",
"country.tuvalu": "Tuvalu",
"country.us_virgin_islands": "Us virgin islands",
"country.uganda": "Uganda",
"country.ukraine": "Ukraine",
"country.united_arab_emirates": "United arab emirates",
"country.united_kingdom": "United kingdom",
"country.united_states": "United states",
"country.uruguay": "Uruguay",
"country.uzbekistan": "Uzbekistan",
"country.vanuatu": "Vanuatu",
"country.vatican_city": "Vatican city",
"country.venezuela": "Venezuela",
"country.vietnam": "Vietnam",
"country.wallis_and_futuna": "Wallis and futuna",
"country.western_sahara": "Western sahara",
"country.yemen": "Yemen",
"country.zambia": "Zambia",
"country.zimbabwe": "Zimbabwe"
}

View File

@@ -4,6 +4,9 @@
"description": "لطفا برای شروع شماره موبایل/ایمیل خود را وارد کنید.",
"emailOrPhoneLabel": "شماره موبایل/ایمیل",
"submitButton": "ورود/ثبت‌نام",
"loginWithGoogle": "ورود با گوگل"
"loginWithGoogle": "ورود با گوگل",
"emailIsInvalid": "ایمیل وارد شده نامعتبر میباشد",
"phoneNumberIsInvalid": "شماره وارد شده نامعتبر میباشد",
"thisFieldIsRequired": "این فیلد الزامی است"
}
}

View File

@@ -2,6 +2,7 @@
"labels": {
"search": "جست و جو"
},
"country"
"messages": {
"noResualtFound": "نتیجه ای یافت نشد."
}

View File

@@ -0,0 +1,182 @@
{
"country.afghanistan": "افغانستان",
"country.aland_islands": "جزایر آلند",
"country.albania": "آلبانی",
"country.algeria": "الجزایر",
"country.american_samoa": "ساموای آمریکایی",
"country.andorra": "آندورا",
"country.angola": "آنگولا",
"country.anguilla": "آنگویلا",
"country.antarctica": "جنوبگان",
"country.antigua_and_barbuda": "آنتیگوا و باربودا",
"country.argentina": "آرژانتین",
"country.armenia": "ارمنستان",
"country.aruba": "آروبا",
"country.australia": "استرالیا",
"country.austria": "اتریش",
"country.azerbaijan": "آذربایجان",
"country.bahamas": "باهاما",
"country.bahrain": "بحرین",
"country.bangladesh": "بنگلادش",
"country.barbados": "باربادوس",
"country.belarus": "بلاروس",
"country.belgium": "بلژیک",
"country.belize": "بلیز",
"country.benin": "بنین",
"country.bermuda": "برمودا",
"country.bhutan": "بوتان",
"country.bolivia": "بولیوی",
"country.bosnia_and_herzegovina": "بوسنی و هرزگوین",
"country.botswana": "بوتسوانا",
"country.brazil": "برزیل",
"country.british_virgin_islands": "جزایر ویرجین بریتانیا",
"country.brunei": "برونئی",
"country.bulgaria": "بلغارستان",
"country.burkina_faso": "بورکینافاسو",
"country.burundi": "بوروندی",
"country.cambodia": "کامبوج",
"country.cameroon": "کامرون",
"country.canada": "کانادا",
"country.cape_verde": "کیپ ورد",
"country.cayman_islands": "جزایر کیمن",
"country.central_african_republic": "جمهوری آفریقای مرکزی",
"country.chad": "چاد",
"country.chile": "شیلی",
"country.china": "چین",
"country.colombia": "کلمبیا",
"country.comoros": "کومور",
"country.costa_rica": "کاستاریکا",
"country.cote_divoire": "ساحل عاج",
"country.croatia": "کرواسی",
"country.cuba": "کوبا",
"country.cyprus": "قبرس",
"country.czech_republic": "جمهوری چک",
"country.denmark": "دانمارک",
"country.djibouti": "جیبوتی",
"country.dominica": "دومینیکا",
"country.dominican_republic": "جمهوری دومینیکن",
"country.ecuador": "اکوادور",
"country.egypt": "مصر",
"country.el_salvador": "السالوادور",
"country.equatorial_guinea": "گینه استوایی",
"country.eritrea": "اریتره",
"country.estonia": "استونی",
"country.eswatini": "سوازیلند",
"country.ethiopia": "اتیوپی",
"country.fiji": "فیجی",
"country.finland": "فنلاند",
"country.france": "فرانسه",
"country.gabon": "گابن",
"country.gambia": "گامبیا",
"country.georgia": "گرجستان",
"country.germany": "آلمان",
"country.ghana": "غنا",
"country.greece": "یونان",
"country.guatemala": "گواتمالا",
"country.guinea": "گینه",
"country.guinea_bissau": "گینه بیسائو",
"country.guyana": "گویان",
"country.haiti": "هائیتی",
"country.honduras": "هندوراس",
"country.hungary": "مجارستان",
"country.iceland": "ایسلند",
"country.india": "هندوستان",
"country.indonesia": "اندونزی",
"country.iran": "ایران",
"country.iraq": "عراق",
"country.ireland": "ایرلند",
"country.israel": "اسرائیل",
"country.italy": "ایتالیا",
"country.jamaica": "جامائیکا",
"country.japan": "ژاپن",
"country.jordan": "اردن",
"country.kazakhstan": "قزاقستان",
"country.kenya": "کنیا",
"country.kuwait": "کویت",
"country.kyrgyzstan": "قرقیزستان",
"country.laos": "لائوس",
"country.latvia": "لتونی",
"country.lebanon": "لبنان",
"country.lesotho": "لسوتو",
"country.liberia": "لیبریا",
"country.libya": "لیبی",
"country.luxembourg": "لوکزامبورگ",
"country.malaysia": "مالزی",
"country.maldives": "مالدیو",
"country.mali": "مالی",
"country.malta": "مالت",
"country.mauritania": "موریتانی",
"country.mauritius": "موریس",
"country.mexico": "مکزیک",
"country.moldova": "مولداوی",
"country.monaco": "موناکو",
"country.mongolia": "مغولستان",
"country.morocco": "مراکش",
"country.mozambique": "موزامبیک",
"country.myanmar": "میانمار",
"country.namibia": "نامیبیا",
"country.nepal": "نپال",
"country.netherlands": "هلند",
"country.new_zealand": "نیوزیلند",
"country.nicaragua": "نیکاراگوئه",
"country.niger": "نیجر",
"country.nigeria": "نیجریه",
"country.north_korea": "کره شمالی",
"country.north_macedonia": "مقدونیه",
"country.norway": "نروژ",
"country.oman": "عمان",
"country.pakistan": "پاکستان",
"country.palau": "پالائو",
"country.panama": "پاناما",
"country.papua_new_guinea": "پاپوآ گینه نو",
"country.paraguay": "پاراگوئه",
"country.peru": "پرو",
"country.philippines": "فیلیپین",
"country.poland": "لهستان",
"country.portugal": "پرتغال",
"country.qatar": "قطر",
"country.romania": "رومانی",
"country.russia": "روسیه",
"country.rwanda": "رواندا",
"country.saudi_arabia": "عربستان سعودی",
"country.senegal": "سنگال",
"country.serbia": "صربستان",
"country.seychelles": "سیشل",
"country.sierra_leone": "سیرالئون",
"country.singapore": "سنگاپور",
"country.south_africa": "آفریقای جنوبی",
"country.south_korea": "کره جنوبی",
"country.south_sudan": "سودان جنوبی",
"country.spain": "اسپانیا",
"country.sri_lanka": "سری‌لانکا",
"country.sudan": "سودان",
"country.suriname": "سورینام",
"country.sweden": "سوئد",
"country.switzerland": "سوئیس",
"country.syria": "سوریه",
"country.taiwan": "تایوان",
"country.tajikistan": "تاجیکستان",
"country.tanzania": "تانزانیا",
"country.thailand": "تایلند",
"country.timor_leste": "تیمور شرقی",
"country.togo": "توگو",
"country.tonga": "تونگا",
"country.trinidad_and_tobago": "ترینیداد و توباگو",
"country.tunisia": "تونس",
"country.turkey": "ترکیه",
"country.turkmenistan": "ترکمنستان",
"country.tuvalu": "تووالو",
"country.uganda": "اوگاندا",
"country.ukraine": "اوکراین",
"country.united_arab_emirates": "امارات متحده عربی",
"country.united_kingdom": "انگلستان",
"country.united_states": "ایالات متحده آمریکا",
"country.uruguay": "اروگوئه",
"country.uzbekistan": "ازبکستان",
"country.vanuatu": "وانواتو",
"country.venezuela": "ونزوئلا",
"country.vietnam": "ویتنام",
"country.yemen": "یمن",
"country.zambia": "زامبیا",
"country.zimbabwe": "زیمبابوه"
}

View File

@@ -1,14 +1,14 @@
import { CssBaseline } from '@mui/material';
import './App.css';
import { LanguageManager } from './components/LanguageManager';
import { LoginPage } from './features/authentication/routes/LoginPage';
import { AuthenticationPage } from './features/authentication/routes/AuthenticationPage';
function App() {
return (
<>
<CssBaseline />
<LanguageManager />
<LoginPage />
<AuthenticationPage />
</>
);
}

View File

@@ -0,0 +1,25 @@
import React, { useState, type JSX } from 'react';
import { LoginRegisterForm } from './LoginRegiserForm';
import type { AuthMode, AuthType } from '../types/auth-types';
export const AuthenticationContainer = (): JSX.Element => {
const [authMode, setAuthMode] = useState<AuthMode>('login');
const [authType, setAuthType] = useState<AuthType>('phone');
const [currentStep, setCurrentStep] = useState<
'emailOrPassword' | 'verify' | 'enterPassword'
>('emailOrPassword');
const handleLoginRegister = (value: string) => {};
return (
<>
{currentStep === 'emailOrPassword' && (
<LoginRegisterForm
authType={authType}
setAuthType={setAuthType}
onLoginRegisterSubmit={handleLoginRegister}
/>
)}
</>
);
};

View File

@@ -0,0 +1,138 @@
import { Box, Button, Stack, TextField, Typography } from '@mui/material';
import { useRef, useState, type Dispatch } from 'react';
import { useTranslation } from 'react-i18next';
import { CountryCodeSelector } from './CountryCodeSelector';
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';
export interface LoginRegisterFormProps {
authType: AuthType;
setAuthType: Dispatch<AuthType>;
onLoginRegisterSubmit: (value: string) => void;
}
export function LoginRegisterForm({
authType,
setAuthType,
}: LoginRegisterFormProps) {
const { t, i18n } = useTranslation('authentication');
const [value, setValue] = useState('');
const [countryCode, setCountryCode] = useState('+98');
const textFieldRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const dir = i18n.dir();
const [error, setError] = useState<string>();
const [touched, setTouched] = useState<boolean>(false);
const inputError: boolean = touched && !!error;
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
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)) {
setAuthType('phone');
} else {
setAuthType('email');
}
};
const handleBlur = () => {
setTouched(true);
validateInput(value, authType);
};
const validateInput = (value: string, authType: AuthType) => {
if (!value) {
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 {
setError(undefined);
}
};
const isInputValid = (value: string, authType: AuthType): boolean => {
if (!value) {
return false;
}
if (authType === 'email' && !isEmail(value)) {
return false;
}
if (authType === 'phone' && false /* TODO */) {
return false;
}
return true;
};
const handleSubmit = () => {
if (isInputValid(value, authType)) {
} else {
inputRef.current?.focus();
validateInput(value, authType);
}
};
const showAdornment = authType === 'phone' && value.length > 0;
return (
<Box sx={{ width: '100%' }}>
<Stack spacing={1}>
<Typography variant="h5">{t('loginForm.title')}</Typography>
<Typography variant="body2" color="text.secondary">
{t('loginForm.description')}
</Typography>
</Stack>
<TextField
ref={textFieldRef}
inputRef={inputRef}
label={t('loginForm.emailOrPhoneLabel')}
value={value}
onChange={handleInputChange}
onBlur={handleBlur}
error={inputError}
helperText={inputError ? error : ''}
autoFocus
slotProps={{
htmlInput: { dir: 'auto', sx: { lineHeight: 1.5, paddingX: 0 } },
input: {
startAdornment: dir === 'ltr' && (
<CountryCodeSelector
value={countryCode}
onChange={setCountryCode}
show={showAdornment}
menuAnchor={textFieldRef.current}
onCloseFocusRef={inputRef}
/>
),
endAdornment: dir === 'rtl' && (
<CountryCodeSelector
value={countryCode}
onChange={setCountryCode}
show={showAdornment}
menuAnchor={textFieldRef.current}
onCloseFocusRef={inputRef}
/>
),
},
}}
sx={{ my: 4 }}
/>
<Stack spacing={2}>
<Button onClick={handleSubmit}>{t('loginForm.submitButton')}</Button>
<Button variant="outlined" startIcon={<Google variant="Bold" />}>
{t('loginForm.loginWithGoogle')}
</Button>
</Stack>
</Box>
);
}

View File

@@ -16,7 +16,7 @@ export function SmsOtpForm({ value, type }: SmsOtpProps) {
<Box
sx={{
display: 'flex',
flexDirection: 'row',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
gap: 4,

View File

@@ -3,13 +3,9 @@ import Logo from '@/components/Logo';
import { Paper } from '@mui/material';
import { SmsOtpForm } from '../components/SmsOtpForm';
import { useState } from 'react';
import { AuthenticationContainer } from '../components/AuthenticationContainer';
export function LoginPage() {
const [phoneOrEmail, setPhoneOrEmail] = useState<string>(
'sajadmirjalili82@gmail.com',
);
const [type, setType] = useState<'phone' | 'email'>('phone');
export function AuthenticationPage() {
return (
<FlexBox
direction="column"
@@ -29,8 +25,7 @@ export function LoginPage() {
width: '34.5rem',
}}
>
{/* <LoginForm /> */}
<SmsOtpForm value={phoneOrEmail} type={type} />
<AuthenticationContainer />
</Paper>
</FlexBox>
);

View File

@@ -0,0 +1,3 @@
export type AuthType = 'email' | 'phone';
export type AuthMode = 'register' | 'login';

View File

@@ -1,11 +1,10 @@
import { blue } from '@mui/material/colors';
import type { Palette } from './color.type';
export const PALETTE: Palette = {
primary: {
light: {
main: '#212121',
dark: '#000000',
light: '#616161',
main: blue.A400,
contrastText: '#FFFFFF',
},
// TODO

View File

@@ -0,0 +1,2 @@
export const isEmail = (value: string) =>
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value);