You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
376 lines
9.6 KiB
376 lines
9.6 KiB
import "../style/home/home.css"
|
|
|
|
import { Header } from "./template/Header"
|
|
import { BASE } from "../Constants"
|
|
import Draggable from "react-draggable";
|
|
import {NULL_POS} from "../components/arrows/Pos";
|
|
import {contains} from "../components/arrows/Box";
|
|
import React, {useRef, useState} from "react";
|
|
import { fetchAPI } from "../Fetcher"
|
|
import {User} from "../model/User";
|
|
import { FaShare } from "react-icons/fa";
|
|
import {SaveStates} from "../components/editor/SavingState";
|
|
|
|
interface Tactic {
|
|
id: number
|
|
name: string
|
|
creation_date: string
|
|
}
|
|
|
|
interface Team {
|
|
id: number
|
|
name: string
|
|
picture: string
|
|
main_color: string
|
|
second_color: string
|
|
}
|
|
|
|
export default function Home({
|
|
lastTactics,
|
|
allTactics,
|
|
teams,
|
|
user,
|
|
}: {
|
|
lastTactics: Tactic[]
|
|
allTactics: Tactic[]
|
|
teams: Team[]
|
|
user: User
|
|
}) {
|
|
return (
|
|
<div id="main">
|
|
<Header user={user} />
|
|
<Body
|
|
lastTactics={lastTactics}
|
|
allTactics={allTactics}
|
|
teams={teams}
|
|
user={user}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function Body({
|
|
lastTactics,
|
|
allTactics,
|
|
teams,
|
|
user,
|
|
}: {
|
|
lastTactics: Tactic[]
|
|
allTactics: Tactic[]
|
|
teams: Team[]
|
|
user : User
|
|
}) {
|
|
const widthPersonalSpace = 78
|
|
const widthSideMenu = 100 - widthPersonalSpace
|
|
return (
|
|
<div id="body">
|
|
<PersonalSpace width={widthPersonalSpace} allTactics={allTactics} teams={teams} user={user}/>
|
|
<SideMenu
|
|
width={widthSideMenu}
|
|
lastTactics={lastTactics}
|
|
teams={teams}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function SideMenu({
|
|
width,
|
|
lastTactics,
|
|
teams,
|
|
}: {
|
|
width: number
|
|
lastTactics: Tactic[]
|
|
teams: Team[]
|
|
}) {
|
|
return (
|
|
<div id="side-menu" style={{
|
|
width : width + "%",
|
|
}}>
|
|
<div id="side-menu-content">
|
|
<TeamList teams={teams}/>
|
|
<TacticList lastTactics={lastTactics}/>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function PersonalSpace({
|
|
width,
|
|
allTactics,
|
|
teams,
|
|
user,
|
|
}: {
|
|
width: number
|
|
allTactics: Tactic[]
|
|
teams : Team[]
|
|
user : User
|
|
}) {
|
|
return (
|
|
<div
|
|
id="personal-space"
|
|
style={{
|
|
width: width + "%",
|
|
}}>
|
|
<TitlePersonalSpace />
|
|
<BodyPersonalSpace allTactics={allTactics} teams={teams} user={user}/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function TitlePersonalSpace() {
|
|
return (
|
|
<div id="title-personal-space">
|
|
<h2>Espace Personnel</h2>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function TableData({
|
|
allTactics,
|
|
teams,
|
|
user,
|
|
}: {
|
|
allTactics: Tactic[]
|
|
teams : Team[]
|
|
user : User
|
|
}) {
|
|
const nbRow = Math.floor(allTactics.length / 3) + 1
|
|
let listTactic = Array(nbRow)
|
|
for (let i = 0; i < nbRow; i++) {
|
|
listTactic[i] = Array(0)
|
|
}
|
|
let i = 0
|
|
let j = 0
|
|
allTactics.forEach((tactic) => {
|
|
listTactic[i].push(tactic)
|
|
j++
|
|
if (j === 3) {
|
|
i++
|
|
j = 0
|
|
}
|
|
})
|
|
|
|
i = 0
|
|
while (i < nbRow) {
|
|
listTactic[i] = listTactic[i].map((tactic: Tactic, i) => (
|
|
<DraggableTableDataElement key={i} tactic={tactic} teams={teams}/>
|
|
))
|
|
i++
|
|
}
|
|
if (nbRow == 1) {
|
|
if (listTactic[0].length < 3) {
|
|
for (let i = 0; i <= 3 - listTactic[0].length; i++) {
|
|
listTactic[0].push(<td key={"tdNone" + i}></td>)
|
|
}
|
|
}
|
|
}
|
|
|
|
const data = listTactic.map((tactic, rowIndex) => (
|
|
<tr key={rowIndex + "row"}>{tactic}</tr>
|
|
))
|
|
return data
|
|
}
|
|
|
|
|
|
function DraggableTableDataElement({
|
|
tactic,
|
|
teams,
|
|
} : {
|
|
tactic : Tactic
|
|
teams : Team[]
|
|
}) {
|
|
const ref = useRef<HTMLDivElement>(null)
|
|
const [dragging, setDragging] = useState(false)
|
|
const [hovered, setHovered] = useState(false);
|
|
|
|
const handleButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
event.stopPropagation();
|
|
if (!dragging) {
|
|
const userEmail = window.prompt("Entrez l'email à qui partager la tactique :");
|
|
if(userEmail != null) {
|
|
onShareTactic(userEmail, tactic);
|
|
}
|
|
} else {
|
|
setDragging(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Draggable position={NULL_POS}
|
|
nodeRef={ref}
|
|
onDrag={() => setDragging(true)}
|
|
onStop={() => { if(dragging) {
|
|
onDropTactic(ref.current.getBoundingClientRect(), tactic, teams)
|
|
}
|
|
}}
|
|
>
|
|
<td key={tactic.id}
|
|
ref={ref}
|
|
className="data"
|
|
onClick={() => { if(!dragging) {
|
|
location.pathname = BASE + "/tactic/" + tactic.id + "/edit"
|
|
}
|
|
else {
|
|
setDragging(false)
|
|
}
|
|
}}
|
|
onMouseEnter={() => setHovered(true)}
|
|
onMouseLeave={() => setHovered(false)}
|
|
>
|
|
|
|
{truncateString(tactic.name, 25)}
|
|
{hovered && (
|
|
<div className="share-icon-container">
|
|
<button className="share-button share-icon-button" onClick={handleButtonClick}>
|
|
<FaShare className="share-icon" />
|
|
</button>
|
|
</div>
|
|
)}
|
|
</td>
|
|
</Draggable>
|
|
)
|
|
}
|
|
|
|
function BodyPersonalSpace({
|
|
allTactics,
|
|
teams,
|
|
user,
|
|
}: {
|
|
allTactics: Tactic[]
|
|
teams : Team[]
|
|
user : User
|
|
}) {
|
|
let data
|
|
if (allTactics.length == 0) {
|
|
data = <p>Aucune tactique créée !</p>
|
|
} else {
|
|
data = <TableData allTactics={allTactics} teams={teams} user={user}/>
|
|
}
|
|
|
|
return (
|
|
<div id="body-personal-space">
|
|
<table>
|
|
<tbody key="tbody">{data}</tbody>
|
|
</table>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function TeamList({ teams }: { teams: Team[] }) {
|
|
return (
|
|
<div id="teams">
|
|
<div className="titre-side-menu">
|
|
<h2 className="title">Mes équipes</h2>
|
|
<button
|
|
className="new"
|
|
onClick={() => (location.pathname = BASE + "/team/new")}>
|
|
+
|
|
</button>
|
|
</div>
|
|
<SetButtonTeam teams={teams} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function TacticList({ lastTactics }: { lastTactics: Tactic[] }) {
|
|
return (
|
|
<div id="tactic">
|
|
<div className="titre-side-menu">
|
|
<h2 className="title">Mes dernières stratégies</h2>
|
|
<button
|
|
className="new"
|
|
id="create-tactic"
|
|
onClick={() => (location.pathname = BASE + "/tactic/new")}>
|
|
+
|
|
</button>
|
|
</div>
|
|
<SetButtonTactic tactics={lastTactics} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function SetButtonTactic({ tactics }: { tactics: Tactic[] }) {
|
|
const lastTactics = tactics.map((tactic, i) => (
|
|
<ButtonLastTactic key={i} tactic={tactic} />
|
|
))
|
|
return <div className="set-button">{lastTactics}</div>
|
|
}
|
|
|
|
function SetButtonTeam({ teams }: { teams: Team[] }) {
|
|
const listTeam = teams.map((teams, i) => <ButtonTeam key={i} team={teams} />)
|
|
return <div className="set-button">{listTeam}</div>
|
|
}
|
|
|
|
function ButtonTeam({ team }: { team: Team }) {
|
|
const name = truncateString(team.name, 20)
|
|
return (
|
|
<div>
|
|
<div
|
|
id={"button-team-" + team.id}
|
|
className="button-side-menu data"
|
|
onClick={() => {
|
|
location.pathname = BASE + "/team/" + team.id
|
|
}}>
|
|
{name}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function ButtonLastTactic({ tactic }: { tactic: Tactic }) {
|
|
const name = truncateString(tactic.name, 20)
|
|
return (
|
|
<div
|
|
id={"button" + tactic.id}
|
|
className="button-side-menu data"
|
|
onClick={() => {
|
|
location.pathname = BASE + "/tactic/" + tactic.id + "/edit"
|
|
}}>
|
|
{name}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function truncateString(name: string, limit: number): string {
|
|
if (name.length > limit) {
|
|
name = name.substring(0, limit) + "..."
|
|
}
|
|
return name
|
|
}
|
|
|
|
function onDropTactic(ref : DOMRect, tactic : Tactic, teams : Team[]) {
|
|
let shared = false;
|
|
for (const team of teams) {
|
|
if (contains(ref, document.getElementById(`button-team-${team.id}`)!.getBoundingClientRect())) {
|
|
if (!shared) {
|
|
shareTacticToTeam(tactic, team);
|
|
shared = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async function onShareTactic(email: string, tactic: Tactic) {
|
|
const canShareResponse = await fetchAPI(`tactic/${tactic.id}/can-share`, tactic);
|
|
if (canShareResponse.ok) {
|
|
const shareToAccountResponse = await fetchAPI(`tactic/${tactic.id}/share-to-account`, email);
|
|
if (!shareToAccountResponse.ok) {
|
|
alert("Une erreur s'est produite lors du partage de la tactique avec ce compte");
|
|
}
|
|
} else {
|
|
alert("Vous ne pouvez pas partager cette tactique");
|
|
}
|
|
}
|
|
|
|
|
|
async function shareTacticToTeam(tactic : Tactic, team : Team) {
|
|
const canShare = await fetchAPI(`tactic/${tactic.id}/can-share-to-team`, team).then((r) => r.ok)
|
|
if(canShare && confirm("Etes-vous sûr de vouloir partager la tactique " + tactic.name + " avec l'équipe " + team.name)) {
|
|
fetchAPI(`tactic/${tactic.id}/share-to-team`, team)
|
|
}
|
|
if(!canShare) {
|
|
alert("Vous ne pouvez pas partager cette tactique à cette équipe")
|
|
}
|
|
}
|