"use client" import { useRouter } from "next/navigation" import { useState, useSyncExternalStore, useTransition } from "react" import { CopyPlusIcon, DownloadIcon, ExternalLinkIcon, RefreshCwIcon, Trash2Icon } from "lucide-react" import { Button, buttonVariants } from "@/components/ui/button" import { CopyField } from "@/modules/admin/ui/components/copy-field" import { deleteVariant, duplicateVariant, updateShare } from "../../../actions/variants" import { dateFormat, SHARE_EXPIRY_OPTIONS } from "../../../lib/preview" import type { EditorVariant } from "../../views/variant-editor" const selectClass = "h-10 w-full rounded-md border bg-background px-3 text-sm outline-none focus-visible:ring-3 focus-visible:ring-ring/50" const subscribe = () => () => {} function Heading({ title, text }: { title: string; text?: string }) { return (

{title}

{text &&

{text}

}
) } export function SharePanel({ variant, clients, clientId, onClientChange, dirty }: { variant: EditorVariant clients: { id: string; name: string }[] clientId: string | null onClientChange: (clientId: string | null) => void dirty: boolean }) { const router = useRouter() const origin = useSyncExternalStore(subscribe, () => window.location.origin, () => "") const [share, setShare] = useState({ token: variant.shareToken, expiresAt: variant.shareExpiresAt, expired: variant.shareState === "expired" }) // -1 = bestehendes Ablaufdatum beibehalten const [expiry, setExpiry] = useState(variant.shareExpiresAt ? -1 : 0) const [confirmDelete, setConfirmDelete] = useState(false) const [exporting, setExporting] = useState(false) const [error, setError] = useState(null) const [pending, startTransition] = useTransition() function run(action: () => Promise<{ error: string } | unknown>) { startTransition(async () => { const result = await action() if (result && typeof result === "object" && "error" in result) setError(String(result.error)) else setError(null) }) } function applyShare(enabled: boolean, options: { regenerate?: boolean; days?: number } = {}) { run(async () => { const days = options.days ?? (expiry < 0 ? 0 : expiry) const result = await updateShare(variant.id, { enabled, expiresInDays: days, regenerate: options.regenerate }) if (!("error" in result)) { setShare({ ...result, expired: false }) setExpiry(result.expiresAt ? days : 0) } return result }) } async function exportProject() { setExporting(true) try { const response = await fetch(`/api/templates/${variant.id}/export`) if (!response.ok) { const body = await response.json().catch(() => null) setError(body?.error ?? "Export fehlgeschlagen.") return } const fileName = /filename="([^"]+)"/.exec(response.headers.get("Content-Disposition") ?? "")?.[1] ?? "website.zip" const link = document.createElement("a") link.href = URL.createObjectURL(await response.blob()) link.download = fileName link.click() URL.revokeObjectURL(link.href) setError(null) } catch { setError("Export fehlgeschlagen.") } finally { setExporting(false) } } const url = share.token ? `${origin}/demo/${share.token}` : "" return (
{share.token ? (
{share.expired && (

Dieser Link ist abgelaufen. Wähle eine neue Gültigkeit, um ihn wieder zu aktivieren.

)}
Öffnen

„Neuer Link“ macht den bisherigen Link ungültig.

) : ( )}
{dirty &&

Exportiert wird der gespeicherte Stand.

}
{dirty &&

Dupliziert wird der gespeicherte Stand.

} {confirmDelete ? (
) : ( )}
{error &&

{error}

}
) }