import React, { useState, useEffect, useRef, forwardRef } from "react"; import { useParams, useNavigate } from "react-router-dom"; import { ArrowLeft, ArrowRight, Sparkles, User } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { InteractiveHoverButton } from "@/components/ui/interactive-hover-button"; import { PromptAssistantButton } from "@/components/prompts/PromptAssistantButton"; import { Confetti, type ConfettiRef } from "@/components/ui/confetti"; import { cn } from "@/lib/utils"; import { usePrompts } from "@/contexts/PromptsContext"; import { areasService, type AreaItem } from "@/services/areas"; import { PromptGeneratingScreen } from "@/components/prompts/PromptGeneratingScreen"; import { assistentePromptsService } from "@/services/assistentePrompts"; import { promptsService } from "@/services/promptsApi"; import { toast } from "sonner"; import { playSuccessSound } from "@/utils/sound"; export function PromptsFormView() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const { prompts, setPrompts } = usePrompts(); const isEdit = Boolean(id); const prompt = id ? prompts.find((p) => p.id === id) : null; const [areaItems, setAreaItems] = useState([]); const [areasLoading, setAreasLoading] = useState(true); const [titulo, setTitulo] = useState(""); const [descricao, setDescricao] = useState(""); const [areaId, setAreaId] = useState(""); const [conteudo, setConteudo] = useState(""); const [isSaving, setIsSaving] = useState(false); const [isAssistantOpen, setIsAssistantOpen] = useState(false); const [assistantMode, setAssistantMode] = useState<"create" | "refine">("create"); const [assistantInstructions, setAssistantInstructions] = useState(""); const [isAssistantLoading, setIsAssistantLoading] = useState(false); const [isAssistantWorkingInBackground, setIsAssistantWorkingInBackground] = useState(false); const [showGeneratingModal, setShowGeneratingModal] = useState(false); const confettiRef = useRef(null); const abortControllerRef = useRef(null); const hasContent = conteudo.trim().length > 0; const effectiveAreaId = areaId && areaItems.some((a) => a.id === areaId) ? areaId : (areaItems[0]?.id ?? ""); const effectiveAreaName = areaItems.find((a) => a.id === effectiveAreaId)?.nome ?? ""; useEffect(() => { setAreasLoading(true); areasService.listarTotal() .then((data) => setAreaItems(data)) .catch(() => setAreaItems([])) .finally(() => setAreasLoading(false)); }, []); useEffect(() => { if (prompt) { setTitulo(prompt.titulo); setDescricao(prompt.descricao ?? ""); setAreaId(prompt.area_id ?? ""); setConteudo(prompt.conteudo ?? ""); } else if (!id) { setTitulo(""); setDescricao(""); setAreaId(""); setConteudo(""); } }, [prompt, id]); useEffect(() => { if (!id && areaItems.length > 0 && !areaId) { setAreaId(areaItems[0].id); } }, [id, areaItems, areaId]); useEffect(() => { if (id && !prompt && prompts.length > 0) { navigate("/commander/prompts", { replace: true }); } }, [id, prompt, prompts.length, navigate]); useEffect(() => { if (!conteudo.trim() && assistantMode === "refine") { setAssistantMode("create"); } }, [conteudo, assistantMode]); useEffect(() => { return () => { abortControllerRef.current?.abort(); }; }, []); const handleSave = async () => { const finalTitulo = titulo.trim(); const finalAreaId = effectiveAreaId; const finalConteudo = conteudo.trim(); if (!finalTitulo || !finalAreaId) { toast.error("Preencha o título e a área."); return; } if (!finalConteudo) { toast.error("Preencha o conteúdo do prompt."); return; } const finalAreaName = areaItems.find((a) => a.id === finalAreaId)?.nome ?? ""; const finalDescricao = descricao.trim(); setIsSaving(true); try { if (isEdit && prompt) { const res = await promptsService.editar(prompt.id, { titulo: finalTitulo, descricao: finalDescricao, area_id: finalAreaId, conteudo: finalConteudo, }); setPrompts((prev) => prev.map((p) => p.id === prompt.id ? { ...p, id: res.id, titulo: res.titulo, area: finalAreaName, area_id: res.area_id, descricao: finalDescricao || undefined, conteudo: res.conteudo ?? "" } : p ) ); toast.success("Prompt atualizado."); } else { const res = await promptsService.criar({ titulo: finalTitulo, descricao: finalDescricao, area_id: finalAreaId, conteudo: finalConteudo, }); setPrompts((prev) => [...prev, { id: res.id, titulo: res.titulo, area: finalAreaName, area_id: finalAreaId, descricao: finalDescricao || undefined, conteudo: res.conteudo ?? "" }]); toast.success("Prompt criado."); } navigate("/commander/prompts"); } catch (e: unknown) { const message = e && typeof e === "object" && "message" in e ? (e as { message: string }).message : "Erro ao salvar."; toast.error(message); } finally { setIsSaving(false); } }; const handleAssistantSubmit = () => { if (!assistantInstructions.trim()) { toast.error("Preencha as instruções."); return; } if (assistantMode === "refine" && !conteudo.trim()) { toast.error("Não há conteúdo para melhorar."); return; } setIsAssistantOpen(false); setShowGeneratingModal(true); setIsAssistantWorkingInBackground(true); setIsAssistantLoading(true); const ac = new AbortController(); abortControllerRef.current = ac; const signal = ac.signal; const onSuccess = (text: string) => { setConteudo(text); confettiRef.current?.fire({}); playSuccessSound(); const msg = assistantMode === "create" ? "Modelo inicial gerado!" : "Conteúdo atualizado!"; toast.success(msg, { className: "bg-green-600 border-green-700 text-white", }); }; const onFinish = () => { setShowGeneratingModal(false); setIsAssistantLoading(false); setIsAssistantWorkingInBackground(false); abortControllerRef.current = null; }; const onError = (e: unknown) => { const isAborted = (e && typeof e === "object" && "code" in e && (e as { code: string }).code === "ERR_CANCELED") || (e && typeof e === "object" && "name" in e && (e as { name: string }).name === "AbortError"); if (!isAborted) { const message = e && typeof e === "object" && "message" in e ? (e as { message: string }).message : "Erro ao processar."; toast.error(message); } }; if (assistantMode === "create") { assistentePromptsService.gerar(assistantInstructions, signal) .then(onSuccess) .catch(onError) .finally(onFinish); } else { assistentePromptsService.refinar(conteudo, assistantInstructions, signal) .then(onSuccess) .catch(onError) .finally(onFinish); } }; return (
setTitulo(e.target.value)} placeholder="Ex: Prompt para análise de documentos" />
setDescricao(e.target.value)} placeholder="Ex: Breve descrição do prompt" />
{isAssistantWorkingInBackground && (
)} setIsAssistantOpen(true)} disabled={isAssistantWorkingInBackground} loading={isAssistantWorkingInBackground} />