From a65d6d9127c3fa7f6a8ecaec5d1ffd1f47c2bc98 Mon Sep 17 00:00:00 2001 From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:08:53 +0300 Subject: refactor: port to typescript --- frontend/src/components/ModMenu.tsx | 324 ++++++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 frontend/src/components/ModMenu.tsx (limited to 'frontend/src/components/ModMenu.tsx') diff --git a/frontend/src/components/ModMenu.tsx b/frontend/src/components/ModMenu.tsx new file mode 100644 index 0000000..1fe4239 --- /dev/null +++ b/frontend/src/components/ModMenu.tsx @@ -0,0 +1,324 @@ +import React from 'react'; +import ReactMarkdown from 'react-markdown'; + +import { MapSummary } from '../types/Map'; +import { ModMenuContent } from '../types/Content'; +import { API } from '../api/Api'; +import "../css/ModMenu.css" + +interface ModMenuProps { + data: MapSummary; + selectedRun: number; + mapID: string; +} + +const ModMenu: React.FC = ({ data, selectedRun, mapID }) => { + + const [menu, setMenu] = React.useState(0); + const [showButton, setShowButton] = React.useState(1) + + const [routeContent, setRouteContent] = React.useState({ + id: 0, + name: "", + score: 0, + date: "", + showcase: "", + description: "No description available.", + category_id: 1, + }); + + const [image, setImage] = React.useState(""); + const [md, setMd] = React.useState(""); + + function compressImage(file: File): Promise { + const reader = new FileReader(); + reader.readAsDataURL(file); + return new Promise(resolve => { + reader.onload = () => { + const img = new Image(); + if (typeof reader.result === "string") { + img.src = reader.result; + img.onload = () => { + let { width, height } = img; + if (width > 550) { + height *= 550 / width; + width = 550; + } + if (height > 320) { + width *= 320 / height; + height = 320; + } + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + canvas.getContext('2d')!.drawImage(img, 0, 0, width, height); + resolve(canvas.toDataURL(file.type, 0.6)); + }; + } + }; + }); + }; + + const _edit_map_summary_image = async () => { + if (window.confirm("Are you sure you want to submit this to the database?")) { + await API.put_map_image(mapID, image); + } + }; + + const _edit_map_summary_route = async () => { + if (window.confirm("Are you sure you want to submit this to the database?")) { + await API.put_map_summary(mapID, routeContent); + } + }; + + const _create_map_summary_route = async () => { + if (window.confirm("Are you sure you want to submit this to the database?")) { + await API.post_map_summary(mapID, routeContent); + } + }; + + const _delete_map_summary_route = async () => { + if (window.confirm(`Are you sure you want to delete this run from the database? + ${data.summary.routes[selectedRun].category.name} ${data.summary.routes[selectedRun].history.score_count} portals ${data.summary.routes[selectedRun].history.runner_name}`)) { + await API.delete_map_summary(mapID, data.summary.routes[selectedRun].route_id); + } + }; + + React.useEffect(() => { + if (menu === 3) { // add route + setRouteContent({ + id: 0, + name: "", + score: 0, + date: "", + showcase: "", + description: "No description available.", + category_id: 1, + }); + setMd("No description available."); + } + if (menu === 2) { // edit route + setRouteContent({ + id: data.summary.routes[selectedRun].route_id, + name: data.summary.routes[selectedRun].history.runner_name, + score: data.summary.routes[selectedRun].history.score_count, + date: data.summary.routes[selectedRun].history.date.split("T")[0], + showcase: data.summary.routes[selectedRun].showcase, + description: data.summary.routes[selectedRun].description, + category_id: data.summary.routes[selectedRun].category.id, + }); + setMd(data.summary.routes[selectedRun].description); + } + }, [menu]); + + React.useEffect(() => { + const modview = document.querySelector("div#modview") as HTMLElement + if (modview) { + showButton ? modview.style.transform = "translateY(-68%)" + : modview.style.transform = "translateY(0%)" + } + + const modview_block = document.querySelector("#modview_block") as HTMLElement + if (modview_block) { + showButton === 1 ? modview_block.style.display = "none" : modview_block.style.display = "block"// eslint-disable-next-line + } + }, [showButton]) + + return ( +
+ +
+
+ + + + +
+
+ {showButton ? ( + + ) : ( + + )} +
+
+ +
+ { // Edit Image + menu === 1 && ( +
+
+ Current Image: + missing +
+ +
+ New Image: + { + if (e.target.files) { + compressImage(e.target.files[0]) + .then(d => setImage(d)) + } + } + } /> + {image ? () : } + + +
+
+ ) + } + + { // Edit Route + menu === 2 && ( +
+
+ Route ID: + +
+
+ Runner Name: + { + setRouteContent({ + ...routeContent, + name: e.target.value, + }); + }} /> +
+
+ Score: + { + setRouteContent({ + ...routeContent, + score: parseInt(e.target.value), + }); + }} /> +
+
+ Date: + { + setRouteContent({ + ...routeContent, + date: e.target.value, + }); + }} /> +
+
+ Showcase Video: + { + setRouteContent({ + ...routeContent, + showcase: e.target.value, + }); + }} /> +
+
+ Description: +