feat: add the language menu in login or regsiter form

This commit is contained in:
Koosha Lahouti
2025-10-06 12:52:45 +03:30
parent 0cafa8bf81
commit 18634cbf49
4 changed files with 122 additions and 66 deletions

View File

@@ -8,7 +8,10 @@
"emailIsInvalid": "Email is invalid",
"phoneNumberIsInvalid": "Phone number is invalid",
"thisFieldIsRequired": "This field is required",
"googleAuthenticationFailed": "Login with google failed"
"googleAuthenticationFailed": "Login with google failed",
"persian": "Persian(Fa)",
"english": "English(En)",
"accountInfo": "Harmony Account - 2025"
},
"verify": {
"verify": "Verify",

View File

@@ -8,7 +8,10 @@
"emailIsInvalid": "ایمیل وارد شده نامعتبر میباشد",
"phoneNumberIsInvalid": "شماره وارد شده نامعتبر میباشد",
"thisFieldIsRequired": "این فیلد الزامی است",
"googleAuthenticationFailed": "ورود با گوگل با خطا مواجه شد"
"googleAuthenticationFailed": "ورود با گوگل با خطا مواجه شد",
"persian": "فارسی(Fa)",
"english": "انگلیسی(En)",
"accountInfo": "۱۴۰۴-هارمونی اکانت"
},
"verify": {
"verify": "اعتبارسنجی",

View File

@@ -0,0 +1,46 @@
import { Box, Typography, MenuItem, Select, Stack } from '@mui/material';
import { Global } from 'iconsax-react';
import { useTranslation } from 'react-i18next';
export default function LanguageAccountBar() {
const { t, i18n } = useTranslation('authentication');
const handleChange = (event: any) => {
const lang = event.target.value;
i18n.changeLanguage(lang);
document.body.dir = lang === 'fa' ? 'rtl' : 'ltr';
};
return (
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
px: 2,
py: 1,
position: 'absolute',
bottom: 0,
direction: i18n.language === 'fa' ? 'rtl' : 'ltr',
}}
>
<Stack direction="row" alignItems="center" spacing={1}>
<Select
size="small"
value={i18n.language}
onChange={handleChange}
variant="standard"
disableUnderline
>
<MenuItem value="fa">{t('loginForm.persian')}</MenuItem>
<MenuItem value="en">{t('loginForm.english')}</MenuItem>
</Select>
<Global size={20} style={{ color: '#666' }} />
</Stack>
<Typography sx={{ color: 'text.primary' }} variant="body2">
{t('loginForm.accountInfo')}
</Typography>
</Box>
);
}

View File

@@ -15,6 +15,7 @@ import { useApi } from '@/hooks/useApi';
import type { GenerateTokenResponse } from '../../api/identityAPI';
import { GoogleAuthenticationV2 } from './GoogleAuthenticationV2';
import { replacePersianWithRealNumbers } from '@/utils/replacePersianWithRealNumbers';
import LanguageAccountBar from './LanguageSwitcher';
export interface LoginRegisterFormProps {
loginRegisterValue: string;
@@ -143,72 +144,75 @@ export function LoginRegisterForm({
const showAdornment = authType === 'phone' && loginRegisterValue.length > 0;
return (
<AuthenticationCard>
<Box
component="form"
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
if (!userStatusLoading) {
void handleSubmit();
}
}}
>
<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={loginRegisterValue}
onChange={handleInputChange}
onBlur={handleBlur}
error={inputError}
helperText={inputError ? error : ''}
autoFocus
slotProps={{
htmlInput: { dir: 'auto', sx: { lineHeight: 1.5 } },
input: {
endAdornment: i18n.dir() === 'rtl' && (
<CountryCodeSelector
value={countryCode}
onChange={setCountryCode}
show={showAdornment}
menuAnchor={menuAnchorEl}
onCloseFocusRef={inputRef}
/>
),
startAdornment: i18n.dir() === 'ltr' && (
<CountryCodeSelector
value={countryCode}
onChange={setCountryCode}
show={showAdornment}
menuAnchor={menuAnchorEl}
onCloseFocusRef={inputRef}
/>
),
},
<>
<AuthenticationCard>
<Box
component="form"
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
if (!userStatusLoading) {
void handleSubmit();
}
}}
sx={{ my: 4 }}
/>
>
<Stack spacing={1}>
<Typography variant="h5">{t('loginForm.title')}</Typography>
<Typography variant="body2" color="text.secondary">
{t('loginForm.description')}
</Typography>
</Stack>
<Stack spacing={2}>
<Button loading={userStatusLoading} type="submit">
{t('loginForm.submitButton')}
</Button>
<GoogleAuthenticationV2
authFactory={authFactory}
onGoogleAuthenticated={onGoogleAuthenticated}
disabled={userStatusLoading}
<TextField
ref={textFieldRef}
inputRef={inputRef}
label={t('loginForm.emailOrPhoneLabel')}
value={loginRegisterValue}
onChange={handleInputChange}
onBlur={handleBlur}
error={inputError}
helperText={inputError ? error : ''}
autoFocus
slotProps={{
htmlInput: { dir: 'auto', sx: { lineHeight: 1.5 } },
input: {
endAdornment: i18n.dir() === 'rtl' && (
<CountryCodeSelector
value={countryCode}
onChange={setCountryCode}
show={showAdornment}
menuAnchor={menuAnchorEl}
onCloseFocusRef={inputRef}
/>
),
startAdornment: i18n.dir() === 'ltr' && (
<CountryCodeSelector
value={countryCode}
onChange={setCountryCode}
show={showAdornment}
menuAnchor={menuAnchorEl}
onCloseFocusRef={inputRef}
/>
),
},
}}
sx={{ my: 4 }}
/>
</Stack>
</Box>
</AuthenticationCard>
<Stack spacing={2}>
<Button loading={userStatusLoading} type="submit">
{t('loginForm.submitButton')}
</Button>
<GoogleAuthenticationV2
authFactory={authFactory}
onGoogleAuthenticated={onGoogleAuthenticated}
disabled={userStatusLoading}
/>
</Stack>
</Box>
</AuthenticationCard>
<LanguageAccountBar />
</>
);
}