base commit
This commit is contained in:
@@ -1 +1,2 @@
|
||||
export { AuthCallbackPage } from './ui/AuthCallbackPage'
|
||||
export { AuthPage } from './ui/AuthPage'
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { useEffect } from 'react'
|
||||
import Box from '@mui/material/Box'
|
||||
import CircularProgress from '@mui/material/CircularProgress'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom'
|
||||
import { tokenSet } from '@/shared/model/auth'
|
||||
|
||||
export function AuthCallbackPage() {
|
||||
const [params] = useSearchParams()
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(() => {
|
||||
const t = params.get('token')
|
||||
if (t) {
|
||||
tokenSet(t)
|
||||
navigate('/', { replace: true })
|
||||
return
|
||||
}
|
||||
navigate('/auth', { replace: true })
|
||||
}, [navigate, params])
|
||||
|
||||
return (
|
||||
<Box sx={{ py: 6, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2 }}>
|
||||
<CircularProgress />
|
||||
<Typography color="text.secondary">Завершение входа…</Typography>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -9,8 +9,9 @@ import Typography from '@mui/material/Typography'
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import { useUnit } from 'effector-react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom'
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
import { oauthAuthorizeUrl } from '@/shared/lib/oauth-authorize-url'
|
||||
import { $user, tokenSet } from '@/shared/model/auth'
|
||||
|
||||
type AuthResponse = { token: string; user: { id: string; email: string; name?: string | null; phone?: string | null } }
|
||||
@@ -26,6 +27,8 @@ function getApiErrorMessage(err: unknown): string | null {
|
||||
|
||||
export function AuthPage() {
|
||||
const [message, setMessage] = useState<string | null>(null)
|
||||
const [oauthError, setOauthError] = useState<string | null>(null)
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const navigate = useNavigate()
|
||||
const user = useUnit($user)
|
||||
const { register, watch } = useForm<{
|
||||
@@ -45,6 +48,13 @@ export function AuthPage() {
|
||||
if (user) navigate('/', { replace: true })
|
||||
}, [navigate, user])
|
||||
|
||||
useEffect(() => {
|
||||
const err = searchParams.get('oauthError')
|
||||
if (!err) return
|
||||
setOauthError(err)
|
||||
setSearchParams({}, { replace: true })
|
||||
}, [searchParams, setSearchParams])
|
||||
|
||||
const requestCode = useMutation({
|
||||
mutationFn: async () => {
|
||||
await apiClient.post('auth/request-code', { email })
|
||||
@@ -94,6 +104,11 @@ export function AuthPage() {
|
||||
{message}
|
||||
</Alert>
|
||||
)}
|
||||
{oauthError && (
|
||||
<Alert severity="error" sx={{ mb: 2 }} onClose={() => setOauthError(null)}>
|
||||
{oauthError}
|
||||
</Alert>
|
||||
)}
|
||||
{errMsg && (
|
||||
<Alert severity="error" sx={{ mb: 2 }}>
|
||||
{errMsg}
|
||||
@@ -101,6 +116,18 @@ export function AuthPage() {
|
||||
)}
|
||||
|
||||
<Stack spacing={2} sx={{ maxWidth: 520 }}>
|
||||
<Typography variant="subtitle1">Быстрый вход</Typography>
|
||||
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={1.5}>
|
||||
<Button component="a" href={oauthAuthorizeUrl('vk')} variant="outlined" fullWidth>
|
||||
Войти через VK
|
||||
</Button>
|
||||
<Button component="a" href={oauthAuthorizeUrl('yandex')} variant="outlined" fullWidth>
|
||||
Войти через Яндекс
|
||||
</Button>
|
||||
</Stack>
|
||||
|
||||
<Divider>или по email</Divider>
|
||||
|
||||
<TextField label="Email" {...register('email')} fullWidth />
|
||||
|
||||
<Typography variant="h6">Вариант 1: Email + код</Typography>
|
||||
|
||||
Reference in New Issue
Block a user