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;