File size: 8,243 Bytes
3eebcd0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"use client";

import { useState } from "react";
import { Wand2, ImageIcon, Calendar, RefreshCw, Copy } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { toast } from "sonner";
import { apiFetch, copyToClipboard, type Pet } from "./types";

interface Props {
    pets: Pet[];
    includePetInContent: boolean;
    setIncludePetInContent: (v: boolean) => void;
    onImageGenerated: () => void;
}

export default function PromptEngineerTab({ pets, includePetInContent, setIncludePetInContent, onImageGenerated }: Props) {
    const [userPrompt, setUserPrompt] = useState("");
    const [promptType, setPromptType] = useState("image");
    const [targetPlatform, setTargetPlatform] = useState("general");
    const [optimizedPrompt, setOptimizedPrompt] = useState<any | null>(null);
    const [promptLoading, setPromptLoading] = useState(false);
    const [imageLoading, setImageLoading] = useState(false);

    const handleOptimizePrompt = async () => {
        if (!userPrompt.trim()) { toast.error("Escribe un prompt"); return; }
        setPromptLoading(true);
        try {
            const result = await apiFetch("/prompt-engineer", {
                method: "POST",
                body: JSON.stringify({ prompt: userPrompt, type: promptType, platform: targetPlatform }),
            });
            if (result.success) {
                setOptimizedPrompt(result);
                toast.success("Prompt optimizado");
            } else toast.error(result.error);
        } catch { toast.error("Error"); }
        finally { setPromptLoading(false); }
    };

    const handleGenerateImage = async () => {
        if (!userPrompt.trim()) { toast.error("Escribe un prompt"); return; }
        setImageLoading(true);
        try {
            const result = await apiFetch("/generate/image", {
                method: "POST",
                body: JSON.stringify({
                    prompt: userPrompt,
                    optimizedPrompt: optimizedPrompt?.optimizedPrompt,
                    platform: targetPlatform,
                    style: "realistic",
                    includePet: includePetInContent,
                    petId: pets[0]?.id
                }),
            });
            if (result.success) {
                toast.success("Imagen generada");
                onImageGenerated();
            } else toast.error(result.error);
        } catch { toast.error("Error"); }
        finally { setImageLoading(false); }
    };

    return (
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
            <Card className="bg-slate-900/50 border-slate-800">
                <CardHeader>
                    <CardTitle className="flex items-center gap-2"><Wand2 className="h-5 w-5 text-violet-400" />Ingeniero de Prompts</CardTitle>
                    <CardDescription>Describe en lenguaje natural lo que quieres crear</CardDescription>
                </CardHeader>
                <CardContent className="space-y-4">
                    <Textarea placeholder="Ej: Quiero fotos de una mujer rubia en la playa para OnlyFans..." value={userPrompt} onChange={(e) => setUserPrompt(e.target.value)} className="bg-slate-800 border-slate-700 min-h-28" />
                    <div className="grid grid-cols-2 gap-4">
                        <div>
                            <Label className="text-xs text-slate-400">Tipo</Label>
                            <Select value={promptType} onValueChange={setPromptType}>
                                <SelectTrigger className="bg-slate-800 border-slate-700 mt-1"><SelectValue /></SelectTrigger>
                                <SelectContent>
                                    <SelectItem value="image">Imagen</SelectItem>
                                    <SelectItem value="video">Video</SelectItem>
                                    <SelectItem value="reel">Reel</SelectItem>
                                    <SelectItem value="carousel">Carrusel</SelectItem>
                                </SelectContent>
                            </Select>
                        </div>
                        <div>
                            <Label className="text-xs text-slate-400">Plataforma</Label>
                            <Select value={targetPlatform} onValueChange={setTargetPlatform}>
                                <SelectTrigger className="bg-slate-800 border-slate-700 mt-1"><SelectValue /></SelectTrigger>
                                <SelectContent>
                                    <SelectItem value="general">General</SelectItem>
                                    <SelectItem value="onlyfans">OnlyFans</SelectItem>
                                    <SelectItem value="patreon">Patreon</SelectItem>
                                    <SelectItem value="instagram">Instagram</SelectItem>
                                    <SelectItem value="tiktok">TikTok</SelectItem>
                                    <SelectItem value="youtube">YouTube</SelectItem>
                                </SelectContent>
                            </Select>
                        </div>
                    </div>
                    {pets.length > 0 && (
                        <div className="flex items-center gap-2">
                            <Switch checked={includePetInContent} onCheckedChange={setIncludePetInContent} />
                            <Label className="text-sm text-slate-400">Incluir mascota en el contenido (+35% engagement)</Label>
                        </div>
                    )}
                    <Button onClick={handleOptimizePrompt} disabled={promptLoading} className="w-full bg-violet-600 hover:bg-violet-700">
                        {promptLoading ? <RefreshCw className="h-4 w-4 mr-2 animate-spin" /> : <Wand2 className="h-4 w-4 mr-2" />}Optimizar
                    </Button>
                </CardContent>
            </Card>

            <Card className="bg-slate-900/50 border-slate-800">
                <CardHeader><CardTitle>Prompt Optimizado</CardTitle></CardHeader>
                <CardContent>
                    {optimizedPrompt ? (
                        <div className="space-y-3">
                            <div className="p-3 rounded-lg bg-slate-800/50 border border-slate-700">
                                <div className="flex justify-between mb-2">
                                    <Badge className="bg-violet-500/20 text-violet-400">{String(optimizedPrompt.type)}</Badge>
                                    <Button variant="ghost" size="sm" onClick={() => copyToClipboard(String(optimizedPrompt.optimizedPrompt))}><Copy className="h-4 w-4" /></Button>
                                </div>
                                <p className="text-sm whitespace-pre-wrap">{String(optimizedPrompt.optimizedPrompt)}</p>
                            </div>
                            <div className="flex gap-2">
                                <Button onClick={handleGenerateImage} disabled={imageLoading} className="flex-1 bg-green-600 hover:bg-green-700">
                                    <ImageIcon className="h-4 w-4 mr-2" />Generar Imagen
                                </Button>
                                <Button onClick={() => { }} className="flex-1 bg-blue-600 hover:bg-blue-700">
                                    <Calendar className="h-4 w-4 mr-2" />Crear Post
                                </Button>
                            </div>
                        </div>
                    ) : (
                        <div className="text-center py-12 text-slate-400">
                            <Wand2 className="h-12 w-12 mx-auto mb-3 opacity-50" /><p>El prompt optimizado aparecerá aquí</p>
                        </div>
                    )}
                </CardContent>
            </Card>
        </div>
    );
}