import { IssueTrackerContext } from "@thorium/components/useIssueTracker"; import { toast } from "@thorium/context/ToastContext"; import Button from "@thorium/ui/Button"; import Input from "@thorium/ui/Input"; import MarkdownInput from "@thorium/ui/MarkdownInput"; import Modal from "@thorium/ui/Modal"; import randomWords from "@thorium/utils/random-words"; import { type Dispatch, type ReactNode, type SetStateAction, useEffect, useState } from "react"; import packageJson from "../../package.json" with { type: "json" }; import { useThoriumAccount } from "../context/ThoriumAccountContext"; import LoginButton from "./LoginButton"; import { Icon } from "./ui/Icon"; const availableLabels = ["Feature", "Bug", "Design", "Documentation", "Question", "Compliment"]; export const IssueTrackerProvider = ({ children }: { children: ReactNode }) => { const [open, setOpen] = useState(false); return ( {children} ); }; function IssueTracker({ open, setOpen, }: { open: boolean; setOpen: Dispatch>; }) { const { account, refresh } = useThoriumAccount(); const [body, setBody] = useState(""); const [invalid, setInvalid] = useState([]); useEffect( function revalidateOnVisibilityChange() { if (!open) return; function onVisibilityChange() { refresh(); } window.addEventListener("visibilitychange", onVisibilityChange); return () => window.removeEventListener("visibilitychange", onVisibilityChange); }, [refresh, open], ); useEffect( function revalidateOnFocus() { if (!open) return; function onFocus() { refresh(); } window.addEventListener("focus", onFocus); return () => window.removeEventListener("focus", onFocus); }, [refresh, open], ); return ( setOpen(open)} title="Submit an Issue"> {!account ? (

Sign in to Submit Issues

To better track issues and collect feedback, you must be logged in to a Thorium Nova account.

) : !account.accounts?.includes("github") ? (

Connect to Github

To submit issues, you must connect your Thorium Nova account to Github.

Connect Account
) : (
{ event.preventDefault(); const title = event.currentTarget.issueTitle.value; const label = event.currentTarget.label.value; let isInvalid = false; if (!title) { isInvalid = true; setInvalid((invalid) => invalid.concat("title")); } if (!label || label === "Select One") { isInvalid = true; setInvalid((invalid) => invalid.concat("type")); } if (isInvalid) { return; } const requestBody = { repo: "thorium-nova", title, body: `${body} ### Version: ${packageJson.version}`, labels: [label], }; setOpen(false); try { const response = await fetch(`${process.env.THORIUMSIM_URL}/api/issues`, { method: "POST", body: JSON.stringify(requestBody), headers: { "Content-Type": "application/json", Authorization: `Bearer ${account.access_token}`, }, }); const result = (await response.json()) as any; if (!response.ok || result.error) { toast({ title: "Error Submitting Issue", body: result.error || "An unknown error occurred", color: "error", }); return; } toast({ title: "Issue Submitted!", color: "success" }); setBody(""); } catch (err) { if (err instanceof Error) { toast({ title: "Error Submitting Issue", body: err.message || "An unknown error occurred", color: "error", }); } if (typeof err === "string") { toast({ title: "Error Submitting Issue", body: err || "An unknown error occurred", color: "error", }); } } }} > setInvalid(invalid.filter((i) => i !== "title"))} /> e.target.value !== "Select One" && setInvalid(invalid.filter((i) => i !== "type")) } name="label" > {availableLabels.map((label) => ( ))}
)}
); }