diff --git a/src/App.tsx b/src/App.tsx
index 13633cc..79534b3 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,4 +1,4 @@
-import { BrowserRouter, Route, Routes } from "react-router-dom"
+import { BrowserRouter, Outlet, Route, Routes } from "react-router-dom"
import loadable from "@loadable/component"
import { Header } from "./pages/template/Header.tsx"
@@ -13,29 +13,41 @@ const TeamPanelPage = loadable(() => import("./pages/TeamPanel.tsx"))
const NewTacticPage = loadable(() => import("./pages/NewTacticPage.tsx"))
const Editor = loadable(() => import("./pages/Editor.tsx"))
+import './style/app.css'
export default function App() {
-
-
return (
-
+
-
+
- } />
+
} />
} />
- } />
- } />
- } />
- } />
- } />
- } />
+ }>
+ } />
+
+ } />
+ } />
+ } />
+ } />
+ } />
+
+ } />
+
+
)
+}
+
+function AppLayout() {
+ return <>
+
+
+ >
}
\ No newline at end of file
diff --git a/src/Fetcher.ts b/src/Fetcher.ts
index dd2b2b8..b496894 100644
--- a/src/Fetcher.ts
+++ b/src/Fetcher.ts
@@ -1,18 +1,18 @@
import { API, BASE } from "./Constants"
-import { Session } from "./api/session.ts"
+import { getSession, saveSession, Session } from "./api/session.ts"
export function redirect(url: string) {
location.pathname = BASE + url
}
-export function fetchAPI(
+export async function fetchAPI(
url: string,
payload: unknown,
method = "POST",
- session?: Session,
): Promise
{
+ const session = getSession()
const token = session?.auth?.token
const headers = {
@@ -24,19 +24,21 @@ export function fetchAPI(
headers.Authorization = token
}
- return fetch(`${API}/${url}`, {
+ const response = await fetch(`${API}/${url}`, {
method,
headers,
body: JSON.stringify(payload),
})
+
+ return await handleResponse(session, response)
}
-export function fetchAPIGet(
+export async function fetchAPIGet(
url: string,
- session?: Session,
): Promise {
+ const session = getSession()
const token = session?.auth?.token
const headers = {
@@ -48,10 +50,25 @@ export function fetchAPIGet(
headers.Authorization = token
}
- return fetch(`${API}/${url}`, {
+ const response = await fetch(`${API}/${url}`, {
method: "GET",
headers,
})
+
+ return await handleResponse(session, response)
}
+async function handleResponse(session: Session, response: Response): Promise {
+ // if we provided a token but still unauthorized, the token has expired
+ if (response.status == 401) {
+ redirect("/login")
+ saveSession({...session, urlTarget: location.pathname})
+ return response
+ }
+ const nextToken = response.headers.get("Next-Authorization")!
+ const expirationDate = Date.parse(response.headers.get("Next-Authorization-Expiration-Date")!)
+ saveSession({...session, auth: {token: nextToken, expirationDate}})
+
+ return response
+}
diff --git a/src/api/session.ts b/src/api/session.ts
index 506364c..7e32776 100644
--- a/src/api/session.ts
+++ b/src/api/session.ts
@@ -1,12 +1,11 @@
-import { createContext } from "react"
-
export interface Session {
auth?: Authentication
+ urlTarget?: string
}
export interface Authentication {
token: string
- expirationDate: Date
+ expirationDate: number
}
const SESSION_KEY = "session"
diff --git a/src/pages/Editor.tsx b/src/pages/Editor.tsx
index 288194c..c8da3fd 100644
--- a/src/pages/Editor.tsx
+++ b/src/pages/Editor.tsx
@@ -49,6 +49,7 @@ import { Action, ActionKind } from "../model/tactic/Action"
import BallAction from "../components/actions/BallAction"
import { changePlayerBallState, getOrigin, removePlayer } from "../editor/PlayerDomains"
import { CourtBall } from "../components/editor/CourtBall"
+import { getSession } from "../api/session.ts"
const ERROR_STYLE: CSSProperties = {
borderColor: "red",
@@ -56,6 +57,7 @@ const ERROR_STYLE: CSSProperties = {
const GUEST_MODE_CONTENT_STORAGE_KEY = "guest_mode_content"
const GUEST_MODE_TITLE_STORAGE_KEY = "guest_mode_title"
+const DEFAULT_TACTIC_NAME = "Nouvelle tactique"
export interface EditorViewProps {
tactic: Tactic
@@ -70,12 +72,29 @@ export interface EditorPageProps {
}
export default function EditorPage({ courtType }: EditorPageProps) {
- return
+
+ const [id, setId] = useState()
+
+ useEffect(() => {
+ async function initialize() {
+ const response = await fetchAPI("tactics", { name: DEFAULT_TACTIC_NAME }, "POST", getSession())
+ const { id } = await response.json()
+ setId(id)
+ }
+
+ initialize()
+ }, [])
+
+ if (id) {
+ return
+ }
+
+ return Loading Editor, please wait...
}
export interface EditorProps {
@@ -111,7 +130,7 @@ function Editor({ id, name, courtType, content }: EditorProps) {
)
return SaveStates.Guest
}
- return fetchAPI(`tactic/${id}/save`, { content }).then((r) =>
+ return fetchAPI(`tactics/${id}/1`, { content }, "PUT", getSession()).then((r) =>
r.ok ? SaveStates.Ok : SaveStates.Err,
)
}}
@@ -120,7 +139,7 @@ function Editor({ id, name, courtType, content }: EditorProps) {
localStorage.setItem(GUEST_MODE_TITLE_STORAGE_KEY, name)
return true //simulate that the name has been changed
}
- return fetchAPI(`tactic/${id}/edit/name`, { name }).then(
+ return fetchAPI(`tactics/${id}/name`, { name }, "PUT", getSession()).then(
(r) => r.ok,
)
}}
diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx
index ce26803..d7249a8 100644
--- a/src/pages/HomePage.tsx
+++ b/src/pages/HomePage.tsx
@@ -10,7 +10,7 @@ import { User } from "../model/User.ts"
interface Tactic {
id: number
name: string
- creationDate: Date
+ creationDate: number
}
interface Team {
@@ -37,7 +37,7 @@ export default function HomePage() {
}
async function getUser() {
- const response = await fetchAPIGet("user-data", session)
+ const response = await fetchAPIGet("user-data")
setInfo(await response.json())
}
@@ -45,7 +45,7 @@ export default function HomePage() {
}, [])
- const lastTactics = tactics!.sort((a, b) => a.creationDate.getMilliseconds() - b.creationDate.getMilliseconds()).slice(0, 5)
+ const lastTactics = tactics!.sort((a, b) => a.creationDate - b.creationDate).slice(0, 5)
return
}
diff --git a/src/pages/LoginPage.tsx b/src/pages/LoginPage.tsx
index 43a3a28..231b75b 100644
--- a/src/pages/LoginPage.tsx
+++ b/src/pages/LoginPage.tsx
@@ -2,7 +2,7 @@ import { FormEvent, useRef, useState } from "react"
import { BASE } from "../Constants.ts"
import { fetchAPI, redirect } from "../Fetcher.ts"
import { Failure } from "../api/failure.ts"
-import { saveSession } from "../api/session.ts"
+import { getSession, saveSession } from "../api/session.ts"
import "../style/form.css"
export default function LoginApp() {
@@ -22,9 +22,10 @@ export default function LoginApp() {
const response = await fetchAPI("auth/token", {email, password})
if (response.ok) {
+ const session = getSession()
const { token, expirationDate } = await response.json()
- saveSession({ auth: { token, expirationDate } })
- redirect("/")
+ saveSession({...session, auth: { token, expirationDate } })
+ redirect(session.urlTarget ?? "/")
return
}
diff --git a/src/pages/RegisterPage.tsx b/src/pages/RegisterPage.tsx
index 6cb76a2..f3eeebb 100644
--- a/src/pages/RegisterPage.tsx
+++ b/src/pages/RegisterPage.tsx
@@ -4,7 +4,7 @@ import { BASE } from "../Constants.ts"
import "../style/form.css"
import { Failure } from "../api/failure.ts"
import { fetchAPI, redirect } from "../Fetcher.ts"
-import { saveSession } from "../api/session.ts"
+import { getSession, saveSession } from "../api/session.ts"
export default function RegisterPage() {
@@ -36,8 +36,9 @@ export default function RegisterPage() {
if (response.ok) {
const { token, expirationDate } = await response.json()
- saveSession({ auth: { token, expirationDate } })
- redirect("/")
+ const session = getSession()
+ saveSession({...session, auth: { token, expirationDate } })
+ redirect(session.urlTarget ?? "/")
return
}
diff --git a/src/pages/template/Header.tsx b/src/pages/template/Header.tsx
index 38ca4f4..0ea4a67 100644
--- a/src/pages/template/Header.tsx
+++ b/src/pages/template/Header.tsx
@@ -3,20 +3,15 @@ import accountSvg from "../../assets/account.svg"
import "../../style/template/header.css"
import { useEffect, useState } from "react"
import { fetchAPIGet } from "../../Fetcher.ts"
-import { getSession } from "../../api/session.ts"
-/**
- *
- * @param param0 username
- * @returns Header
- */
+
export function Header() {
const [username, setUsername] = useState("")
useEffect(() => {
async function getUsername() {
- const response = await fetchAPIGet("user", getSession())
+ const response = await fetchAPIGet("user")
//TODO check if the response is ok and handle errors
const {name} = await response.json()
setUsername(name)
diff --git a/src/style/app.css b/src/style/app.css
new file mode 100644
index 0000000..09e66b9
--- /dev/null
+++ b/src/style/app.css
@@ -0,0 +1,6 @@
+#app {
+ height: 100vh;
+ width: 100vw;
+ display: flex;
+ flex-direction: column;
+}
\ No newline at end of file
diff --git a/src/style/home/home.css b/src/style/home/home.css
index bc1bf4a..3af258a 100644
--- a/src/style/home/home.css
+++ b/src/style/home/home.css
@@ -5,7 +5,6 @@
body {
/* background-color: #303030; */
- overflow-x: hidden;
}
#main {
diff --git a/src/style/template/header.css b/src/style/template/header.css
index e0fb2c5..78d1289 100644
--- a/src/style/template/header.css
+++ b/src/style/template/header.css
@@ -2,6 +2,7 @@
text-align: center;
background-color: var(--home-main-color);
margin: 0;
+
display: flex;
flex-direction: row;
align-items: center;
@@ -9,6 +10,7 @@
font-family: var(--font-title);
+
height: 50px;
}