fix: authorization / registration

This commit is contained in:
2026-05-10 19:24:32 +03:00
parent 574e27a379
commit 8b0e787fc6
11 changed files with 140 additions and 39 deletions

View File

@@ -0,0 +1,36 @@
import { useState } from 'react'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useNavigate, useLocation } from 'react-router-dom'
import { login } from '@features/auth'
import { tokenStore } from '@shared/api/tokenStore'
import { AUTH_QUERY_KEY } from '@features/auth'
import { ROUTES } from '@shared/config/routes'
export function useLoginForm() {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const navigate = useNavigate()
const location = useLocation()
const queryClient = useQueryClient()
const from = (location.state as { from?: { pathname: string } })?.from?.pathname ?? ROUTES.WALLET
const mutation = useMutation({
mutationFn: login,
onSuccess: ({ access_token }) => {
tokenStore.set(access_token)
queryClient.setQueryData(AUTH_QUERY_KEY, access_token)
navigate(from, { replace: true })
},
})
return {
email, setEmail,
password, setPassword,
isLoading: mutation.isPending,
error: mutation.isError ? 'Неверный email или пароль' : null,
handleSubmit: (e: React.FormEvent) => {
e.preventDefault()
mutation.mutate({ email, password })
},
}
}

View File

@@ -1,4 +1,3 @@
import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { FormField } from '@shared/ui'
import { PrimaryButton } from '@shared/ui'
@@ -6,14 +5,14 @@ import { Button } from '@shared/ui'
import { ROUTES } from '@shared/config/routes'
import logo from '@shared/assets/logo-full-white.png'
import styles from './LoginForm.module.css'
import { useLoginForm } from '../model/useLoginForm'
export function LoginForm() {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const { email, setEmail, password, setPassword, isLoading, error, handleSubmit } = useLoginForm()
const navigate = useNavigate()
return (
<form className={styles.card}>
<form className={styles.card} onSubmit={handleSubmit}>
<div className={styles.logo}>
<img src={logo} alt="ЭКСА" />
</div>
@@ -38,10 +37,12 @@ export function LoginForm() {
/>
</div>
{error && <p className={styles.error}>{error}</p>}
<a className={styles.forgot}>Забыли пароль?</a>
<div className={styles.actions}>
<PrimaryButton label="Войти" />
<PrimaryButton label="Войти" disabled={isLoading} />
<div className={styles.divider}><span>или</span></div>
<Button variant="outline" onClick={() => navigate(ROUTES.REGISTER)}>
Создать новый кошелёк

View File

@@ -1,7 +1,8 @@
import { useState } from 'react'
import { useMutation } from '@tanstack/react-query'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useNavigate } from 'react-router-dom'
import { registrationStart, registrationComplete } from '@features/auth'
import { registrationStart, registrationComplete, AUTH_QUERY_KEY } from '@features/auth'
import { tokenStore } from '@shared/api/tokenStore'
import { ROUTES } from '@shared/config/routes'
import type { ApiErrorResponse } from '@shared/api/types'
@@ -12,6 +13,7 @@ function extractErrorMessage(error: unknown): string {
export function useRegisterForm() {
const navigate = useNavigate()
const queryClient = useQueryClient()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [confirmPassword, setConfirmPassword] = useState('')
@@ -26,8 +28,9 @@ export function useRegisterForm() {
const completeMutation = useMutation({
mutationFn: registrationComplete,
onSuccess: () => {
localStorage.setItem('isAuthenticated', 'true')
onSuccess: ({ access_token }) => {
tokenStore.set(access_token)
queryClient.setQueryData(AUTH_QUERY_KEY, access_token)
navigate(ROUTES.WALLET)
},
})

View File

@@ -3,9 +3,11 @@ import styles from './WalletHeader.module.css'
import { Link } from 'react-router-dom'
import { ROUTES } from '@shared/config/routes'
import { useEffect, useRef, useState } from 'react'
import { useMutation } from '@tanstack/react-query'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useNavigate } from 'react-router-dom'
import { logout } from '@features/auth/api/registrationApi'
import { AUTH_QUERY_KEY } from '@features/auth'
import { tokenStore } from '@shared/api/tokenStore'
import { Notification } from '@shared/ui'
const TICKERS = [
@@ -19,10 +21,15 @@ export function WalletHeader() {
const [error, setError] = useState(false)
const ref = useRef<HTMLDivElement>(null)
const navigate = useNavigate()
const queryClient = useQueryClient()
const { mutate: logoutMutate } = useMutation({
mutationFn: logout,
onSuccess: () => navigate(ROUTES.HOME),
onSuccess: () => {
tokenStore.clear()
queryClient.setQueryData(AUTH_QUERY_KEY, null)
navigate(ROUTES.HOME)
},
onError: () => setError(true),
})