fix css + verify and format

pull/77/head
Vivien DUFOUR 1 year ago
parent c68344dab0
commit d858cc3113

@ -1,7 +1,7 @@
import "../../style/ball.css" import "../../style/ball.css"
import BallSvg from "../../assets/icon/ball.svg?react" import BallSvg from "../../assets/icon/ball.svg?react"
import {Ball} from "../../tactic/CourtObjects"; import { Ball } from "../../tactic/CourtObjects"
export interface CourtBallProps { export interface CourtBallProps {
onMoved: (rect: DOMRect) => void onMoved: (rect: DOMRect) => void
@ -10,8 +10,5 @@ export interface CourtBallProps {
} }
export function BallPiece() { export function BallPiece() {
return ( return <BallSvg className={"ball"} />
<BallSvg className={"ball"}/>
)
} }

@ -3,8 +3,8 @@ import {RefObject} from "react"
import CourtPlayer from "./CourtPlayer" import CourtPlayer from "./CourtPlayer"
import { Player } from "../../tactic/Player" import { Player } from "../../tactic/Player"
import {CourtObject} from "../../tactic/CourtObjects"; import { CourtObject } from "../../tactic/CourtObjects"
import {CourtBall} from "./CourtBall"; import { CourtBall } from "./CourtBall"
export interface BasketCourtProps { export interface BasketCourtProps {
players: Player[] players: Player[]
@ -15,7 +15,7 @@ export interface BasketCourtProps {
onBallRemove: () => void onBallRemove: () => void
onBallMoved: (ball: DOMRect) => void, onBallMoved: (ball: DOMRect) => void
courtImage: string courtImage: string
courtRef: RefObject<HTMLDivElement> courtRef: RefObject<HTMLDivElement>
@ -31,7 +31,6 @@ export function BasketCourt({
courtImage, courtImage,
courtRef, courtRef,
}: BasketCourtProps) { }: BasketCourtProps) {
return ( return (
<div <div
id="court-container" id="court-container"
@ -51,19 +50,19 @@ export function BasketCourt({
) )
})} })}
{objects.map(object => { {objects.map((object) => {
if (object.type == "ball") { if (object.type == "ball") {
return <CourtBall return (
<CourtBall
onMoved={onBallMoved} onMoved={onBallMoved}
ball={object} ball={object}
onRemove={onBallRemove} onRemove={onBallRemove}
key="ball" key="ball"
/> />
)
} }
throw new Error("unknown court object", object.type) throw new Error("unknown court object", object.type)
})} })}
</div> </div>
) )
} }

@ -1,7 +1,6 @@
import React, {useRef} from "react"; import React, { useRef } from "react"
import Draggable from "react-draggable"; import Draggable from "react-draggable"
import {BallPiece, CourtBallProps} from "./BallPiece"; import { BallPiece, CourtBallProps } from "./BallPiece"
export function CourtBall({ onMoved, ball, onRemove }: CourtBallProps) { export function CourtBall({ onMoved, ball, onRemove }: CourtBallProps) {
const pieceRef = useRef<HTMLDivElement>(null) const pieceRef = useRef<HTMLDivElement>(null)
@ -12,9 +11,9 @@ export function CourtBall({onMoved, ball, onRemove}: CourtBallProps) {
return ( return (
<Draggable <Draggable
onStop={() => onMoved(pieceRef.current!.getBoundingClientRect())} onStop={() => onMoved(pieceRef.current!.getBoundingClientRect())}
nodeRef={pieceRef} nodeRef={pieceRef}>
> <div
<div className={"ball-div"} className={"ball-div"}
ref={pieceRef} ref={pieceRef}
tabIndex={0} tabIndex={0}
onKeyUp={(e) => { onKeyUp={(e) => {
@ -24,8 +23,7 @@ export function CourtBall({onMoved, ball, onRemove}: CourtBallProps) {
position: "absolute", position: "absolute",
left: `${x * 100}%`, left: `${x * 100}%`,
top: `${y * 100}%`, top: `${y * 100}%`,
}} }}>
>
<BallPiece /> <BallPiece />
</div> </div>
</Draggable> </Draggable>

@ -68,13 +68,20 @@ export default function CourtPlayer({
if (e.key == "Delete") onRemove() if (e.key == "Delete") onRemove()
}}> }}>
<div className="player-selection-tab"> <div className="player-selection-tab">
{hasBall && (<Draggable nodeRef={ballPiece} {hasBall && (
onStop={() => onBallDrop(ballPiece.current!.getBoundingClientRect())} <Draggable
nodeRef={ballPiece}
onStop={() =>
onBallDrop(
ballPiece.current!.getBoundingClientRect(),
)
}
position={{ x: 0, y: 0 }}> position={{ x: 0, y: 0 }}>
<div ref={ballPiece}> <div ref={ballPiece}>
<BallPiece /> <BallPiece />
</div> </div>
</Draggable>)} </Draggable>
)}
</div> </div>
<PlayerPiece <PlayerPiece
team={player.team} team={player.team}

@ -8,9 +8,7 @@
width: 20px; width: 20px;
height: 20px; height: 20px;
cursor: pointer; cursor: pointer;
tabIndex: 0;
} }
.ball-div:focus-within { .ball-div:focus-within {
} }

@ -32,6 +32,8 @@
#racks { #racks {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center;
height: 25px;
} }
.title-input { .title-input {
@ -46,6 +48,10 @@
#allies-rack { #allies-rack {
width: 125px; width: 125px;
min-width: 125px; min-width: 125px;
display: flex;
flex-direction: row;
align-items: flex-end;
justify-content: flex-start;
} }
#opponent-rack { #opponent-rack {
@ -111,5 +117,3 @@
.save-state-guest { .save-state-guest {
color: gray; color: gray;
} }

