From ee541db053ca8a9cb89a59ff72c16370a31f4915 Mon Sep 17 00:00:00 2001 From: Alexey Groshev <82907949+walkerman-on@users.noreply.github.com> Date: Mon, 18 Mar 2024 22:22:38 +0300 Subject: [PATCH 01/24] Making first step in fetchData (facility/factory)) --- json-server/db.json | 356 ++++++++++++++++++ package.json | 1 + .../providers/StoreProvider/config/store.ts | 4 + .../providers/StoreProvider/config/types.ts | 6 +- src/entities/Auth/index.ts | 2 +- .../Auth/model/selectors/userSelector.ts | 4 +- src/entities/Auth/model/slice/userSlice.ts | 6 +- src/entities/Auth/model/types/user.ts | 2 +- src/entities/Facility/api/fetchFacilities.ts | 21 ++ src/entities/Facility/index.ts | 3 + .../Facility/model/slice/facilitySlice.ts | 33 ++ src/entities/Facility/types/types.ts | 18 + src/entities/Factory/api/fetchFactories.ts | 21 ++ src/entities/Factory/index.ts | 3 + .../Factory/model/slice/factorySlice.ts | 33 ++ src/entities/Factory/types/types.ts | 13 + src/pages/MainPage/ui/MainPage.tsx | 55 ++- src/shared/api/api.ts | 6 + src/shared/ui/Select/IProps.ts | 3 +- src/shared/ui/Select/Select.tsx | 12 +- 20 files changed, 566 insertions(+), 36 deletions(-) create mode 100644 json-server/db.json create mode 100644 src/entities/Facility/api/fetchFacilities.ts create mode 100644 src/entities/Facility/index.ts create mode 100644 src/entities/Facility/model/slice/facilitySlice.ts create mode 100644 src/entities/Facility/types/types.ts create mode 100644 src/entities/Factory/api/fetchFactories.ts create mode 100644 src/entities/Factory/index.ts create mode 100644 src/entities/Factory/model/slice/factorySlice.ts create mode 100644 src/entities/Factory/types/types.ts create mode 100644 src/shared/api/api.ts diff --git a/json-server/db.json b/json-server/db.json new file mode 100644 index 0000000..6aea200 --- /dev/null +++ b/json-server/db.json @@ -0,0 +1,356 @@ + { + "facility": [ + { + "id": 1, + "title": "Установка 23: Сжижжение газа", + "description": "Это описание установки", + "enabled": true, + "visible": true, + "technologicalParameters": [ + { + "pressure": [ + { + "id": 1, + "title": "P", + "unit": "мПа", + "value": 7.5 + }, + { + "id": 2, + "title": "P", + "unit": "мПа", + "value": 3.2 + }, + { + "id": 3, + "title": "P", + "unit": "мПа", + "value": 0.6 + }, + { + "id": 4, + "title": "P", + "unit": "мПа", + "value": 6.2 + } + ] + }, + { + "pressureDrop": [ + { + "id": 1, + "title": "ΔP", + "unit": "мПа", + "value": 0.01 + }, + { + "id": 2, + "title": "ΔP", + "unit": "мПа", + "value": 0.2 + }, + { + "id": 3, + "title": "ΔP", + "unit": "мПа", + "value": 0.01 + }, + { + "id": 4, + "title": "ΔP", + "unit": "мПа", + "value": 0.01 + }, + { + "id": 5, + "title": "ΔP", + "unit": "мПа", + "value": 0.01 + }, + { + "id": 6, + "title": "ΔP", + "unit": "мПа", + "value": 0.01 + }, + { + "id": 7, + "title": "ΔP", + "unit": "мПа", + "value": 0.01 + }, + { + "id": 8, + "title": "ΔP", + "unit": "мПа", + "value": 0.01 + }, + { + "id": 9, + "title": "ΔP", + "unit": "мПа", + "value": 0.01 + }, + { + "id": 10, + "title": "ΔP", + "unit": "мПа", + "value": 0.01 + } + ] + }, + { + "temperature": [ + { + "id": 1, + "title": "T", + "unit": "°C", + "value": 32 + }, + { + "id": 2, + "title": "T", + "unit": "°C", + "value": -50 + }, + { + "id": 3, + "title": "T", + "unit": "°C", + "value": -30 + }, + { + "id": 4, + "title": "T", + "unit": "°C", + "value": -35 + }, + { + "id": 5, + "title": "T", + "unit": "°C", + "value": -110 + }, + { + "id": 6, + "title": "T", + "unit": "°C", + "value": -150 + }, + { + "id": 7, + "title": "T", + "unit": "°C", + "value": -155 + }, + { + "id": 8, + "title": "T", + "unit": "°C", + "value": -30 + }, + { + "id": 9, + "title": "T", + "unit": "°C", + "value": -110 + } + ] + }, + { + "flow": [ + { + "id": 1, + "title": "Q", + "unit": "кг/ч", + "value": 17500 + }, + { + "id": 1, + "title": "Q", + "unit": "кг/ч", + "value": 19500 + } + ] + }, + { + "liquidLevel": [ + { + "id": 1, + "title": "H", + "unit": "%", + "value": 7 + }, + { + "id": 2, + "title": "H", + "unit": "%", + "value": 32.4 + } + ] + }, + { + "valve": [ + { + "id": 1, + "title": "M", + "unit": "%", + "value": 30 + }, + { + "id": 2, + "title": "M", + "unit": "%", + "value": 30 + }, + { + "id": 3, + "title": "M", + "unit": "%", + "value": 30 + }, + { + "id": 4, + "title": "M", + "unit": "%", + "value": 30 + }, + { + "id": 5, + "title": "M", + "unit": "%", + "value": 30 + }, + { + "id": 6, + "title": "M", + "unit": "%", + "value": 30 + }, + { + "id": 7, + "title": "M", + "unit": "%", + "value": 30 + }, + { + "id": 8, + "title": "M", + "unit": "%", + "value": 30 + }, + { + "id": 9, + "title": "M", + "unit": "%", + "value": 30 + } + ] + } + ] + }, + { + "id": 2, + "title": "Установка 22: Удаление тяжелых углеводородов", + "description": "Это описание установки", + "enabled": false, + "visible": true + }, + { + "id": 3, + "title": "Установка 41: Охлаждение", + "description": "Это описание установки", + "enabled": false, + "visible": true + }, + { + "id": 4, + "title": "Установка 12: Удаление кислых газов и метанола", + "description": "Это описание установки", + "enabled": false, + "visible": true + }, + { + "id": 5, + "title": "Установка 11: Удаление ртути", + "description": "Это описание установки", + "enabled": false, + "visible": true + }, + { + "id": 6, + "title": "Установка 05: Отделение очистки газа", + "description": "Это описание установки", + "enabled": false, + "visible": true + }, + { + "id": 7, + "title": "Установка 16: Отделение осушки газа", + "description": "Это описание установки", + "enabled": false, + "visible": true + }, + { + "id": 8, + "title": "Установка 47: Отделение хранения, подачи и дозирования хладагентов", + "description": "Это описание установки", + "enabled": false, + "visible": true + }, + { + "id": 9, + "title": "Установка 87: Система масла-теплоносителя", + "description": "Это описание установки", + "enabled": false, + "visible": true + }, + { + "id": 10, + "title": "Установка 95: Система воздуха КИП и технического воздуха", + "description": "Это описание установки", + "enabled": false, + "visible": true + }, + { + "id": 11, + "title": "Установка 97: Сбор сточной воды", + "description": "Это описание установки", + "enabled": false, + "visible": true + }, + { + "id": 12, + "title": "Установка 94: Система азота", + "description": "Это описание установки", + "enabled": false, + "visible": true + } + ], + "factory": [ + { + "id": 1, + "title": "Газпром СПГ Портовая", + "enabled": true, + "visible": true + }, + { + "id": 2, + "title": "ТПП Нефтеавтоматика", + "enabled": false, + "visible": true + }, + { + "id": 3, + "title": "ООО «Транснефть – Балтика»", + "enabled": false, + "visible": true + }, + { + "id": 4, + "title": "Газпромнефть-Восток", + "enabled": false, + "visible": true + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index 1aabd0b..0f7eff4 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "start": "webpack serve --env port=3000", "build:prod": "webpack --env mode=production", "build:dev": "webpack --env mode=development", + "dev:server": "npx json-server --watch ./json-server/db.json -p 3001", "prettier": "npx prettier --write **/*.{ts,tsx}" }, "keywords": [], diff --git a/src/app/providers/StoreProvider/config/store.ts b/src/app/providers/StoreProvider/config/store.ts index df0bf12..7884581 100644 --- a/src/app/providers/StoreProvider/config/store.ts +++ b/src/app/providers/StoreProvider/config/store.ts @@ -1,8 +1,12 @@ import { configureStore } from '@reduxjs/toolkit'; import { userReducer } from 'entities/Auth/index'; +import {factoryReducer} from "entities/Factory/index" +import { facilityReducer } from 'entities/Facility'; export const store = configureStore({ reducer: { user: userReducer, + factory: factoryReducer, + facility: facilityReducer }, }); diff --git a/src/app/providers/StoreProvider/config/types.ts b/src/app/providers/StoreProvider/config/types.ts index 65b3163..1a7b261 100644 --- a/src/app/providers/StoreProvider/config/types.ts +++ b/src/app/providers/StoreProvider/config/types.ts @@ -1,9 +1,9 @@ -import { UserSchema } from 'entities/Auth'; +import { UserState } from 'entities/Auth'; import { store } from './store'; export type AppDispatch = typeof store.dispatch; export type RootState = ReturnType; -export interface StateSchema { - user: UserSchema; +export interface IUserState { + user: UserState; } diff --git a/src/entities/Auth/index.ts b/src/entities/Auth/index.ts index 89a8639..abc198e 100644 --- a/src/entities/Auth/index.ts +++ b/src/entities/Auth/index.ts @@ -1,2 +1,2 @@ export { default as userReducer } from './model/slice/userSlice'; -export type { User, UserSchema } from './model/types/user'; +export type { User, UserState } from './model/types/user'; diff --git a/src/entities/Auth/model/selectors/userSelector.ts b/src/entities/Auth/model/selectors/userSelector.ts index 29deabd..4b9f2a7 100644 --- a/src/entities/Auth/model/selectors/userSelector.ts +++ b/src/entities/Auth/model/selectors/userSelector.ts @@ -1,3 +1,3 @@ -import { StateSchema } from 'app/providers/StoreProvider'; +import { IUserState } from 'app/providers/StoreProvider'; -export const getUserSelector = (state: StateSchema) => state.user; +export const getUserSelector = (state: IUserState) => state.user; diff --git a/src/entities/Auth/model/slice/userSlice.ts b/src/entities/Auth/model/slice/userSlice.ts index dfaa430..a4c3fbd 100644 --- a/src/entities/Auth/model/slice/userSlice.ts +++ b/src/entities/Auth/model/slice/userSlice.ts @@ -1,7 +1,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { User, UserSchema } from '../types/user'; +import { User, UserState } from '../types/user'; -const initialState: UserSchema = { +const initialState: UserState = { isAuthorized: false, user: null, }; @@ -10,7 +10,7 @@ const userSlice = createSlice({ name: 'user', initialState, reducers: { - setUser(state: UserSchema, { payload }: PayloadAction) { + setUser(state: UserState, { payload }: PayloadAction) { state.user = payload; state.isAuthorized = true; }, diff --git a/src/entities/Auth/model/types/user.ts b/src/entities/Auth/model/types/user.ts index 6bddba4..b85aae8 100644 --- a/src/entities/Auth/model/types/user.ts +++ b/src/entities/Auth/model/types/user.ts @@ -8,7 +8,7 @@ export interface User { avatar?: string; } -export interface UserSchema { +export interface UserState { user: User | null; isAuthorized: boolean; } diff --git a/src/entities/Facility/api/fetchFacilities.ts b/src/entities/Facility/api/fetchFacilities.ts new file mode 100644 index 0000000..b910bb9 --- /dev/null +++ b/src/entities/Facility/api/fetchFacilities.ts @@ -0,0 +1,21 @@ +import axios from "axios" +import { createAsyncThunk } from "@reduxjs/toolkit" +import { IFacility } from "../types/types" +import { $api } from "shared/api/api" + +export const fetchFacilities = createAsyncThunk( + "fetchFacilities", + async (_, { rejectWithValue }) => { + try { + const res = await $api.get("/facility") + + if (!res.data) { + throw new Error("Server Error!") + } + + return res.data + } catch (error) { + return rejectWithValue(error.message) + } + } +) \ No newline at end of file diff --git a/src/entities/Facility/index.ts b/src/entities/Facility/index.ts new file mode 100644 index 0000000..f230a37 --- /dev/null +++ b/src/entities/Facility/index.ts @@ -0,0 +1,3 @@ +export {default as facilityReducer} from "./model/slice/facilitySlice" +export * from "./types/types" +export {fetchFacilities} from "./api/fetchFacilities" \ No newline at end of file diff --git a/src/entities/Facility/model/slice/facilitySlice.ts b/src/entities/Facility/model/slice/facilitySlice.ts new file mode 100644 index 0000000..c0d24a4 --- /dev/null +++ b/src/entities/Facility/model/slice/facilitySlice.ts @@ -0,0 +1,33 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { fetchFacilities } from "entities/Facility/api/fetchFacilities"; +import {IFacilityState} from "../../types/types" + +const initialState:IFacilityState = { + list: [], + error: null, + loading: false +} + +export const facilitySlice = createSlice({ + name: "facility", + initialState, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(fetchFacilities.fulfilled, (state, action) => { + state.list = action.payload + state.loading = false + state.error = null + }) + .addCase(fetchFacilities.pending, (state) => { + state.loading = true + state.error = null + }) + .addCase(fetchFacilities.rejected, (state, action) => { + state.loading = false + state.error = action.payload + }) + } +}) + +export default facilitySlice.reducer \ No newline at end of file diff --git a/src/entities/Facility/types/types.ts b/src/entities/Facility/types/types.ts new file mode 100644 index 0000000..f708eeb --- /dev/null +++ b/src/entities/Facility/types/types.ts @@ -0,0 +1,18 @@ +export interface IFacility { + id: number, + title: string, + description: string, + enabled?: boolean, + visible?: boolean + technologicalParameters: [] +} + +export interface IFacilityState { + list: IFacility[], + error: string | null, + loading: boolean +} + +export interface IParametrs { + +} \ No newline at end of file diff --git a/src/entities/Factory/api/fetchFactories.ts b/src/entities/Factory/api/fetchFactories.ts new file mode 100644 index 0000000..64b8a99 --- /dev/null +++ b/src/entities/Factory/api/fetchFactories.ts @@ -0,0 +1,21 @@ +import axios from "axios" +import { createAsyncThunk } from "@reduxjs/toolkit" +import { IFactory } from "../types/types" +import { $api } from "shared/api/api"; + +export const fetchFactories = createAsyncThunk( + "fetchFactories", + async (_, { rejectWithValue }) => { + try { + const res = await $api.get("/factory") + + if (!res.data) { + throw new Error("Server Error!") + } + + return res.data + } catch (error) { + return rejectWithValue(error.message) + } + } +) \ No newline at end of file diff --git a/src/entities/Factory/index.ts b/src/entities/Factory/index.ts new file mode 100644 index 0000000..a204232 --- /dev/null +++ b/src/entities/Factory/index.ts @@ -0,0 +1,3 @@ +export {default as factoryReducer} from "./model/slice/factorySlice" +export * from "./model/slice/factorySlice" +export {fetchFactories} from "./api/fetchFactories" \ No newline at end of file diff --git a/src/entities/Factory/model/slice/factorySlice.ts b/src/entities/Factory/model/slice/factorySlice.ts new file mode 100644 index 0000000..4d2bc23 --- /dev/null +++ b/src/entities/Factory/model/slice/factorySlice.ts @@ -0,0 +1,33 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { fetchFactories } from "entities/Factory/api/fetchFactories"; +import {IFactoryState} from "../../types/types" + +const initialState:IFactoryState = { + list: [], + error: null, + loading: false +} + +export const factorySlice = createSlice({ + name: "factory", + initialState, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(fetchFactories.fulfilled, (state, action) => { + state.list = action.payload + state.loading = false + state.error = null + }) + .addCase(fetchFactories.pending, (state) => { + state.loading = true + state.error = null + }) + .addCase(fetchFactories.rejected, (state, action) => { + state.loading = false + state.error = action.payload + }) + } +}) + +export default factorySlice.reducer \ No newline at end of file diff --git a/src/entities/Factory/types/types.ts b/src/entities/Factory/types/types.ts new file mode 100644 index 0000000..d9364d4 --- /dev/null +++ b/src/entities/Factory/types/types.ts @@ -0,0 +1,13 @@ +export interface IFactory { + id: number, + key: string, + title: string, + enabled?: boolean, + visible?: boolean +} + +export interface IFactoryState { + list: IFactory[], + error: string | null, + loading: boolean, +} diff --git a/src/pages/MainPage/ui/MainPage.tsx b/src/pages/MainPage/ui/MainPage.tsx index 147792b..492f5f8 100644 --- a/src/pages/MainPage/ui/MainPage.tsx +++ b/src/pages/MainPage/ui/MainPage.tsx @@ -8,22 +8,50 @@ import { Select } from 'shared/ui/Select/index'; import cl from './MainPage.module.scss' import LogoutIcon from 'shared/assets/icons/LogoutIcon'; import { ThemeSwitcher } from 'shared/ui/ThemeSwitcher'; +import { useAppSelector } from 'shared/lib/hooks/useAppSelector/useAppSelector'; +import { useAppDispatch } from 'shared/lib/hooks/useAppDispatch/useAppDispatch'; +import {fetchFactories} from "entities/Factory/index" +import { fetchFacilities } from 'entities/Facility'; +import { useEffect, useMemo } from 'react'; +import { ISelectProps } from 'shared/ui/Select/IProps'; const MainPage = () => { const { logout, user } = useLogout(); const { theme } = useTheme(); + const {list, error} = useAppSelector(state => state.factory) + const facility = useAppSelector(state => state.facility) + const dispatch = useAppDispatch() - interface FactoriesProps { - value: string, - label: string, - disabled?: boolean - } - const Factories: FactoriesProps[] = [ - { value: 'portovaya', label: 'Завод по сжижению газа (СПГ Портовая)'}, - { value: 'lucy', label: 'Завод по переработке нефти "Киришинефтеоргсинтез"' }, - { value: 'Yiminghe', label: 'yiminghe' }, - { value: 'disabled', label: 'Disabled', disabled: true }, - ] + const listFactories: ISelectProps['options'] = useMemo( + () => + list + ?.filter((elem) => elem.visible) + ?.map((elem) => ({ + value: elem.id, + label: elem.title, + disabled: !elem.enabled, + })), + [list], + ); + const listFacilities: ISelectProps['options'] = useMemo( + () => + facility.list + ?.filter((elem) => elem.visible) + ?.map((elem) => ({ + value: elem.id, + label: elem.title, + disabled: !elem.enabled, + })), + [facility.list], + ); + + useEffect(() => { + dispatch(fetchFactories()) + }, [dispatch]) + + useEffect(() => { + dispatch(fetchFacilities()) + }, [dispatch]) return (