All checks were successful
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 2s
Monorepo Pipeline / 🧪 Test (push) Successful in 1m20s
Monorepo Pipeline / 🏗️ Build (push) Successful in 3m22s
Monorepo Pipeline / 🧹 Lint (push) Successful in 3m33s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
113 lines
4.1 KiB
TypeScript
113 lines
4.1 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { useForm, useField } from "@payloadcms/ui";
|
|
export function GenerateThumbnailButton({ path }: { path: string }) {
|
|
const [isGenerating, setIsGenerating] = useState(false);
|
|
const [instructions, setInstructions] = useState("");
|
|
|
|
useEffect(() => {
|
|
if (!isGenerating) return;
|
|
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
|
|
e.preventDefault();
|
|
e.returnValue =
|
|
"Bild-Generierung läuft noch (dies dauert bis zu 2 Minuten). Wenn Sie neu laden, bricht der Vorgang ab!";
|
|
};
|
|
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
return () => window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
}, [isGenerating]);
|
|
|
|
const { fields } = useForm();
|
|
const { value, setValue } = useField({ path });
|
|
|
|
const extractText = (lexicalRoot: any): string => {
|
|
if (!lexicalRoot) return "";
|
|
let text = "";
|
|
const iterate = (node: any) => {
|
|
if (node.text) text += node.text + " ";
|
|
if (node.children) node.children.forEach(iterate);
|
|
};
|
|
iterate(lexicalRoot);
|
|
return text;
|
|
};
|
|
|
|
const handleGenerate = async () => {
|
|
const title = (fields?.title?.value as string) || "";
|
|
const lexicalValue = fields?.content?.value as any;
|
|
const legacyValue = fields?.legacyMdx?.value as string;
|
|
|
|
let draftContent = legacyValue || "";
|
|
if (!draftContent && lexicalValue?.root) {
|
|
draftContent = extractText(lexicalValue.root);
|
|
}
|
|
|
|
setIsGenerating(true);
|
|
try {
|
|
const resData = await fetch("/api/api/mintel-ai/generate-thumbnail", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({
|
|
draftContent,
|
|
title,
|
|
instructions,
|
|
}),
|
|
});
|
|
const res = await resData.json();
|
|
|
|
if (res.success && res.mediaId) {
|
|
setValue(res.mediaId);
|
|
} else {
|
|
alert("Fehler: " + res.error);
|
|
}
|
|
} catch (e: any) {
|
|
console.error(e);
|
|
alert("Unerwarteter Fehler.");
|
|
} finally {
|
|
setIsGenerating(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex gap-2 items-center mt-2 mb-4">
|
|
<textarea
|
|
value={instructions}
|
|
onChange={(e) => setInstructions(e.target.value)}
|
|
placeholder="Optionale Thumbnail-Detailanweisung (Farben, Stimmung, etc.)..."
|
|
disabled={isGenerating}
|
|
style={{
|
|
width: "100%",
|
|
minHeight: "40px",
|
|
padding: "8px 12px",
|
|
fontSize: "14px",
|
|
borderRadius: "4px",
|
|
border: "1px solid var(--theme-elevation-200)",
|
|
background: "var(--theme-elevation-50)",
|
|
color: "var(--theme-text)",
|
|
marginBottom: "8px",
|
|
}}
|
|
/>
|
|
<button
|
|
type="button"
|
|
onClick={handleGenerate}
|
|
disabled={isGenerating}
|
|
className="btn btn--icon-style-none btn--size-medium"
|
|
style={{
|
|
background: "var(--theme-elevation-150)",
|
|
border: "1px solid var(--theme-elevation-200)",
|
|
color: "var(--theme-text)",
|
|
boxShadow: "0 2px 4px rgba(0,0,0,0.05)",
|
|
transition: "all 0.2s ease",
|
|
opacity: isGenerating ? 0.6 : 1,
|
|
cursor: isGenerating ? "not-allowed" : "pointer",
|
|
}}
|
|
>
|
|
<span className="btn__content">
|
|
{isGenerating
|
|
? "✨ AI arbeitet (dauert ca. 1-2 Min)..."
|
|
: "✨ AI Thumbnail Generieren"}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|