From 98eed72af655c00feacdca37e452d7b1cb660d13 Mon Sep 17 00:00:00 2001 From: maxime Date: Mon, 25 Mar 2024 17:09:18 +0100 Subject: [PATCH] add possibility to delete a tactic from the home page --- src/assets/icon/bin.svg | 1 + src/pages/HomePage.tsx | 166 ++++++++++++++++++++++------------- src/pages/VisualizerPage.tsx | 2 +- src/style/home/home.css | 24 ++++- src/style/visualizer.css | 6 +- 5 files changed, 133 insertions(+), 66 deletions(-) create mode 100644 src/assets/icon/bin.svg diff --git a/src/assets/icon/bin.svg b/src/assets/icon/bin.svg new file mode 100644 index 0000000..1ef1c60 --- /dev/null +++ b/src/assets/icon/bin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 1aecb4b..e99a32e 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,9 +1,9 @@ import "../style/home/home.css" import { useNavigate } from "react-router-dom" -import { useEffect, useState } from "react" -import { User } from "../model/User.ts" +import { createContext, Dispatch, useContext, useEffect, useReducer } from "react" import { useAppFetcher } from "../App.tsx" import { Visualizer } from "../components/Visualizer.tsx" +import BinSvg from "../assets/icon/bin.svg?react" interface Tactic { id: number @@ -19,12 +19,55 @@ interface Team { second_color: string } +enum HomePageStateActionKind { + UPDATE_TACTICS = "UPDATE_TACTICS", + UPDATE_TEAMS = "UPDATE_TEAMS", + INIT = "INIT" +} + +type HomePageStateAction = { + type: HomePageStateActionKind.UPDATE_TACTICS, + tactics: Tactic[] +} | { + type: HomePageStateActionKind.UPDATE_TEAMS, + teams: Team[] +} | { + type: HomePageStateActionKind.INIT, + state: HomePageState +} + +interface HomePageState { + tactics: Tactic[] + teams: Team[] +} + +function homePageStateReducer(state: HomePageState, action: HomePageStateAction): HomePageState { + switch (action.type) { + case HomePageStateActionKind.UPDATE_TACTICS: + return { ...state!, tactics: action.tactics } + + case HomePageStateActionKind.UPDATE_TEAMS: + return { ...state!, teams: action.teams } + + case HomePageStateActionKind.INIT: + return action.state + } +} + +interface HomeStateContextMutable { + state: HomePageState, + dispatch: Dispatch +} + +const HomeStateContext = createContext(null) + +function useHomeState() { + return useContext(HomeStateContext) +} + export default function HomePage() { - type UserDataResponse = { user?: User; tactics: Tactic[]; teams: Team[] } - const [{ tactics, teams }, setInfo] = useState({ - tactics: [], - teams: [], - }) + const [state, dispatch] = useReducer(homePageStateReducer, { tactics: [], teams: [] }) + const navigate = useNavigate() const fetcher = useAppFetcher() @@ -32,70 +75,50 @@ export default function HomePage() { useEffect(() => { async function initUserData() { const response = await fetcher.fetchAPIGet("user-data") + if (response.status == 401) { navigate("/login") return // if unauthorized } - setInfo(await response.json()) + type UserDataResponse = { teams: Team[], tactics: Tactic[] } + const { teams, tactics }: UserDataResponse = await response.json() + tactics.sort((a, b) => b.creationDate - a.creationDate) + dispatch({ type: HomePageStateActionKind.INIT, state: { teams, tactics } }) } initUserData() }, [fetcher, navigate]) - tactics!.sort((a, b) => b.creationDate - a.creationDate) - const lastTactics = tactics.slice(0, 5) - return + return ( + + + + ) } -function Home({ - lastTactics, - tactics, - teams, -}: { - lastTactics: Tactic[] - tactics: Tactic[] - teams: Team[] -}) { +function Home() { return (
- +
) } -function Body({ - lastTactics, - tactics, - teams, -}: { - lastTactics: Tactic[] - tactics: Tactic[] - teams: Team[] -}) { +function Body() { const widthPersonalSpace = 78 const widthSideMenu = 100 - widthPersonalSpace return (
- +
) } -function SideMenu({ - width, - tactics, - teams, -}: { - width: number - tactics: Tactic[] - teams: Team[] -}) { +function SideMenu({ width }: { width: number }) { return (
- - + +
) } function PersonalSpace({ - width, - tactics, -}: { - width: number - tactics: Tactic[] -}) { + width, + }: { width: number }) { return (
- +
) } @@ -149,6 +168,8 @@ function TacticGrid({ tactics }: { tactics: Tactic[] }) { function TacticCard({ tactic }: { tactic: Tactic }) { const navigate = useNavigate() + const fetcher = useAppFetcher() + const { state: { tactics }, dispatch } = useHomeState()! return (
-

{tactic.name}

+
+

{tactic.name}

+ { + const response = await fetcher.fetchAPI(`tactics/${tactic.id}`, {}, "DELETE") + if (!response.ok) { + throw Error(`Cannot delete tactic ${tactic.id}!`) + } + dispatch({ + type: HomePageStateActionKind.UPDATE_TACTICS, + tactics: tactics.filter(t => t.id !== tactic.id), + }) + }} + /> +
) } -function BodyPersonalSpace({ tactics }: { tactics: Tactic[] }) { +function BodyPersonalSpace() { + const tactics = useHomeState()!.state.tactics return (
{tactics.length == 0 ? ( @@ -176,7 +213,7 @@ function BodyPersonalSpace({ tactics }: { tactics: Tactic[] }) { ) } -function LastTeamsSideMenu({ teams }: { teams: Team[] }) { +function LastTeamsSideMenu() { const navigate = useNavigate() return (
@@ -186,12 +223,12 @@ function LastTeamsSideMenu({ teams }: { teams: Team[] }) { +
- +
) } -function LastTacticsSideMenu({ tactics }: { tactics: Tactic[] }) { +function LastTacticsSideMenu() { const navigate = useNavigate() return ( @@ -205,26 +242,29 @@ function LastTacticsSideMenu({ tactics }: { tactics: Tactic[] }) { + - + ) } -function SetButtonTactic({ tactics }: { tactics: Tactic[] }) { +function SetButtonTactic() { + const tactics = useHomeState()!.state.tactics.slice(0, 5) const lastTactics = tactics.map((tactic) => ( - + )) return
{lastTactics}
} -function SetButtonTeam({ teams }: { teams: Team[] }) { +function SetButtonTeam() { + const teams = useHomeState()!.state.teams + const listTeam = teams.map((team) => ( - + )) return
{listTeam}
} -function ButtonTeam({ team }: { team: Team }) { +function TeamCard({ team }: { team: Team }) { const name = truncateString(team.name, 20) const navigate = useNavigate() @@ -242,7 +282,7 @@ function ButtonTeam({ team }: { team: Team }) { ) } -function ButtonLastTactic({ tactic }: { tactic: Tactic }) { +function LastTacticCard({ tactic }: { tactic: Tactic }) { const name = truncateString(tactic.name, 20) const navigate = useNavigate() diff --git a/src/pages/VisualizerPage.tsx b/src/pages/VisualizerPage.tsx index 971a0dd..9a66766 100644 --- a/src/pages/VisualizerPage.tsx +++ b/src/pages/VisualizerPage.tsx @@ -205,7 +205,7 @@ function VisualizerPageContent({ -
+
{isStepsTreeVisible ? (