diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e628808..dcde421 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -27,7 +27,7 @@ jobs:
- name: Yarn Install
run: |
cd ./frontend
- yarn install
+ yarn install --frozen-lockfile
- name: Yarn Test
run: |
cd ./frontend
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index f56e067..572bd6a 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,7 +1,7 @@
import * as React from "react";
import "./App.css";
import {Faro} from "@grafana/faro-web-sdk";
-import {createBrowserRouter, redirect, RouterProvider} from "react-router-dom";
+import {createBrowserRouter, Outlet, redirect, RouterProvider} from "react-router-dom";
import CreateCharacter from "./first-edition/pages/CreateCharacter";
import CharacterList from "./shared/pages/CharacterList";
import ErrorBoundary from "./shared/ErrorBoundary";
@@ -14,11 +14,28 @@ import { useSelector, useDispatch } from 'react-redux'
import {load, setUser, unsetUser, userSelector} from './shared/domain-models/userSlice'
import {setCharacter} from "./second-edition/domain-models/characterSlice";
+function RootLayout() {
+ return (
+ <>
+
+
+
+
+
+ >
+ )
+}
+
function Router(props: {faro?: Faro}) {
const dispatch = useDispatch.withTypes()()
const fetchedUser = useSelector.withTypes()(userSelector)
- if (fetchedUser.state === "not-started") {
+ React.useEffect(() => {
+ if (fetchedUser.state !== "not-started") {
+ return;
+ }
+
+ let isCancelled = false;
dispatch(load())
fetch(`${window.location.origin}/api/User/me`)
.then(response => {
@@ -28,88 +45,97 @@ function Router(props: {faro?: Faro}) {
console.log(response)
})
.then(userNameResponse => {
+ if (isCancelled) {
+ return;
+ }
+
if (userNameResponse && userNameResponse.length > 0) {
dispatch(setUser(userNameResponse))
} else {
dispatch(unsetUser())
}
-
})
.catch(() => {
+ if (isCancelled) {
+ return;
+ }
+
dispatch(unsetUser())
})
- }
+ return () => {
+ isCancelled = true;
+ }
+ }, [dispatch, fetchedUser.state])
-
- const router = createBrowserRouter([
+ const router = React.useMemo(() => createBrowserRouter([
{
path: "/",
- loader: () => fetchedUser.email == null ? redirect("/2e/karakter") : redirect("/karaktereim")
+ element: ,
+ children: [
+ {
+ index: true,
+ loader: () => fetchedUser.email == null ? redirect("/2e/karakter") : redirect("/karaktereim")
+ },
+ {
+ path: "karaktereim",
+ element: ,
+ loader: () => fetch(`${window.location.origin}/api/Character`),
+ ErrorBoundary: ErrorBoundary,
+ },
+ {
+ path: "1e",
+ loader: () => redirect("/1e/karakter")
+ },
+ {
+ path: "1e/karakter",
+ element: ,
+ ErrorBoundary: ErrorBoundary,
+ },
+ {
+ path: "1e/karakter/:id",
+ element: ,
+ loader: args => fetch(`${window.location.origin}/api/Character1E/${args.params.id}`),
+ ErrorBoundary: ErrorBoundary,
+ },
+ {
+ path: "2e",
+ loader: () => redirect("/2e/karakter")
+ },
+ {
+ path: "2e/karakter",
+ element: ,
+ ErrorBoundary: ErrorBoundary,
+ },
+ {
+ path: "2e/karakter/:id",
+ element: ,
+ loader: async args => {
+ const response = await fetch(`${window.location.origin}/api/Character2E/${args.params.id}`)
+ if (response.ok) {
+ const loaded2Echaracter = await response.json()
+ dispatch(setCharacter(loaded2Echaracter))
+ return loaded2Echaracter;
+ }
+ return {
+ isPublic: false,
+ error: response.statusText,
+ };
+ },
+ ErrorBoundary: ErrorBoundary,
+ },
+ ],
},
- {
- path: "/karaktereim",
- element: ,
- loader: () => fetch(`${window.location.origin}/api/Character`),
- ErrorBoundary: ErrorBoundary,
- },
- {
- path: "/1e",
- loader: () => redirect("/1e/karakter")
- },
- {
- path: "/1e/karakter",
- element: ,
- ErrorBoundary: ErrorBoundary,
- },
- {
- path: "/1e/karakter/:id",
- element: ,
- loader: args => fetch(`${window.location.origin}/api/Character1E/${args.params.id}`),
- ErrorBoundary: ErrorBoundary,
- },
- {
- path: "/2e",
- loader: () => redirect("/2e/karakter")
- },
- {
- path: "/2e/karakter",
- element: ,
- ErrorBoundary: ErrorBoundary,
- },
- {
- path: "/2e/karakter/:id",
- element: ,
- loader: async args => {
- const response = await fetch(`${window.location.origin}/api/Character2E/${args.params.id}`)
- if (response.ok) {
- const loaded2Echaracter = await response.json()
- dispatch(setCharacter(loaded2Echaracter))
- return loaded2Echaracter;
- }
- return {
- isPublic: false,
- error: response.statusText,
- };
- },
- ErrorBoundary: ErrorBoundary,
- },
- ]);
+ ]), [dispatch, fetchedUser.email, props.faro]);
- return (
-
-
-
- )
+ return
}
function App(props: { faro?: Faro }) {
return (
-
-
);
}
diff --git a/frontend/src/first-edition/pages/CreateCharacter.tsx b/frontend/src/first-edition/pages/CreateCharacter.tsx
index c6f5319..acbd103 100644
--- a/frontend/src/first-edition/pages/CreateCharacter.tsx
+++ b/frontend/src/first-edition/pages/CreateCharacter.tsx
@@ -1,4 +1,4 @@
-import React, {useState} from 'react';
+import React, {useCallback, useEffect, useMemo, useState} from 'react';
import './CreateCharacter.less'
import {Faj, TulajdonsagokFajjal} from "../domain-models/faj";
import {Osztaly, SetFelszerelesForChangedOsztaly} from "../domain-models/osztaly"
@@ -56,15 +56,43 @@ function CreateCharacterPage(props: {
let [karakter, changeKarakter] = useState(initialKarakterInputs)
- const tulajdonsagokFajjal = TulajdonsagokFajjal(karakter.tulajdonsagok, karakter.faj)
+ const tulajdonsagokFajjal = useMemo(() => TulajdonsagokFajjal(karakter.tulajdonsagok, karakter.faj), [karakter.tulajdonsagok, karakter.faj])
- const changeKepzettseg = (k: KepzettsegId[]) => changeKarakter({...karakter, kepzettsegek: k})
- const changeTolvajKepzettseg = (tk?: KepzettsegId[]) => changeKarakter({...karakter, tolvajKepzettsegek: tk})
- SetDefaultTolvajKepzettsegek(karakter, changeTolvajKepzettseg)
- SetDefaultKepzettsegek({...karakter, tulajdonsagok: tulajdonsagokFajjal}, changeKepzettseg)
- const availableKepzettsegList = AvailableKezpettsegList(karakter.osztaly)
- const setFelszereles = (f: KarakterFelszereles) => changeKarakter({...karakter, felszereles: f})
- SetFelszerelesForChangedOsztaly(karakter.osztaly, karakter.felszereles, setFelszereles)
+ const changeKepzettseg = useCallback((k: KepzettsegId[]) => {
+ changeKarakter(prev => ({...prev, kepzettsegek: k}))
+ }, [])
+ const changeTolvajKepzettseg = useCallback((tk?: KepzettsegId[]) => {
+ changeKarakter(prev => ({...prev, tolvajKepzettsegek: tk}))
+ }, [])
+ const availableKepzettsegList = useMemo(() => AvailableKezpettsegList(karakter.osztaly), [karakter.osztaly])
+ const setFelszereles = useCallback((f: KarakterFelszereles) => {
+ changeKarakter(prev => ({...prev, felszereles: f}))
+ }, [])
+
+ const tolvajDefaultsInput = useMemo(() => ({
+ osztaly: karakter.osztaly,
+ tolvajKepzettsegek: karakter.tolvajKepzettsegek,
+ }), [karakter.osztaly, karakter.tolvajKepzettsegek])
+
+ const kepzettsegDefaultsInput = useMemo(() => ({
+ osztaly: karakter.osztaly,
+ faj: karakter.faj,
+ tulajdonsagok: tulajdonsagokFajjal,
+ kepzettsegek: karakter.kepzettsegek,
+ tolvajKepzettsegek: karakter.tolvajKepzettsegek,
+ }), [karakter.osztaly, karakter.faj, tulajdonsagokFajjal, karakter.kepzettsegek, karakter.tolvajKepzettsegek])
+
+ useEffect(() => {
+ SetDefaultTolvajKepzettsegek(tolvajDefaultsInput, changeTolvajKepzettseg)
+ }, [tolvajDefaultsInput, changeTolvajKepzettseg])
+
+ useEffect(() => {
+ SetDefaultKepzettsegek(kepzettsegDefaultsInput, changeKepzettseg)
+ }, [kepzettsegDefaultsInput, changeKepzettseg])
+
+ useEffect(() => {
+ SetFelszerelesForChangedOsztaly(karakter.osztaly, karakter.felszereles, setFelszereles)
+ }, [karakter.osztaly, karakter.felszereles, setFelszereles])
const levelUp = () => LevelUp(karakter, changeKarakter)
const levelDown = () => LevelDown(karakter, changeKarakter)
diff --git a/frontend/src/shared/Header.tsx b/frontend/src/shared/Header.tsx
index bf9e5d3..11185a4 100644
--- a/frontend/src/shared/Header.tsx
+++ b/frontend/src/shared/Header.tsx
@@ -1,24 +1,28 @@
import * as React from "react";
import axios from "axios";
import {Container, Nav, Navbar} from "react-bootstrap";
-import {userSelector} from "./domain-models/userSlice";
-import {RootState} from "../store";
-import {useSelector} from "react-redux";
-
-async function logout() {
- await axios.post("/Identity/Account/Logout")
- document.location.reload()
-}
+import {unsetUser, userSelector} from "./domain-models/userSlice";
+import {AppDispatch, RootState} from "../store";
+import {useDispatch, useSelector} from "react-redux";
+import {Link, useNavigate} from "react-router-dom";
function Header() {
+ const dispatch = useDispatch.withTypes()();
+ const navigate = useNavigate();
const fetchedUser = useSelector.withTypes()(userSelector);
+
+ const logout = async () => {
+ await axios.post("/Identity/Account/Logout")
+ dispatch(unsetUser())
+ navigate("/")
+ }
return
- Kemkas
- {fetchedUser.email != null && Karaktereim}
+ Kemkas
+ {fetchedUser.email != null && Karaktereim}