@ -1,13 +1,10 @@
export type CourtObject = { type: "ball" } & Ball export type CourtObject = { type: "ball" } & Ball
export interface Ball { export interface Ball {
/** /**
* The ball is a "ball" court object * The ball is a "ball" court object
*/ */
readonly type: "ball", readonly type: "ball"
/** /**
* Percentage of the player's position to the bottom (0 means top, 1 means bottom, 0.5 means middle) * Percentage of the player's position to the bottom (0 means top, 1 means bottom, 0.5 means middle)

@ -1,5 +1,5 @@
import { Player } from "./Player" import { Player } from "./Player"
import {CourtObject} from "./CourtObjects"; import { CourtObject } from "./CourtObjects"
export interface Tactic { export interface Tactic {
id: number id: number

@ -1,4 +1,11 @@
import {CSSProperties, Dispatch, SetStateAction, useCallback, useRef, useState,} from "react" import {
CSSProperties,
Dispatch,
SetStateAction,
useCallback,
useRef,
useState,
} from "react"
import "../style/editor.css" import "../style/editor.css"
import TitleInput from "../components/TitleInput" import TitleInput from "../components/TitleInput"
import { BasketCourt } from "../components/editor/BasketCourt" import { BasketCourt } from "../components/editor/BasketCourt"
@ -7,23 +14,23 @@ import plainCourt from "../assets/court/full_court.svg"
import halfCourt from "../assets/court/half_court.svg" import halfCourt from "../assets/court/half_court.svg"
import { BallPiece } from "../components/editor/BallPiece"
import { Rack } from "../components/Rack" import { Rack } from "../components/Rack"
import { PlayerPiece } from "../components/editor/PlayerPiece" import { PlayerPiece } from "../components/editor/PlayerPiece"
import { Player } from "../tactic/Player"
import {BallPiece, CourtBall} from "../components/editor/BallPiece";
import { Tactic, TacticContent } from "../tactic/Tactic" import { Tactic, TacticContent } from "../tactic/Tactic"
import { fetchAPI } from "../Fetcher" import { fetchAPI } from "../Fetcher"
import { Team } from "../tactic/Team" import { Team } from "../tactic/Team"
import { calculateRatio } from "../Utils" import { calculateRatio } from "../Utils"
import SavingState, { import SavingState, {
SaveState, SaveState,
SaveStates, SaveStates,
} from "../components/editor/SavingState" } from "../components/editor/SavingState"
import {CourtObject} from "../tactic/CourtObjects"; import {CourtObject} from "../tactic/CourtObjects";
import {Simulate} from "react-dom/test-utils";
const ERROR_STYLE: CSSProperties = { const ERROR_STYLE: CSSProperties = {
@ -57,12 +64,14 @@ interface RackedPlayer {
type RackedCourtObject = { key: "ball" } type RackedCourtObject = { key: "ball" }
export default function Editor({ export default function Editor({
id, id,
name, name,
courtType, courtType,
content, content,
}: EditorProps) { }: EditorProps) {
const isInGuestMode = id == -1 const isInGuestMode = id == -1
const storage_content = localStorage.getItem(GUEST_MODE_CONTENT_STORAGE_KEY) const storage_content = localStorage.getItem(GUEST_MODE_CONTENT_STORAGE_KEY)
@ -101,7 +110,8 @@ export default function Editor({
(r) => r.ok, (r) => r.ok,
) )
}} }}
courtType={courtType}/> courtType={courtType}
/>
) )
} }
@ -111,7 +121,6 @@ function EditorView({
onNameChange, onNameChange,
courtType, courtType,
}: EditorViewProps) { }: EditorViewProps) {
const isInGuestMode = id == -1 const isInGuestMode = id == -1
const [titleStyle, setTitleStyle] = useState<CSSProperties>({}) const [titleStyle, setTitleStyle] = useState<CSSProperties>({})
@ -128,12 +137,14 @@ function EditorView({
getRackPlayers(Team.Opponents, content.players), getRackPlayers(Team.Opponents, content.players),
) )
const [objects, setObjects] = useState<RackedCourtObject[]>(isBallOnCourt(content) ? [] : [{key: "ball"}]) const [objects, setObjects] = useState<RackedCourtObject[]>(
isBallOnCourt(content) ? [] : [{ key: "ball" }],
)
const courtDivContentRef = useRef<HTMLDivElement>(null) const courtDivContentRef = useRef<HTMLDivElement>(null)
const canDetach = (bounds: DOMRect) => { const isBoundsOnCourt = (bounds: DOMRect) => {
const courtBounds = courtDivContentRef.current!.getBoundingClientRect() const courtBounds = courtDivContentRef.current!.getBoundingClientRect()
// check if refBounds overlaps courtBounds // check if refBounds overlaps courtBounds
@ -145,8 +156,6 @@ function EditorView({
) )
} }
const onPieceDetach = (ref: HTMLDivElement, element: RackedPlayer) => { const onPieceDetach = (ref: HTMLDivElement, element: RackedPlayer) => {
const refBounds = ref.getBoundingClientRect() const refBounds = ref.getBoundingClientRect()
const courtBounds = courtDivContentRef.current!.getBoundingClientRect() const courtBounds = courtDivContentRef.current!.getBoundingClientRect()
@ -171,7 +180,10 @@ function EditorView({
}) })
} }
const onObjectDetach = (ref: HTMLDivElement, rackedObject: RackedCourtObject) => { const onObjectDetach = (
ref: HTMLDivElement,
rackedObject: RackedCourtObject,
) => {
const refBounds = ref.getBoundingClientRect() const refBounds = ref.getBoundingClientRect()
const courtBounds = courtDivContentRef.current!.getBoundingClientRect() const courtBounds = courtDivContentRef.current!.getBoundingClientRect()
@ -181,23 +193,27 @@ function EditorView({
switch (rackedObject.key) { switch (rackedObject.key) {
case "ball": case "ball":
const ballObj = content.objects.findIndex(o => o.type == "ball") const ballObj = content.objects.findIndex(
const playerCollidedIdx = getPlayerCollided(refBounds, content.players) (o) => o.type == "ball",
)
const playerCollidedIdx = getPlayerCollided(
refBounds,
content.players,
)
if (playerCollidedIdx != -1) { if (playerCollidedIdx != -1) {
onBallDropOnPlayer(playerCollidedIdx) onBallDropOnPlayer(playerCollidedIdx)
setContent((content) => { setContent((content) => {
return { return {
...content, ...content,
objects : content.objects.toSpliced(ballObj, 1) objects: content.objects.toSpliced(ballObj, 1),
} }
}) })
return return
} } else {
else {
courtObject = { courtObject = {
type: "ball", type: "ball",
rightRatio: x, rightRatio: x,
bottomRatio: y bottomRatio: y,
} }
} }
break break
@ -207,20 +223,22 @@ function EditorView({
} }
setContent((content) => { setContent((content) => {
return ({ return {
...content, ...content,
objects: [ objects: [...content.objects, courtObject],
...content.objects, }
courtObject,
]
})
}) })
} }
const getPlayerCollided = (bounds: DOMRect, players: Player[]): number | -1 => { const getPlayerCollided = (
bounds: DOMRect,
players: Player[],
): number | -1 => {
for (let i = 0; i < players.length; i++) { for (let i = 0; i < players.length; i++) {
const player = players[i] const player = players[i]
const playerBounds = document.getElementById(player.id)!.getBoundingClientRect() const playerBounds = document
.getElementById(player.id)!
.getBoundingClientRect()
const doesOverlap = !( const doesOverlap = !(
bounds.top > playerBounds.bottom || bounds.top > playerBounds.bottom ||
bounds.right < playerBounds.left || bounds.right < playerBounds.left ||
@ -234,33 +252,50 @@ function EditorView({
return -1 return -1
} }
const onBallDropOnPlayer = (playerCollidedIdx: number) => { const onBallDropOnPlayer = (playerCollidedIdx: number) => {
setContent((content) => { setContent((content) => {
const ballObj = content.objects.findIndex(o => o.type == "ball") const ballObj = content.objects.findIndex((o) => o.type == "ball")
let player = content.players.at(playerCollidedIdx) as Player let player = content.players.at(playerCollidedIdx) as Player
return { return {
...content, ...content,
players: content.players.toSpliced(playerCollidedIdx, 1, {...player, hasBall: true}), players: content.players.toSpliced(playerCollidedIdx, 1, {
objects : content.objects.toSpliced(ballObj, 1) ...player,
hasBall: true,
}),
objects: content.objects.toSpliced(ballObj, 1),
} }
}) })
} }
const onBallDrop = (refBounds: DOMRect) => { const onBallDrop = (refBounds: DOMRect) => {
if (!isBoundsOnCourt(refBounds)) {
setContent((content) => {
const ballObj = content.objects.findIndex(
(o) => o.type == "ball",
)
return {
...content,
objects: content.objects.toSpliced(ballObj, 1),
}
})
setObjects([{ key: "ball" }])
}
const playerCollidedIdx = getPlayerCollided(refBounds, content.players) const playerCollidedIdx = getPlayerCollided(refBounds, content.players)
if (playerCollidedIdx != -1) { if (playerCollidedIdx != -1) {
setContent((content) => { setContent((content) => {
return { return {
...content, ...content,
players: content.players.map((player) => ({...player, hasBall: false})), players: content.players.map((player) => ({
...player,
hasBall: false,
})),
} }
}) })
onBallDropOnPlayer(playerCollidedIdx) onBallDropOnPlayer(playerCollidedIdx)
return return
} }
if(content.objects.findIndex(o => o.type == "ball") != -1) { if (content.objects.findIndex((o) => o.type == "ball") != -1) {
return return
} }
@ -271,17 +306,17 @@ function EditorView({
courtObject = { courtObject = {
type: "ball", type: "ball",
rightRatio: x, rightRatio: x,
bottomRatio: y bottomRatio: y,
} }
setContent((content) => { setContent((content) => {
return { return {
...content, ...content,
players: content.players.map((player) => ({...player, hasBall: false})), players: content.players.map((player) => ({
objects: [ ...player,
...content.objects, hasBall: false,
courtObject, })),
] objects: [...content.objects, courtObject],
} }
}) })
} }
@ -313,7 +348,9 @@ function EditorView({
id="allies-rack" id="allies-rack"
objects={allies} objects={allies}
onChange={setAllies} onChange={setAllies}
canDetach={div => canDetach(div.getBoundingClientRect())} canDetach={(div) =>
isBoundsOnCourt(div.getBoundingClientRect())
}
onElementDetached={onPieceDetach} onElementDetached={onPieceDetach}
render={({ team, key }) => ( render={({ team, key }) => (
<PlayerPiece <PlayerPiece
@ -325,18 +362,24 @@ function EditorView({
)} )}
/> />
<Rack id={"objects"} <Rack
id={"objects"}
objects={objects} objects={objects}
onChange={setObjects} onChange={setObjects}
canDetach={div => canDetach(div.getBoundingClientRect())} canDetach={(div) =>
isBoundsOnCourt(div.getBoundingClientRect())
}
onElementDetached={onObjectDetach} onElementDetached={onObjectDetach}
render={renderCourtObject}/> render={renderCourtObject}
/>
<Rack <Rack
id="opponent-rack" id="opponent-rack"
objects={opponents} objects={opponents}
onChange={setOpponents} onChange={setOpponents}
canDetach={div => canDetach(div.getBoundingClientRect())} canDetach={(div) =>
isBoundsOnCourt(div.getBoundingClientRect())
}
onElementDetached={onPieceDetach} onElementDetached={onPieceDetach}
render={({ team, key }) => ( render={({ team, key }) => (
<PlayerPiece <PlayerPiece
@ -376,9 +419,7 @@ function EditorView({
player, player,
false, false,
), ),
objects: [ objects: [...content.objects],
...content.objects,
]
})) }))
let setter let setter
switch (player.team) { switch (player.team) {
@ -402,10 +443,15 @@ function EditorView({
}} }}
onBallRemove={() => { onBallRemove={() => {
setContent((content) => { setContent((content) => {
const ballObj = content.objects.findIndex(o => o.type == "ball") const ballObj = content.objects.findIndex(
(o) => o.type == "ball",
)
return { return {
...content, ...content,
objects: content.objects.toSpliced(ballObj, 1) objects: content.objects.toSpliced(
ballObj,
1,
),
} }
}) })
setObjects([{ key: "ball" }]) setObjects([{ key: "ball" }])
@ -419,10 +465,10 @@ function EditorView({
} }
function isBallOnCourt(content: TacticContent) { function isBallOnCourt(content: TacticContent) {
if(content.players.findIndex(p => p.hasBall) != -1) { if (content.players.findIndex((p) => p.hasBall) != -1) {
return true return true
} }
return content.objects.findIndex(o => o.type == "ball") != -1 return content.objects.findIndex((o) => o.type == "ball") != -1
} }
function renderCourtObject(courtObject: RackedCourtObject) { function renderCourtObject(courtObject: RackedCourtObject) {

Loading…
Cancel
Save