diff --git a/backend/index.js b/backend/index.js
index 9d77270..9295906 100644
--- a/backend/index.js
+++ b/backend/index.js
@@ -67,4 +67,4 @@ app.get("/search", async (req, res) => {
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
-});
+});
\ No newline at end of file
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index b9f54b1..d2124d0 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8,12 +8,15 @@
"name": "spring-music-player",
"version": "0.0.0",
"dependencies": {
+ "@reduxjs/toolkit": "^2.2.5",
"axios": "^1.6.8",
"he": "^1.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-h5-audio-player": "^3.9.1",
"react-icons": "^5.2.1",
+ "react-redux": "^9.1.2",
+ "redux-persist": "^6.0.0",
"swiper": "^11.1.3"
},
"devDependencies": {
@@ -1022,6 +1025,29 @@
"node": ">=14"
}
},
+ "node_modules/@reduxjs/toolkit": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.5.tgz",
+ "integrity": "sha512-aeFA/s5NCG7NoJe/MhmwREJxRkDs0ZaSqt0MxhWUrwCf1UQXpwR87RROJEql0uAkLI6U7snBOYOcKw83ew3FPg==",
+ "dependencies": {
+ "immer": "^10.0.3",
+ "redux": "^5.0.1",
+ "redux-thunk": "^3.1.0",
+ "reselect": "^5.1.0"
+ },
+ "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/@rollup/rollup-android-arm-eabi": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz",
@@ -1281,13 +1307,13 @@
"version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
- "dev": true
+ "devOptional": true
},
"node_modules/@types/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.1.tgz",
"integrity": "sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==",
- "dev": true,
+ "devOptional": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
@@ -1302,6 +1328,11 @@
"@types/react": "*"
}
},
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
+ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
+ },
"node_modules/@ungap/structured-clone": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
@@ -1878,7 +1909,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "dev": true
+ "devOptional": true
},
"node_modules/data-view-buffer": {
"version": "1.0.1",
@@ -3015,6 +3046,15 @@
"node": ">= 4"
}
},
+ "node_modules/immer": {
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
+ "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
+ "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",
@@ -4329,6 +4369,28 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true
},
+ "node_modules/react-redux": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",
+ "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==",
+ "dependencies": {
+ "@types/use-sync-external-store": "^0.0.3",
+ "use-sync-external-store": "^1.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^18.2.25",
+ "react": "^18.0",
+ "redux": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-refresh": {
"version": "0.14.2",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
@@ -4359,6 +4421,27 @@
"node": ">=8.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-persist": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz",
+ "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==",
+ "peerDependencies": {
+ "redux": ">4.0.0"
+ }
+ },
+ "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",
@@ -4403,6 +4486,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/resolve": {
"version": "2.0.0-next.5",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
@@ -5202,6 +5290,14 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
+ "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 96bcde6..cea30f1 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -10,12 +10,15 @@
"preview": "vite preview"
},
"dependencies": {
+ "@reduxjs/toolkit": "^2.2.5",
"axios": "^1.6.8",
"he": "^1.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-h5-audio-player": "^3.9.1",
"react-icons": "^5.2.1",
+ "react-redux": "^9.1.2",
+ "redux-persist": "^6.0.0",
"swiper": "^11.1.3"
},
"devDependencies": {
diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx
index 54b39dd..3e0c876 100644
--- a/frontend/src/main.jsx
+++ b/frontend/src/main.jsx
@@ -1,10 +1,20 @@
-import React from 'react'
-import ReactDOM from 'react-dom/client'
-import App from './App.jsx'
-import './index.css'
+import React from "react";
+import ReactDOM from "react-dom/client";
+import App from "./App.jsx";
+import "./index.css";
+import { Provider } from "react-redux";
+import { store } from "./redux/store.js";
+import { PersistGate } from "redux-persist/integration/react";
+import { persistStore } from "redux-persist";
-ReactDOM.createRoot(document.getElementById('root')).render(
-
-
- ,
-)
+const persistor = persistStore(store);
+
+ReactDOM.createRoot(document.getElementById("root")).render(
+
+
+
+
+
+
+
+);
diff --git a/frontend/src/redux/auth-slice.js b/frontend/src/redux/auth-slice.js
new file mode 100644
index 0000000..b1f4a97
--- /dev/null
+++ b/frontend/src/redux/auth-slice.js
@@ -0,0 +1,38 @@
+import { createSlice } from "@reduxjs/toolkit";
+
+const initialState = {
+ value:{
+ username:"",
+ isAuth:false,
+ email:"",
+ }
+}
+
+export const auth = createSlice({
+ name:"auth",
+ initialState,
+ reducers:{
+ logOut:()=>{
+ return initialState
+ },
+ logIn:(state,action)=>{
+ return {
+ value : {
+ isAuth:true,
+ email:action.payload.email
+ }
+ }
+ },
+ setUsername:(state,action) => {
+ return {
+ value : {
+ isAuth:true,
+ username:action.payload.username
+ }
+ }
+ }
+ }
+})
+
+export const {logIn,logOut,setUsername} = auth.actions;
+export default auth.reducer;
\ No newline at end of file
diff --git a/frontend/src/redux/store.js b/frontend/src/redux/store.js
new file mode 100644
index 0000000..ae48d43
--- /dev/null
+++ b/frontend/src/redux/store.js
@@ -0,0 +1,20 @@
+import { configureStore } from "@reduxjs/toolkit";
+import authReducer from "./auth-slice";
+import storage from 'redux-persist/lib/storage';
+import {persistReducer} from "redux-persist"
+import { combineReducers } from "@reduxjs/toolkit";
+
+const persistConfig = {
+ key: 'root',
+ storage
+}
+
+const reducer = combineReducers({
+ auth:authReducer,
+})
+
+const persistedReducer = persistReducer(persistConfig,reducer)
+
+export const store=configureStore({
+ reducer: persistedReducer,
+})
\ No newline at end of file