написал store, authslice и асинхронную функцию запрроса для авторизации

This commit is contained in:
2025-10-23 20:51:59 +03:00
parent 172d6a68b4
commit bc920da1be
7 changed files with 1234 additions and 2 deletions
+1132 -2
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -10,8 +10,11 @@
"preview": "vite preview"
},
"dependencies": {
"@reduxjs/toolkit": "^2.9.2",
"antd": "^5.27.6",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-redux": "^9.2.0",
"react-router": "^7.9.4",
"react-router-dom": "^7.9.4"
},
+6
View File
@@ -0,0 +1,6 @@
import { useDispatch, useSelector } from 'react-redux';
import type {TypedUseSelectorHook} from 'react-redux';
import type { RootState, AppDispatch } from './store';
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
+11
View File
@@ -0,0 +1,11 @@
import { configureStore } from "@reduxjs/toolkit";
import authReducer from "../features/auth/authSlice";
export const store = configureStore({
reducer: {
auth: authReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
+46
View File
@@ -0,0 +1,46 @@
import { createSlice } from "@reduxjs/toolkit";
import type {PayloadAction} from "@reduxjs/toolkit";
import { loginThunk } from "./authThunks";
interface AuthState {
token: string | null;
loading: boolean;
error: string | null;
}
const initialState: AuthState = {
token: null,
loading: false,
error: null
};
const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
logout(state) {
state.token = null;
state.error = null;
localStorage.removeItem("token");
}
},
extraReducers: builder => {
builder
.addCase(loginThunk.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(loginThunk.fulfilled, (state, action) => {
state.loading = false;
state.token = action.payload.token;
state.error = null;
})
.addCase(loginThunk.rejected, (state, action) => {
state.loading = false;
state.error = action.payload ?? "Ошибка авторизации";
});
}
});
export const { logout } = authSlice.actions;
export default authSlice.reducer;
+32
View File
@@ -0,0 +1,32 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
export const loginThunk = createAsyncThunk<
{ token: string; user: { id: string; name: string; role: string} },
{ email: string; password: string },
{ rejectValue: string }
>(
"auth/login",
async ({ email, password }, thunkAPI) => {
try {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ email, password })
});
if (!response.ok) {
const data = await response.json();
return thunkAPI.rejectWithValue(data.message || "Ошибка авторизации");
}
const data = await response.json();
return { token: data.token, user: {
id: data.user.id,
name: data.user.name,
role: data.user.role
} };
} catch (err) {
return thunkAPI.rejectWithValue("Ошибка сети");
}
}
);
+4
View File
@@ -4,11 +4,15 @@ import './index.css'
import App from './App.tsx'
import { BrowserRouter } from 'react-router'
import AppRoutes from './app/routes.tsx'
import { Provider } from 'react-redux'
import { store } from './app/store.ts'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<BrowserRouter>
<Provider store={store}>
<AppRoutes />
</Provider>
</BrowserRouter>
</StrictMode>,
)