переделал страницу с наборами линз с помощью redux

This commit is contained in:
Андрей Дувакин 2025-03-26 16:55:26 +05:00
parent 94ef12b336
commit 0c0fbd89c0
16 changed files with 417 additions and 191 deletions

View File

@ -191,7 +191,7 @@ LensFormModal.propTypes = {
visible: PropTypes.bool.isRequired, visible: PropTypes.bool.isRequired,
onCancel: PropTypes.func.isRequired, onCancel: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired,
lens: LensPropType.isRequired, lens: LensPropType,
} }
export default LensFormModal; export default LensFormModal;

View File

@ -1,7 +1,6 @@
import {useState, useEffect} from "react"; import {useState, useEffect} from "react";
import {Modal, Button, Form, Input, Table, InputNumber, Select, Space, notification} from "antd"; import {Modal, Button, Form, Input, Table, InputNumber, Select, Space, notification} from "antd";
import {PlusOutlined, DeleteOutlined} from "@ant-design/icons"; import {PlusOutlined, DeleteOutlined} from "@ant-design/icons";
import axios from "axios";
import getAllLensTypes from "../../api/lens_types/getAllLensTypes.js"; import getAllLensTypes from "../../api/lens_types/getAllLensTypes.js";
import {useAuth} from "../../AuthContext.jsx"; import {useAuth} from "../../AuthContext.jsx";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
@ -29,7 +28,6 @@ const SetFormModal = ({visible, onCancel, setData, onSubmit}) => {
fetchSetContents(); fetchSetContents();
}, [setData, form]); }, [setData, form]);
const fetchSetContents = async () => { const fetchSetContents = async () => {
if (!setData) return; if (!setData) return;
@ -96,7 +94,8 @@ const SetFormModal = ({visible, onCancel, setData, onSubmit}) => {
const handleSubmit = () => { const handleSubmit = () => {
form.validateFields().then(values => { form.validateFields().then(values => {
if (!validateContent()) return; if (!validateContent()) return;
onSubmit({...values}, content); const sanitizedContent = content.map(({id, ...rest}) => rest);
onSubmit({...values}, sanitizedContent);
}); });
}; };
@ -255,7 +254,7 @@ SetFormModal.propTypes = {
visible: PropTypes.bool.isRequired, visible: PropTypes.bool.isRequired,
onCancel: PropTypes.func.isRequired, onCancel: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired,
setData: SetPropType.isRequired, setData: SetPropType,
} }
export default SetFormModal; export default SetFormModal;

View File

@ -4,11 +4,9 @@ import {
useDeleteLensMutation, useDeleteLensMutation,
useGetLensesQuery, useGetLensesQuery,
useUpdateLensMutation useUpdateLensMutation
} from "../redux/services/lensesApi.js"; } from "../../redux/services/lensesApi.js";
import {
closeModal
} from "../redux/slices/lensesSlice.js";
import {notification} from "antd"; import {notification} from "antd";
import {closeModal} from "../../redux/slices/lensesSlice.js";
const useLenses = () => { const useLenses = () => {
@ -44,6 +42,8 @@ const useLenses = () => {
}; };
const handleModalSubmit = async (lensData) => { const handleModalSubmit = async (lensData) => {
dispatch(closeModal());
try { try {
if (selectedLens) { if (selectedLens) {
await updateLens({id: selectedLens.id, ...lensData}).unwrap(); await updateLens({id: selectedLens.id, ...lensData}).unwrap();
@ -60,7 +60,6 @@ const useLenses = () => {
placement: "topRight", placement: "topRight",
}); });
} }
dispatch(closeModal());
} catch (error) { } catch (error) {
notification.error({ notification.error({
message: "Ошибка", message: "Ошибка",

View File

@ -5,10 +5,8 @@ import {
useDeletePatientMutation, useDeletePatientMutation,
useGetPatientsQuery, useGetPatientsQuery,
useUpdatePatientMutation useUpdatePatientMutation
} from "../redux/services/patientsApi"; } from "../../redux/services/patientsApi.js";
import { import {closeModal} from "../../redux/slices/patientsSlice.js";
closeModal,
} from "../redux/slices/patientsSlice";
const usePatients = () => { const usePatients = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -41,6 +39,8 @@ const usePatients = () => {
}; };
const handleModalSubmit = async (patientData) => { const handleModalSubmit = async (patientData) => {
dispatch(closeModal());
try { try {
if (selectedPatient) { if (selectedPatient) {
await updatePatient({ id: selectedPatient.id, ...patientData }).unwrap(); await updatePatient({ id: selectedPatient.id, ...patientData }).unwrap();
@ -57,7 +57,6 @@ const usePatients = () => {
placement: "topRight", placement: "topRight",
}); });
} }
dispatch(closeModal());
} catch (error) { } catch (error) {
notification.error({ notification.error({
message: "Ошибка", message: "Ошибка",
@ -76,4 +75,4 @@ const usePatients = () => {
}; };
}; };
export default usePatients; export default usePatients;

View File

@ -0,0 +1,118 @@
import {useDispatch, useSelector} from "react-redux";
import {notification} from "antd";
import {
useAddSetMutation, useAppendLensesFromSetMutation,
useDeleteSetMutation,
useGetSetsQuery,
useUpdateSetMutation
} from "../../redux/services/setsApi.js";
import {closeModal} from "../../redux/slices/setsSlice.js";
import {useAddSetContentMutation, useUpdateSetContentMutation} from "../../redux/services/setContentApi.js";
const useSets = () => {
const dispatch = useDispatch();
const {
selectedSet,
} = useSelector(state => state.setsUI);
const {data: sets = [], isLoading, isError} = useGetSetsQuery({
pollingInterval: 20000,
});
const [addSet] = useAddSetMutation();
const [appendLensFromSet] = useAppendLensesFromSetMutation();
const [updateSet] = useUpdateSetMutation();
const [deleteSet] = useDeleteSetMutation();
const [setContent] = useAddSetContentMutation();
const [updateContent] = useUpdateSetContentMutation();
const handleDeleteSet = async (setId) => {
try {
await deleteSet(setId).unwrap();
notification.success({
message: "Набор удален",
description: "Набор успешно удален.",
placement: "topRight",
});
} catch (error) {
notification.error({
message: "Ошибка удаления",
description: error.data?.message || "Не удалось удалить набор",
placement: "topRight",
});
}
};
const handleAppendSet = async (set) => {
try {
await appendLensFromSet(set.id).unwrap();
notification.success({
message: "Линзы добавлены",
description: "Линзы успешно добавлены.",
placement: "topRight",
});
} catch (error) {
notification.error({
message: "Ошибка добавления",
description: error.data?.message || "Не удалось добавить линзы из набора в общий список",
placement: "topRight",
});
}
};
const handleModalSetSubmit = async (set, content = []) => {
dispatch(closeModal());
try {
let refreshedSet;
if (selectedSet) {
refreshedSet = await updateSet({id: selectedSet.id, ...set}).unwrap();
notification.success({
message: "Набор обновлен",
description: "Набор успешно обновлен.",
placement: "topRight",
});
} else {
refreshedSet = await addSet(set).unwrap();
notification.success({
message: "Набор добавлен",
description: "Набор успешно добавлен.",
placement: "topRight",
});
}
if (refreshedSet && selectedSet) {
await updateContent({setId: refreshedSet.id, setContent: content}).unwrap();
} else if (refreshedSet && !selectedSet) {
await setContent({setId: refreshedSet.id, setContent: content}).unwrap();
} else {
notification.error({
message: "Ошибка",
description: "Не удалось сохранить содержимое набора",
placement: "topRight",
});
}
} catch (error) {
notification.error({
message: "Ошибка добавления",
description: error.data?.message || "Произошла ошибка при сохранении",
placement: "topRight",
});
}
};
return {
sets,
isLoading,
isError,
addSet,
updateSet,
handleDeleteSet,
handleAppendSet,
handleModalSetSubmit,
};
};
export default useSets;

View File

@ -1,5 +1,5 @@
import {useEffect} from "react"; import {useEffect} from "react";
import {getCachedInfo} from "../utils/cachedInfoUtils.js"; import {getCachedInfo} from "../../utils/cachedInfoUtils.js";
import { import {
closeModal, closeModal,
openModal, openModal,
@ -7,7 +7,7 @@ import {
setSearchParams, setSearchParams,
setSearchText, setShowAdvancedSearch, setSearchText, setShowAdvancedSearch,
setViewMode setViewMode
} from "../redux/slices/lensesSlice.js"; } from "../../redux/slices/lensesSlice.js";
import {useDispatch, useSelector} from "react-redux"; import {useDispatch, useSelector} from "react-redux";
@ -30,6 +30,10 @@ const useLensesUI = (lenses) => {
if (cachedViewMode) dispatch(setViewMode(cachedViewMode)); if (cachedViewMode) dispatch(setViewMode(cachedViewMode));
}, [dispatch]); }, [dispatch]);
const containerStyle = { padding: 20 };
const filterBarStyle = { marginBottom: 20 };
const formItemStyle = { width: "100%" };
const handleSetSearchText = (value) => dispatch(setSearchText(value)); const handleSetSearchText = (value) => dispatch(setSearchText(value));
const handleCloseModal = () => dispatch(closeModal()); const handleCloseModal = () => dispatch(closeModal());
const handleSetCurrentPage = (page) => dispatch(setCurrentPage(page)); const handleSetCurrentPage = (page) => dispatch(setCurrentPage(page));
@ -101,6 +105,9 @@ const useLensesUI = (lenses) => {
showAdvancedSearch, showAdvancedSearch,
searchParams, searchParams,
pagination, pagination,
containerStyle,
filterBarStyle,
formItemStyle,
filteredLenses: filteredLenses.map(lens => ({...lens, key: lens.id})), filteredLenses: filteredLenses.map(lens => ({...lens, key: lens.id})),
handleSetSearchText, handleSetSearchText,
handleAddLens, handleAddLens,

View File

@ -1,6 +1,7 @@
import { useEffect, useMemo } from "react"; import { useEffect, useMemo } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { import {
closeModal,
openModal, openModal,
selectPatient, selectPatient,
setCurrentPage, setCurrentPage,
@ -8,9 +9,8 @@ import {
setSearchText, setSearchText,
setSortOrder, setSortOrder,
setViewMode setViewMode
} from "../redux/slices/patientsSlice"; } from "../../redux/slices/patientsSlice.js";
import { closeModal } from "../redux/slices/lensesSlice"; import { getCachedInfo } from "../../utils/cachedInfoUtils.js";
import { getCachedInfo } from "../utils/cachedInfoUtils";
const usePatientsUI = (patients) => { const usePatientsUI = (patients) => {
const dispatch = useDispatch(); const dispatch = useDispatch();

View File

@ -0,0 +1,81 @@
import {useDispatch, useSelector} from "react-redux";
import {useEffect} from "react";
import {
closeModal,
openModal,
selectSet,
setCurrentPage,
setPageSize,
setSearchText
} from "../../redux/slices/setsSlice.js";
const useSetsUI = (sets) => {
const dispatch = useDispatch();
const {
searchText,
currentPage,
pageSize,
selectedSet,
isModalVisible,
} = useSelector(state => state.setsUI);
useEffect(() => {
document.title = "Наборы линз";
}, [dispatch]);
const containerStyle = { padding: 20 };
const filterBarStyle = { marginBottom: 20 };
const formItemStyle = { width: "100%" };
const handleSetSearchText = (value) => dispatch(setSearchText(value));
const handleCloseModal = () => dispatch(closeModal());
const handleSetCurrentPage = (page) => dispatch(setCurrentPage(page));
const handleSetPageSize = (size) => dispatch(setPageSize(size));
const handleAddSet = () => {
dispatch(selectSet(null));
dispatch(openModal());
};
const handleEditSet = (set) => {
dispatch(selectSet(set));
dispatch(openModal());
};
const handlePaginationChange = (page, pageSize) => {
handleSetCurrentPage(page);
handleSetPageSize(pageSize);
};
const pagination = {
currentPage: currentPage,
pageSize: pageSize,
showSizeChanger: true,
pageSizeOptions: ["5", "10", "20", "50"],
onChange: (page, newPageSize) => {
handlePaginationChange(page, newPageSize);
},
};
const filteredSets = sets.filter(set => set.title.toLowerCase().includes(searchText.toLowerCase()));
return {
searchText,
currentPage,
pageSize,
selectedSet,
isModalVisible,
pagination,
filteredSets,
containerStyle,
filterBarStyle,
formItemStyle,
handleSetSearchText,
handleAddSet,
handleEditSet,
handleCloseModal,
};
};
export default useSetsUI;

View File

@ -22,8 +22,8 @@ import PatientListCard from "../components/patients/PatientListCard.jsx";
import PatientFormModal from "../components/patients/PatientFormModal.jsx"; import PatientFormModal from "../components/patients/PatientFormModal.jsx";
import SelectViewMode from "../components/SelectViewMode.jsx"; import SelectViewMode from "../components/SelectViewMode.jsx";
import LoadingIndicator from "../components/LoadingIndicator.jsx"; import LoadingIndicator from "../components/LoadingIndicator.jsx";
import usePatients from "../hooks/usePatients.js"; import usePatients from "../hooks/data/usePatients.js";
import usePatientsUI from "../hooks/usePatientsUI.js"; import usePatientsUI from "../hooks/ui/usePatientsUI.js";
const {Option} = Select; const {Option} = Select;
const {Title} = Typography; const {Title} = Typography;

View File

@ -26,8 +26,8 @@ import LensCard from "../../components/lenses/LensListCard.jsx";
import LensFormModal from "../../components/lenses/LensFormModal.jsx"; import LensFormModal from "../../components/lenses/LensFormModal.jsx";
import SelectViewMode from "../../components/SelectViewMode.jsx"; import SelectViewMode from "../../components/SelectViewMode.jsx";
import LoadingIndicator from "../../components/LoadingIndicator.jsx"; import LoadingIndicator from "../../components/LoadingIndicator.jsx";
import useLenses from "../../hooks/useLenses.js"; import useLenses from "../../hooks/data/useLenses.js";
import useLensesUI from "../../hooks/useLensesUI.js"; import useLensesUI from "../../hooks/ui/useLensesUI.js";
const {Option} = Select; const {Option} = Select;
const {useBreakpoint} = Grid; const {useBreakpoint} = Grid;

View File

@ -1,160 +1,31 @@
import {useAuth} from "../../AuthContext.jsx"; import {FloatButton, Input, List, Row, Typography} from "antd";
import {useEffect, useState} from "react";
import {FloatButton, Input, List, notification, Row, Typography} from "antd";
import getAllSets from "../../api/sets/getAllSets.js";
import {PlusOutlined, SwitcherOutlined} from "@ant-design/icons"; import {PlusOutlined, SwitcherOutlined} from "@ant-design/icons";
import SetListCard from "../../components/sets/SetListCard.jsx"; import SetListCard from "../../components/sets/SetListCard.jsx";
import SetFormModal from "../../components/sets/SetFormModal.jsx"; import SetFormModal from "../../components/sets/SetFormModal.jsx";
import updateSet from "../../api/sets/updateSet.js";
import addSet from "../../api/sets/addSet.js";
import deleteSet from "../../api/sets/deleteSet.js";
import addSetContent from "../../api/set_content/addSetContent.js";
import updateSetContent from "../../api/set_content/updateSetContent.js";
import appendLensesFromSet from "../../api/sets/appendLensesFromSet.js";
import LoadingIndicator from "../../components/LoadingIndicator.jsx"; import LoadingIndicator from "../../components/LoadingIndicator.jsx";
import {cacheInfo, getCachedInfo, getCacheTimestamp} from "../../utils/cachedInfoUtils.js"; import useSets from "../../hooks/data/useSets.js";
import useSetsUI from "../../hooks/ui/useSetsUI.js";
const {Title} = Typography; const {Title} = Typography;
const SetLensesPage = () => { const SetLensesPage = () => {
const {api} = useAuth(); const setsData = useSets();
const setsUI = useSetsUI(setsData.sets);
const [current, setCurrent] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [searchText, setSearchText] = useState("");
const [sets, setSets] = useState([]);
const [loading, setLoading] = useState(true);
const [isModalVisible, setIsModalVisible] = useState(false);
const [selectedSet, setSelectedSet] = useState(null);
useEffect(() => {
fetchSetsWithCache();
}, []);
useEffect(() => {
if (!isModalVisible) {
const intervalId = setInterval(fetchSets, 5000);
return () => clearInterval(intervalId);
}
}, [isModalVisible]);
const fetchSetsWithCache = async () => {
const cachedData = getCachedInfo("setsData");
const cacheTimestamp = getCacheTimestamp("setsData");
if (cachedData && cacheTimestamp && (Date.now() - cacheTimestamp) < 60 * 1000) {
setSets(cachedData);
setLoading(false);
} else {
await fetchSets();
}
};
const fetchSets = async () => {
const data = await getAllSets(api);
setSets(data);
setLoading(false);
cacheInfo("setsData", data);
};
const filteredSets = sets.filter(set => set.title.toLowerCase().includes(searchText.toLowerCase()));
const handleAddSet = () => {
setSelectedSet(null);
setIsModalVisible(true);
};
const handleEditSet = (set) => {
setSelectedSet(set);
setIsModalVisible(true);
};
const handleDeleteSet = async (set_id) => {
await deleteSet(api, set_id);
notification.success({
message: "Набор удален",
description: "Набор успешно удален.",
placement: "topRight",
});
await fetchSets();
};
const handleCancel = () => {
setIsModalVisible(false);
};
const handleAppendSet = async (set) => {
await appendLensesFromSet(api, set.id);
notification.success({
message: "Линзы добавлены",
description: "Линзы успешно добавлены.",
placement: "topRight",
});
};
const handleModalSetSubmit = async (set, content = []) => {
setIsModalVisible(false);
let refreshed_set;
if (selectedSet) {
refreshed_set = await editCurrentSet(set);
} else {
refreshed_set = await addNewSet(set);
}
if (refreshed_set && selectedSet) {
await updateContent(content, refreshed_set.id);
} else if (refreshed_set && !selectedSet) {
await setContent(content, refreshed_set.id);
}
await fetchSets();
};
const setContent = async (content, set_id) => {
await addSetContent(api, content, set_id);
};
const updateContent = async (content, set_id) => {
await updateSetContent(api, content, set_id);
};
const editCurrentSet = async (set) => {
const refreshed_set = await updateSet(api, selectedSet.id, set);
notification.success({
message: "Набор обновлен",
description: "Набор успешно обновлен.",
placement: "topRight",
});
return refreshed_set;
};
const addNewSet = async (set) => {
const refreshed_set = await addSet(api, set);
notification.success({
message: "Набор добавлен",
description: "Набор успешно добавлен.",
placement: "topRight",
});
return refreshed_set;
};
return ( return (
<div style={{padding: 20}}> <div style={setsUI.containerStyle}>
<Title level={1}><SwitcherOutlined/> Наборы линз</Title> <Title level={1}><SwitcherOutlined/> Наборы линз</Title>
<Row style={{marginBottom: 20}}> <Row style={setsUI.filterBarStyle}>
<Input <Input
placeholder="Поиск набора" placeholder="Поиск набора"
onChange={(e) => setSearchText(e.target.value)} onChange={(e) => setsUI.handleSetSearchText(e.target.value)}
style={{width: "100%"}} style={setsUI.formItemStyle}
allowClear allowClear
/> />
</Row> </Row>
{loading ? ( {setsData.isLoading ? (
<LoadingIndicator/> <LoadingIndicator/>
) : ( ) : (
<List <List
@ -167,43 +38,33 @@ const SetLensesPage = () => {
xl: 3, xl: 3,
xxl: 3, xxl: 3,
}} }}
dataSource={filteredSets} dataSource={setsUI.filteredSets}
renderItem={(set) => ( renderItem={(set) => (
<List.Item> <List.Item>
<SetListCard <SetListCard
set={set} set={set}
handleEditSet={handleEditSet} handleEditSet={setsUI.handleEditSet}
handleDeleteSet={handleDeleteSet} handleDeleteSet={setsData.handleDeleteSet}
handleAppendSet={handleAppendSet} handleAppendSet={setsData.handleAppendSet}
/> />
</List.Item> </List.Item>
)} )}
pagination={{ pagination={setsUI.pagination}
current,
pageSize,
showSizeChanger: true,
pageSizeOptions: ["5", "10", "20", "50"],
onChange: (page, newPageSize) => {
setCurrent(page);
setPageSize(newPageSize);
},
}}
/> />
)} )}
<FloatButton <FloatButton
icon={<PlusOutlined/>} icon={<PlusOutlined/>}
type="primary" type="primary"
style={{position: "fixed", bottom: 40, right: 40}}
tooltip="Добавить набор" tooltip="Добавить набор"
onClick={handleAddSet} onClick={setsUI.handleAddSet}
/> />
<SetFormModal <SetFormModal
visible={isModalVisible} visible={setsUI.isModalVisible}
onCancel={handleCancel} onCancel={setsUI.handleCloseModal}
onSubmit={handleModalSetSubmit} onSubmit={setsData.handleModalSetSubmit}
setData={selectedSet} setData={setsUI.selectedSet}
/> />
</div> </div>
); );

View File

@ -1,4 +1,4 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' import {createApi, fetchBaseQuery} from '@reduxjs/toolkit/query/react'
import CONFIG from "../../core/сonfig.js"; import CONFIG from "../../core/сonfig.js";
export const patientsApi = createApi({ export const patientsApi = createApi({
@ -27,7 +27,7 @@ export const patientsApi = createApi({
invalidatesTags: ['Patient'] invalidatesTags: ['Patient']
}), }),
updatePatient: builder.mutation({ updatePatient: builder.mutation({
query: ({ id, ...patient }) => ({ query: ({id, ...patient}) => ({
url: `/patients/${id}/`, url: `/patients/${id}/`,
method: 'PUT', method: 'PUT',
body: patient body: patient
@ -48,5 +48,5 @@ export const {
useGetPatientsQuery, useGetPatientsQuery,
useAddPatientMutation, useAddPatientMutation,
useUpdatePatientMutation, useUpdatePatientMutation,
useDeletePatientMutation useDeletePatientMutation,
} = patientsApi } = patientsApi;

View File

@ -0,0 +1,43 @@
import {createApi, fetchBaseQuery} from '@reduxjs/toolkit/query/react';
import CONFIG from "../../core/сonfig.js";
export const setContentApi = createApi({
reducerPath: 'setContentApi',
baseQuery: fetchBaseQuery({
baseUrl: CONFIG.BASE_URL,
prepareHeaders: (headers) => {
const token = localStorage.getItem('access_token');
if (token) headers.set('Authorization', `Bearer ${token}`);
return headers;
}
}),
tagTypes: ['SetContent'],
endpoints: (builder) => ({
getSetContent: builder.query({
query: (setId) => `/set_content/${setId}`,
providesTags: ['SetContent'],
}),
addSetContent: builder.mutation({
query: ({setId, setContent}) => ({
url: `/set_content/${setId}/`,
method: 'POST',
body: setContent
}),
invalidatesTags: ['SetContent']
}),
updateSetContent: builder.mutation({
query: ({setId, setContent}) => ({
url: `/set_content/${setId}/`,
method: 'PUT',
body: setContent
}),
invalidatesTags: ['SetContent']
}),
}),
});
export const {
useGetSetContentQuery,
useAddSetContentMutation,
useUpdateSetContentMutation,
} = setContentApi;

View File

@ -0,0 +1,60 @@
import {createApi, fetchBaseQuery} from '@reduxjs/toolkit/query/react'
import CONFIG from "../../core/сonfig.js";
export const setsApi = createApi({
reducerPath: 'setsApi',
baseQuery: fetchBaseQuery({
baseUrl: CONFIG.BASE_URL,
prepareHeaders: (headers) => {
const token = localStorage.getItem('access_token');
if (token) headers.set('Authorization', `Bearer ${token}`);
return headers;
}
}),
tagTypes: ['Set'],
endpoints: (builder) => ({
getSets: builder.query({
query: () => '/sets/',
providesTags: ['Set'],
refetchOnMountOrArgChange: 5
}),
addSet: builder.mutation({
query: (set) => ({
url: '/sets/',
method: 'POST',
body: set
}),
invalidatesTags: ['Set']
}),
updateSet: builder.mutation({
query: ({id, ...set}) => ({
url: `/sets/${id}/`,
method: 'PUT',
body: set
}),
invalidatesTags: ['Set']
}),
deleteSet: builder.mutation({
query: (id) => ({
url: `/sets/${id}/`,
method: 'DELETE'
}),
invalidatesTags: ['Set']
}),
appendLensesFromSet: builder.mutation({
query: (id) => ({
url: `/sets/append_lenses/${id}/`,
method: 'POST',
}),
invalidatesTags: ['Set']
}),
}),
});
export const {
useGetSetsQuery,
useAddSetMutation,
useUpdateSetMutation,
useDeleteSetMutation,
useAppendLensesFromSetMutation,
} = setsApi;

View File

@ -0,0 +1,46 @@
import {createSlice} from '@reduxjs/toolkit'
const initialState = {
searchText: '',
currentPage: 1,
pageSize: 10,
selectedSet: null,
isModalVisible: false,
};
const setsSlice = createSlice({
name: 'setsUI',
initialState,
reducers: {
setSearchText: (state, action) => {
state.searchText = action.payload;
},
setCurrentPage: (state, action) => {
state.currentPage = action.payload;
},
setPageSize: (state, action) => {
state.pageSize = action.payload;
},
openModal: (state) => {
state.isModalVisible = true;
},
closeModal: (state) => {
state.isModalVisible = false;
state.selectedSet = null;
},
selectSet: (state, action) => {
state.selectedSet = action.payload;
}
}
});
export const {
selectSet,
setSearchText,
setCurrentPage,
setPageSize,
openModal,
closeModal
} = setsSlice.actions;
export default setsSlice.reducer;

View File

@ -2,7 +2,10 @@ import {configureStore} from '@reduxjs/toolkit';
import {patientsApi} from './services/patientsApi.js'; import {patientsApi} from './services/patientsApi.js';
import patientsUIReducer from './slices/patientsSlice.js'; import patientsUIReducer from './slices/patientsSlice.js';
import {lensesApi} from './services/lensesApi.js'; import {lensesApi} from './services/lensesApi.js';
import lensesReducer from './slices/lensesSlice.js'; import lensesUIReducer from './slices/lensesSlice.js';
import {setsApi} from "./services/setsApi.js";
import setsUIReducer from './slices/setsSlice.js';
import {setContentApi} from "./services/setContentApi.js";
export const store = configureStore({ export const store = configureStore({
reducer: { reducer: {
@ -10,10 +13,20 @@ export const store = configureStore({
patientsUI: patientsUIReducer, patientsUI: patientsUIReducer,
[lensesApi.reducerPath]: lensesApi.reducer, [lensesApi.reducerPath]: lensesApi.reducer,
lensesUI: lensesReducer, lensesUI: lensesUIReducer,
[setsApi.reducerPath]: setsApi.reducer,
setsUI: setsUIReducer,
[setContentApi.reducerPath]: setContentApi.reducer,
}, },
middleware: (getDefaultMiddleware) => ( middleware: (getDefaultMiddleware) => (
getDefaultMiddleware().concat(patientsApi.middleware, lensesApi.middleware) getDefaultMiddleware().concat(
patientsApi.middleware,
lensesApi.middleware,
setsApi.middleware,
setContentApi.middleware,
)
) )
}); });