"use client"; import { MOD_ENDPOINT, PACK_ENDPOINT, PACKS_ENDPOINT } from "@/api/ENDPOINTS"; import { Pack } from "@/types/pack"; import { Button, Card, Label, Select, Spinner, TextInput, } from "flowbite-react"; import { useSearchParams } from "next/navigation"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import { Modal, ModalBody, ModalFooter, ModalHeader } from "flowbite-react"; import { HiDownload, HiPlusCircle, HiTrash } from "react-icons/hi"; import { ModTable } from "../components/ModTable"; import { toast } from "react-toastify"; export default function PackPage() { const [packData, setPackData] = useState(null); const [packDataLoading, setPackDataLoading] = useState(true); const router = useRouter(); const id = useSearchParams().get("id") || ""; const [addModModalOpen, setAddModModalOpen] = useState(true); const [modSource, setModSource] = useState<"Modrinth" | "CurseForge">( "Modrinth" ); const [modUrl, setModUrl] = useState({ placeholer: "https://modrinth.com/mod/{ slug }", value: "", }); // const [modParams, setModParams] = useState<{ // slug: string; // version: string | null; // }>({ // slug: "", // version: null, // }); async function _getPacksData() { const res = await fetch(PACK_ENDPOINT("getPack", id)); if (!res.ok) router.push("/404"); const data: Pack = await res.json(); setPackData(data); setPackDataLoading(false); } useEffect(() => { if (id) { _getPacksData(); } else { router.push("/404"); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // eslint-disable-next-line @typescript-eslint/no-explicit-any const handleImageUpdate = (e: any) => { if (!packData || !window) return; const file = e.target.files[0]; const fileReader = new FileReader(); fileReader.onloadend = () => { const content = fileReader.result; fetch(`${PACK_ENDPOINT("editPackImage", packData._id)}`, { method: "POST", body: JSON.stringify({ image: content, mimetype: file.type, }), headers: { "content-type": "application/json", accept: "application/json", }, }).then(() => location.reload()); e.target.value = ""; }; fileReader.readAsDataURL(file); }; function deletePack() { if (!packData || !window) return; if (window.confirm(`Delete pack ${packData.title}?`)) { fetch(`${PACKS_ENDPOINT("deletePack", packData._id)}`); const ur = new URL(window.location.href); ur.searchParams.delete("id"); ur.pathname = "/"; window.location.href = ur.href; } } // eslint-disable-next-line @typescript-eslint/no-explicit-any const handleModSource = (e: any) => { switch (e.target.value) { case "Modrinth": setModSource("Modrinth"); setModUrl({ placeholer: "https://modrinth.com/mod/{ slug }", value: "", }); break; case "CurseForge": setModSource("CurseForge"); setModUrl({ placeholer: "https://www.curseforge.com/minecraft/mc-mods/{ slug }", value: "", }); break; } }; async function addMod() { let slug = null; let version = null; if (!modUrl.value) { toast.error("Mod url is required", { autoClose: 2500, closeOnClick: true, draggable: true, }); return; } switch (modSource) { case "Modrinth": const _tmp = modUrl.value.split("/mod/"); if (_tmp.length == 1) { toast.error("invalid Modrinth url", { autoClose: 2500, closeOnClick: true, draggable: true, }); return; } const _tmp2 = _tmp[1].split("/version/"); slug = _tmp2[0]; if (_tmp2.length > 1) { version = _tmp2[1]; } break; case "CurseForge": const _tmp3 = modUrl.value.split("/mc-mods/"); if (_tmp3.length == 1) { toast.error("invalid CurseForge url", { autoClose: 2500, closeOnClick: true, draggable: true, }); return; } const _tmp4 = _tmp3[1].split("/files/"); slug = _tmp4[0]; if (_tmp4.length > 1) { version = _tmp4[1]; } break; } slug = slug.replace("/", ""); version = version ? version.replace("/", "") : null; // if (packMods.find((elem) => elem.slug == slug)) { // toast.error(`mod (${slug}) already exists`, { // autoClose: 2500, // closeOnClick: true, // draggable: true, // }); // return; // } if (!packData) return; const tid = toast.loading(`Adding mod`); const res = await fetch(MOD_ENDPOINT("addMod", packData._id), { method: "POST", body: JSON.stringify({ slug, version, source: modSource, }), headers: { "content-type": "application/json", accept: "application/json", }, }); const data = await res.json(); if (data.status != "ok") { toast.update(tid, { render: data.message, type: "error", isLoading: false, autoClose: 2500, closeOnClick: true, draggable: true, }); return; } toast.update(tid, { render: data.message, type: "success", isLoading: false, autoClose: 2500, closeOnClick: true, draggable: true, }); setModUrl({ ...modUrl, value: "" }); _getPacksData(); } return (
{packDataLoading && (
)} {packData && (

{packData.version}

{packData.modloader}

handleImageUpdate(e)} id="pack-icon" className="hidden" name="image" type="file" />

{packData.title}

by {packData.author}

{packData.mods.length} mods

v{packData.modpackVersion}

)} setAddModModalOpen(false)} > Terms of Service
setModUrl({ ...modUrl, value: e.target.value }) } value={modUrl.value} placeholder={modUrl.placeholer} required />
); }