This commit is contained in:
CanbiZ 2025-02-07 10:58:22 +01:00
parent 135010dc8e
commit 3cc7a8ceea
5 changed files with 76 additions and 21 deletions

View File

@ -23,7 +23,7 @@ import { fetchCategories } from "@/lib/data";
import { Category } from "@/lib/types";
import { cn } from "@/lib/utils";
import { format } from "date-fns";
import { CalendarIcon, Check, Clipboard } from "lucide-react";
import { CalendarIcon, Check, Clipboard, Download } from "lucide-react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { toast } from "sonner";
import { z } from "zod";
@ -97,6 +97,21 @@ export default function JSONGenerator() {
toast.success("Copied metadata to clipboard");
}, [script]);
const handleDownload = useCallback(() => {
const jsonString = JSON.stringify(script, null, 2);
const blob = new Blob([jsonString], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `${script.slug || "script"}.json`;
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(url);
document.body.removeChild(a);
}, [script]);
const handleDateSelect = useCallback(
(date: Date | undefined) => {
updateScript("date_created", format(date || new Date(), "yyyy-MM-dd"));
@ -313,18 +328,26 @@ export default function JSONGenerator() {
<div className="w-1/2 p-4 bg-background overflow-y-auto">
{validationAlert}
<div className="relative">
{/* Copy Button */}
<Button
className="absolute right-2 top-2"
className="absolute right-10 top-2"
size="icon"
variant="outline"
onClick={handleCopy}
>
{isCopied ? (
<Check className="h-4 w-4" />
) : (
<Clipboard className="h-4 w-4" />
)}
{isCopied ? <Check className="h-4 w-4" /> : <Clipboard className="h-4 w-4" />}
</Button>
{/* Download Button */}
<Button
className="absolute right-2 top-2"
size="icon"
variant="outline"
onClick={handleDownload}
>
<Download className="h-4 w-4" />
</Button>
<pre className="mt-4 p-4 bg-secondary rounded shadow overflow-x-scroll">
{JSON.stringify(script, null, 2)}
</pre>
@ -332,4 +355,4 @@ export default function JSONGenerator() {
</div>
</div>
);
}
}

View File

@ -57,7 +57,7 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="en" suppressHydrationWarning>
<html lang="en" className="dark" suppressHydrationWarning>
<head>
<script
defer
@ -69,17 +69,12 @@ export default function RootLayout({
<link rel="preconnect" href="https://api.github.com" />
</head>
<body className={inter.className}>
<ThemeProvider
attribute="class"
defaultTheme="dark"
enableSystem
disableTransitionOnChange
>
<ThemeProvider>
<div className="flex w-full flex-col justify-center">
<Navbar />
<div className="flex min-h-screen flex-col justify-center">
<div className="flex w-full justify-center">
<div className="w-full max-w-7xl ">
<div className="w-full max-w-7xl">
<NuqsAdapter>{children}</NuqsAdapter>
<Toaster richColors />
</div>

View File

@ -14,7 +14,7 @@ import Particles from "@/components/ui/particles";
import { Separator } from "@/components/ui/separator";
import { basePath } from "@/config/siteConfig";
import { cn } from "@/lib/utils";
import { ArrowRightIcon, ExternalLink } from "lucide-react";
import { ArrowRightIcon, ExternalLink, FileJson, Server } from "lucide-react";
import { useTheme } from "next-themes";
import Link from "next/link";
import { useEffect, useState } from "react";

View File

@ -1,12 +1,14 @@
import { basePath } from "@/config/siteConfig";
import Link from "next/link";
import { FileJson, Server, ExternalLink } from "lucide-react";
export default function Footer() {
return (
<div className="supports-backdrop-blur:bg-background/90 mt-auto flex border-t border-border bg-background/40 py-6 backdrop-blur-lg">
<div className="flex w-full justify-between">
<div className="mx-6 w-full max-w-7xl text-xs sm:text-sm text-muted-foreground">
Website built by the community. The source code is avaliable on{" "}
<div className="mx-6 w-full max-w-7xl flex justify-between text-xs sm:text-sm text-muted-foreground">
{/* Link zu GitHub (links) */}
<div>
Website built by the community. The source code is available on{" "}
<Link
href={`https://github.com/community-scripts/${basePath}`}
target="_blank"
@ -18,7 +20,27 @@ export default function Footer() {
</Link>
.
</div>
{/* Neue Links (rechts) */}
<div className="flex gap-4">
{/* JSON Editor */}
<Link
href="/json-editor"
className="flex items-center gap-2 text-primary hover:underline"
>
<FileJson className="h-4 w-4" /> JSON Editor
</Link>
{/* API (jetzt auf /data) */}
<Link
href="/data"
className="flex items-center gap-2 text-primary hover:underline"
>
<Server className="h-4 w-4" /> API Documentation
</Link>
</div>
</div>
</div>
);
}

View File

@ -2,7 +2,22 @@
import { ThemeProvider as NextThemesProvider } from "next-themes";
import { type ThemeProviderProps } from "next-themes/dist/types";
import { useEffect, useState } from "react";
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
return <div className="bg-black h-screen w-screen" />;
}
return (
<NextThemesProvider attribute="class" defaultTheme="dark" enableSystem {...props}>
{children}
</NextThemesProvider>
);
}