diff --git a/.env b/.env
index 88ae8ef..5fc3483 100644
--- a/.env
+++ b/.env
@@ -1,2 +1,2 @@
-VITE_API_ENDPOINT=http://localhost:5254
-VITE_BASE=
+VITE_API_ENDPOINT=https://iqball.maxou.dev/api/dotnet-master
+#VITE_API_ENDPOINT=http://localhost:5254
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index e2c5b87..da35694 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -5,6 +5,8 @@ module.exports = {
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
+ "plugin:react/recommended",
+ "plugin:react/jsx-runtime",
],
ignorePatterns: ["dist", ".eslintrc.cjs"],
parser: "@typescript-eslint/parser",
diff --git a/.gitignore b/.gitignore
index 265f50c..780376a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,7 +14,6 @@ dist-ssr
# Editor directories and files
.vscode/*
-!.vscode/extensions.json
.idea
.DS_Store
*.suo
diff --git a/ci/.drone.yml b/ci/.drone.yml
index 0652133..683325f 100644
--- a/ci/.drone.yml
+++ b/ci/.drone.yml
@@ -25,8 +25,8 @@ steps:
depends_on:
- "front CI"
commands:
- - sed -Ei "s/VITE_BASE=/VITE_BASE=\\/${DRONE_BRANCH}/g" .env
- - npm run build -- --base=/$DRONE_BRANCH
+ - echo "VITE_API_ENDPOINT=https://iqball.maxou.dev/api/dotnet-$(echo $DRONE_BRANCH | tr / _)" > .env.STAGE
+ - npm run build -- --base=/$DRONE_BRANCH --mode STAGE
- mv dist/* /outputs
diff --git a/src/App.tsx b/src/App.tsx
index f28f8a9..4312161 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -3,7 +3,6 @@ import { BrowserRouter, Outlet, Route, Routes } from "react-router-dom"
import { Header } from "./pages/template/Header.tsx"
import "./style/app.css"
import { lazy } from "react"
-import { BASE } from "./Constants.ts"
const HomePage = lazy(() => import("./pages/HomePage.tsx"))
const LoginPage = lazy(() => import("./pages/LoginPage.tsx"))
@@ -17,7 +16,7 @@ const Editor = lazy(() => import("./pages/Editor.tsx"))
export default function App() {
return (
-
+
diff --git a/src/Constants.ts b/src/Constants.ts
index 013db50..4f77f36 100644
--- a/src/Constants.ts
+++ b/src/Constants.ts
@@ -6,4 +6,4 @@ export const API = import.meta.env.VITE_API_ENDPOINT
/**
* This constant defines the base app's endpoint.
*/
-export const BASE = import.meta.env.VITE_BASE
+export const BASE = import.meta.env.BASE_URL.slice(0, import.meta.env.BASE_URL.length - 1)
diff --git a/src/Fetcher.ts b/src/Fetcher.ts
index f4af2ce..ab4c7ad 100644
--- a/src/Fetcher.ts
+++ b/src/Fetcher.ts
@@ -1,9 +1,6 @@
-import { API, BASE } from "./Constants"
+import { API } from "./Constants"
import { getSession, saveSession, Session } from "./api/session.ts"
-
-export function redirect(url: string) {
- location.pathname = BASE + url
-}
+import { redirect } from "react-router-dom"
export async function fetchAPI(
url: string,
@@ -62,11 +59,11 @@ async function handleResponse(
redirectIfNotAuth: boolean,
): Promise {
// if we provided a token but still unauthorized, the token has expired
+ console.log(response.status)
if (response.status == 401) {
if (!redirectIfNotAuth) return response
- redirect("/login")
saveSession({ ...session, urlTarget: location.pathname })
- return response
+ return redirect("/login")
}
const nextToken = response.headers.get("Next-Authorization")!
diff --git a/src/pages/Editor.tsx b/src/pages/Editor.tsx
index 45eb129..6277ad2 100644
--- a/src/pages/Editor.tsx
+++ b/src/pages/Editor.tsx
@@ -99,20 +99,23 @@ interface EditorPageProps {
}
export default function EditorPage({ guestMode }: EditorPageProps) {
- const [tactic, setTactic] = useState()
- const { tacticId: idStr } = useParams()
- const id = guestMode ? -1 : parseInt(idStr!)
-
- useEffect(() => {
+ const [tactic, setTactic] = useState(() => {
if (guestMode) {
- setTactic({
+ return {
id: -1,
courtType: "PLAIN",
content: '{"components": []}',
name: DEFAULT_TACTIC_NAME,
- })
- return
+ }
}
+ return null;
+ })
+ const { tacticId: idStr } = useParams()
+ const id = guestMode ? -1 : parseInt(idStr!)
+
+ useEffect(() => {
+ if (guestMode)
+ return
async function initialize() {
const infoResponse = fetchAPIGet(`tactics/${id}`)
diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx
index 8b94656..6d480d3 100644
--- a/src/pages/HomePage.tsx
+++ b/src/pages/HomePage.tsx
@@ -1,11 +1,11 @@
import "../style/home/home.css"
-// import AccountSvg from "../assets/account.svg?react"
import { BASE } from "../Constants"
import { getSession } from "../api/session.ts"
-import { fetchAPIGet, redirect } from "../Fetcher.ts"
-import { useLayoutEffect, useState } from "react"
+import { useNavigate } from "react-router-dom"
+import { startTransition, useLayoutEffect, useState } from "react"
import { User } from "../model/User.ts"
+import { fetchAPIGet } from "../Fetcher.ts"
interface Tactic {
id: number
@@ -28,11 +28,15 @@ export default function HomePage() {
teams: [],
})
+ const navigate = useNavigate()
+
useLayoutEffect(() => {
const session = getSession()
if (!session.auth) {
- redirect("/login")
+ startTransition(() => {
+ navigate("/login")
+ })
return
}
@@ -42,7 +46,7 @@ export default function HomePage() {
}
getUser()
- }, [])
+ }, [navigate])
tactics!.sort((a, b) => b.creationDate - a.creationDate)
diff --git a/src/pages/LoginPage.tsx b/src/pages/LoginPage.tsx
index 9b12ea3..6d65091 100644
--- a/src/pages/LoginPage.tsx
+++ b/src/pages/LoginPage.tsx
@@ -1,21 +1,22 @@
-import { FormEvent, useRef, useState } from "react"
+import { FormEvent, startTransition, useState } from "react"
import { BASE } from "../Constants.ts"
-import { fetchAPI, redirect } from "../Fetcher.ts"
+import { fetchAPI } from "../Fetcher.ts"
import { Failure } from "../api/failure.ts"
import { getSession, saveSession } from "../api/session.ts"
import "../style/form.css"
+import { useNavigate } from "react-router-dom"
export default function LoginApp() {
const [errors, setErrors] = useState([])
- const emailRef = useRef(null)
- const passwordRef = useRef(null)
+ const navigate = useNavigate()
async function handleSubmit(e: FormEvent) {
e.preventDefault()
- const email = emailRef.current!.value
- const password = passwordRef.current!.value
+ const { email, password } = Object.fromEntries(
+ new FormData(e.target as HTMLFormElement),
+ )
const response = await fetchAPI(
"auth/token",
@@ -28,7 +29,9 @@ export default function LoginApp() {
const session = getSession()
const { token, expirationDate } = await response.json()
saveSession({ ...session, auth: { token, expirationDate }, urlTarget: undefined })
- redirect(session.urlTarget ?? "/")
+ startTransition(() => {
+ navigate(session.urlTarget ?? "/")
+ })
return
}
@@ -38,7 +41,7 @@ export default function LoginApp() {
{
type: "Non autorisé",
messages: [
- "L'adresse email ou le mot de passe sont invalide.",
+ "L'adresse email ou le mot de passe sont invalides.",
],
},
])
@@ -81,7 +84,6 @@ export default function LoginApp() {
Mot de passe :
{
// if user is not authenticated
if (!getSession().auth) {
- redirect(`/tactic/edit-guest`)
+ startTransition(() => {
+ navigate(`/tactic/edit-guest`)
+ })
}
const response = await fetchAPI(
@@ -62,8 +68,10 @@ function CourtKindButton({
)
const { id } = await response.json()
- redirect(`/tactic/${id}/edit`)
- }, [courtType])}>
+ startTransition(() => {
+ navigate(`/tactic/${id}/edit`)
+ })
+ }, [courtType, navigate])}>
![]()
(null)
@@ -14,6 +15,8 @@ export default function RegisterPage() {
const [errors, setErrors] = useState
([])
+ const navigate = useNavigate()
+
async function handleSubmit(e: FormEvent) {
e.preventDefault()
@@ -44,7 +47,9 @@ export default function RegisterPage() {
const { token, expirationDate } = await response.json()
const session = getSession()
saveSession({ ...session, auth: { token, expirationDate }, urlTarget: undefined })
- redirect(session.urlTarget ?? "/")
+ startTransition(() => {
+ navigate(session.urlTarget ?? "/")
+ })
return
}
diff --git a/src/pages/Visualizer.tsx b/src/pages/Visualizer.tsx
index 6103358..6f3b67a 100644
--- a/src/pages/Visualizer.tsx
+++ b/src/pages/Visualizer.tsx
@@ -2,22 +2,22 @@
// import "../style/visualizer.css"
// import Court from "../assets/court/full_court.svg"
//
-// // export default function Visualizer({ id, name }: { id: number; name: string }) {
-// // const [style, setStyle] = useState({})
-// //
-// // return (
-// //
-// //
-// //
{name}
-// //
-// //
-// //

-// //
-// //
-// // )
-// // }
+// export default function Visualizer({ id, name }: { id: number; name: string }) {
+// const [style, setStyle] = useState({})
+//
+// return (
+//
+//
+//
{name}
+//
+//
+//

+//
+//
+// )
+// }
diff --git a/src/pages/template/Header.tsx b/src/pages/template/Header.tsx
index 5f93ae7..4316098 100644
--- a/src/pages/template/Header.tsx
+++ b/src/pages/template/Header.tsx
@@ -1,8 +1,9 @@
import AccountSvg from "../../assets/account.svg?react"
import "../../style/template/header.css"
-import { useEffect, useState } from "react"
-import { fetchAPIGet, redirect } from "../../Fetcher.ts"
+import { startTransition, useEffect, useState } from "react"
+import { fetchAPIGet } from "../../Fetcher.ts"
import { getSession, saveSession } from "../../api/session.ts"
+import { useNavigate } from "react-router-dom"
export function Header() {
const session = getSession()
@@ -10,6 +11,8 @@ export function Header() {
session.username ?? null,
)
+ const navigate = useNavigate()
+
useEffect(() => {
async function loadUsername() {
const response = await fetchAPIGet("user", false)
@@ -36,7 +39,7 @@ export function Header() {
redirect("/")}>
+ onClick={() => startTransition(() => navigate("/"))}>
IQBall
@@ -46,14 +49,19 @@ export function Header() {
id="clickable-header-right"
onClick={() => {
if (username) {
- redirect("/settings")
+ startTransition(() => {
+ navigate("/settings")
+ })
return
}
saveSession({
...session,
urlTarget: location.pathname,
})
- redirect("/login")
+
+ startTransition(() => {
+ navigate("/login")
+ })
}}>
{/*
*/}
diff --git a/vite.config.ts b/vite.config.ts
index 8e2f5c5..214327e 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -13,8 +13,6 @@ export default defineConfig({
cssInjectedByJsPlugin({
relativeCSSInjection: true,
}),
- svgr({
- include: "**/*.svg?react",
- }),
+ svgr(),
],
})