finish auth

parent 248c660b
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
"react-material-symbols": "^4.4.0", "react-material-symbols": "^4.4.0",
"react-redux": "^9.1.2", "react-redux": "^9.1.2",
"react-router": "^6.25.1", "react-router": "^6.25.1",
"react-router-dom": "^6.25.1" "react-router-dom": "^6.25.1",
"redux-persist": "^6.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.14.12", "@types/node": "^20.14.12",
...@@ -3908,6 +3909,14 @@ ...@@ -3908,6 +3909,14 @@
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
}, },
"node_modules/redux-persist": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz",
"integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==",
"peerDependencies": {
"redux": ">4.0.0"
}
},
"node_modules/redux-thunk": { "node_modules/redux-thunk": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
......
...@@ -20,7 +20,8 @@ ...@@ -20,7 +20,8 @@
"react-material-symbols": "^4.4.0", "react-material-symbols": "^4.4.0",
"react-redux": "^9.1.2", "react-redux": "^9.1.2",
"react-router": "^6.25.1", "react-router": "^6.25.1",
"react-router-dom": "^6.25.1" "react-router-dom": "^6.25.1",
"redux-persist": "^6.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.14.12", "@types/node": "^20.14.12",
......
...@@ -9,7 +9,7 @@ import './Header.css'; ...@@ -9,7 +9,7 @@ import './Header.css';
type MenuItem = Required<MenuProps>['items'][number]; type MenuItem = Required<MenuProps>['items'][number];
const items: MenuItem[] = [ const MenuItems: MenuItem[] = [
{ key: '1', icon: <MaterialSymbol icon='list' size={24} color='#fff' />, label: <Link to="/">Список организаций</Link> }, { key: '1', icon: <MaterialSymbol icon='list' size={24} color='#fff' />, label: <Link to="/">Список организаций</Link> },
{ key: '2', icon: <MaterialSymbol icon='developer_guide' size={24} color='#fff' />, label: <Link to="/">Справочники</Link> }, { key: '2', icon: <MaterialSymbol icon='developer_guide' size={24} color='#fff' />, label: <Link to="/">Справочники</Link> },
{ key: '3', icon: <MaterialSymbol icon='info' size={24} color='#fff' />, label: <Link to="/requests">Информация о запросах</Link> }, { key: '3', icon: <MaterialSymbol icon='info' size={24} color='#fff' />, label: <Link to="/requests">Информация о запросах</Link> },
...@@ -47,7 +47,7 @@ const Header: React.FC = () => { ...@@ -47,7 +47,7 @@ const Header: React.FC = () => {
> >
<Menu <Menu
theme='dark' theme='dark'
items={items} items={MenuItems}
defaultSelectedKeys={['1']} defaultSelectedKeys={['1']}
mode='inline' mode='inline'
className="menu" className="menu"
......
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { RootState } from '../../main'; // Add this import to get the RootState import { RootState } from '../../main';
interface Organization { interface Organization {
id: number; id: number;
...@@ -33,14 +33,14 @@ export const apiSlice = createApi({ ...@@ -33,14 +33,14 @@ export const apiSlice = createApi({
}), }),
tagTypes: ["organizations"], tagTypes: ["organizations"],
endpoints: (builder) => ({ endpoints: (builder) => ({
getOrganizations: builder.query<Organization[], void>({ getOrganizations: builder.query<Organization[], void>({ // получить информацию
query: () => '/list', query: () => '/list',
providesTags: ["organizations"], providesTags: ["organizations"], // для управления кэшем или инвалидации данных в системе управления состоянием
}), }),
getOrganization: builder.query<Organization, string>({ getOrganization: builder.query<Organization, string>({
query: (orgId) => `/info?id=${orgId}`, query: (orgId) => `/info?id=${orgId}`,
}), }),
addNewOrganization: builder.mutation<Organization, Partial<Organization>>({ addNewOrganization: builder.mutation<Organization, Partial<Organization>>({ // изменение данных
query: (initialOrg) => ({ query: (initialOrg) => ({
url: '/add', url: '/add',
method: 'POST', method: 'POST',
......
...@@ -3,14 +3,17 @@ import ReactDOM from 'react-dom/client'; ...@@ -3,14 +3,17 @@ import ReactDOM from 'react-dom/client';
import App from './App.tsx'; import App from './App.tsx';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import './index.css'; import './index.css';
import store from '../src/store/store.ts'; import {store, persistor} from '../src/store/store.ts';
import { PersistGate } from 'redux-persist/integration/react';
export type RootState = ReturnType<typeof store.getState>; export type RootState = ReturnType<typeof store.getState>;
ReactDOM.createRoot(document.getElementById('root')!).render( ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode> <React.StrictMode>
<Provider store={store}> <Provider store={store}>
<App /> <PersistGate loading={null} persistor={persistor}>
<App/>
</PersistGate>
</Provider> </Provider>
</React.StrictMode>, </React.StrictMode>,
); );
...@@ -7,13 +7,13 @@ import styles from './AuthPage.module.css'; ...@@ -7,13 +7,13 @@ import styles from './AuthPage.module.css';
// import { useGetOrganizationsQuery } from '../../features/api/apiSlice'; // import { useGetOrganizationsQuery } from '../../features/api/apiSlice';
const AuthPage: React.FC = () => { const AuthPage: React.FC = () => {
const [token, setTokenInput] = useState(''); const [token, setTokenInput] = useState<string>('');
const navigate = useNavigate(); const navigate = useNavigate();
const dispatch = useDispatch(); const dispatch = useDispatch();
const handleLogin = async () => { const handleLogin = async () => {
try { try {
const response = await fetch('http://77.243.80.217:8080/esutd/api/organizations/list', { const response = await fetch('http://77.243.80.217:8080/esutd/api/organizations/list', { // Get запрос
headers: { headers: {
'Authorization': `Bearer ${token}`, 'Authorization': `Bearer ${token}`,
}, },
......
...@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router'; ...@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router';
import { Button, Space, Tag, Modal, message } from 'antd'; import { Button, Space, Tag, Modal, message } from 'antd';
import type { TableProps } from 'antd'; import type { TableProps } from 'antd';
import { useDeleteOrganizationMutation } from '../../features/api/apiSlice'; import { useDeleteOrganizationMutation } from '../../features/api/apiSlice';
import { getStatusText, getStatusColor } from './utils';
export interface DataType { export interface DataType {
id: number; id: number;
...@@ -13,24 +14,6 @@ export interface DataType { ...@@ -13,24 +14,6 @@ export interface DataType {
host: string; host: string;
} }
const getStatusText = (status: number) => {
switch (status) {
case 0: return "удален";
case 1: return "заблокирован";
case 2: return "активен";
default: return "неизвестно";
}
}
const getStatusColor = (status: number) => {
switch (status) {
case 0: return 'red';
case 1: return 'orange';
case 2: return 'green';
default: return 'grey';
}
}
export const columns: TableProps<DataType>['columns'] = [ export const columns: TableProps<DataType>['columns'] = [
{ {
title: "ID", title: "ID",
...@@ -107,22 +90,16 @@ export const ActionColumn: React.FC<{ data: DataType }> = ({ data }) => { ...@@ -107,22 +90,16 @@ export const ActionColumn: React.FC<{ data: DataType }> = ({ data }) => {
return ( return (
<Space> <Space>
<Button onClick={handleEditClick} /> <Button onClick={handleEditClick}>Изменить</Button>
<Button onClick={showDeleteModal} /> <Button onClick={showDeleteModal} type="primary" danger>Удалить</Button>
<Modal <Modal
open={open} open={open}
title={`Вы уверены в том, что хотите удалить ${data.name}?`} title={`Вы уверены, что хотите удалить ${data.name}?`}
footer={() => ( onOk={handleDeleteModalOk}
<div style={{ textAlign: 'start', marginTop: '1rem' }}> onCancel={handleDeleteModalCancel}
<Button key="submit" type="primary" danger onClick={handleDeleteModalOk} style={{ marginRight: '.5rem' }}> >
Удалить <p>Подтвердите удаление организации.</p>
</Button> </Modal>
<Button key="back" onClick={handleDeleteModalCancel}>
Назад
</Button>
</div>
)}
/>
</Space> </Space>
) )
} }
export const getStatusText = (status: number) => {
switch (status) {
case 0: return "удален";
case 1: return "заблокирован";
case 2: return "активен";
default: return "неизвестно";
}
}
export const getStatusColor = (status: number) => {
switch (status) {
case 0: return 'red';
case 1: return 'orange';
case 2: return 'green';
default: return 'grey';
}
}
import { configureStore, Store, createSlice, PayloadAction } from '@reduxjs/toolkit'; import { configureStore, Store, createSlice, PayloadAction } from '@reduxjs/toolkit';
import { apiSlice } from '../features/api/apiSlice'; import { apiSlice } from '../features/api/apiSlice';
import mainPaginationReducer from '../features/pagination/mainPagination'; import mainPaginationReducer from '../features/pagination/mainPagination';
import storage from 'redux-persist/lib/storage';
import { persistReducer, persistStore } from 'redux-persist';
interface AuthState { interface AuthState {
token: string | null; token: string | null;
} }
const initialState: AuthState = { const initialState: AuthState = {
token: localStorage.getItem('token'), token: null,
}; };
const authSlice = createSlice({ const authSlice = createSlice({
...@@ -16,26 +17,33 @@ const authSlice = createSlice({ ...@@ -16,26 +17,33 @@ const authSlice = createSlice({
reducers: { reducers: {
setToken: (state, action: PayloadAction<string>) => { setToken: (state, action: PayloadAction<string>) => {
state.token = action.payload; state.token = action.payload;
localStorage.setItem('token', action.payload);
}, },
clearToken: (state) => { clearToken: (state) => {
state.token = null; state.token = null;
localStorage.removeItem('token');
}, },
}, },
}); });
export const { setToken, clearToken } = authSlice.actions; export const { setToken, clearToken } = authSlice.actions;
const persistConfig = {
key: 'root',
storage,
};
const persistedReducer = persistReducer(persistConfig, authSlice.reducer);
const store: Store = configureStore({ const store: Store = configureStore({
reducer: { reducer: {
auth: authSlice.reducer, auth: persistedReducer,
mainPagination: mainPaginationReducer, mainPagination: mainPaginationReducer,
[apiSlice.reducerPath]: apiSlice.reducer, [apiSlice.reducerPath]: apiSlice.reducer,
}, },
middleware: (getDefaultMiddleware) => middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(apiSlice.middleware), getDefaultMiddleware({ serializableCheck: false}).concat(apiSlice.middleware),
}); });
export default store; const persistor = persistStore(store);
export { store, persistor };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment