import { Button, ButtonGroup, Flex } from "@chakra-ui/react"; import { t, Trans } from "@lingui/macro"; import Breadcrumbs from "components/common/Breadcrumbs"; import { stages } from "lib/lists/stages"; import { NextPage } from "next"; import dynamic from "next/dynamic"; import { useEffect, useRef, useState } from "react"; import { FaBomb, FaFileDownload, FaFileImage, FaFileUpload, } from "react-icons/fa"; import DraggableImageAdder from "./DraggableImageAdder"; import DraggableToolsSelector from "./DraggableToolsSelector"; import StageSelector from "./StageSelector"; const MapSketch = dynamic(() => import("./MapSketch"), { ssr: false, }); export type Tool = "pencil" | "line" | "rectangle" | "circle" | "select"; export interface PlannerMapBg { view?: "M" | "R"; stage: string; mode?: "SZ" | "TC" | "RM" | "CB"; tide?: "low" | "mid" | "high"; } const stageToCode = new Map([ ["Ancho-V Games", "AG"], ["Arowana Mall", "AM"], ["Blackbelly Skatepark", "BS"], ["Camp Triggerfish", "CT"], ["Goby Arena", "GA"], ["Humpback Pump Track", "HP"], ["Inkblot Art Academy", "IA"], ["Kelp Dome", "KD"], ["Musselforge Fitness", "MF"], ["MakoMart", "MK"], ["Manta Maria", "MM"], ["Moray Towers", "MT"], ["New Albacore Hotel", "NA"], ["Port Mackerel", "PM"], ["Piranha Pit", "PP"], ["Snapper Canal", "SC"], ["Shellendorf Institute", "SI"], ["Starfish Mainstage", "SM"], ["Skipper Pavilion", "SP"], ["Sturgeon Shipyard", "SS"], ["The Reef", "TR"], ["Wahoo World", "WH"], ["Walleye Warehouse", "WW"], ]); const plannerMapBgToImage = (bg: PlannerMapBg) => { if (!bg.tide) return `images/plannerMaps/${bg.view} ${stageToCode.get(bg.stage)} ${ bg.mode }.png`; return `images/plannerMaps/${bg.stage}-${bg.tide}.png`; }; const defaultValue = { shadowWidth: 0, shadowOffset: 0, enableRemoveSelected: false, fillWithColor: false, fillWithBackgroundColor: false, drawings: [], canUndo: false, canRedo: false, controlledSize: false, sketchWidth: 600, sketchHeight: 600, stretched: true, stretchedX: false, stretchedY: false, originX: "left", originY: "top", expandTools: false, expandControls: false, expandColors: false, expandBack: false, expandImages: false, expandControlled: false, enableCopyPaste: false, backgroundImage: { type: "image", version: "2.4.3", originX: "left", originY: "top", left: 0, top: 0, width: 1127, height: 634, fill: "rgb(0,0,0)", stroke: null, strokeWidth: 0, strokeDashArray: null, strokeLineCap: "butt", strokeLineJoin: "miter", strokeMiterLimit: 4, scaleX: 1, scaleY: 1, angle: 0, flipX: false, flipY: false, opacity: 1, shadow: null, visible: true, clipTo: null, backgroundColor: "", fillRule: "nonzero", paintFirst: "fill", globalCompositeOperation: "source-over", transformMatrix: null, skewX: 0, skewY: 0, crossOrigin: "", cropX: 0, cropY: 0, src: "/images/plannerMaps/M%20TR%20SZ.png", filters: [], }, }; const MapPlannerPage: NextPage = () => { const fileInput = useRef(null); const sketch = useRef(null); const [tool, setTool] = useState("pencil"); const [color, setColor] = useState("#f44336"); const [canUndo, setCanUndo] = useState(false); const [canRedo, setCanRedo] = useState(false); const [bg, setBg] = useState({ view: "M", stage: "The Reef", mode: "SZ", }); const [controlledValue, setControlledValue] = useState(defaultValue); const addImageToSketch = (imgSrc: string) => { sketch.current.addImg(imgSrc); setTool("select"); }; const addTextToSketch = () => { sketch.current.addText("Double-click to edit", { fill: color, fontFamily: "lato", stroke: "#000000", strokeWidth: 3, paintFirst: "stroke", }); setTool("select"); }; const undo = () => { sketch.current.undo(); setCanUndo(sketch.current.canUndo()); setCanRedo(sketch.current.canRedo()); }; const redo = () => { sketch.current.redo(); setCanUndo(sketch.current.canUndo()); setCanRedo(sketch.current.canRedo()); }; const removeSelected = () => { sketch.current.removeSelected(); }; const onSketchChange = () => { if (!sketch.current) return; let prev = canUndo; let now = sketch.current.canUndo(); if (prev !== now) { setCanUndo(now); } }; const getDateFormatted = () => { const today = new Date(); const date = today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate(); const time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(); return date + " " + time; }; const download = (dataUrl: string, extension: string) => { if (!bg) return; let a = document.createElement("a"); document.body.appendChild(a); a.style.display = "none"; a.href = dataUrl; a.download = `${bg.stage} plans ${getDateFormatted()}.${extension}`; a.click(); window.URL.revokeObjectURL(dataUrl); }; const handleUpload = () => { if (!fileInput.current) { return; } fileInput.current.click(); }; const files = fileInput.current?.files; useEffect(() => { if (!fileInput.current?.files?.length) return; const fileObj = fileInput.current.files[0]; const reader = new FileReader(); reader.onload = function (event) { const jsonObj = JSON.parse(event.target!.result as any); setControlledValue(jsonObj); const imgSrc = jsonObj.backgroundImage.src; const searchFolder = "plannerMaps"; const imgName = imgSrc .slice(imgSrc.lastIndexOf(searchFolder) + searchFolder.length + 1, -4) .replace(/%20/g, " "); const salmonRunMaps = [ "Spawning Grounds", "Marooner's Bay", "Lost Outpost", "Salmonid Smokeyard", "Ruins of Ark Polaris‎‎", ]; let isSalmonRunMap = false; for (const map of salmonRunMaps) { if (imgName.startsWith(map)) { isSalmonRunMap = true; const imageNameParts = imgName.split("-"); if (imageNameParts.length > 1) { const tide = imageNameParts[1]; setBg({ tide: tide, stage: map }); } } } if (!isSalmonRunMap) { const imageNameParts = imgName.split(" "); if (imageNameParts.length > 2) { const view = imageNameParts[0]; const mapCode = imageNameParts[1]; const mode = imageNameParts[2]; let mapName = ""; stageToCode.forEach((value, key) => { if (value === mapCode) { mapName = key; } }); setBg({ view, stage: mapName, mode }); } } }; reader.readAsText(fileObj); }, [files]); useEffect(() => { if (!sketch.current) return; setCanUndo(false); sketch.current.setBackgroundFromDataUrl(plannerMapBgToImage(bg)); // eslint-disable-next-line react-hooks/exhaustive-deps }, [bg]); return ( <> setColor(newColor)} /> addImageToSketch(imgSrc)} /> { const newStage = e.target.value; if (newStage === "") { return; } const newIsSalmonRunStage = !stages.includes(newStage as any); const oldIsSalmonRunStage = !stages.includes(bg.stage as any); if (newIsSalmonRunStage === oldIsSalmonRunStage) { setBg({ ...bg, stage: e.target.value }); return; } if (newIsSalmonRunStage) { setBg({ stage: e.target.value, tide: "mid" }); return; } setBg({ stage: e.target.value, mode: "SZ", view: "M" }); }} currentBackground={bg} changeMode={(mode) => setBg({ ...bg, mode })} changeTide={(tide: "low" | "mid" | "high") => setBg({ ...bg, tide })} changeView={(view: "M" | "R") => setBg({ ...bg, view })} /> setBg({ ...bg })} /> ); }; export default MapPlannerPage;