"use client"; import Image from "next/image"; import { Separator } from "@app/components/ui/separator"; import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext"; import { useState, useTransition } from "react"; import { Popover, PopoverContent, PopoverTrigger } from "@app/components/ui/popover"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@app/components/ui/tooltip"; import { Button } from "./ui/button"; import { Credenza, CredenzaBody, CredenzaClose, CredenzaContent, CredenzaDescription, CredenzaFooter, CredenzaHeader, CredenzaTitle } from "./Credenza"; import { z } from "zod"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "./ui/form"; import { Input } from "./ui/input"; import { toast } from "@app/hooks/useToast"; import { createApiClient, formatAxiosError } from "@app/lib/api"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { AxiosResponse } from "axios"; import { ValidateSupporterKeyResponse } from "@server/routers/supporterKey"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "./ui/card"; import { Check, ExternalLink, Heart } from "lucide-react"; import confetti from "canvas-confetti"; import { useTranslations } from "next-intl"; interface SupporterStatusProps { isCollapsed?: boolean; } export default function SupporterStatus({ isCollapsed = false }: SupporterStatusProps) { const { supporterStatus, updateSupporterStatus } = useSupporterStatusContext(); const [supportOpen, setSupportOpen] = useState(false); const [keyOpen, setKeyOpen] = useState(false); const [purchaseOptionsOpen, setPurchaseOptionsOpen] = useState(false); const { env } = useEnvContext(); const api = createApiClient({ env }); const t = useTranslations(); const formSchema = z.object({ githubUsername: z.string().nonempty({ error: "GitHub username is required" }), key: z.string().nonempty({ error: "Supporter key is required" }) }); const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { githubUsername: "", key: "" } }); async function hide() { await api.post("/supporter-key/hide"); updateSupporterStatus({ visible: false }); } async function onSubmit(values: z.infer) { try { const res = await api.post< AxiosResponse >("/supporter-key/validate", { githubUsername: values.githubUsername, key: values.key }); const data = res.data.data; if (!data || !data.valid) { toast({ variant: "destructive", title: t("supportKeyInvalid"), description: t("supportKeyInvalidDescription") }); return; } // Trigger the toast toast({ variant: "default", title: t("supportKeyValid"), description: t("supportKeyValidDescription") }); // Fireworks-style confetti const duration = 5 * 1000; // 5 seconds const animationEnd = Date.now() + duration; const defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0, colors: ["#FFA500", "#FF4500", "#FFD700"] // Orange hues }; function randomInRange(min: number, max: number) { return Math.random() * (max - min) + min; } const interval = setInterval(() => { const timeLeft = animationEnd - Date.now(); if (timeLeft <= 0) { clearInterval(interval); return; } const particleCount = 50 * (timeLeft / duration); // Launch confetti from two random horizontal positions confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } }); confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } }); }, 250); setPurchaseOptionsOpen(false); setKeyOpen(false); updateSupporterStatus({ visible: false }); } catch (error) { toast({ variant: "destructive", title: t("error"), description: formatAxiosError( error, t("supportKeyErrorValidationDescription") ) }); return; } } return ( <> { setPurchaseOptionsOpen(val); }} > {t("supportKey")}

{t("supportKeyDescription")}

{t("supportKeyPet")}

{t("supportKeyPurchase")}{" "} {t("supportKeyPurchaseLink")} {" "} {t("supportKeyPurchase2")}{" "} {t("supportKeyLearnMore")}

{t("supportKeyOptions")}

{t("supportKetOptionFull")}

$95

  • {t("forWholeServer")}
  • {t("lifetimePurchase")}
  • {t("supporterStatus")}
{t("supportKeyOptionLimited")}

$25

  • {t("forFiveUsers")}
  • {t("lifetimePurchase")}
  • {t("supporterStatus")}
{supporterStatus?.tier !== "Limited Supporter" ? ( ) : ( )}
{ setKeyOpen(val); }} > {t("supportKeyEnter")} {t("supportKeyEnterDescription")}
( {t("githubUsername")} )} /> ( {t("supportKeyInput")} )} />
{supporterStatus?.visible ? ( isCollapsed ? (

{t("supportKeyBuy")}

) : ( ) ) : null} ); }