|
|
|
@ -16,7 +16,9 @@ import halfCourt from "../assets/court/half_court.svg"
|
|
|
|
|
import { Rack } from "../components/Rack"
|
|
|
|
|
import { PlayerPiece } from "../components/editor/PlayerPiece"
|
|
|
|
|
|
|
|
|
|
import { BallPiece } from "../components/editor/BallPiece"
|
|
|
|
|
import {BallPiece, CourtBall} from "../components/editor/BallPiece";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { Player } from "../tactic/Player"
|
|
|
|
|
import { Tactic, TacticContent } from "../tactic/Tactic"
|
|
|
|
|
import { fetchAPI } from "../Fetcher"
|
|
|
|
@ -26,7 +28,8 @@ import SavingState, {
|
|
|
|
|
SaveState,
|
|
|
|
|
SaveStates,
|
|
|
|
|
} from "../components/editor/SavingState"
|
|
|
|
|
import * as Console from "console";
|
|
|
|
|
import {Ball} from "../tactic/Ball";
|
|
|
|
|
import Draggable from "react-draggable";
|
|
|
|
|
|
|
|
|
|
const ERROR_STYLE: CSSProperties = {
|
|
|
|
|
borderColor: "red",
|
|
|
|
@ -57,7 +60,12 @@ interface RackedPlayer {
|
|
|
|
|
key: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function Editor({ id, name, courtType, content }: EditorProps) {
|
|
|
|
|
export default function Editor({
|
|
|
|
|
id,
|
|
|
|
|
name,
|
|
|
|
|
courtType,
|
|
|
|
|
content,
|
|
|
|
|
}: EditorProps) {
|
|
|
|
|
const isInGuestMode = id == -1
|
|
|
|
|
|
|
|
|
|
const storage_content = localStorage.getItem(GUEST_MODE_CONTENT_STORAGE_KEY)
|
|
|
|
@ -96,17 +104,17 @@ export default function Editor({ id, name, courtType, content }: EditorProps) {
|
|
|
|
|
(r) => r.ok,
|
|
|
|
|
)
|
|
|
|
|
}}
|
|
|
|
|
courtType={courtType}
|
|
|
|
|
/>
|
|
|
|
|
courtType={courtType}/>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function EditorView({
|
|
|
|
|
tactic: { id, name, content: initialContent },
|
|
|
|
|
onContentChange,
|
|
|
|
|
onNameChange,
|
|
|
|
|
courtType,
|
|
|
|
|
}: EditorViewProps) {
|
|
|
|
|
tactic: {id, name, content: initialContent},
|
|
|
|
|
onContentChange,
|
|
|
|
|
onNameChange,
|
|
|
|
|
courtType,
|
|
|
|
|
}: EditorViewProps) {
|
|
|
|
|
|
|
|
|
|
const isInGuestMode = id == -1
|
|
|
|
|
|
|
|
|
|
const [titleStyle, setTitleStyle] = useState<CSSProperties>({})
|
|
|
|
@ -131,16 +139,15 @@ function EditorView({
|
|
|
|
|
|
|
|
|
|
const courtDivContentRef = useRef<HTMLDivElement>(null)
|
|
|
|
|
|
|
|
|
|
const canDetach = (ref: HTMLDivElement) => {
|
|
|
|
|
const refBounds = ref.getBoundingClientRect()
|
|
|
|
|
const canDetach = (bounds: DOMRect) => {
|
|
|
|
|
const courtBounds = courtDivContentRef.current!.getBoundingClientRect()
|
|
|
|
|
|
|
|
|
|
// check if refBounds overlaps courtBounds
|
|
|
|
|
return !(
|
|
|
|
|
refBounds.top > courtBounds.bottom ||
|
|
|
|
|
refBounds.right < courtBounds.left ||
|
|
|
|
|
refBounds.bottom < courtBounds.top ||
|
|
|
|
|
refBounds.left > courtBounds.right
|
|
|
|
|
bounds.top > courtBounds.bottom ||
|
|
|
|
|
bounds.right < courtBounds.left ||
|
|
|
|
|
bounds.bottom < courtBounds.top ||
|
|
|
|
|
bounds.left > courtBounds.right
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -163,18 +170,21 @@ function EditorView({
|
|
|
|
|
hasBall: false,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
ball: content.ball
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const onBallDrop = (ref: HTMLDivElement) => {
|
|
|
|
|
const ballBounds = ref.getBoundingClientRect()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const onBallDrop = (ballBounds: DOMRect) => {
|
|
|
|
|
let ballAssigned = false
|
|
|
|
|
|
|
|
|
|
setContent((content) => {
|
|
|
|
|
const players = content.players.map((player) => {
|
|
|
|
|
setContent(content => {
|
|
|
|
|
const players = content.players.map(player => {
|
|
|
|
|
if (ballAssigned) {
|
|
|
|
|
return { ...player, hasBall: false }
|
|
|
|
|
return {...player, hasBall: false}
|
|
|
|
|
}
|
|
|
|
|
const playerBounds = document
|
|
|
|
|
.getElementById(player.id)!
|
|
|
|
@ -190,8 +200,7 @@ function EditorView({
|
|
|
|
|
}
|
|
|
|
|
return { ...player, hasBall: doesOverlap }
|
|
|
|
|
})
|
|
|
|
|
setShowBall(!ballAssigned)
|
|
|
|
|
return { players: players }
|
|
|
|
|
return {players: players, ball: content.ball}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -200,7 +209,8 @@ function EditorView({
|
|
|
|
|
<div id="topbar-div">
|
|
|
|
|
<div id="topbar-left">
|
|
|
|
|
|
|
|
|
|
<SavingState state={saveState} />
|
|
|
|
|
<SavingState state={saveState}/>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
<div id="title-input-div">
|
|
|
|
|
<TitleInput
|
|
|
|
@ -233,12 +243,11 @@ function EditorView({
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
{showBall && (
|
|
|
|
|
<BallPiece
|
|
|
|
|
onDrop={() => onBallDrop(ballPiece.current!)}
|
|
|
|
|
pieceRef={ballPiece}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
{rackBall && <CourtBall onDrop={pos => {
|
|
|
|
|
if (canDetach(pos)) {
|
|
|
|
|
onBallDetach(pos)
|
|
|
|
|
}
|
|
|
|
|
}}/>}
|
|
|
|
|
|
|
|
|
|
<Rack
|
|
|
|
|
id="opponent-rack"
|
|
|
|
@ -260,6 +269,7 @@ function EditorView({
|
|
|
|
|
<div id="court-div-bounds">
|
|
|
|
|
<BasketCourt
|
|
|
|
|
players={content.players}
|
|
|
|
|
ball={content.ball}
|
|
|
|
|
onBallDrop={onBallDrop}
|
|
|
|
|
courtImage={
|
|
|
|
|
courtType == "PLAIN" ? plainCourt : halfCourt
|
|
|
|
@ -272,6 +282,7 @@ function EditorView({
|
|
|
|
|
player,
|
|
|
|
|
true,
|
|
|
|
|
),
|
|
|
|
|
ball: content.ball
|
|
|
|
|
}))
|
|
|
|
|
}}
|
|
|
|
|
onPlayerRemove={(player) => {
|
|
|
|
@ -281,6 +292,7 @@ function EditorView({
|
|
|
|
|
player,
|
|
|
|
|
false,
|
|
|
|
|
),
|
|
|
|
|
ball: content.ball
|
|
|
|
|
}))
|
|
|
|
|
let setter
|
|
|
|
|
switch (player.team) {
|
|
|
|
@ -293,6 +305,7 @@ function EditorView({
|
|
|
|
|
if (player.hasBall) {
|
|
|
|
|
setShowBall(true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setter((players) => [
|
|
|
|
|
...players,
|
|
|
|
|
{
|
|
|
|
|