Commit 589dfa53 authored by Merekeyev Dias's avatar Merekeyev Dias

added syncBtn funcionality

parent 6880164c
...@@ -6,7 +6,6 @@ import Header from './components/Header/Header'; ...@@ -6,7 +6,6 @@ import Header from './components/Header/Header';
import AuthPage from './pages/AuthPage/AuthPage'; import AuthPage from './pages/AuthPage/AuthPage';
import HomePage from './pages/HomePage/HomePage'; import HomePage from './pages/HomePage/HomePage';
import RequestPage from './pages/RequestPage/RequestPage'; import RequestPage from './pages/RequestPage/RequestPage';
import ManualPage from './pages/ManualPage/ManualPage';
import AddEditPage from './pages/ManageOrganization/ManageOrganization'; import AddEditPage from './pages/ManageOrganization/ManageOrganization';
import './App.css'; import './App.css';
...@@ -35,7 +34,6 @@ const App: React.FC = () => { ...@@ -35,7 +34,6 @@ const App: React.FC = () => {
<Route path="/" element={<HomePage />} /> <Route path="/" element={<HomePage />} />
<Route path="/add" element={<AddEditPage />} /> <Route path="/add" element={<AddEditPage />} />
<Route path="/edit/:id" element={<AddEditPage />} /> <Route path="/edit/:id" element={<AddEditPage />} />
<Route path='/manuals' element={<ManualPage />} />
<Route path="/requests" element={<RequestPage />} /> <Route path="/requests" element={<RequestPage />} />
<Route path="/*" element={<Navigate to="/" />} /> <Route path="/*" element={<Navigate to="/" />} />
</Route> </Route>
......
...@@ -11,7 +11,6 @@ type MenuItem = Required<MenuProps>['items'][number]; ...@@ -11,7 +11,6 @@ type MenuItem = Required<MenuProps>['items'][number];
const MenuItems: MenuItem[] = [ const MenuItems: MenuItem[] = [
{ key: 'org', icon: <MaterialSymbol icon='list' size={24} color='#fff' />, label: <Link to="/">Список организаций</Link> }, { key: 'org', icon: <MaterialSymbol icon='list' size={24} color='#fff' />, label: <Link to="/">Список организаций</Link> },
{ key: 'man', icon: <MaterialSymbol icon='developer_guide' size={24} color='#fff' />, label: <Link to="/manuals">Справочники</Link> },
{ key: 'req', icon: <MaterialSymbol icon='info' size={24} color='#fff' />, label: <Link to="/requests">Информация о запросах</Link> }, { key: 'req', icon: <MaterialSymbol icon='info' size={24} color='#fff' />, label: <Link to="/requests">Информация о запросах</Link> },
]; ];
...@@ -25,8 +24,6 @@ const Header: React.FC = () => { ...@@ -25,8 +24,6 @@ const Header: React.FC = () => {
useEffect(() => { useEffect(() => {
const pathToNavKey = (path: string) => { const pathToNavKey = (path: string) => {
switch (path) { switch (path) {
case '/manuals':
return 'man';
case '/requests': case '/requests':
return 'req'; return 'req';
default: default:
......
...@@ -19,6 +19,6 @@ export const apiSlice = createApi({ ...@@ -19,6 +19,6 @@ export const apiSlice = createApi({
return headers; return headers;
}, },
}), }),
tagTypes: ["organizations", "requests"], tagTypes: ["organizations", "requests", "manuals"],
endpoints: () => ({}), endpoints: () => ({}),
}); });
\ No newline at end of file
import { apiSlice } from "./apiSlice";
export const manualApiSlice = apiSlice.injectEndpoints({
endpoints: (builder) => ({
updateDictionary: builder.mutation({
query: (codes) => ({
url: 'dictionary/update',
method: 'POST',
body: codes,
}), invalidatesTags: ['manuals']
})
})
})
export const {
useUpdateDictionaryMutation
} = manualApiSlice;
\ No newline at end of file
...@@ -11,6 +11,7 @@ interface Organization { ...@@ -11,6 +11,7 @@ interface Organization {
login: string; login: string;
password: string; password: string;
host: string; host: string;
checked?: Boolean;
} }
export const organizationApiSlice = apiSlice.injectEndpoints({ export const organizationApiSlice = apiSlice.injectEndpoints({
......
import { createSlice } from "@reduxjs/toolkit";
interface InitialState {
checkedCodes: string[];
disabled: boolean;
}
const initialState: InitialState = {
checkedCodes: [],
disabled: true
};
const syncBtnSlice = createSlice({
name: 'syncBtn',
initialState,
reducers: {
addCheckedCodes: (state, action) => {
state.checkedCodes.push(action.payload);
},
removeCheckedCodes: (state, action) => {
state.checkedCodes = state.checkedCodes.filter(code => code !== action.payload);
},
setDisabled: (state, action) => {
state.disabled = action.payload;
}
}
});
export const { addCheckedCodes, removeCheckedCodes, setDisabled } = syncBtnSlice.actions;
export default syncBtnSlice.reducer;
\ No newline at end of file
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useNavigate } from 'react-router'; import { useNavigate } from 'react-router';
import { Button, Space, Tag, Modal, message } from 'antd'; import { Button, Space, Tag, Modal, Checkbox, message } from 'antd';
import type { TableProps } from 'antd'; import type { TableProps } from 'antd';
import { useDispatch } from 'react-redux';
import { useDeleteOrganizationMutation } from '../../features/api/organizationApiSlice'; import { useDeleteOrganizationMutation } from '../../features/api/organizationApiSlice';
import { getStatusText, getStatusColor } from './utils'; import { getStatusText, getStatusColor } from './utils';
import { addCheckedCodes, removeCheckedCodes } from '../../features/sync_btn/syncBtn';
export interface DataType { export interface DataType {
id: number; id: number;
...@@ -15,6 +17,10 @@ export interface DataType { ...@@ -15,6 +17,10 @@ export interface DataType {
} }
export const columns: TableProps<DataType>['columns'] = [ export const columns: TableProps<DataType>['columns'] = [
{
width: '1%',
render: (_, record) => <CheckboxColumn data={record} />
},
{ {
title: "ID", title: "ID",
dataIndex: "id", dataIndex: "id",
...@@ -53,14 +59,33 @@ export const columns: TableProps<DataType>['columns'] = [ ...@@ -53,14 +59,33 @@ export const columns: TableProps<DataType>['columns'] = [
{ {
title: "Действия", title: "Действия",
width: 60, width: 60,
render: (_, record) => { render: (_, record) => <ActionColumn data={record} />
return (
<ActionColumn data={record} />
)
}
} }
] ]
export const CheckboxColumn: React.FC<{ data: DataType }> = ({ data }) => {
const dispatch = useDispatch();
const [checked, setChecked] = useState(false);
const handleCheck = (e: { target: { checked: any; }; }) => {
const isChecked = e.target.checked;
setChecked(isChecked);
if (isChecked) {
dispatch(addCheckedCodes(data.code));
} else {
dispatch(removeCheckedCodes(data.code));
}
};
return (
<Checkbox
className='checkbox_org--custom'
checked={checked}
onChange={handleCheck}
/>
);
};
export const ActionColumn: React.FC<{ data: DataType }> = ({ data }) => { export const ActionColumn: React.FC<{ data: DataType }> = ({ data }) => {
const [open, setOpen] = useState<boolean>(false); const [open, setOpen] = useState<boolean>(false);
const navigate = useNavigate(); const navigate = useNavigate();
......
import React, { createRef, useEffect } from 'react'; import React, { createRef, useEffect, useState } from 'react';
import { useNavigate } from 'react-router'; import { useNavigate } from 'react-router';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { Button, Pagination, Spin, Table } from 'antd'; import { Button, message, Pagination, Space, Spin, Table } from 'antd';
import { useGetOrganizationsQuery } from '../../features/api/organizationApiSlice'; import { useDeleteOrganizationMutation, useGetOrganizationsQuery } from '../../features/api/organizationApiSlice';
import { setCurrentPage, setTotalOrgNumber } from '../../features/pagination/mainPagination'; import { setCurrentPage, setTotalOrgNumber } from '../../features/pagination/mainPagination';
import { DataType, columns } from './Columns'; import { DataType, columns } from './Columns';
import { TableRef } from 'antd/es/table'; import { TableRef } from 'antd/es/table';
import './Homepage.css'; import './Homepage.css';
import { setDisabled } from '../../features/sync_btn/syncBtn';
const HomePage: React.FC = () => { const HomePage: React.FC = () => {
const navigate = useNavigate(); const navigate = useNavigate();
...@@ -15,11 +16,24 @@ const HomePage: React.FC = () => { ...@@ -15,11 +16,24 @@ const HomePage: React.FC = () => {
const totalOrgNumber = useSelector((state: any) => state.mainPagination.totalOrgNumber); const totalOrgNumber = useSelector((state: any) => state.mainPagination.totalOrgNumber);
const currentPage = useSelector((state: any) => state.mainPagination.currentPage); const currentPage = useSelector((state: any) => state.mainPagination.currentPage);
const ORG_NUMBER_PER_PAGE = useSelector((state: any) => state.mainPagination.ORG_NUMBER_PER_PAGE); const ORG_NUMBER_PER_PAGE = useSelector((state: any) => state.mainPagination.ORG_NUMBER_PER_PAGE);
const syncBtnState = useSelector((state: any) => state.syncBtn.disabled);
const checkedCodes = useSelector((state: any) => state.syncBtn.checkedCodes);
const [updateDictionary] = useDeleteOrganizationMutation();
const handleAddClick = () => { const handleAddClick = () => {
navigate("/add"); navigate("/add");
}; };
const handleSyncClick = async () => {
try {
console.log(checkedCodes);
await updateDictionary(JSON.stringify(checkedCodes)).unwrap();
message.success('Организации успешны синхронизированы!')
} catch (err) {
message.error('Произошла ошибка при синхронизации организации!')
}
};
const handlePaginationChange = (page: number) => { const handlePaginationChange = (page: number) => {
/* /*
scrollIntoView resets to the top of the table after changing the page with Pagination. But the bug was found - the div above the table scrolls to top of the page too, under the Header component. It happens because of overflow scrollIntoView resets to the top of the table after changing the page with Pagination. But the bug was found - the div above the table scrolls to top of the page too, under the Header component. It happens because of overflow
...@@ -64,18 +78,32 @@ const HomePage: React.FC = () => { ...@@ -64,18 +78,32 @@ const HomePage: React.FC = () => {
} }
}, [isSuccess, orgs]); }, [isSuccess, orgs]);
useEffect(() => {
if (checkedCodes.length > 0) {
dispatch(setDisabled(false));
} else {
dispatch(setDisabled(true));
}
}, [checkedCodes, dispatch])
return ( return (
<div className="container"> <div className="container">
<section className='section'> <section className='section'>
<div> <Space size={'middle'}>
<Button <Button
className='add_title' className='add_title'
type='primary'
onClick={handleAddClick} onClick={handleAddClick}
> >
Добавить Добавить
</Button> </Button>
</div> <Button
className='add_title'
onClick={handleSyncClick}
disabled={syncBtnState}
>
Синхронизировать справочники
</Button>
</Space>
<div className="data"> <div className="data">
{table} {table}
</div> </div>
......
...@@ -32,3 +32,9 @@ ...@@ -32,3 +32,9 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
} }
/* Custom checkbox */
.checkbox_org--custom .ant-checkbox-inner {
border-color: #33333386;
}
\ No newline at end of file
import React from "react";
const ManualPage:React.FC = () => {
return (
<>
</>
)
}
export default ManualPage;
\ No newline at end of file
...@@ -45,7 +45,7 @@ const RequestPage: React.FC = () => { ...@@ -45,7 +45,7 @@ const RequestPage: React.FC = () => {
const applyFilters = () => { const applyFilters = () => {
let filtered = reqs.list; let filtered = reqs.list;
/* /*
subtract method is added because of the unique dates (hh:mm:ss = 00:00:00). The code below is the easiest way to deal with it, but it is not the ideal form subtract method is added because of the unique dates (hh:mm:ss = 00:00:00). The code below is the easiest way to deal with it, but it might be not the ideal form
*/ */
const adjustedStartDate = dayjs(startDate).subtract(1, 'day'); const adjustedStartDate = dayjs(startDate).subtract(1, 'day');
if (startDate && endDate) { if (startDate && endDate) {
......
...@@ -4,6 +4,7 @@ import { persistReducer, persistStore } from 'redux-persist'; ...@@ -4,6 +4,7 @@ import { persistReducer, persistStore } from 'redux-persist';
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 reqPaginationReducer from '../features/pagination/reqPagination'; import reqPaginationReducer from '../features/pagination/reqPagination';
import syncBtnReducer from '../features/sync_btn/syncBtn';
interface AuthState { interface AuthState {
token: string | null; token: string | null;
...@@ -40,6 +41,7 @@ const store: Store = configureStore({ ...@@ -40,6 +41,7 @@ const store: Store = configureStore({
auth: persistedReducer, auth: persistedReducer,
mainPagination: mainPaginationReducer, mainPagination: mainPaginationReducer,
reqPagination: reqPaginationReducer, reqPagination: reqPaginationReducer,
syncBtn: syncBtnReducer,
[apiSlice.reducerPath]: apiSlice.reducer, [apiSlice.reducerPath]: apiSlice.reducer,
}, },
middleware: (getDefaultMiddleware) => middleware: (getDefaultMiddleware) =>
......
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