diff --git a/frontend/app/package-lock.json b/frontend/app/package-lock.json index e8441e0..b92bd66 100644 --- a/frontend/app/package-lock.json +++ b/frontend/app/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "@ant-design/icons": "^5.3.5", + "@reduxjs/toolkit": "^2.2.2", "antd": "^5.15.4", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -400,6 +401,29 @@ "react-dom": ">=16.9.0" } }, + "node_modules/@reduxjs/toolkit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.2.tgz", + "integrity": "sha512-454GZrEx3G6QSYwIx9ROaso1HR6sTH8qyZBe3KEsdWVGU3ayV8jYCwdaEJV3vl9V6+pi3GRl+7Xl7AeDna6qwQ==", + "dependencies": { + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.0.1" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@rsbuild/core": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-0.5.4.tgz", @@ -2364,6 +2388,15 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.4.tgz", + "integrity": "sha512-cuBuGK40P/sk5IzWa9QPUaAdvPHjkk1c+xYsd9oZw+YQQEV+10G0P5uMpGctZZKnyQ+ibRO08bD25nWLmYi2pw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -3979,6 +4012,19 @@ "node": ">=0.10.0" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -4023,6 +4069,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/reselect": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.0.tgz", + "integrity": "sha512-aw7jcGLDpSgNDyWBQLv2cedml85qd95/iszJjN988zX1t7AVRJi19d9kto5+W7oCfQ94gyo40dVbT6g2k4/kXg==" + }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", diff --git a/frontend/app/package.json b/frontend/app/package.json index 7d7b8f4..1a0092f 100644 --- a/frontend/app/package.json +++ b/frontend/app/package.json @@ -9,6 +9,7 @@ }, "dependencies": { "@ant-design/icons": "^5.3.5", + "@reduxjs/toolkit": "^2.2.2", "antd": "^5.15.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/frontend/app/src/App.tsx b/frontend/app/src/App.tsx index 3b1b482..24f06dc 100644 --- a/frontend/app/src/App.tsx +++ b/frontend/app/src/App.tsx @@ -1,15 +1,20 @@ -import { ConfigProvider } from 'antd'; -import './App.css'; -import HeaderComponent from './components/HeaderComponent'; -import { theme } from './config/style'; +import React from "react"; +import { ConfigProvider } from "antd"; +import "./App.css"; +import HeaderComponent from "./components/HeaderComponent"; +import { theme } from "./config/style"; +import { Provider } from "react-redux"; +import { store } from "./config/store"; const App = () => { return ( - -
- -
-
+ + +
+ +
+
+
); }; diff --git a/frontend/app/src/config/baseUrl.ts b/frontend/app/src/config/baseUrl.ts new file mode 100644 index 0000000..331e71a --- /dev/null +++ b/frontend/app/src/config/baseUrl.ts @@ -0,0 +1 @@ +export const baseUrl = "http://localhost/api/" \ No newline at end of file diff --git a/frontend/app/src/config/store.ts b/frontend/app/src/config/store.ts new file mode 100644 index 0000000..44a211b --- /dev/null +++ b/frontend/app/src/config/store.ts @@ -0,0 +1,18 @@ +import { configureStore } from '@reduxjs/toolkit' +import { setupListeners } from '@reduxjs/toolkit/query' +import { AuthApi } from '../slice/AuthApi' + +export const store = configureStore({ + reducer: { + // Add the generated reducer as a specific top-level slice + [AuthApi.reducerPath]: AuthApi.reducer, + }, + // Adding the api middleware enables caching, invalidation, polling, + // and other useful features of `rtk-query`. + middleware: (getDefaultMiddleware) => + getDefaultMiddleware().concat(AuthApi.middleware), +}) + +// optional, but required for refetchOnFocus/refetchOnReconnect behaviors +// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization +setupListeners(store.dispatch) \ No newline at end of file diff --git a/frontend/app/src/slice/AuthApi.ts b/frontend/app/src/slice/AuthApi.ts new file mode 100644 index 0000000..cb9d6d7 --- /dev/null +++ b/frontend/app/src/slice/AuthApi.ts @@ -0,0 +1,14 @@ +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' +import { baseUrl } from '../config/baseUrl' + +export const AuthApi = createApi({ + reducerPath: 'AuthApi', + baseQuery: fetchBaseQuery({ baseUrl: `${baseUrl}auth/` }), + endpoints: (builder) => ({ + getUser: builder.query({ + query: () => 'me/', + }), + }), +}) + +export const { useGetUserQuery } = AuthApi \ No newline at end of file diff --git a/frontend/app/src/slice/UserApi.ts b/frontend/app/src/slice/UserApi.ts deleted file mode 100644 index e69de29..0000000