Files
shop-server/client/src/pages/auth/ui/AuthPage.tsx
T

176 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useState } from 'react'
import Alert from '@mui/material/Alert'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Paper from '@mui/material/Paper'
import Stack from '@mui/material/Stack'
import { alpha, useTheme } from '@mui/material/styles'
import Typography from '@mui/material/Typography'
import { useUnit } from 'effector-react'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { AuthCodeForm } from '@/features/auth-code'
import { AuthForgotForm } from '@/features/auth-forgot'
import { OAuthButtons } from '@/features/auth-oauth'
import { AuthPasswordForm } from '@/features/auth-password'
import { $user } from '@/shared/model/auth'
import { BearLogo } from '@/shared/ui/BearLogo'
export function AuthPage() {
const theme = useTheme()
const [message, setMessage] = useState<string | null>(null)
const [oauthError, setOauthError] = useState<string | null>(null)
const [tab, setTab] = useState(0)
const [isRegister, setIsRegister] = useState(false)
const [showForgot, setShowForgot] = useState(false)
const [searchParams, setSearchParams] = useSearchParams()
const navigate = useNavigate()
const user = useUnit($user)
useEffect(() => {
if (user) navigate('/', { replace: true })
}, [navigate, user])
useEffect(() => {
const err = searchParams.get('oauthError')
if (!err) return
const timeoutId = setTimeout(() => {
setOauthError(err)
setSearchParams({}, { replace: true })
}, 0)
return () => clearTimeout(timeoutId)
}, [])
if (showForgot) {
return (
<Box
sx={{
display: 'flex',
alignItems: 'start',
justifyContent: 'center',
minHeight: 'calc(100vh - 64px)',
px: 2,
background: `radial-gradient(circle at 50% 30%, ${alpha(theme.palette.primary.main, 0.05)} 0%, transparent 70%)`,
}}
>
<Box sx={{ width: '100%', maxWidth: 440 }}>
<Box sx={{ display: 'flex', justifyContent: 'center', mb: 2 }}>
<BearLogo sx={{ width: 72, height: 72 }} />
</Box>
<Typography variant="h5" sx={{ fontWeight: 700, textAlign: 'center' }} gutterBottom>
Восстановление пароля
</Typography>
<Paper
sx={{
p: 4,
borderRadius: 3,
border: `1px solid ${theme.palette.divider}`,
}}
>
<AuthForgotForm onBack={() => setShowForgot(false)} />
</Paper>
</Box>
</Box>
)
}
return (
<Box
sx={{
display: 'flex',
alignItems: 'start',
justifyContent: 'center',
minHeight: 'calc(100vh - 64px)',
px: 2,
background: `radial-gradient(circle at 50% 30%, ${alpha(theme.palette.primary.main, 0.05)} 0%, transparent 70%)`,
}}
>
<Box sx={{ width: '100%', maxWidth: 440 }}>
<Box sx={{ display: 'flex', justifyContent: 'center', mb: 2 }}>
<BearLogo sx={{ width: 72, height: 72 }} />
</Box>
<Typography variant="h5" sx={{ fontWeight: 700, textAlign: 'center' }} gutterBottom>
Добро пожаловать <br />в Любимый Креатив
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ textAlign: 'center', mb: 3 }}>
Войдите или зарегистрируйтесь, чтобы продолжить
</Typography>
<Paper
sx={{
p: 4,
borderRadius: 3,
border: `1px solid ${theme.palette.divider}`,
}}
>
<Stack direction="row" spacing={1} sx={{ mb: 3 }}>
{[
{ label: 'Пароль', idx: 0 },
{ label: 'Код', idx: 1 },
].map(({ label, idx }) => (
<Button
key={idx}
variant={tab === idx ? 'contained' : 'outlined'}
size="small"
sx={{
borderRadius: '24px',
flex: 1,
textTransform: 'none',
'&:hover': { transform: 'none', borderWidth: '1px' },
}}
onClick={() => {
setTab(idx)
if (idx === 0) setIsRegister(false)
setMessage(null)
setOauthError(null)
}}
>
{label}
</Button>
))}
</Stack>
{oauthError && (
<Alert severity="error" variant="outlined" sx={{ mb: 2 }} onClose={() => setOauthError(null)}>
{oauthError}
</Alert>
)}
{message && (
<Alert severity="success" variant="outlined" sx={{ mb: 2 }} onClose={() => setMessage(null)}>
{message}
</Alert>
)}
{tab === 0 && (
<AuthPasswordForm
isRegister={isRegister}
onRegisterChange={setIsRegister}
onSuccess={() => navigate('/', { replace: true })}
/>
)}
{tab === 1 && <AuthCodeForm onSuccess={() => navigate('/', { replace: true })} />}
<Box sx={{ mt: 2, mb: 1, display: 'flex', justifyContent: 'center' }}>
<Button variant="text" size="small" onClick={() => setShowForgot(true)}>
Забыли пароль?
</Button>
</Box>
<Box sx={{ mt: 3, mb: 1, display: 'flex', alignItems: 'center', gap: 1 }}>
<Box sx={{ flex: 1, borderBottom: `1px solid ${theme.palette.divider}` }} />
<Typography variant="body2" color="text.secondary" sx={{ px: 1, whiteSpace: 'nowrap' }}>
или
</Typography>
<Box sx={{ flex: 1, borderBottom: `1px solid ${theme.palette.divider}` }} />
</Box>
<OAuthButtons />
</Paper>
</Box>
</Box>
)
}