"use client" import * as React from "react" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Textarea } from "@/components/ui/textarea" import { Badge } from "@/components/ui/badge" import { useMutation } from "convex/react" import { api } from "@/convex/_generated/api" type SectionKey = | "profile" | "features" | "competitors" | "keywords" | "problems" | "personas" | "useCases" | "dorkQueries" function summarizeItem(item: any) { if (typeof item === "string") return item if (!item || typeof item !== "object") return String(item) if (item.name && item.role) return `${item.name} ยท ${item.role}` if (item.name) return item.name if (item.term) return item.term if (item.problem) return item.problem if (item.scenario) return item.scenario if (item.query) return item.query return JSON.stringify(item) } export function SectionEditor({ analysisId, sectionKey, title, items, }: { analysisId: string sectionKey: SectionKey title: string items: any[] }) { const addItem = useMutation(api.analysisSections.addItem) const removeItem = useMutation(api.analysisSections.removeItem) const [isRepromptOpen, setIsRepromptOpen] = React.useState(false) const [repromptText, setRepromptText] = React.useState("") const [isAddOpen, setIsAddOpen] = React.useState(false) const [addText, setAddText] = React.useState("") const [isBusy, setIsBusy] = React.useState(false) const handleAdd = async () => { setIsBusy(true) try { let parsed: any = addText if (addText.trim().startsWith("{") || addText.trim().startsWith("[")) { parsed = JSON.parse(addText) } await addItem({ analysisId: analysisId as any, sectionKey, item: parsed }) setAddText("") setIsAddOpen(false) } finally { setIsBusy(false) } } const handleReprompt = async () => { setIsBusy(true) try { const response = await fetch("/api/analysis/reprompt", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ analysisId, sectionKey, prompt: repromptText.trim() || undefined, }), }) if (!response.ok) { const data = await response.json() throw new Error(data.error || "Reprompt failed") } setRepromptText("") setIsRepromptOpen(false) } finally { setIsBusy(false) } } return ( {title} setIsAddOpen(true)}> Add setIsRepromptOpen(true)}> Reprompt {items.length === 0 ? ( No items yet. ) : ( items.map((item, index) => ( {summarizeItem(item)} #{index + 1} removeItem({ analysisId: analysisId as any, sectionKey, index })} > Remove )) )} Add to {title} Paste JSON for an item, or plain text for a string entry. setAddText(event.target.value)} placeholder='{"name":"...", "description":"..."}' className="min-h-[160px]" /> setIsAddOpen(false)} disabled={isBusy}> Cancel Save Reprompt {title} Provide guidance to regenerate just this section. setRepromptText(event.target.value)} placeholder="Focus on B2B teams in healthcare..." className="min-h-[140px]" /> setIsRepromptOpen(false)} disabled={isBusy}> Cancel Reprompt ) } export function ProfileSectionEditor({ analysisId, items, }: { analysisId: string items: Record }) { const replaceSection = useMutation(api.analysisSections.replaceSection) const [isRepromptOpen, setIsRepromptOpen] = React.useState(false) const [isEditOpen, setIsEditOpen] = React.useState(false) const [repromptText, setRepromptText] = React.useState("") const [editText, setEditText] = React.useState(JSON.stringify(items, null, 2)) const [isBusy, setIsBusy] = React.useState(false) React.useEffect(() => { setEditText(JSON.stringify(items, null, 2)) }, [items]) const handleSave = async () => { setIsBusy(true) try { const parsed = JSON.parse(editText) await replaceSection({ analysisId: analysisId as any, sectionKey: "profile", items: parsed, source: "mixed", }) setIsEditOpen(false) } finally { setIsBusy(false) } } const handleReprompt = async () => { setIsBusy(true) try { const response = await fetch("/api/analysis/reprompt", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ analysisId, sectionKey: "profile", prompt: repromptText.trim() || undefined, }), }) if (!response.ok) { const data = await response.json() throw new Error(data.error || "Reprompt failed") } setRepromptText("") setIsRepromptOpen(false) } finally { setIsBusy(false) } } return ( Product Profile setIsEditOpen(true)}> Edit setIsRepromptOpen(true)}> Reprompt Product:{" "} {items.productName || "Not set"} Tagline:{" "} {items.tagline || "Not set"} Category:{" "} {items.category || "Not set"} Positioning:{" "} {items.positioning || "Not set"} Edit Profile Update the profile JSON. setEditText(event.target.value)} className="min-h-[200px]" /> setIsEditOpen(false)} disabled={isBusy}> Cancel Save Reprompt Profile Provide guidance to regenerate the profile. setRepromptText(event.target.value)} className="min-h-[140px]" /> setIsRepromptOpen(false)} disabled={isBusy}> Cancel Reprompt ) }