add possibility to delete a tactic from the home page

pull/120/head
maxime 1 year ago
parent 7289a956b3
commit 98eed72af6

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 456 511.82"><path fill="#FD3B3B" d="M48.42 140.13h361.99c17.36 0 29.82 9.78 28.08 28.17l-30.73 317.1c-1.23 13.36-8.99 26.42-25.3 26.42H76.34c-13.63-.73-23.74-9.75-25.09-24.14L20.79 168.99c-1.74-18.38 9.75-28.86 27.63-28.86zM24.49 38.15h136.47V28.1c0-15.94 10.2-28.1 27.02-28.1h81.28c17.3 0 27.65 11.77 27.65 28.01v10.14h138.66c.57 0 1.11.07 1.68.13 10.23.93 18.15 9.02 18.69 19.22.03.79.06 1.39.06 2.17v42.76c0 5.99-4.73 10.89-10.62 11.19-.54 0-1.09.03-1.63.03H11.22c-5.92 0-10.77-4.6-11.19-10.38 0-.72-.03-1.47-.03-2.23v-39.5c0-10.93 4.21-20.71 16.82-23.02 2.53-.45 5.09-.37 7.67-.37zm83.78 208.38c-.51-10.17 8.21-18.83 19.53-19.31 11.31-.49 20.94 7.4 21.45 17.57l8.7 160.62c.51 10.18-8.22 18.84-19.53 19.32-11.32.48-20.94-7.4-21.46-17.57l-8.69-160.63zm201.7-1.74c.51-10.17 10.14-18.06 21.45-17.57 11.32.48 20.04 9.14 19.53 19.31l-8.66 160.63c-.52 10.17-10.14 18.05-21.46 17.57-11.31-.48-20.04-9.14-19.53-19.32l8.67-160.62zm-102.94.87c0-10.23 9.23-18.53 20.58-18.53 11.34 0 20.58 8.3 20.58 18.53v160.63c0 10.23-9.24 18.53-20.58 18.53-11.35 0-20.58-8.3-20.58-18.53V245.66z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -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<HomePageStateAction>
}
const HomeStateContext = createContext<HomeStateContextMutable | null>(null)
function useHomeState() {
return useContext(HomeStateContext)
}
export default function HomePage() {
type UserDataResponse = { user?: User; tactics: Tactic[]; teams: Team[] }
const [{ tactics, teams }, setInfo] = useState<UserDataResponse>({
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 <Home teams={teams!} tactics={tactics!} lastTactics={lastTactics} />
return (
<HomeStateContext.Provider value={{ state, dispatch }}>
<Home />
</HomeStateContext.Provider>
)
}
function Home({
lastTactics,
tactics,
teams,
}: {
lastTactics: Tactic[]
tactics: Tactic[]
teams: Team[]
}) {
function Home() {
return (
<div id="main">
<Body lastTactics={lastTactics} tactics={tactics} teams={teams} />
<Body />
</div>
)
}
function Body({
lastTactics,
tactics,
teams,
}: {
lastTactics: Tactic[]
tactics: Tactic[]
teams: Team[]
}) {
function Body() {
const widthPersonalSpace = 78
const widthSideMenu = 100 - widthPersonalSpace
return (
<div id="body">
<PersonalSpace width={widthPersonalSpace} tactics={tactics} />
<PersonalSpace width={widthPersonalSpace} />
<SideMenu
width={widthSideMenu}
tactics={lastTactics}
teams={teams}
/>
</div>
)
}
function SideMenu({
width,
tactics,
teams,
}: {
width: number
tactics: Tactic[]
teams: Team[]
}) {
function SideMenu({ width }: { width: number }) {
return (
<div
id="side-menu"
@ -103,20 +126,16 @@ function SideMenu({
width: width + "%",
}}>
<div id="side-menu-content">
<LastTeamsSideMenu teams={teams} />
<LastTacticsSideMenu tactics={tactics} />
<LastTeamsSideMenu />
<LastTacticsSideMenu />
</div>
</div>
)
}
function PersonalSpace({
width,
tactics,
}: {
width: number
tactics: Tactic[]
}) {
width,
}: { width: number }) {
return (
<div
id="personal-space"
@ -124,7 +143,7 @@ function PersonalSpace({
width: width + "%",
}}>
<TitlePersonalSpace />
<BodyPersonalSpace tactics={tactics} />
<BodyPersonalSpace />
</div>
)
}
@ -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 (
<div className={"tactic-card"}>
<div
@ -159,12 +180,28 @@ function TacticCard({ tactic }: { tactic: Tactic }) {
tacticId={tactic.id}
/>
</div>
<p className="tactic-card-title">{tactic.name}</p>
<div className="tactic-card-content">
<p className="tactic-card-title">{tactic.name}</p>
<BinSvg
className="tactic-card-remove-btn"
onClick={async () => {
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),
})
}}
/>
</div>
</div>
)
}
function BodyPersonalSpace({ tactics }: { tactics: Tactic[] }) {
function BodyPersonalSpace() {
const tactics = useHomeState()!.state.tactics
return (
<div id="body-personal-space">
{tactics.length == 0 ? (
@ -176,7 +213,7 @@ function BodyPersonalSpace({ tactics }: { tactics: Tactic[] }) {
)
}
function LastTeamsSideMenu({ teams }: { teams: Team[] }) {
function LastTeamsSideMenu() {
const navigate = useNavigate()
return (
<div id="teams">
@ -186,12 +223,12 @@ function LastTeamsSideMenu({ teams }: { teams: Team[] }) {
+
</button>
</div>
<SetButtonTeam teams={teams} />
<SetButtonTeam />
</div>
)
}
function LastTacticsSideMenu({ tactics }: { tactics: Tactic[] }) {
function LastTacticsSideMenu() {
const navigate = useNavigate()
return (
@ -205,26 +242,29 @@ function LastTacticsSideMenu({ tactics }: { tactics: Tactic[] }) {
+
</button>
</div>
<SetButtonTactic tactics={tactics} />
<SetButtonTactic />
</div>
)
}
function SetButtonTactic({ tactics }: { tactics: Tactic[] }) {
function SetButtonTactic() {
const tactics = useHomeState()!.state.tactics.slice(0, 5)
const lastTactics = tactics.map((tactic) => (
<ButtonLastTactic key={tactic.id} tactic={tactic} />
<LastTacticCard key={tactic.id} tactic={tactic} />
))
return <div className="set-button">{lastTactics}</div>
}
function SetButtonTeam({ teams }: { teams: Team[] }) {
function SetButtonTeam() {
const teams = useHomeState()!.state.teams
const listTeam = teams.map((team) => (
<ButtonTeam key={team.id} team={team} />
<TeamCard key={team.id} team={team} />
))
return <div className="set-button">{listTeam}</div>
}
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()

@ -205,7 +205,7 @@ function VisualizerPageContent({
</div>
</div>
<div id="editor-div">
<div id="visualizer-div">
{isStepsTreeVisible ? (
<SplitLayout
rightWidth={editorContentCurtainWidth}

@ -61,15 +61,37 @@ body {
width: 32%;
}
.tactic-card-title {
.tactic-card-content {
display: flex;
flex-direction: column;
align-items: center;
pointer-events: none;
z-index: 1000;
position: absolute;
}
.tactic-card-title {
user-select: none;
padding: 0 10px 0 10px;
border-radius: 200px;
background: rgba(236, 235, 235, 0.87);
}
.tactic-card-remove-btn {
pointer-events: all;
width: 30px;
height: 30px;
cursor: pointer;
transition: scale .5s;
}
.tactic-card-remove-btn:hover {
scale: 1.25;
}
.tactic-card-preview {
display: flex;
justify-content: center;

@ -14,8 +14,12 @@
overflow: hidden;
}
#editor-div {
#visualizer-div {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
align-content: center;
}
.curtain {

Loading…
Cancel
Save