|
|
|
@ -19,8 +19,8 @@ import { BallPiece } from "../components/editor/BallPiece"
|
|
|
|
|
import { Rack } from "../components/Rack"
|
|
|
|
|
import { PlayerPiece } from "../components/editor/PlayerPiece"
|
|
|
|
|
|
|
|
|
|
import { Tactic, TacticComponent, TacticContent } from "../model/tactic/Tactic"
|
|
|
|
|
import { fetchAPI } from "../Fetcher"
|
|
|
|
|
import { CourtType, Tactic, TacticComponent, TacticContent } from "../model/tactic/Tactic"
|
|
|
|
|
import { fetchAPI, fetchAPIGet } from "../Fetcher"
|
|
|
|
|
|
|
|
|
|
import SavingState, { SaveState, SaveStates } from "../components/editor/SavingState"
|
|
|
|
|
|
|
|
|
@ -49,7 +49,7 @@ import { Action, ActionKind } from "../model/tactic/Action"
|
|
|
|
|
import BallAction from "../components/actions/BallAction"
|
|
|
|
|
import { changePlayerBallState, getOrigin, removePlayer } from "../editor/PlayerDomains"
|
|
|
|
|
import { CourtBall } from "../components/editor/CourtBall"
|
|
|
|
|
import { getSession } from "../api/session.ts"
|
|
|
|
|
import { useParams } from "react-router-dom"
|
|
|
|
|
|
|
|
|
|
const ERROR_STYLE: CSSProperties = {
|
|
|
|
|
borderColor: "red",
|
|
|
|
@ -63,27 +63,81 @@ export interface EditorViewProps {
|
|
|
|
|
tactic: Tactic
|
|
|
|
|
onContentChange: (tactic: TacticContent) => Promise<SaveState>
|
|
|
|
|
onNameChange: (name: string) => Promise<boolean>
|
|
|
|
|
courtType: "PLAIN" | "HALF"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type EditorCreateNewAction = { type: "new", courtType: CourtType }
|
|
|
|
|
type EditorOpenAction = { type: "open" }
|
|
|
|
|
|
|
|
|
|
type EditorAction = EditorCreateNewAction | EditorOpenAction
|
|
|
|
|
|
|
|
|
|
export interface EditorPageProps {
|
|
|
|
|
courtType: "PLAIN" | "HALF"
|
|
|
|
|
action: EditorAction
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function EditorPage({ action }: EditorPageProps) {
|
|
|
|
|
console.log(action)
|
|
|
|
|
if (action.type === "new") {
|
|
|
|
|
return <EditorCreateNew {...action} />
|
|
|
|
|
}
|
|
|
|
|
return <EditorOpen />
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface TacticDto {
|
|
|
|
|
id: number
|
|
|
|
|
name: string
|
|
|
|
|
courtType: CourtType
|
|
|
|
|
content: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function EditorPage({ courtType }: EditorPageProps) {
|
|
|
|
|
|
|
|
|
|
function EditorOpen() {
|
|
|
|
|
const { tacticId: idStr } = useParams()
|
|
|
|
|
const id = parseInt(idStr!)
|
|
|
|
|
|
|
|
|
|
const [tactic, setTactic] = useState<TacticDto>()
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
async function initialize() {
|
|
|
|
|
console.log("initializing")
|
|
|
|
|
const infoResponse = fetchAPIGet(`tactics/${id}`)
|
|
|
|
|
const contentResponse = fetchAPIGet(`tactics/${id}/1`)
|
|
|
|
|
const { name, courtType } = await (await infoResponse).json()
|
|
|
|
|
const { content } = await (await contentResponse).json()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setTactic({ id, name, courtType, content })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initialize()
|
|
|
|
|
}, [id])
|
|
|
|
|
|
|
|
|
|
if (tactic) {
|
|
|
|
|
return <Editor
|
|
|
|
|
id={id}
|
|
|
|
|
courtType={tactic.courtType}
|
|
|
|
|
content={tactic.content}
|
|
|
|
|
name={tactic.name}
|
|
|
|
|
/>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return <EditorLoadingScreen />
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function EditorCreateNew({ courtType }: EditorCreateNewAction) {
|
|
|
|
|
const [id, setId] = useState<number>()
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
async function initialize() {
|
|
|
|
|
const response = await fetchAPI("tactics", { name: DEFAULT_TACTIC_NAME }, "POST", getSession())
|
|
|
|
|
const response = await fetchAPI("tactics", {
|
|
|
|
|
name: DEFAULT_TACTIC_NAME,
|
|
|
|
|
courtType
|
|
|
|
|
}, "POST")
|
|
|
|
|
const { id } = await response.json()
|
|
|
|
|
setId(id)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initialize()
|
|
|
|
|
}, [])
|
|
|
|
|
}, [courtType])
|
|
|
|
|
|
|
|
|
|
if (id) {
|
|
|
|
|
return <Editor
|
|
|
|
@ -94,6 +148,10 @@ export default function EditorPage({ courtType }: EditorPageProps) {
|
|
|
|
|
/>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return <EditorLoadingScreen />
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function EditorLoadingScreen() {
|
|
|
|
|
return <div>Loading Editor, please wait...</div>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -101,7 +159,7 @@ export interface EditorProps {
|
|
|
|
|
id: number
|
|
|
|
|
name: string
|
|
|
|
|
content: string
|
|
|
|
|
courtType: "PLAIN" | "HALF"
|
|
|
|
|
courtType: CourtType
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Editor({ id, name, courtType, content }: EditorProps) {
|
|
|
|
@ -120,6 +178,7 @@ function Editor({ id, name, courtType, content }: EditorProps) {
|
|
|
|
|
tactic={{
|
|
|
|
|
name: editorName,
|
|
|
|
|
id,
|
|
|
|
|
courtType,
|
|
|
|
|
content: JSON.parse(editorContent),
|
|
|
|
|
}}
|
|
|
|
|
onContentChange={async (content: TacticContent) => {
|
|
|
|
@ -130,7 +189,7 @@ function Editor({ id, name, courtType, content }: EditorProps) {
|
|
|
|
|
)
|
|
|
|
|
return SaveStates.Guest
|
|
|
|
|
}
|
|
|
|
|
return fetchAPI(`tactics/${id}/1`, { content }, "PUT", getSession()).then((r) =>
|
|
|
|
|
return fetchAPI(`tactics/${id}/1`, { content }, "PUT").then((r) =>
|
|
|
|
|
r.ok ? SaveStates.Ok : SaveStates.Err,
|
|
|
|
|
)
|
|
|
|
|
}}
|
|
|
|
@ -139,20 +198,18 @@ function Editor({ id, name, courtType, content }: EditorProps) {
|
|
|
|
|
localStorage.setItem(GUEST_MODE_TITLE_STORAGE_KEY, name)
|
|
|
|
|
return true //simulate that the name has been changed
|
|
|
|
|
}
|
|
|
|
|
return fetchAPI(`tactics/${id}/name`, { name }, "PUT", getSession()).then(
|
|
|
|
|
return fetchAPI(`tactics/${id}/name`, { name }, "PUT").then(
|
|
|
|
|
(r) => r.ok,
|
|
|
|
|
)
|
|
|
|
|
}}
|
|
|
|
|
courtType={courtType}
|
|
|
|
|
/>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function EditorView({
|
|
|
|
|
tactic: { id, name, content: initialContent },
|
|
|
|
|
tactic: { id, name, content: initialContent, courtType },
|
|
|
|
|
onContentChange,
|
|
|
|
|
onNameChange,
|
|
|
|
|
courtType,
|
|
|
|
|
}: EditorViewProps) {
|
|
|
|
|
const isInGuestMode = id == -1
|
|
|
|
|
|
|
|
|
|