forked from VinokurovVE/tests
Refactored store
This commit is contained in:
@ -8,7 +8,7 @@ import MainLayout from "./layouts/MainLayout"
|
|||||||
import SignIn from "./pages/auth/SignIn"
|
import SignIn from "./pages/auth/SignIn"
|
||||||
import ApiTest from "./pages/ApiTest"
|
import ApiTest from "./pages/ApiTest"
|
||||||
import SignUp from "./pages/auth/SignUp"
|
import SignUp from "./pages/auth/SignUp"
|
||||||
import { useAuthStore } from "./store/auth"
|
import { initAuth, useAuthStore } from "./store/auth"
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import { CircularProgress } from "@mui/material"
|
import { CircularProgress } from "@mui/material"
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ function App() {
|
|||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
auth.initializeAuth()
|
initAuth()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
// Once auth is there, set loading to false and render the app
|
// Once auth is there, set loading to false and render the app
|
||||||
|
@ -13,7 +13,7 @@ export default function DataTable(props: Props) {
|
|||||||
columns={props.columns}
|
columns={props.columns}
|
||||||
initialState={{
|
initialState={{
|
||||||
pagination: {
|
pagination: {
|
||||||
paginationModel: { page: 0, pageSize: 5 },
|
paginationModel: { page: 0, pageSize: 10 },
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
pageSizeOptions={[10, 20, 50, 100]}
|
pageSizeOptions={[10, 20, 50, 100]}
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
import { memo, useEffect, useMemo, useState } from "react";
|
import { memo, useEffect, useMemo, useState } from "react";
|
||||||
import UserService from "../services/UserService";
|
import UserService from "../services/UserService";
|
||||||
import AuthService from "../services/AuthService";
|
|
||||||
|
|
||||||
export default function useUserData<T>(token: string, initData: T): T {
|
export default function useUserData<T>(token: string, initData: T): T {
|
||||||
const [userData, setUserData] = useState<T>(initData)
|
const [userData, setUserData] = useState<T>(initData)
|
||||||
|
|
||||||
useEffect(()=> {
|
useEffect(()=> {
|
||||||
const fetchUserData = async (token: string) => {
|
const fetchUserData = async (token: string) => {
|
||||||
const response = await AuthService.getCurrentUser(token)
|
const response = await UserService.getCurrentUser(token)
|
||||||
setUserData(response.data)
|
setUserData(response.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
export const USER_DATA_KEY = 'userData';
|
||||||
|
export const TOKEN_AUTH_KEY = 'authToken'
|
||||||
|
export const TOKEN_ISSUED_DATE_KEY = 'tokenIssuedDate';
|
||||||
|
export const TOKEN_EXPIRY_DURATION = 7 * 24 * 60 * 60 * 1000;
|
@ -18,4 +18,4 @@ axiosInstance.interceptors.request.use(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export default axiosInstance;
|
export default axiosInstance;
|
@ -1,3 +1,27 @@
|
|||||||
|
export interface User {
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserData extends User {
|
||||||
|
email: string;
|
||||||
|
login: string;
|
||||||
|
phone: string;
|
||||||
|
name: string;
|
||||||
|
surname: string;
|
||||||
|
is_active: boolean;
|
||||||
|
role_id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserCreds extends User {
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AuthState {
|
||||||
|
isAuthenticated: boolean;
|
||||||
|
token: string | null;
|
||||||
|
userData: UserData | {};
|
||||||
|
}
|
||||||
|
|
||||||
export interface SignUpFormData {
|
export interface SignUpFormData {
|
||||||
email: string;
|
email: string;
|
||||||
login: string;
|
login: string;
|
@ -1,6 +1,6 @@
|
|||||||
// Layout for dashboard with responsive drawer
|
// Layout for dashboard with responsive drawer
|
||||||
|
|
||||||
import { Navigate, Outlet } from "react-router-dom"
|
import { Link, NavLink, Navigate, Outlet, useLocation, useNavigate } from "react-router-dom"
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import AppBar from '@mui/material/AppBar';
|
import AppBar from '@mui/material/AppBar';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
@ -17,7 +17,8 @@ import MenuIcon from '@mui/icons-material/Menu';
|
|||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import { Api, ExitToApp, Home, People, Settings, Shield } from "@mui/icons-material";
|
import { Api, ExitToApp, Home, People, Settings, Shield } from "@mui/icons-material";
|
||||||
import { UserData, useAuthStore } from "../store/auth";
|
import { getUserData, useAuthStore } from "../store/auth";
|
||||||
|
import { UserData } from "../interfaces/auth";
|
||||||
|
|
||||||
const drawerWidth = 240;
|
const drawerWidth = 240;
|
||||||
|
|
||||||
@ -25,6 +26,10 @@ export default function DashboardLayout() {
|
|||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const [userData, setUserData] = React.useState<UserData>();
|
const [userData, setUserData] = React.useState<UserData>();
|
||||||
|
|
||||||
|
const location = useLocation()
|
||||||
|
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
//const { window } = props;
|
//const { window } = props;
|
||||||
const [mobileOpen, setMobileOpen] = React.useState(false);
|
const [mobileOpen, setMobileOpen] = React.useState(false);
|
||||||
const [isClosing, setIsClosing] = React.useState(false);
|
const [isClosing, setIsClosing] = React.useState(false);
|
||||||
@ -95,7 +100,12 @@ export default function DashboardLayout() {
|
|||||||
<List>
|
<List>
|
||||||
{pages.map((item, index) => (
|
{pages.map((item, index) => (
|
||||||
<ListItem key={index} disablePadding>
|
<ListItem key={index} disablePadding>
|
||||||
<ListItemButton href={item.path}>
|
<ListItemButton
|
||||||
|
onClick={() => {
|
||||||
|
navigate(item.path)
|
||||||
|
}}
|
||||||
|
selected={location.pathname === item.path}
|
||||||
|
>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
{item.icon}
|
{item.icon}
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
@ -110,7 +120,12 @@ export default function DashboardLayout() {
|
|||||||
<List>
|
<List>
|
||||||
{misc.map((item, index) => (
|
{misc.map((item, index) => (
|
||||||
<ListItem key={index} disablePadding>
|
<ListItem key={index} disablePadding>
|
||||||
<ListItemButton href={item.path}>
|
<ListItemButton
|
||||||
|
onClick={() => {
|
||||||
|
navigate(item.path)
|
||||||
|
}}
|
||||||
|
selected={location.pathname === item.path}
|
||||||
|
>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
{item.icon}
|
{item.icon}
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
@ -124,13 +139,20 @@ export default function DashboardLayout() {
|
|||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (authStore) {
|
if (authStore) {
|
||||||
const stored = authStore.getUserData()
|
const stored = getUserData()
|
||||||
if (stored) {
|
if (stored) {
|
||||||
setUserData(stored)
|
setUserData(stored)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [authStore])
|
}, [authStore])
|
||||||
|
|
||||||
|
const getPageTitle = () => {
|
||||||
|
const currentPath = location.pathname;
|
||||||
|
const allPages = [...pages, ...misc];
|
||||||
|
const currentPage = allPages.find(page => page.path === currentPath);
|
||||||
|
return currentPage ? currentPage.label : "Dashboard";
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -156,7 +178,7 @@ export default function DashboardLayout() {
|
|||||||
<MenuIcon />
|
<MenuIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Typography variant="h6" noWrap component="div">
|
<Typography variant="h6" noWrap component="div">
|
||||||
Dashboard
|
{getPageTitle()}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
|
@ -4,8 +4,6 @@ import { Outlet } from "react-router-dom";
|
|||||||
|
|
||||||
export default function MainLayout() {
|
export default function MainLayout() {
|
||||||
return (
|
return (
|
||||||
<>
|
<Outlet />
|
||||||
<Outlet/>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -1,15 +1,14 @@
|
|||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import UserService from "../services/UserService"
|
|
||||||
import AuthService from "../services/AuthService"
|
|
||||||
import { Button } from "@mui/material"
|
import { Button } from "@mui/material"
|
||||||
import DataTable from "../components/DataTable"
|
import DataTable from "../components/DataTable"
|
||||||
import { GridColDef } from "@mui/x-data-grid"
|
import { GridColDef } from "@mui/x-data-grid"
|
||||||
|
import UserService from "../services/UserService"
|
||||||
|
|
||||||
export default function ApiTest() {
|
export default function ApiTest() {
|
||||||
const [users, setUsers] = useState<any>(null)
|
const [users, setUsers] = useState<any>(null)
|
||||||
|
|
||||||
const getUsers = async () => {
|
const getUsers = async () => {
|
||||||
await AuthService.getUsers().then(response => {
|
await UserService.getUsers().then(response => {
|
||||||
setUsers(response.data)
|
setUsers(response.data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import AuthService from "../services/AuthService"
|
|
||||||
import { Box, Button } from "@mui/material"
|
import { Box, Button } from "@mui/material"
|
||||||
import DataTable from "../components/DataTable"
|
import DataTable from "../components/DataTable"
|
||||||
import { GridColDef } from "@mui/x-data-grid"
|
import { GridColDef } from "@mui/x-data-grid"
|
||||||
|
import UserService from "../services/UserService"
|
||||||
|
|
||||||
export default function Users() {
|
export default function Users() {
|
||||||
const [users, setUsers] = useState<any>(null)
|
const [users, setUsers] = useState<any>(null)
|
||||||
|
|
||||||
const getUsers = async () => {
|
const getUsers = async () => {
|
||||||
await AuthService.getUsers().then(response => {
|
await UserService.getUsers().then(response => {
|
||||||
setUsers(response.data)
|
setUsers(response.data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import React, { useState, ChangeEvent, FormEvent } from 'react';
|
|
||||||
import { useForm, SubmitHandler } from 'react-hook-form';
|
import { useForm, SubmitHandler } from 'react-hook-form';
|
||||||
import { TextField, Button, Container, Typography, Box } from '@mui/material';
|
import { TextField, Button, Container, Typography, Box } from '@mui/material';
|
||||||
import axios, { AxiosResponse } from 'axios';
|
import { AxiosResponse } from 'axios';
|
||||||
import { SignInFormData, ApiResponse } from '../../types/auth';
|
import { SignInFormData, ApiResponse } from '../../interfaces/auth';
|
||||||
import { UserData, useAuthStore } from '../../store/auth';
|
import { login, setUserData } from '../../store/auth';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import axiosInstance from '../../http/axiosInstance';
|
|
||||||
import AuthService from '../../services/AuthService';
|
import AuthService from '../../services/AuthService';
|
||||||
|
import UserService from '../../services/UserService';
|
||||||
|
|
||||||
const SignIn = () => {
|
const SignIn = () => {
|
||||||
const { register, handleSubmit, formState: { errors } } = useForm<SignInFormData>({
|
const { register, handleSubmit, formState: { errors } } = useForm<SignInFormData>({
|
||||||
@ -20,7 +19,6 @@ const SignIn = () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const onSubmit: SubmitHandler<SignInFormData> = async (data) => {
|
const onSubmit: SubmitHandler<SignInFormData> = async (data) => {
|
||||||
@ -30,21 +28,18 @@ const SignIn = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response: AxiosResponse<ApiResponse> = await axiosInstance.post(`/auth/login`, formBody, {
|
const response: AxiosResponse<ApiResponse> = await AuthService.login(formBody)
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
console.log('Вход произошел успешно:', response.data);
|
console.log('Вход произошел успешно:', response.data);
|
||||||
|
|
||||||
const token = response.data.access_token
|
const token = response.data.access_token
|
||||||
|
|
||||||
const userDataResponse: AxiosResponse<ApiResponse> = await AuthService.getCurrentUser(token)
|
const userDataResponse: AxiosResponse<ApiResponse> = await UserService.getCurrentUser(token)
|
||||||
|
|
||||||
console.log('Пользователь:', userDataResponse.data)
|
console.log('Пользователь:', userDataResponse.data)
|
||||||
|
|
||||||
authStore.setUserData(JSON.stringify(userDataResponse.data))
|
setUserData(JSON.stringify(userDataResponse.data))
|
||||||
authStore.login(token)
|
|
||||||
|
login(token)
|
||||||
|
|
||||||
navigate('/');
|
navigate('/');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -63,7 +58,8 @@ const SignIn = () => {
|
|||||||
fullWidth
|
fullWidth
|
||||||
margin="normal"
|
margin="normal"
|
||||||
label="Логин"
|
label="Логин"
|
||||||
{...register('username', { required: 'Логин обязателен' })}
|
required
|
||||||
|
{...register('username', { required: 'Введите логин' })}
|
||||||
error={!!errors.username}
|
error={!!errors.username}
|
||||||
helperText={errors.username?.message}
|
helperText={errors.username?.message}
|
||||||
/>
|
/>
|
||||||
@ -72,7 +68,8 @@ const SignIn = () => {
|
|||||||
margin="normal"
|
margin="normal"
|
||||||
type="password"
|
type="password"
|
||||||
label="Пароль"
|
label="Пароль"
|
||||||
{...register('password', { required: 'Пароль обязателен' })}
|
required
|
||||||
|
{...register('password', { required: 'Введите пароль' })}
|
||||||
error={!!errors.password}
|
error={!!errors.password}
|
||||||
helperText={errors.password?.message}
|
helperText={errors.password?.message}
|
||||||
/>
|
/>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import React, { useState, ChangeEvent, FormEvent } from 'react';
|
|
||||||
import { useForm, SubmitHandler } from 'react-hook-form';
|
import { useForm, SubmitHandler } from 'react-hook-form';
|
||||||
import { TextField, Button, Container, Typography, Box } from '@mui/material';
|
import { TextField, Button, Container, Typography, Box } from '@mui/material';
|
||||||
import axios, { AxiosResponse } from 'axios';
|
import axios, { AxiosResponse } from 'axios';
|
||||||
import { SignUpFormData, ApiResponse } from '../../types/auth';
|
import { SignUpFormData, ApiResponse } from '../../interfaces/auth';
|
||||||
import axiosInstance from '../../http/axiosInstance';
|
import axiosInstance from '../../http/axiosInstance';
|
||||||
|
import UserService from '../../services/UserService';
|
||||||
|
|
||||||
const SignUp = () => {
|
const SignUp = () => {
|
||||||
const { register, handleSubmit, formState: { errors } } = useForm<SignUpFormData>({
|
const { register, handleSubmit, formState: { errors } } = useForm<SignUpFormData>({
|
||||||
@ -21,7 +21,7 @@ const SignUp = () => {
|
|||||||
|
|
||||||
const onSubmit: SubmitHandler<SignUpFormData> = async (data) => {
|
const onSubmit: SubmitHandler<SignUpFormData> = async (data) => {
|
||||||
try {
|
try {
|
||||||
const response: AxiosResponse<ApiResponse> = await axiosInstance.post(`${import.meta.env.VITE_API_AUTH_URL}/auth/user`, data);
|
const response: AxiosResponse<ApiResponse> = await UserService.createUser(data)
|
||||||
console.log('Успешная регистрация:', response.data);
|
console.log('Успешная регистрация:', response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка регистрации:', error);
|
console.error('Ошибка регистрации:', error);
|
||||||
@ -34,23 +34,28 @@ const SignUp = () => {
|
|||||||
<Typography variant="h4" component="h1" gutterBottom>
|
<Typography variant="h4" component="h1" gutterBottom>
|
||||||
Регистрация
|
Регистрация
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="normal"
|
margin="normal"
|
||||||
label="Email"
|
label="Email"
|
||||||
|
required
|
||||||
{...register('email', { required: 'Email обязателен' })}
|
{...register('email', { required: 'Email обязателен' })}
|
||||||
error={!!errors.email}
|
error={!!errors.email}
|
||||||
helperText={errors.email?.message}
|
helperText={errors.email?.message}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="normal"
|
margin="normal"
|
||||||
label="Логин"
|
label="Логин"
|
||||||
|
required
|
||||||
{...register('login', { required: 'Логин обязателен' })}
|
{...register('login', { required: 'Логин обязателен' })}
|
||||||
error={!!errors.login}
|
error={!!errors.login}
|
||||||
helperText={errors.login?.message}
|
helperText={errors.login?.message}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="normal"
|
margin="normal"
|
||||||
@ -59,6 +64,7 @@ const SignUp = () => {
|
|||||||
error={!!errors.phone}
|
error={!!errors.phone}
|
||||||
helperText={errors.phone?.message}
|
helperText={errors.phone?.message}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="normal"
|
margin="normal"
|
||||||
@ -67,6 +73,7 @@ const SignUp = () => {
|
|||||||
error={!!errors.name}
|
error={!!errors.name}
|
||||||
helperText={errors.name?.message}
|
helperText={errors.name?.message}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="normal"
|
margin="normal"
|
||||||
@ -75,15 +82,18 @@ const SignUp = () => {
|
|||||||
error={!!errors.surname}
|
error={!!errors.surname}
|
||||||
helperText={errors.surname?.message}
|
helperText={errors.surname?.message}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
margin="normal"
|
margin="normal"
|
||||||
type="password"
|
type="password"
|
||||||
label="Пароль"
|
label="Пароль"
|
||||||
|
required
|
||||||
{...register('password', { required: 'Пароль обязателен' })}
|
{...register('password', { required: 'Пароль обязателен' })}
|
||||||
error={!!errors.password}
|
error={!!errors.password}
|
||||||
helperText={errors.password?.message}
|
helperText={errors.password?.message}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button type="submit" variant="contained" color="primary">
|
<Button type="submit" variant="contained" color="primary">
|
||||||
Зарегистрироваться
|
Зарегистрироваться
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import axios from "axios";
|
|
||||||
import axiosInstance from "../http/axiosInstance";
|
import axiosInstance from "../http/axiosInstance";
|
||||||
|
|
||||||
export default class AuthService {
|
export default class AuthService {
|
||||||
static async hello() {
|
static async login(data: any) {
|
||||||
return await axios.get(`${import.meta.env.VITE_API_AUTH_URL}/hello`)
|
return await axiosInstance.post(`/auth/login`, data, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getUsers() {
|
static async refreshToken(token: string) {
|
||||||
return await axiosInstance.get(`/auth/user`)
|
return await axiosInstance.post(`/auth/refresh_token/${token}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getCurrentUser(token: string){
|
static async getCurrentUser(token: string) {
|
||||||
return await axiosInstance.get(`/auth/get_current_user/${token}`)
|
return await axiosInstance.get(`/auth/get_current_user/${token}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,29 +1,32 @@
|
|||||||
// Data mockup
|
import axiosInstance from "../http/axiosInstance";
|
||||||
let users =
|
import { UserCreds, UserData } from "../interfaces/auth";
|
||||||
[
|
|
||||||
{
|
|
||||||
"email": "string",
|
|
||||||
"login": "string",
|
|
||||||
"phone": "string",
|
|
||||||
"name": "string",
|
|
||||||
"surname": "string",
|
|
||||||
"is_active": true,
|
|
||||||
"id": 0,
|
|
||||||
"role_id": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
export default class UserService {
|
export default class UserService {
|
||||||
static async getUsers() {
|
static async createUser(data: any) {
|
||||||
new Promise((resolve, reject) => {
|
return await axiosInstance.post(`/auth/user`, data)
|
||||||
if (!users) {
|
}
|
||||||
return setTimeout(
|
|
||||||
() => reject(new Error('Users not found')),
|
|
||||||
250
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => resolve(users), 250)
|
static async getCurrentUser(token: string) {
|
||||||
})
|
return await axiosInstance.get(`/auth/get_current_user/${token}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getUsers() {
|
||||||
|
return await axiosInstance.get(`/auth/user`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// static async deleteUser(id: number) {
|
||||||
|
// return await axiosInstance.delete(`/auth/user/${id}`)
|
||||||
|
// }
|
||||||
|
|
||||||
|
static async getUser(id: number) {
|
||||||
|
return await axiosInstance.get(`/auth/user/${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async updatePassword(data: UserCreds) {
|
||||||
|
return await axiosInstance.put(`/auth/user/password_change`, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async updateUser(data: UserData) {
|
||||||
|
return await axiosInstance.put(`/auth/user`, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,50 +1,83 @@
|
|||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
|
import { TOKEN_AUTH_KEY, TOKEN_EXPIRY_DURATION, TOKEN_ISSUED_DATE_KEY, USER_DATA_KEY } from '../constants';
|
||||||
|
import { AuthState } from '../interfaces/auth';
|
||||||
|
import AuthService from '../services/AuthService';
|
||||||
|
|
||||||
export interface UserData {
|
export const useAuthStore = create<AuthState>((set, get) => ({
|
||||||
id: number;
|
|
||||||
email: string;
|
|
||||||
login: string;
|
|
||||||
phone: string;
|
|
||||||
name: string;
|
|
||||||
surname: string;
|
|
||||||
is_active: boolean;
|
|
||||||
role_id: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AuthState {
|
|
||||||
isAuthenticated: boolean;
|
|
||||||
token: string | null;
|
|
||||||
login: (token: string) => void;
|
|
||||||
logout: () => void;
|
|
||||||
initializeAuth: () => void;
|
|
||||||
userData: UserData | {};
|
|
||||||
getUserData: () => UserData;
|
|
||||||
setUserData: (userData: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useAuthStore = create<AuthState>((set) => ({
|
|
||||||
isAuthenticated: false,
|
isAuthenticated: false,
|
||||||
token: null,
|
token: null,
|
||||||
login: (token: string) => {
|
|
||||||
localStorage.setItem('authToken', token);
|
|
||||||
set({ isAuthenticated: true, token });
|
|
||||||
},
|
|
||||||
logout: () => {
|
|
||||||
localStorage.removeItem('authToken');
|
|
||||||
set({ isAuthenticated: false, token: null });
|
|
||||||
},
|
|
||||||
initializeAuth: () => {
|
|
||||||
const token = localStorage.getItem('authToken');
|
|
||||||
if (token) {
|
|
||||||
set({ isAuthenticated: true, token });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userData: {},
|
userData: {},
|
||||||
setUserData: (userData: string) => {
|
}));
|
||||||
localStorage.setItem('userData', userData)
|
|
||||||
},
|
const login = (token: string) => {
|
||||||
getUserData: () => {
|
const issuedDate = Date.now();
|
||||||
const userData = localStorage.getItem('userData')
|
localStorage.setItem(TOKEN_AUTH_KEY, token);
|
||||||
return JSON.parse(userData || "")
|
localStorage.setItem(TOKEN_ISSUED_DATE_KEY, issuedDate.toString());
|
||||||
|
useAuthStore.setState(() => ({ isAuthenticated: true, token: token }))
|
||||||
|
}
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
localStorage.removeItem(TOKEN_AUTH_KEY);
|
||||||
|
localStorage.removeItem(USER_DATA_KEY);
|
||||||
|
localStorage.removeItem(TOKEN_ISSUED_DATE_KEY);
|
||||||
|
useAuthStore.setState(() => ({ isAuthenticated: false, token: null, userData: {} }));
|
||||||
|
}
|
||||||
|
|
||||||
|
const initAuth = async () => {
|
||||||
|
const token = localStorage.getItem(TOKEN_AUTH_KEY);
|
||||||
|
const issuedDate = parseInt(localStorage.getItem(TOKEN_ISSUED_DATE_KEY) || '0', 10);
|
||||||
|
const currentTime = Date.now();
|
||||||
|
|
||||||
|
if (token && issuedDate) {
|
||||||
|
if (currentTime - issuedDate < TOKEN_EXPIRY_DURATION) {
|
||||||
|
useAuthStore.setState(() => ({ isAuthenticated: true, token: token }))
|
||||||
|
} else {
|
||||||
|
console.log("refreshing token")
|
||||||
|
try {
|
||||||
|
await refreshToken();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Token refresh failed:', error);
|
||||||
|
logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logout()
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
|
|
||||||
|
const refreshToken = async () => {
|
||||||
|
const token = useAuthStore.getState().token
|
||||||
|
if (!token) throw new Error('No token to refresh');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await AuthService.refreshToken(token)
|
||||||
|
const newToken = response.data.access_token;
|
||||||
|
const newIssuedDate = Date.now();
|
||||||
|
localStorage.setItem(TOKEN_AUTH_KEY, newToken);
|
||||||
|
localStorage.setItem(TOKEN_ISSUED_DATE_KEY, newIssuedDate.toString());
|
||||||
|
useAuthStore.setState(() => ({ token: newToken }))
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to refresh token:', error);
|
||||||
|
logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUserData = () => {
|
||||||
|
const userData = localStorage.getItem(USER_DATA_KEY)
|
||||||
|
return userData ? JSON.parse(userData) : {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setUserData = (userData: string) => {
|
||||||
|
const parsedData = JSON.parse(userData)
|
||||||
|
localStorage.setItem(USER_DATA_KEY, userData)
|
||||||
|
useAuthStore.setState(() => ({ userData: parsedData }))
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getUserData,
|
||||||
|
setUserData,
|
||||||
|
refreshToken,
|
||||||
|
initAuth,
|
||||||
|
login,
|
||||||
|
logout
|
||||||
|
}
|
Reference in New Issue
Block a user