From 672b965f4d901ac9f1958dc502d414cc5b9d13bf Mon Sep 17 00:00:00 2001 From: yznahmad Date: Sat, 21 Jun 2025 05:30:52 +0300 Subject: [PATCH] Add 30 n123456884 --- webapp/package-lock.json | 32 ++++++++++++++ webapp/package.json | 1 + webapp/src/redux/provider.tsx | 11 ++++- webapp/src/redux/store.ts | 80 +++++++++++++++++++++++------------ webapp/src/redux/types.d.ts | 19 +++++++++ 5 files changed, 114 insertions(+), 29 deletions(-) create mode 100644 webapp/src/redux/types.d.ts diff --git a/webapp/package-lock.json b/webapp/package-lock.json index f8f81ed..7e90efa 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -24,6 +24,7 @@ "@types/bcrypt": "^5.0.0", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", + "@types/redux-persist": "^4.0.0", "apexcharts": "^3.42.0", "autoprefixer": "10.4.14", "axios": "^1.4.0", @@ -1665,6 +1666,27 @@ "@types/react": "*" } }, + "node_modules/@types/redux-persist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/redux-persist/-/redux-persist-4.0.0.tgz", + "integrity": "sha512-VyDn75G7+Xkebp5Lxowk2t7HeT4VLSy92nyoQu1dZxk+ySBBdvV0yVR/upE4z24eVFxMp6Fo3CisQpkl4v1k3w==", + "license": "MIT", + "dependencies": { + "redux": "^3.6.0" + } + }, + "node_modules/@types/redux-persist/node_modules/redux": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", + "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "license": "MIT", + "dependencies": { + "lodash": "^4.2.1", + "lodash-es": "^4.2.1", + "loose-envify": "^1.1.0", + "symbol-observable": "^1.0.3" + } + }, "node_modules/@types/scheduler": { "version": "0.16.3", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", @@ -5919,6 +5941,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz", "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", + "license": "MIT", "peerDependencies": { "redux": ">4.0.0" } @@ -6708,6 +6731,15 @@ "node": ">= 0.8.0" } }, + "node_modules/symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/synckit": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", diff --git a/webapp/package.json b/webapp/package.json index 9d18147..49f7c1b 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -25,6 +25,7 @@ "@types/bcrypt": "^5.0.0", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", + "@types/redux-persist": "^4.0.0", "apexcharts": "^3.42.0", "autoprefixer": "10.4.14", "axios": "^1.4.0", diff --git a/webapp/src/redux/provider.tsx b/webapp/src/redux/provider.tsx index 1474c04..7d2a91f 100644 --- a/webapp/src/redux/provider.tsx +++ b/webapp/src/redux/provider.tsx @@ -7,10 +7,17 @@ */ import React from "react" -import { store } from './store' import { Provider } from "react-redux" +import { PersistGate } from 'redux-persist/integration/react'; +import { store, persistor } from './store'; export function ReduxProvider({children} : {children : React.ReactNode}) { - return {children} + return ( + + + {children} + + + ) } \ No newline at end of file diff --git a/webapp/src/redux/store.ts b/webapp/src/redux/store.ts index b93fd37..0b463b8 100644 --- a/webapp/src/redux/store.ts +++ b/webapp/src/redux/store.ts @@ -3,11 +3,14 @@ * @description Redux store , all the app state goes right here * * source : https://www.youtube.com/watch?v=Yokjzp91A4o */ -import { TypedUseSelectorHook , useSelector } from 'react-redux'; -import { configureStore } from '@reduxjs/toolkit' -import authReducer from './features/auth-slice' -import themeTypeReducer from './features/theme-slice' -import alertReducer from './features/alert-slice' +import { TypedUseSelectorHook, useSelector } from 'react-redux'; +import { configureStore } from '@reduxjs/toolkit'; +import { persistStore, persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from 'redux-persist'; +import storage from 'redux-persist/lib/storage'; +import { combineReducers } from 'redux'; +import authReducer from './features/auth-slice'; +import themeTypeReducer from './features/theme-slice'; +import alertReducer from './features/alert-slice'; import settingsReducer from './features/settings-slice'; import sidebarReducer from './features/sidebar-slice'; import servicesReducer from './features/services-slice'; @@ -19,26 +22,49 @@ import equipmentsReducer from './features/equipments-slice'; import expensesReducer from './features/expenses-slice'; import incomesReducer from './features/incomes-slice'; -// init the store +// Combine all reducers +const rootReducer = combineReducers({ + authReducer, // handle auth states + themeTypeReducer, // handle app theme + alertReducer, // handle app alert + settingsReducer, // handle the app settings + sidebarReducer, // handle dashboard sidebar state + servicesReducer, // handle the services page state + membersReducer, // handle the members page state + workersReducer, // handle the workers page state + productsReducer, // handle the products page state + statisticsReducer, // handle the statistics state + equipmentsReducer, // handle the equipments state + expensesReducer, // handle the expenses state + incomesReducer, // handle the incomes state +}); + +// Persist config +const persistConfig = { + key: 'root', + version: 1, + storage, + whitelist: ['settingsReducer', 'authReducer', 'themeTypeReducer'], // Only persist these reducers +}; + +const persistedReducer = persistReducer(persistConfig, rootReducer); + +// Configure the store export const store = configureStore({ - reducer: { // get state and do some work & update it after that - authReducer, // handle auth states - themeTypeReducer, // handle app theme - alertReducer, // handle app alert - settingsReducer, // handle the app settings - sidebarReducer, // handle dashboard sidebar state - servicesReducer, // handle the services page state - membersReducer, // handle the members page state - workersReducer, // handle the workers page state - productsReducer, // handle the products page state - statisticsReducer, // handle the statistics state - equipmentsReducer, // handle the equipments state - expensesReducer, // handle the expenses state - incomesReducer, // handle the incomes state - } -}) -// export the needed types -export type RootState = ReturnType -export type AppDispatch = typeof store.dispatch -// export the store selector -export const useAppSelector : TypedUseSelectorHook = useSelector \ No newline at end of file + reducer: persistedReducer, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + serializableCheck: { + ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], + }, + }), +}); + +export const persistor = persistStore(store); + +// Export types +export type RootState = ReturnType; +export type AppDispatch = typeof store.dispatch; + +// Export the store selector +export const useAppSelector: TypedUseSelectorHook = useSelector; \ No newline at end of file diff --git a/webapp/src/redux/types.d.ts b/webapp/src/redux/types.d.ts new file mode 100644 index 0000000..6228f5b --- /dev/null +++ b/webapp/src/redux/types.d.ts @@ -0,0 +1,19 @@ +import { RootState, AppDispatch } from './store'; + +declare module 'react-redux' { + interface DefaultRootState extends RootState {} + function useDispatch(): AppDispatch; +} + +declare module 'redux-persist' { + interface PersistState { + version: number; + rehydrated: boolean; + } +} + +declare module 'redux-persist/integration/react' { + import { PersistGateProps } from 'redux-persist/es/integration/react'; + export { PersistGate }; + export const PersistGate: React.ComponentType; +}