From 8738153c40ba670c42824f0b8d38fac77d148360 Mon Sep 17 00:00:00 2001 From: dragoni7 Date: Wed, 10 Jul 2024 15:52:25 -0700 Subject: [PATCH] Added redux. Began set up redux infrastructure --- package-lock.json | 142 ++++++++++++++++++++++- package.json | 5 +- src/app/App.tsx | 19 +-- src/app/routes/Dashboard.tsx | 4 +- src/app/routes/Landing.tsx | 106 ++++++++++------- src/features/membership/BungieAccount.ts | 40 +++---- src/features/profile/Actions.ts | 0 src/features/profile/Reducer.ts | 0 src/main.tsx | 15 +-- src/redux/MembershipReducer.tsx | 21 ++++ src/redux/index.ts | 11 ++ 11 files changed, 275 insertions(+), 88 deletions(-) delete mode 100644 src/features/profile/Actions.ts delete mode 100644 src/features/profile/Reducer.ts create mode 100644 src/redux/MembershipReducer.tsx create mode 100644 src/redux/index.ts diff --git a/package-lock.json b/package-lock.json index 6e6a490..556eb0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,11 +12,14 @@ "@emotion/styled": "^11.11.5", "@mui/material": "^5.15.20", "@mui/system": "^5.15.20", + "@reduxjs/toolkit": "^2.2.6", "@tanstack/react-table": "^8.17.3", "axios": "^1.7.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^6.23.1" + "react-redux": "^9.1.2", + "react-router-dom": "^6.23.1", + "redux": "^5.0.1" }, "devDependencies": { "@types/node": "^20.14.8", @@ -1327,6 +1330,29 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@reduxjs/toolkit": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.6.tgz", + "integrity": "sha512-kH0r495c5z1t0g796eDQAkYbEQ3a1OLYN9o8jQQVZyKyw367pfRGS+qZLkHYvFHiUUdafpoSlQ2QYObIApjPWA==", + "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/@remix-run/router": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz", @@ -1666,6 +1692,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", @@ -3205,6 +3236,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", @@ -4206,6 +4246,28 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, + "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", @@ -4260,6 +4322,19 @@ "react-dom": ">=16.6.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", @@ -4304,6 +4379,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -4862,6 +4942,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/vite": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz", @@ -5843,6 +5931,17 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, + "@reduxjs/toolkit": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.6.tgz", + "integrity": "sha512-kH0r495c5z1t0g796eDQAkYbEQ3a1OLYN9o8jQQVZyKyw367pfRGS+qZLkHYvFHiUUdafpoSlQ2QYObIApjPWA==", + "requires": { + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + } + }, "@remix-run/router": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz", @@ -6065,6 +6164,11 @@ "@types/react": "*" } }, + "@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==" + }, "@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -7185,6 +7289,11 @@ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true }, + "immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==" + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -7871,6 +7980,15 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, + "react-redux": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", + "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==", + "requires": { + "@types/use-sync-external-store": "^0.0.3", + "use-sync-external-store": "^1.0.0" + } + }, "react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", @@ -7905,6 +8023,17 @@ "prop-types": "^15.6.2" } }, + "redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" + }, + "redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "requires": {} + }, "reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -7937,6 +8066,11 @@ "set-function-name": "^2.0.1" } }, + "reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" + }, "resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -8311,6 +8445,12 @@ "punycode": "^2.1.0" } }, + "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==", + "requires": {} + }, "vite": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz", diff --git a/package.json b/package.json index a32c5f2..b8d8890 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,14 @@ "@emotion/styled": "^11.11.5", "@mui/material": "^5.15.20", "@mui/system": "^5.15.20", + "@reduxjs/toolkit": "^2.2.6", "@tanstack/react-table": "^8.17.3", "axios": "^1.7.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^6.23.1" + "react-redux": "^9.1.2", + "react-router-dom": "^6.23.1", + "redux": "^5.0.1" }, "devDependencies": { "@types/node": "^20.14.8", diff --git a/src/app/App.tsx b/src/app/App.tsx index 1e1dd73..e75742c 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -1,18 +1,21 @@ -import { RouterProvider } from "react-router-dom" -import { useMemo } from "react" +import { RouterProvider } from "react-router-dom"; +import { useMemo } from "react"; import { createRouter } from "./routes"; +import { Provider } from "react-redux"; +import { store } from "../redux"; const AppRouter = () => { - const router = useMemo(() => createRouter(), []) + const router = useMemo(() => createRouter(), []); - return -} + return ; +}; function App() { return ( - - ) + + + + ); } export default App; - diff --git a/src/app/routes/Dashboard.tsx b/src/app/routes/Dashboard.tsx index e469ab3..d4ca586 100644 --- a/src/app/routes/Dashboard.tsx +++ b/src/app/routes/Dashboard.tsx @@ -58,8 +58,8 @@ const RightPane = styled("div")({ export const Dashboard = () => { useEffect(() => { - getCurrentMembershipData(); - getProfile(localStorage.getItem("primaryMembershipId") as string); + //getCurrentMembershipData(); + //getProfile(localStorage.getItem("primaryMembershipId") as string); }, []); return ( diff --git a/src/app/routes/Landing.tsx b/src/app/routes/Landing.tsx index a57c10b..5639c8c 100644 --- a/src/app/routes/Landing.tsx +++ b/src/app/routes/Landing.tsx @@ -1,51 +1,67 @@ -import { useNavigate } from 'react-router' +import { useNavigate } from "react-router"; -import React, { useEffect} from "react" -import BungieLogin from '../../features/auth/BungieLogin' -import { regenerateTokens } from '../../lib/bungie_api/TokenService' -import { isAuthenticated } from '../../lib/bungie_api/AuthService' -import { Container, Grid, Paper } from '@mui/material' +import React, { useEffect, useState } from "react"; +import BungieLogin from "../../features/auth/BungieLogin"; +import { regenerateTokens } from "../../lib/bungie_api/TokenService"; +import { isAuthenticated } from "../../lib/bungie_api/AuthService"; +import { Container, Grid, Paper } from "@mui/material"; +import { useDispatch } from "react-redux"; +import { updateMembershipId } from "../../redux/MembershipReducer"; +import { getCurrentMembershipData } from "../../features/membership/BungieAccount"; export const LandingRoute = () => { + const navigate = useNavigate(); + const dispatch = useDispatch(); - const navigate = useNavigate() - - useEffect( () => { + useEffect(() => { + setTimeout(async () => { + if (isAuthenticated()) { + console.log("Already authenticated"); + var destinyMembershipId = await getCurrentMembershipData(); + console.log(destinyMembershipId); + dispatch(updateMembershipId(destinyMembershipId)); - setTimeout(()=>{ - if (isAuthenticated()) { - console.log("Already authenticated") - navigate('/app') - } - else if (regenerateTokens()) { - console.log("Tokens regenerated and authenticated") - navigate('/app') - } - else { - console.log("Not authenticated") - } - }, 300) - }, []) + navigate("/app"); + } else if (regenerateTokens()) { + console.log("Tokens regenerated and authenticated"); + var destinyMembershipId = await getCurrentMembershipData(); + console.log(destinyMembershipId); + dispatch(updateMembershipId(destinyMembershipId)); + navigate("/app"); + } else { + console.log("Not authenticated"); + } + }, 300); + }, []); - return ( - - - - - -

