base commit
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
import Alert from '@mui/material/Alert'
|
||||
import Box from '@mui/material/Box'
|
||||
import Button from '@mui/material/Button'
|
||||
import Divider from '@mui/material/Divider'
|
||||
import Stack from '@mui/material/Stack'
|
||||
import TextField from '@mui/material/TextField'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import { useUnit } from 'effector-react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import {
|
||||
$changePasswordError,
|
||||
$requestEmailChangeCodeError,
|
||||
$updateProfileError,
|
||||
$user,
|
||||
$verifyEmailChangeError,
|
||||
changePasswordFx,
|
||||
requestEmailChangeCodeFx,
|
||||
updateProfileFx,
|
||||
verifyEmailChangeFx,
|
||||
} from '@/shared/model/auth'
|
||||
|
||||
export function MePage() {
|
||||
const user = useUnit($user)
|
||||
const pendingPassword = useUnit(changePasswordFx.pending)
|
||||
const pendingEmailReq = useUnit(requestEmailChangeCodeFx.pending)
|
||||
const pendingEmailVerify = useUnit(verifyEmailChangeFx.pending)
|
||||
const pendingProfile = useUnit(updateProfileFx.pending)
|
||||
const errorPassword = useUnit($changePasswordError)
|
||||
const errorEmailReq = useUnit($requestEmailChangeCodeError)
|
||||
const errorProfile = useUnit($updateProfileError)
|
||||
const errorEmailVerify = useUnit($verifyEmailChangeError)
|
||||
|
||||
const passwordForm = useForm<{ currentPassword: string; newPassword: string }>({
|
||||
defaultValues: { currentPassword: '', newPassword: '' },
|
||||
mode: 'onChange',
|
||||
})
|
||||
|
||||
const emailForm = useForm<{ newEmail: string; code: string }>({
|
||||
defaultValues: { newEmail: '', code: '' },
|
||||
mode: 'onChange',
|
||||
})
|
||||
|
||||
const profileForm = useForm<{ name: string }>({
|
||||
defaultValues: { name: user?.name ? String(user.name) : '' },
|
||||
mode: 'onChange',
|
||||
})
|
||||
|
||||
const passwordErrorMsg =
|
||||
(errorPassword as any)?.response?.data?.error ? String((errorPassword as any).response.data.error) : null
|
||||
const emailErrorMsg =
|
||||
(errorEmailReq as any)?.response?.data?.error
|
||||
? String((errorEmailReq as any).response.data.error)
|
||||
: (errorEmailVerify as any)?.response?.data?.error
|
||||
? String((errorEmailVerify as any).response.data.error)
|
||||
: null
|
||||
const profileErrorMsg =
|
||||
(errorProfile as any)?.response?.data?.error ? String((errorProfile as any).response.data.error) : null
|
||||
|
||||
if (!user) {
|
||||
return <Alert severity="info">Нужно войти. Перейдите на страницу «Вход».</Alert>
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Typography variant="h4" gutterBottom>
|
||||
Профиль
|
||||
</Typography>
|
||||
<Typography color="text.secondary" sx={{ mb: 3 }}>
|
||||
Текущая почта: <b>{user.email}</b>
|
||||
</Typography>
|
||||
|
||||
{passwordErrorMsg && (
|
||||
<Alert severity="error" sx={{ mb: 2 }}>
|
||||
{passwordErrorMsg}
|
||||
</Alert>
|
||||
)}
|
||||
{emailErrorMsg && (
|
||||
<Alert severity="error" sx={{ mb: 2 }}>
|
||||
{emailErrorMsg}
|
||||
</Alert>
|
||||
)}
|
||||
{profileErrorMsg && (
|
||||
<Alert severity="error" sx={{ mb: 2 }}>
|
||||
{profileErrorMsg}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Stack spacing={3} sx={{ maxWidth: 560 }}>
|
||||
<Box>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Имя / ник
|
||||
</Typography>
|
||||
<Stack spacing={2}>
|
||||
<TextField
|
||||
label="Имя или ник"
|
||||
helperText="До 40 символов"
|
||||
slotProps={{ htmlInput: { maxLength: 40 } }}
|
||||
{...profileForm.register('name')}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={pendingProfile}
|
||||
onClick={() => {
|
||||
const raw = profileForm.getValues('name')
|
||||
const name = raw.trim()
|
||||
updateProfileFx({ name: name.length ? name : null })
|
||||
}}
|
||||
>
|
||||
Сохранить имя
|
||||
</Button>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Box>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Смена почты
|
||||
</Typography>
|
||||
<Stack spacing={2}>
|
||||
<TextField label="Новая почта" {...emailForm.register('newEmail')} />
|
||||
<Button
|
||||
variant="outlined"
|
||||
disabled={!emailForm.watch('newEmail') || pendingEmailReq}
|
||||
onClick={() => requestEmailChangeCodeFx(emailForm.getValues('newEmail').trim())}
|
||||
>
|
||||
Отправить код на новую почту
|
||||
</Button>
|
||||
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>
|
||||
<TextField label="Код (6 цифр)" inputMode="numeric" {...emailForm.register('code')} />
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={emailForm.watch('code').trim().length !== 6 || pendingEmailVerify}
|
||||
onClick={() =>
|
||||
verifyEmailChangeFx({
|
||||
newEmail: emailForm.getValues('newEmail').trim(),
|
||||
code: emailForm.getValues('code').trim(),
|
||||
})
|
||||
}
|
||||
>
|
||||
Подтвердить
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Box>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Смена пароля
|
||||
</Typography>
|
||||
<Stack spacing={2}>
|
||||
<TextField
|
||||
label="Текущий пароль (если установлен)"
|
||||
type="password"
|
||||
{...passwordForm.register('currentPassword')}
|
||||
/>
|
||||
<TextField label="Новый пароль" type="password" {...passwordForm.register('newPassword')} />
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={passwordForm.watch('newPassword').length < 8 || pendingPassword}
|
||||
onClick={() =>
|
||||
changePasswordFx({
|
||||
currentPassword: passwordForm.getValues('currentPassword') || undefined,
|
||||
newPassword: passwordForm.getValues('newPassword'),
|
||||
})
|
||||
}
|
||||
>
|
||||
Сохранить пароль
|
||||
</Button>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user