Commit 24fa6480 authored by Merekeyev Dias's avatar Merekeyev Dias

refactoring

parent 41fd096a
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { RootState } from '../main';
import { notification } from 'antd';
const baseQuery = fetchBaseQuery({
baseUrl: 'http://77.243.80.217:8080/esutd/api',
prepareHeaders: (headers, { getState }) => {
const accessToken = (getState() as RootState).auth.token;
if (accessToken) {
headers.set("Authorization", `Bearer ${accessToken}`);
}
headers.set("Accept", "*/*");
return headers;
},
});
export const apiSlice = createApi({
reducerPath: 'api',
baseQuery: async (arg, api, extraOptions) => {
try {
const result: any = await baseQuery(arg, api, extraOptions);
if (result && result.error && result.error.data.errorMessage) {
notification.error({ message: result.error.data.errorMessage });
}
return result;
} catch (error) {
console.error("Error occurred during API call:", error);
throw error;
}
},
tagTypes: ["organizations", "requests", "manuals"],
endpoints: () => ({}),
});
\ No newline at end of file
import { apiSlice } from "./apiSlice"; import { apiSlice } from "./mainApi";
export const manualApiSlice = apiSlice.injectEndpoints({ export const manualApiSlice = apiSlice.injectEndpoints({
endpoints: (builder) => ({ endpoints: (builder) => ({
......
import { apiSlice } from "./apiSlice"; import { apiSlice } from "./mainApi";
interface Organization { interface Organization {
id: number; id: number;
...@@ -18,33 +18,26 @@ export const organizationApiSlice = apiSlice.injectEndpoints({ ...@@ -18,33 +18,26 @@ export const organizationApiSlice = apiSlice.injectEndpoints({
endpoints: (builder) => ({ endpoints: (builder) => ({
getOrganizations: builder.query<Organization[], void>({ getOrganizations: builder.query<Organization[], void>({
query: () => 'organizations/list', query: () => 'organizations/list',
providesTags: ["organizations"], providesTags: [{ type: "organizations", id: "LIST" }],
}), }),
getOrganization: builder.query<Organization, string>({ getOrganization: builder.query<Organization, string>({
query: (orgId) => `organizations/info?id=${orgId}`, query: (orgId) => `organizations/info?id=${orgId}`,
}), providesTags: (_, __, arg) => [{ type: "organizations", id: arg }]
addNewOrganization: builder.mutation<Organization, Partial<Organization>>({
query: (initialOrg) => ({
url: 'organizations/save',
method: 'POST',
body: initialOrg,
}),
invalidatesTags: ["organizations"],
}), }),
editOrganization: builder.mutation<Organization, Partial<Organization>>({ editOrganization: builder.mutation<Organization, Partial<Organization>>({
query: ({ ...rest }) => ({ query: ( initialOrg ) => ({
url: `organizations/save?id=${rest.id}`, url: `organizations/save?id=${initialOrg.id}`,
method: 'POST', method: 'POST',
body: rest, body: initialOrg,
}), }),
invalidatesTags: ["organizations"], invalidatesTags: (res) => [{ type: "organizations", id: res?.id }, { type: "organizations", id: "LIST" }],
}), }),
deleteOrganization: builder.mutation<{ success: boolean; code: string }, string>({ deleteOrganization: builder.mutation<{ success: boolean; code: string }, string>({
query: (orgCode) => ({ query: (orgCode) => ({
url: `organizations/delete?code=${orgCode}`, url: `organizations/delete?code=${orgCode}`,
method: 'POST' method: 'POST'
}), }),
invalidatesTags: ["organizations"], invalidatesTags: [{ type: "organizations", id: "LIST" }],
}), }),
}) })
}) })
...@@ -52,7 +45,6 @@ export const organizationApiSlice = apiSlice.injectEndpoints({ ...@@ -52,7 +45,6 @@ export const organizationApiSlice = apiSlice.injectEndpoints({
export const { export const {
useGetOrganizationsQuery, useGetOrganizationsQuery,
useGetOrganizationQuery, useGetOrganizationQuery,
useAddNewOrganizationMutation,
useEditOrganizationMutation, useEditOrganizationMutation,
useDeleteOrganizationMutation, useDeleteOrganizationMutation,
} = organizationApiSlice; } = organizationApiSlice;
\ No newline at end of file
import { apiSlice } from "./apiSlice"; import { apiSlice } from "./mainApi";
interface Request { interface Request {
id: number; id: number;
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
display: flex; display: flex;
padding: 1rem .5rem; padding: 1rem .5rem;
justify-content: space-between; justify-content: space-between;
/* min-width: 1440px; */
} }
.header_left { .header_left {
......
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Link, useNavigate, useLocation } from 'react-router-dom'; import { Link, useNavigate, useLocation } from 'react-router-dom';
import { Menu, Button, Drawer } from 'antd';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { clearToken } from '../../store/store'; import { Menu, Button, Drawer } from 'antd';
import type { MenuProps } from 'antd'; import type { MenuProps } from 'antd';
import { clearToken } from '@/store/store';
import './Header.css'; import './Header.css';
type MenuItem = Required<MenuProps>['items'][number]; type MenuItem = Required<MenuProps>['items'][number];
......
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { RootState } from '../../main';
export const apiSlice = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({
baseUrl: "http://77.243.80.217:8080/esutd/api",
prepareHeaders: (headers, { getState }) => {
const state = getState() as RootState;
const accessToken = state.auth.token;
if (accessToken) {
headers.set("Authorization", `Bearer ${accessToken}`);
}
headers.set("Content-Type", "application/json");
headers.set("Accept", "application/json");
return headers;
},
}),
tagTypes: ["organizations", "requests", "manuals"],
endpoints: () => ({}),
});
\ No newline at end of file
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
left: 50%; left: 50%;
-webkit-transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
padding: 24px;
padding: 1.5rem;
background-color: rgba(209, 209, 209, 0.866); background-color: rgba(209, 209, 209, 0.866);
border-radius: 8px; border-radius: .5rem;
} }
.form_btn { .form_btn {
......
...@@ -2,9 +2,9 @@ import React, { useState } from 'react'; ...@@ -2,9 +2,9 @@ import React, { useState } from 'react';
import { Input, Typography, Button, notification } from 'antd'; import { Input, Typography, Button, notification } from 'antd';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { setToken } from '../../store/store';
import { setToken } from '@/store/store';
import styles from './AuthPage.module.css'; import styles from './AuthPage.module.css';
// import { useGetOrganizationsQuery } from '../../features/api/apiSlice';
const AuthPage: React.FC = () => { const AuthPage: React.FC = () => {
const [token, setTokenInput] = useState<string>(''); const [token, setTokenInput] = useState<string>('');
...@@ -13,7 +13,7 @@ const AuthPage: React.FC = () => { ...@@ -13,7 +13,7 @@ const AuthPage: React.FC = () => {
const handleLogin = async () => { const handleLogin = async () => {
try { try {
const response = await fetch('http://77.243.80.217:8080/esutd/api/organizations/list', { // Get запрос const response = await fetch('http://77.243.80.217:8080/esutd/api/organizations/list', {
headers: { headers: {
'Authorization': `Bearer ${token}`, 'Authorization': `Bearer ${token}`,
}, },
...@@ -42,7 +42,6 @@ const AuthPage: React.FC = () => { ...@@ -42,7 +42,6 @@ const AuthPage: React.FC = () => {
}; };
return ( return (
<div className={styles.wrapper}>
<div className={styles.form}> <div className={styles.form}>
<Typography.Title level={5}>Токен</Typography.Title> <Typography.Title level={5}>Токен</Typography.Title>
<Input <Input
...@@ -53,7 +52,6 @@ const AuthPage: React.FC = () => { ...@@ -53,7 +52,6 @@ const AuthPage: React.FC = () => {
/> />
<Button className={styles.form_btn} type="primary" onClick={handleLogin}>Войти</Button> <Button className={styles.form_btn} type="primary" onClick={handleLogin}>Войти</Button>
</div> </div>
</div>
); );
}; };
......
...@@ -4,9 +4,9 @@ import { useDispatch, useSelector } from 'react-redux'; ...@@ -4,9 +4,9 @@ import { useDispatch, useSelector } from 'react-redux';
import { Button, Space, Tag, Modal, Checkbox, message } from 'antd'; import { Button, Space, Tag, Modal, Checkbox, message } from 'antd';
import type { TableProps } from 'antd'; import type { TableProps } from 'antd';
import { useDeleteOrganizationMutation } from '../../features/api/organizationApiSlice'; import { useDeleteOrganizationMutation } from '@/api/organizationApi';
import { addCheckedCode, removeCheckedCode } from '../../features/sync_btn/syncBtn'; import { addCheckedCode, removeCheckedCode } from '@/store/slices/syncBtn';
import { setCurrentPage } from '../../features/pagination/mainPagination'; import { setCurrentPage } from '@/store/slices/mainPagination';
import { getStatusText, getStatusColor } from './utils'; import { getStatusText, getStatusColor } from './utils';
export interface DataType { export interface DataType {
......
import React, { createRef, useEffect, useState } 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, message, Space, Spin, Table } from 'antd'; import { Button, message, Space, Table } from 'antd';
import { TableRef } from 'antd/es/table'; import { TableRef } from 'antd/es/table';
import { useGetOrganizationsQuery } from '../../features/api/organizationApiSlice'; import { useGetOrganizationsQuery } from '@/api/organizationApi';
import { useUpdateDictionaryMutation } from '../../features/api/manualApiSlice'; import { useUpdateDictionaryMutation } from '@/api/manualApi';
import { setCurrentPage, setTotalOrgNumber } from '../../features/pagination/mainPagination'; import { setCurrentPage, setTotalOrgNumber } from '@/store/slices/mainPagination';
import { setDisabled, clearCheckedCodes } from '../../features/sync_btn/syncBtn'; import { setDisabled, clearCheckedCodes } from '@/store/slices/syncBtn';
import { DataType, columns } from './Columns'; import { DataType, columns } from './Columns';
import './Homepage.css'; import './Homepage.css';
...@@ -15,38 +15,33 @@ const HomePage: React.FC = () => { ...@@ -15,38 +15,33 @@ const HomePage: React.FC = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const dispatch = useDispatch(); const dispatch = useDispatch();
const tableRef = createRef<TableRef>(); const tableRef = createRef<TableRef>();
const [updateDictionary] = useUpdateDictionaryMutation();
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 syncBtnState = useSelector((state: any) => state.syncBtn.disabled);
const checkedCodes = useSelector((state: any) => state.syncBtn.checkedCodes); const checkedCodes = useSelector((state: any) => state.syncBtn.checkedCodes);
const [updateDictionary] = useUpdateDictionaryMutation();
const [isSyncLoading, setIsSyncLoading] = useState(false); const [isSyncLoading, setIsSyncLoading] = useState(false);
const [isTableLoading, setIsTableLoading] = useState(false);
const handleAddClick = () => { const handleAddClick = () => {
navigate("/add"); navigate("/add");
}; };
const handleSyncClick = async () => { const handleSyncClick = async () => {
setIsSyncLoading(true); setIsSyncLoading(true);
try {
console.log(checkedCodes); console.log(checkedCodes);
await updateDictionary(checkedCodes).unwrap(); await updateDictionary(checkedCodes).unwrap();
message.success('Организации успешны синхронизированы!') message.success('Организации успешны синхронизированы!')
} catch (err) {
console.log(err);
message.error('Произошла ошибка при синхронизации организации!')
} finally {
dispatch(clearCheckedCodes()); dispatch(clearCheckedCodes());
setIsSyncLoading(false); setIsSyncLoading(false);
} };
};
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
*/
// tableRef.current?.nativeElement.scrollIntoView({ behavior: 'smooth' });
dispatch(setCurrentPage(page)); dispatch(setCurrentPage(page));
}; };
...@@ -66,15 +61,19 @@ const HomePage: React.FC = () => { ...@@ -66,15 +61,19 @@ const HomePage: React.FC = () => {
let table; let table;
if (isLoading) { if (isSuccess) {
table = <Spin />
} else if (isSuccess) {
table = <Table table = <Table
dataSource={paginatedData(orgs)} dataSource={paginatedData(orgs)}
columns={columns} columns={columns}
rowKey="id" rowKey="id"
className='home_table' className='home_table'
ref={tableRef} ref={tableRef}
loading={isTableLoading}
scroll={{
scrollToFirstRowOnChange: true,
x: 'max-content',
y: 470
}}
pagination={{ pagination={{
position: ['bottomCenter'], position: ['bottomCenter'],
defaultCurrent: 1, defaultCurrent: 1,
...@@ -91,7 +90,10 @@ const HomePage: React.FC = () => { ...@@ -91,7 +90,10 @@ const HomePage: React.FC = () => {
} }
useEffect(() => { useEffect(() => {
if (isSuccess) { if (isLoading) {
setIsTableLoading(true);
} else if (isSuccess) {
setIsTableLoading(false);
dispatch(setTotalOrgNumber(orgs.length)); dispatch(setTotalOrgNumber(orgs.length));
} }
}, [isSuccess, orgs]); }, [isSuccess, orgs]);
...@@ -128,17 +130,6 @@ const HomePage: React.FC = () => { ...@@ -128,17 +130,6 @@ const HomePage: React.FC = () => {
<div className="data"> <div className="data">
{table} {table}
</div> </div>
{/* <div className='pagination-container'>
<Pagination
current={currentPage}
defaultCurrent={1}
pageSize={ORG_NUMBER_PER_PAGE}
total={totalOrgNumber}
onChange={handlePaginationChange}
hideOnSinglePage={true}
showSizeChanger={false}
/>
</div> */}
</section> </section>
</div> </div>
); );
......
.section {
margin-top: 10px 20px;
display: flex;
flex-direction: column;
height: calc(100vh - 60px);
}
.add_title { .add_title {
font-size: 12px; font-size: 12px;
line-height: 18px; line-height: 18px;
...@@ -13,28 +6,7 @@ ...@@ -13,28 +6,7 @@
margin-left: -10px; margin-left: -10px;
} }
.data { /* Custom antd checkbox */
flex: 1;
overflow-y: auto;
padding-bottom: 60px;
margin-top: 20px;
margin-left: -10px;
}
.pagination-container {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background: white;
padding: 10px 20px;
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
display: flex;
justify-content: center;
}
/* Custom checkbox */
.checkbox_org--custom .ant-checkbox-inner { .checkbox_org--custom .ant-checkbox-inner {
border-color: #33333386; border-color: #33333386;
} }
\ No newline at end of file
.container {
display: flex;
flex-direction: column;
height: calc(100vh - 80px);
padding: 10px 20px;
overflow: hidden;
}
.form { .form {
margin: 10px 20px 50px; margin: 10px 20px 50px;
padding-right: 20px; padding-right: 20px;
......
...@@ -3,8 +3,8 @@ import { useNavigate, useParams } from 'react-router'; ...@@ -3,8 +3,8 @@ import { useNavigate, useParams } from 'react-router';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { Form, Input, Button, Select, message } from 'antd'; import { Form, Input, Button, Select, message } from 'antd';
import { useAddNewOrganizationMutation, useEditOrganizationMutation, useGetOrganizationQuery, useGetOrganizationsQuery } from '../../features/api/organizationApiSlice'; import { useEditOrganizationMutation, useGetOrganizationQuery, useGetOrganizationsQuery } from '@/api/organizationApi';
import { setTotalOrgNumber, setCurrentPage } from '../../features/pagination/mainPagination'; import { setTotalOrgNumber, setCurrentPage } from '@/store/slices/mainPagination';
import './ManageOrganization.css'; import './ManageOrganization.css';
interface OrganizationValues { interface OrganizationValues {
...@@ -28,7 +28,6 @@ const ManageOrganization: React.FC = () => { ...@@ -28,7 +28,6 @@ const ManageOrganization: React.FC = () => {
const isEdit = Boolean(id); const isEdit = Boolean(id);
const { data, isLoading, isError } = useGetOrganizationQuery(id!, { skip: !isEdit }); const { data, isLoading, isError } = useGetOrganizationQuery(id!, { skip: !isEdit });
const { data: organizations } = useGetOrganizationsQuery(); const { data: organizations } = useGetOrganizationsQuery();
const [addNewOrganization] = useAddNewOrganizationMutation();
const [editOrganization] = useEditOrganizationMutation(); const [editOrganization] = useEditOrganizationMutation();
const [form] = Form.useForm(); const [form] = Form.useForm();
const totalOrgNumber = useSelector((state: any) => state.mainPagination.totalOrgNumber); const totalOrgNumber = useSelector((state: any) => state.mainPagination.totalOrgNumber);
...@@ -65,7 +64,6 @@ const ManageOrganization: React.FC = () => { ...@@ -65,7 +64,6 @@ const ManageOrganization: React.FC = () => {
await editOrganization({ ...normalizedValues }).unwrap(); await editOrganization({ ...normalizedValues }).unwrap();
message.success('Организация успешно обновлена!'); message.success('Организация успешно обновлена!');
} else { } else {
await addNewOrganization({ ...normalizedValues, created: new Date().toISOString() }).unwrap();
message.success('Организация успешно добавлена!'); message.success('Организация успешно добавлена!');
dispatch(setTotalOrgNumber(totalOrgNumber + 1)); dispatch(setTotalOrgNumber(totalOrgNumber + 1));
const newCurrentPage = Math.ceil((totalOrgNumber + 1) / ORG_NUMBER_PER_PAGE); const newCurrentPage = Math.ceil((totalOrgNumber + 1) / ORG_NUMBER_PER_PAGE);
......
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Button, Tag, Modal, message } from 'antd'; import { Button, Tag, Modal, message } from 'antd';
import type { TableProps } from 'antd'; import type { TableProps } from 'antd';
import { getStatusText, getStatusColor, openXMLInNewPage, downloadXML } from './utils';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { getStatusText, getStatusColor, openXMLInNewPage, downloadXML } from './utils';
export interface DataType { export interface DataType {
id: number; id: number;
xml: string; xml: string;
...@@ -22,16 +23,21 @@ export const columns: TableProps<DataType>['columns'] = [ ...@@ -22,16 +23,21 @@ export const columns: TableProps<DataType>['columns'] = [
title: "ID", title: "ID",
dataIndex: "id", dataIndex: "id",
key: "id", key: "id",
width: '1%'
}, },
{ {
title: "XML", title: "XML",
dataIndex: "xml", dataIndex: "xml",
key: "xml", key: "xml",
width: '1%',
render: (_, record) => ( render: (_, record) => (
<div style={{display: 'flex', alignItems: 'center', gap: 5}}> <div style={{display: 'flex', alignItems: 'center', gap: 5}}>
<Button type='link' onClick={() => downloadXML(record.xml, record.id)} style={{padding: 0}}> <Button
<img src="img/download_icon.png" alt="" width={18}/> type='link'
</Button> onClick={() => downloadXML(record.xml, record.id)}
style={{padding: 0}}
icon={<span className='material-icons'>download</span>}
/>
<Button type='link' onClick={() => openXMLInNewPage(record.xml)} style={{padding: 0}}>Открыть XML</Button> <Button type='link' onClick={() => openXMLInNewPage(record.xml)} style={{padding: 0}}>Открыть XML</Button>
</div> </div>
), ),
...@@ -40,25 +46,28 @@ export const columns: TableProps<DataType>['columns'] = [ ...@@ -40,25 +46,28 @@ export const columns: TableProps<DataType>['columns'] = [
title: "Дата отправки", title: "Дата отправки",
dataIndex: "sendDate", dataIndex: "sendDate",
key: "sendDate", key: "sendDate",
width: '11%', width: '6%',
render: (_, record) => ( render: (_, record) => (
<span>{dayjs(record.sendDate).format('DD-MM-YYYY HH:mm:ss')}</span> <span>{dayjs(record.sendDate).format('DD-MM-YYYY HH:mm:ss')}</span>
) )
}, },
{ {
title: "Код организации", title: "Код",
dataIndex: "orgCode", dataIndex: "orgCode",
key: "esutdOrganizationCode", key: "esutdOrganizationCode",
width: '5%'
}, },
{ {
title: "Метод", title: "Метод",
dataIndex: "requestType", dataIndex: "requestType",
key: "requestType" key: "requestType",
width: '1%'
}, },
{ {
title: "Статус", title: "Статус",
dataIndex: "status", dataIndex: "status",
key: "status", key: "status",
width: '1%',
render: (_, record) => ( render: (_, record) => (
<Tag color={getStatusColor(record.status)} style={{ fontSize: '12px' }}> <Tag color={getStatusColor(record.status)} style={{ fontSize: '12px' }}>
{getStatusText(record.status)} {getStatusText(record.status)}
...@@ -69,6 +78,7 @@ export const columns: TableProps<DataType>['columns'] = [ ...@@ -69,6 +78,7 @@ export const columns: TableProps<DataType>['columns'] = [
title: "Сообщение об ошибке", title: "Сообщение об ошибке",
dataIndex: "errorMessage", dataIndex: "errorMessage",
key: "errorMessage", key: "errorMessage",
width: '1%',
render: (_, record) => ( render: (_, record) => (
<Button type='link' onClick={() => openXMLInNewPage(record.xml)} style={{padding: 0}}>Открыть сообщение</Button> <Button type='link' onClick={() => openXMLInNewPage(record.xml)} style={{padding: 0}}>Открыть сообщение</Button>
) )
...@@ -76,16 +86,17 @@ export const columns: TableProps<DataType>['columns'] = [ ...@@ -76,16 +86,17 @@ export const columns: TableProps<DataType>['columns'] = [
{ {
title: "Дата переотправки", title: "Дата переотправки",
dataIndex: "resendDate", dataIndex: "resendDate",
key: "resendDate" key: "resendDate",
width: '6%'
}, },
{ {
title: "Количество попыток", title: "Количество попыток",
dataIndex: "resentCount", dataIndex: "resentCount",
key: "resentCount" key: "resentCount",
width: '5%'
}, },
{ {
title: "Действия", width: '1%',
width: 60,
render: (_, record) => { render: (_, record) => {
return ( return (
<ResendColumn <ResendColumn
......
...@@ -9,15 +9,3 @@ ...@@ -9,15 +9,3 @@
display: flex; display: flex;
gap: 1rem; gap: 1rem;
} }
.pagination_container {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
padding: .5rem 1rem;
display: flex;
justify-content: center;
background: white;
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
}
\ No newline at end of file
import React, { useEffect, useState, createRef } from 'react'; import React, { useEffect, useState, createRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import dayjs, { Dayjs } from 'dayjs'; import dayjs, { Dayjs } from 'dayjs';
import isBetween from 'dayjs/plugin/isBetween'; import isBetween from 'dayjs/plugin/isBetween';
import { DatePicker, Select, Button, Spin, Table } from 'antd'; dayjs.extend(isBetween);
import { useDispatch, useSelector } from 'react-redux'; import { DatePicker, Select, Button, Table } from 'antd';
import { columns, DataType } from './Columns';
import { useGetRequestsQuery } from '../../features/api/requestApiSlice';
import { setCurrentPage, setTotalReqNumber } from '../../features/pagination/reqPagination';
import { TableRef } from 'antd/es/table'; import { TableRef } from 'antd/es/table';
import { useGetRequestsQuery } from '@/api/requestApi';
import { setCurrentPage, setTotalReqNumber } from '@/store/slices/reqPagination'
import { columns, DataType } from './Columns';
import './RequestPage.css'; import './RequestPage.css';
dayjs.extend(isBetween);
const DATE_FORMAT = 'YYYY-MM-DD'; const DATE_FORMAT = 'YYYY-MM-DD';
const DEFAULT_DATES = { const DEFAULT_DATES = {
...@@ -32,8 +33,6 @@ const RequestPage: React.FC = () => { ...@@ -32,8 +33,6 @@ const RequestPage: React.FC = () => {
const [isTableLoading, setIsTableLoading] = useState(false); const [isTableLoading, setIsTableLoading] = useState(false);
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
//tableRef.current?.nativeElement.scrollIntoView({ behavior: 'smooth' });
dispatch(setCurrentPage(page)); dispatch(setCurrentPage(page));
}; };
...@@ -103,6 +102,13 @@ const RequestPage: React.FC = () => { ...@@ -103,6 +102,13 @@ const RequestPage: React.FC = () => {
dataSource={paginateData(data)} dataSource={paginateData(data)}
columns={columns} columns={columns}
loading={isTableLoading} loading={isTableLoading}
rowKey="id"
ref={tableRef}
scroll={{
scrollToFirstRowOnChange: true,
x: 'max-content',
y: 400
}}
pagination={{ pagination={{
position: ['bottomCenter'], position: ['bottomCenter'],
current: currentPage, current: currentPage,
...@@ -112,8 +118,6 @@ const RequestPage: React.FC = () => { ...@@ -112,8 +118,6 @@ const RequestPage: React.FC = () => {
onChange: handlePaginationChange, onChange: handlePaginationChange,
hideOnSinglePage: true hideOnSinglePage: true
}} }}
rowKey="id"
ref={tableRef}
/>; />;
} else if (isError) { } else if (isError) {
table = <div>{error.toString()}</div>; table = <div>{error.toString()}</div>;
...@@ -167,7 +171,6 @@ const RequestPage: React.FC = () => { ...@@ -167,7 +171,6 @@ const RequestPage: React.FC = () => {
/> />
</div> </div>
</div> </div>
<Button <Button
type='primary' type='primary'
onClick={applyFilters} onClick={applyFilters}
......
...@@ -9,7 +9,7 @@ interface InitialState { ...@@ -9,7 +9,7 @@ interface InitialState {
const initialState: InitialState = { const initialState: InitialState = {
currentPage: 1, currentPage: 1,
totalOrgNumber: 0, totalOrgNumber: 0,
ORG_NUMBER_PER_PAGE: 11 ORG_NUMBER_PER_PAGE: 15
} }
const mainPaginationSlice = createSlice({ const mainPaginationSlice = createSlice({
......
import { configureStore, Store, createSlice, PayloadAction } from '@reduxjs/toolkit'; import { configureStore, Store, createSlice, PayloadAction } from '@reduxjs/toolkit';
import storage from 'redux-persist/lib/storage'; import storage from 'redux-persist/lib/storage';
import { persistReducer, persistStore } from 'redux-persist'; import { persistReducer, persistStore } from 'redux-persist';
import { apiSlice } from '../features/api/apiSlice';
import mainPaginationReducer from '../features/pagination/mainPagination'; import { apiSlice } from '../api/mainApi';
import reqPaginationReducer from '../features/pagination/reqPagination'; import mainPaginationReducer from './slices/mainPagination';
import syncBtnReducer from '../features/sync_btn/syncBtn'; import reqPaginationReducer from './slices/reqPagination';
import syncBtnReducer from './slices/syncBtn';
interface AuthState { interface AuthState {
token: string | null; token: string | null;
......
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", // This must be specified if "paths" is. "baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"composite": true, "composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020", "target": "ES2020",
......
...@@ -3,6 +3,11 @@ import react from '@vitejs/plugin-react'; ...@@ -3,6 +3,11 @@ import react from '@vitejs/plugin-react';
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],
resolve: {
alias: {
'@': '/src',
},
},
server: { server: {
proxy: { proxy: {
'/api': { '/api': {
......
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