fix tactic edition, bring back guest mode

pull/116/head
maxime 1 year ago committed by maxime.batista
parent de698a58f5
commit 0312cb3645

@ -28,13 +28,13 @@ export default function App() {
<Route path={"/"} element={<AppLayout />}>
<Route path={"/"} element={<HomePage />} />
<Route path={"/home"} element={<HomePage />} />
<Route path={"/team/new"} element={<CreateTeamPage />} />
<Route path={"/team/:teamId"} element={<TeamPanelPage />} />
<Route path={"/tactic/new"} element={<NewTacticPage />} />
<Route path={"/tactic/new/plain"} element={<Editor action={{type: "new", courtType: "PLAIN"}}/>} />
<Route path={"/tactic/new/half"} element={<Editor action={{type: "new", courtType: "HALF"}} />} />
<Route path={"/tactic/:tacticId/edit"} element={<Editor action={{type: "open" }}/>}/>
<Route path={"/tactic/:tacticId/edit"} element={<Editor guestMode={false} />} />
<Route path={"/tactic/edit-guest"} element={<Editor guestMode={true} />} />
<Route path={"*"} element={<NotFoundPage />} />
</Route>

@ -10,6 +10,7 @@ export async function fetchAPI(
url: string,
payload: unknown,
method = "POST",
redirectIfNotAuth: boolean = true,
): Promise<Response> {
const session = getSession()
@ -30,12 +31,13 @@ export async function fetchAPI(
body: JSON.stringify(payload),
})
return await handleResponse(session, response)
return await handleResponse(session, response, redirectIfNotAuth)
}
export async function fetchAPIGet(
url: string,
redirectIfNotAuth: boolean = true,
): Promise<Response> {
const session = getSession()
@ -55,12 +57,14 @@ export async function fetchAPIGet(
headers,
})
return await handleResponse(session, response)
return await handleResponse(session, response, redirectIfNotAuth)
}
async function handleResponse(session: Session, response: Response): Promise<Response> {
async function handleResponse(session: Session, response: Response, redirectIfNotAuth: boolean): Promise<Response> {
// if we provided a token but still unauthorized, the token has expired
if (response.status == 401) {
if (!redirectIfNotAuth)
return response
redirect("/login")
saveSession({ ...session, urlTarget: location.pathname })
return response

@ -1,6 +1,7 @@
export interface Session {
auth?: Authentication
urlTarget?: string
username?: string
}
export interface Authentication {

@ -50,6 +50,7 @@ import BallAction from "../components/actions/BallAction"
import { changePlayerBallState, getOrigin, removePlayer } from "../editor/PlayerDomains"
import { CourtBall } from "../components/editor/CourtBall"
import { useParams } from "react-router-dom"
import { DEFAULT_TACTIC_NAME } from "./NewTacticPage.tsx"
const ERROR_STYLE: CSSProperties = {
borderColor: "red",
@ -57,31 +58,12 @@ 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
onContentChange: (tactic: TacticContent) => Promise<SaveState>
onNameChange: (name: string) => Promise<boolean>
}
type EditorCreateNewAction = { type: "new", courtType: CourtType }
type EditorOpenAction = { type: "open" }
type EditorAction = EditorCreateNewAction | EditorOpenAction
export interface EditorPageProps {
action: EditorAction
}
export default function EditorPage({ action }: EditorPageProps) {
console.log(action)
if (action.type === "new") {
return <EditorCreateNew {...action} />
}
return <EditorOpen />
}
interface TacticDto {
id: number
name: string
@ -89,14 +71,22 @@ interface TacticDto {
content: string
}
interface EditorPageProps {
guestMode: boolean
}
function EditorOpen() {
const { tacticId: idStr } = useParams()
const id = parseInt(idStr!)
export default function EditorPage({ guestMode }: EditorPageProps) {
const [tactic, setTactic] = useState<TacticDto>()
const { tacticId: idStr } = useParams()
const id = guestMode ? -1 : parseInt(idStr!)
useEffect(() => {
if (guestMode) {
setTactic({id: -1, courtType: "PLAIN", content: "{\"components\": []}", name: DEFAULT_TACTIC_NAME})
return
}
async function initialize() {
console.log("initializing")
const infoResponse = fetchAPIGet(`tactics/${id}`)
@ -109,7 +99,7 @@ function EditorOpen() {
}
initialize()
}, [id])
}, [guestMode, id, idStr])
if (tactic) {
return <Editor
@ -123,33 +113,6 @@ function EditorOpen() {
return <EditorLoadingScreen />
}
function EditorCreateNew({ courtType }: EditorCreateNewAction) {
const [id, setId] = useState<number>()
useEffect(() => {
async function initialize() {
const response = await fetchAPI("tactics", {
name: DEFAULT_TACTIC_NAME,
courtType
}, "POST")
const { id } = await response.json()
setId(id)
}
initialize()
}, [courtType])
if (id) {
return <Editor
id={id}
courtType={courtType}
content={JSON.stringify({ components: [] })}
name={DEFAULT_TACTIC_NAME}
/>
}
return <EditorLoadingScreen />
}
function EditorLoadingScreen() {
return <div>Loading Editor, please wait...</div>
@ -165,13 +128,13 @@ export interface EditorProps {
function Editor({ id, name, courtType, content }: EditorProps) {
const isInGuestMode = id == -1
const storage_content = localStorage.getItem(GUEST_MODE_CONTENT_STORAGE_KEY)
const storageContent = localStorage.getItem(GUEST_MODE_CONTENT_STORAGE_KEY)
const editorContent =
isInGuestMode && storage_content != null ? storage_content : content
isInGuestMode && storageContent != null ? storageContent : content
const storage_name = localStorage.getItem(GUEST_MODE_TITLE_STORAGE_KEY)
const storageName = localStorage.getItem(GUEST_MODE_TITLE_STORAGE_KEY)
const editorName =
isInGuestMode && storage_name != null ? storage_name : name
isInGuestMode && storageName != null ? storageName : name
return (
<EditorView

@ -32,7 +32,7 @@ export default function HomePage() {
const session = getSession()
if (!session.auth) {
redirect("/register")
redirect("/login")
return
}

@ -3,7 +3,13 @@ import "../style/new_tactic_panel.css"
import plainCourt from "../assets/court/full_court.svg"
import halfCourt from "../assets/court/half_court.svg"
import { BASE } from "../Constants"
import { CourtType } from "../model/tactic/Tactic.ts"
import { useCallback } from "react"
import { fetchAPI, redirect } from "../Fetcher.ts"
import { getSession } from "../api/session.ts"
export const DEFAULT_TACTIC_NAME = "Nouvelle tactique"
export default function NewTacticPage() {
return (
@ -16,12 +22,12 @@ export default function NewTacticPage() {
<CourtKindButton
name="Terrain complet"
image={plainCourt}
redirect="/tactic/new/plain"
courtType={"PLAIN"}
/>
<CourtKindButton
name="Demi-terrain"
image={halfCourt}
redirect="/tactic/new/half"
courtType={"HALF"}
/>
</div>
</div>
@ -32,16 +38,31 @@ export default function NewTacticPage() {
function CourtKindButton({
name,
image,
redirect,
courtType,
}: {
name: string
image: string
redirect: string
courtType: CourtType
}) {
return (
<div
className="court-kind-button"
onClick={() => (location.href = BASE + redirect)}>
onClick={useCallback(async () => {
// if user is not authenticated
if (!getSession().auth) {
redirect(`/tactic/edit-guest`)
}
const response = await fetchAPI("tactics", {
name: DEFAULT_TACTIC_NAME,
courtType,
}, "POST")
const { id } = await response.json()
redirect(`/tactic/${id}/edit`)
}, [courtType])}>
<div className="court-kind-button-top">
<div className="court-kind-button-image-div">
<img

@ -1,24 +1,39 @@
import { BASE } from "../../Constants"
import accountSvg from "../../assets/account.svg"
import AccountSvg from "../../assets/account.svg?react"
import "../../style/template/header.css"
import { useEffect, useState } from "react"
import { fetchAPIGet } from "../../Fetcher.ts"
import { fetchAPIGet, redirect } from "../../Fetcher.ts"
import { getSession, saveSession } from "../../api/session.ts"
export function Header() {
const [username, setUsername] = useState("")
const session = getSession()
const [username, setUsername] = useState<string | null>(session.username ?? null)
useEffect(() => {
async function getUsername() {
const response = await fetchAPIGet("user")
async function loadUsername() {
const response = await fetchAPIGet("user", false)
if (response.status == 401) { //if unauthorized
return
}
console.log(session)
//TODO check if the response is ok and handle errors
const {name} = await response.json()
setUsername(name)
const { name: username } = await response.json()
saveSession({ ...session, username })
setUsername(username)
}
getUsername()
}, [])
// if the user is authenticated and the username is not already present in the session,
if (session.auth && !session.username)
loadUsername()
}, [session])
return (
<div id="header">
@ -27,23 +42,24 @@ export function Header() {
<p
id="iqball"
className="clickable"
onClick={() => {
location.pathname = BASE + "/"
}}>
onClick={() => redirect("/")}>
IQBall
</p>
</div>
<div id="header-right">
<div className="clickable" id="clickable-header-right">
{/* <AccountSvg id="img-account" /> */}
<img
id="img-account"
src={accountSvg}
<div className="clickable"
id="clickable-header-right"
onClick={() => {
location.pathname = BASE + "/settings"
}}
/>
<p id="username">{username}</p>
if (username) {
redirect("/settings")
return
}
saveSession({...session, urlTarget: location.pathname})
redirect("/login")
}}>
{/* <AccountSvg id="img-account" /> */}
<AccountSvg id="img-account" />
<p id="username">{username ?? "Log In"}</p>
</div>
</div>
</div>

@ -9,9 +9,6 @@
justify-content: space-between;
font-family: var(--font-title);
height: 50px;
}
#img-account {
@ -31,7 +28,7 @@
#username {
color: var(--main-contrast-color);
margin-left: 10px;
margin: 0 0 0 10px;
}
#clickable-header-right:hover #username {
@ -48,10 +45,6 @@
justify-content: space-evenly;
}
#clickable-header-right:hover {
border: orange 1px solid;
}
.clickable {
cursor: pointer;
}

Loading…
Cancel
Save