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.
82 lines
2.4 KiB
82 lines
2.4 KiB
import { ReactElement, ReactNode, RefObject, useEffect, useState } from "react"
|
|
import { Action } from "../../model/tactic/Action"
|
|
|
|
import { CourtAction } from "./CourtAction"
|
|
import {
|
|
ComponentId,
|
|
CourtType,
|
|
TacticComponent,
|
|
} from "../../model/tactic/TacticInfo.ts"
|
|
import PlainCourt from "../../assets/court/full_court.svg?react"
|
|
import HalfCourt from "../../assets/court/half_court.svg?react"
|
|
|
|
import "../../style/court.css"
|
|
|
|
export interface BasketCourtProps {
|
|
components: TacticComponent[]
|
|
parentComponents: TacticComponent[] | null
|
|
previewAction?: ActionPreview | null
|
|
|
|
renderComponent: (comp: TacticComponent, isFromParent: boolean) => ReactNode
|
|
renderActions: (comp: TacticComponent, isFromParent: boolean) => ReactNode[]
|
|
|
|
courtImage: ReactElement
|
|
courtRef: RefObject<HTMLDivElement>
|
|
}
|
|
|
|
export interface ActionPreview extends Action {
|
|
origin: ComponentId
|
|
isInvalid: boolean
|
|
}
|
|
|
|
export function BasketCourt({
|
|
components,
|
|
parentComponents,
|
|
previewAction,
|
|
|
|
renderComponent,
|
|
renderActions,
|
|
|
|
courtImage,
|
|
courtRef,
|
|
}: BasketCourtProps) {
|
|
const [court, setCourt] = useState(courtRef.current)
|
|
|
|
//force update once the court reference is set
|
|
useEffect(() => {
|
|
setCourt(courtRef.current)
|
|
}, [courtRef])
|
|
|
|
return (
|
|
<div
|
|
className="court-container"
|
|
ref={courtRef}
|
|
style={{ position: "relative" }}>
|
|
{courtImage}
|
|
|
|
{court && parentComponents?.map((i) => renderComponent(i, true))}
|
|
{court && parentComponents?.flatMap((i) => renderActions(i, true))}
|
|
|
|
{court && components.map((i) => renderComponent(i, false))}
|
|
{court && components.flatMap((i) => renderActions(i, false))}
|
|
|
|
{previewAction && (
|
|
<CourtAction
|
|
courtRef={courtRef}
|
|
action={previewAction}
|
|
origin={previewAction.origin}
|
|
color={previewAction.isInvalid ? "red" : "black"}
|
|
isEditable={true}
|
|
/>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function Court({ courtType }: { courtType: CourtType }) {
|
|
const CourtSvg = courtType === "PLAIN" ? PlainCourt : HalfCourt
|
|
const courtSpecificClassName =
|
|
courtType === "PLAIN" ? "plain-court" : "half-court"
|
|
return <CourtSvg className={`court-image ${courtSpecificClassName}`} />
|
|
}
|