import clsx from "clsx"; import { useEffect, useState } from "react"; import {ErrorBanner} from "../../../components/ui/banners/ErrorBanner"; import WarningBanner from "../../../components/ui/banners/WarningBanner"; import {ButtonPrimary} from "../../../components/ui/buttons/ButtonPrimary"; import {ButtonSecondary} from "../../../components/ui/buttons/ButtonSecondary"; import ChatGptIcon from "../../../components/ui/icons/ai/ChatGptIcon"; import CheckIcon from "../../../components/ui/icons/CheckIcon"; import ExclamationTriangleIcon from "../../../components/ui/icons/ExclamationTriangleIcon"; import InputText from "../../../components/ui/input/InputText"; import SlideOverWideEmpty from "../../../components/ui/slideOvers/SlideOverWideEmpty"; import Tabs from "../../../components/ui/tabs/Tabs"; import { PageBlock } from "../../pageBlocks/components/blocks/PageBlock"; import { PageBlockDto } from "../../pageBlocks/dtos/PageBlockDto"; import { siteTags } from "../../pageBlocks/utils/defaultSeoMetaTags"; import AIPageBuilderService from "../services/AIPageBuilderService"; import { useApp } from "../../../hooks"; import { useSearchParams } from "next/navigation"; interface Props { block: PageBlockDto; onGenerated: (block: PageBlockDto) => void; onLoading?: (isLoading: boolean) => void; onError?: (error: string) => void; } export default function ChatGptGeneratePageBlockButton({ block, onGenerated, onError, onLoading }: Props) { const { t } = useApp(); const [searchParams, setSearchParams] = useSearchParams(); const [selectedTab, selectTab] = useState(0); const [response, setResponse] = useState(""); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [finishedBlock, setFinishedBlock] = useState(); const [isSettingParameters, setIsSettingParameters] = useState(false); const [parameters, setParameters] = useState( [ { name: "Website Title", value: siteTags.title }, { name: "Website Description", value: siteTags.description }, { name: "Website Keywords", value: siteTags.keywords }, { name: "Website Image", value: siteTags.image }, { name: "Page Details", value: "" }, ] .map((p) => `${p.name}: ${p.value}`) .join("\n") ); useEffect(() => { let aiGenerateBlocks = searchParams["aiGenerateBlocks"]; if (aiGenerateBlocks) { let decoded = decodeURIComponent(aiGenerateBlocks); setParameters(decoded); /* searchParams.delete("aiGenerateBlocks"); setSearchParams(searchParams, { preventScrollReset: true, }); */ onClick(decoded); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [searchParams]); useEffect(() => { if (error && onError) { onError(error); } }, [error, onError]); useEffect(() => { if (finishedBlock) { onGenerated(finishedBlock); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [finishedBlock]); useEffect(() => { if (onLoading) { onLoading(isLoading); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isLoading]); useEffect(() => { if (response && !isLoading) { let finishedBlock = AIPageBuilderService.parseChatGptContentToBlock(response); if (finishedBlock) { setFinishedBlock(finishedBlock); selectTab(2); } else { setError("Could not parse response"); } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isLoading, response]); async function onClick(info: string) { let prompt = AIPageBuilderService.getBlockPrompt({ block, info, }); if (!prompt) { setError("Block not supported"); } // eslint-disable-next-line no-console console.log({ prompt }); setResponse(""); setIsLoading(true); setError(null); setFinishedBlock(undefined); const response = await fetch("/api/ai/openai/chatgpt", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ prompt, role: "assistant", }), }); if (!response.ok) { const jsonBody = await response.text(); setError(response.statusText + ": " + jsonBody); setIsLoading(false); return; } // This data is a ReadableStream const data = response.body; if (!data) { setError("No data"); return; } const reader = data.getReader(); const decoder = new TextDecoder(); let done = false; while (!done) { const { value, done: doneReading } = await reader.read(); done = doneReading; const chunkValue = decoder.decode(value); setResponse((prev) => prev + chunkValue); } setIsLoading(false); } function handleSubmit(event: React.FormEvent) { event.preventDefault(); event.stopPropagation(); // setIsSettingParameters(false); selectTab(1); onClick(parameters); } return ( <> setIsSettingParameters(true)} > {error ? ( <> ) : finishedBlock ? ( <> ) : ( <> )} setIsSettingParameters(false)}>
selectTab(index)} tabs={[{ name: `Generate` }, { name: `Response` }, { name: `Generated Block` }]} />
{selectedTab === 0 && (
setParameters(value)} />
setIsSettingParameters(false)}>Cancel Generate
)} {selectedTab === 1 && (
{error && }
)} {selectedTab === 2 && (
{finishedBlock ? : }
)}
); }