import { useEffect, useMemo, useState, type ReactElement } from "react"; import { useNavigate } from "react-router-dom"; import { Layout } from "@/components/layout/Layout"; import { FormField, FormSelect, FormTextArea, PrimaryButton, SecondaryButton } from "@/components/shared"; import { Plus, Trash2 } from "lucide-react"; import { aiService } from "@/services/ai-service"; import { showToast } from "@/utils/toast"; type PromptVariable = { name: string; type: "string" | "number" | "boolean" | "array"; required: boolean; default: string; }; const PromptCreate = (): ReactElement => { const navigate = useNavigate(); const [isSubmitting, setIsSubmitting] = useState(false); const [providers, setProviders] = useState>([]); const [models, setModels] = useState>([]); const [form, setForm] = useState({ name: "", description: "", use_case: "", system_message: "", user_template: "", provider: "", model: "", temperature: "0.3", max_tokens: "2048", tags: "", is_default: false, }); const [variables, setVariables] = useState([ { name: "focus_areas", type: "string", required: false, default: "regulatory obligations, deadlines, action items" }, ]); useEffect(() => { const loadMeta = async (): Promise => { try { const [providerData, modelData] = await Promise.all([aiService.getProviders(), aiService.getModels()]); setProviders(providerData.map((p) => ({ value: p.name, label: p.displayName || p.name }))); setModels(modelData.map((m) => ({ value: m.id, label: `${m.id} (${m.provider})` }))); } catch (err: unknown) { showToast.error( (err as { response?: { data?: { error?: { message?: string } } } })?.response?.data?.error?.message || "Failed to load provider metadata", ); } }; void loadMeta(); }, []); const parsedTags = useMemo( () => form.tags .split(",") .map((tag) => tag.trim()) .filter(Boolean), [form.tags], ); const addVariable = (): void => { setVariables((prev) => [...prev, { name: "", type: "string", required: false, default: "" }]); }; const updateVariable = (index: number, patch: Partial): void => { setVariables((prev) => prev.map((item, idx) => (idx === index ? { ...item, ...patch } : item))); }; const removeVariable = (index: number): void => { setVariables((prev) => prev.filter((_, idx) => idx !== index)); }; const handleSubmit = async (): Promise => { if (!form.name.trim() || !form.use_case.trim() || !form.user_template.trim()) { showToast.error("Name, use case, and user template are required"); return; } const sanitizedVariables = variables .filter((v) => v.name.trim()) .map((v) => ({ name: v.name.trim(), type: v.type, required: v.required, ...(v.default.trim() ? { default: v.default.trim() } : {}), })); setIsSubmitting(true); try { await aiService.createPrompt({ name: form.name.trim(), description: form.description.trim() || undefined, use_case: form.use_case.trim(), system_message: form.system_message.trim() || undefined, user_template: form.user_template, model: form.model || undefined, provider: form.provider || undefined, temperature: Number(form.temperature), max_tokens: Number(form.max_tokens), variables: sanitizedVariables, tags: parsedTags, is_default: form.is_default, }); showToast.success("Prompt created successfully"); navigate("/tenant/ai/prompts"); } catch (err: unknown) { showToast.error( (err as { response?: { data?: { error?: { message?: string } } } })?.response?.data?.error?.message || "Failed to create prompt", ); } finally { setIsSubmitting(false); } }; return (
setForm((prev) => ({ ...prev, name: e.target.value }))} placeholder="e.g., Code Review Assitant" helperText="Max 255 characters. Must be unique per tenant and version" /> setForm((prev) => ({ ...prev, use_case: e.target.value }))} placeholder="doc_summary" />
setForm((prev) => ({ ...prev, description: e.target.value }))} placeholder="Describe what this prompt template is used for..." helperText="Optional template summary to explain the purpose and expected usage." /> setForm((prev) => ({ ...prev, system_message: e.target.value }))} placeholder="You are a regulatory compliance expert..." /> setForm((prev) => ({ ...prev, user_template: e.target.value }))} placeholder={"Summarize the following document:\n\n{{document_text}}\n\nFocus on: {{focus_areas}}"} />
setForm((prev) => ({ ...prev, provider: value }))} options={providers} placeholder="Select provider" /> setForm((prev) => ({ ...prev, model: value }))} options={models} placeholder="Select model" /> setForm((prev) => ({ ...prev, temperature: e.target.value }))} /> setForm((prev) => ({ ...prev, max_tokens: e.target.value }))} />
setForm((prev) => ({ ...prev, tags: e.target.value }))} placeholder="compliance, document, summary" />

Variables

{variables.length === 0 &&

No variables added.

} {variables.map((variable, index) => (
updateVariable(index, { name: e.target.value })} placeholder="focus_areas" /> updateVariable(index, { type: value as PromptVariable["type"] })} options={[ { value: "string", label: "string" }, { value: "number", label: "number" }, { value: "boolean", label: "boolean" }, { value: "array", label: "array" }, ]} /> updateVariable(index, { default: e.target.value })} placeholder="optional default" />
))}
navigate("/tenant/ai/prompts")}>Cancel {isSubmitting ? "Creating..." : "Create Prompt"}
); }; export default PromptCreate;