- D2Loadouts -

-
- - D2Loadouts requires permission to read your Destiny 2 information - - - - -
-
-
-
- ) -} + return ( + + + + + +

D2Loadouts

+
+ + D2Loadouts requires permission to read your Destiny 2 information + + + + +
+
+
+
+ ); +}; diff --git a/src/features/membership/BungieAccount.ts b/src/features/membership/BungieAccount.ts index e4d75e8..bd3aaec 100644 --- a/src/features/membership/BungieAccount.ts +++ b/src/features/membership/BungieAccount.ts @@ -1,30 +1,26 @@ import { _get } from "../../lib/bungie_api/BungieApiClient"; import { getMembershipId, getTokens } from "../../lib/bungie_api/TokensStore"; -export function getCurrentMembershipData() { +export async function getCurrentMembershipData(): Promise { + const membershipId = getMembershipId(); + const accessToken = getTokens()?.accessToken.value; - const membershipId = getMembershipId() - const accessToken = getTokens()?.accessToken + const response = await _get( + `/Platform/User/GetMembershipsById/${membershipId}/1/`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + } + ); - _get(`/Platform/User/GetMembershipsById/${membershipId}/1/`, { - headers: { - 'Authorization': `Bearer ${accessToken}}` - } - }) - .then(response => { - if (response.data.Response) { + if (response.data.Response) { + const primaryMembershipId = response.data.Response.primaryMembershipId; - const primaryMembershipId = response.data.Response.primaryMembershipId - const displayName = response.data.Response.bungieNetUser.displayName + return primaryMembershipId; + } else { + console.log("Could not get response"); + } - localStorage.setItem("primaryMembershipId", JSON.stringify(primaryMembershipId)) - - return true - } - else { - console.log("Could not get response") - return false - } - }) + return ""; } - diff --git a/src/features/profile/Actions.ts b/src/features/profile/Actions.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/features/profile/Reducer.ts b/src/features/profile/Reducer.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/main.tsx b/src/main.tsx index 68a8c15..cf9b43d 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,11 +1,8 @@ -import React from 'react' -import { createRoot } from 'react-dom/client' -import App from './app/App' -import './index.css' +import { createRoot } from "react-dom/client"; +import App from "./app/App"; +import "./index.css"; -const root = document.getElementById('root') -if (!root) throw new Error('no root element found') +const root = document.getElementById("root"); +if (!root) throw new Error("no root element found"); -createRoot(root).render( - -) +createRoot(root).render(); diff --git a/src/redux/MembershipReducer.tsx b/src/redux/MembershipReducer.tsx new file mode 100644 index 0000000..f9e5b03 --- /dev/null +++ b/src/redux/MembershipReducer.tsx @@ -0,0 +1,21 @@ +import { createSlice, PayloadAction } from "@reduxjs/toolkit"; + +export interface InitialState { + membershipId: string; +} +const initialState: InitialState = { + membershipId: "", +}; + +export const membershipSlice = createSlice({ + name: "membership", + initialState, + reducers: { + updateMembershipId: (state, action: PayloadAction) => { + state.membershipId = action.payload; + }, + }, +}); + +export const { updateMembershipId } = membershipSlice.actions; +export default membershipSlice.reducer; diff --git a/src/redux/index.ts b/src/redux/index.ts new file mode 100644 index 0000000..75926bc --- /dev/null +++ b/src/redux/index.ts @@ -0,0 +1,11 @@ +import MembershipReducer from "./MembershipReducer"; +import { configureStore } from "@reduxjs/toolkit"; + +export const store = configureStore({ + reducer: { + membership: MembershipReducer, + }, +}); + +export type RootState = ReturnType; +export type AppDispatch = typeof store.dispatch;