Spaces:
Build error
Build error
| "use client"; | |
| import { useState } from "react"; | |
| import { Users2, Lightbulb, Star, PawPrint, Sparkles, RefreshCw } from "lucide-react"; | |
| import { Button } from "@/components/ui/button"; | |
| import { Input } from "@/components/ui/input"; | |
| 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, type Influencer } from "./types"; | |
| export default function InfluencersTab() { | |
| const [influencers, setInfluencers] = useState<Influencer[]>([]); | |
| const [influencerNiche, setInfluencerNiche] = useState(""); | |
| const [influencerPlatform, setInfluencerPlatform] = useState(""); | |
| const [influencerWithPets, setInfluencerWithPets] = useState(false); | |
| const [influencerLoading, setInfluencerLoading] = useState(false); | |
| const [characterConcept, setCharacterConcept] = useState<any | null>(null); | |
| const handleAnalyzeInfluencers = async () => { | |
| setInfluencerLoading(true); | |
| try { | |
| const result = await apiFetch("/influencers", { | |
| method: "POST", | |
| body: JSON.stringify({ | |
| targetNiche: influencerNiche || "lifestyle", | |
| targetPlatform: influencerPlatform || undefined, | |
| includePets: influencerWithPets | |
| }), | |
| }); | |
| if (result.success) { | |
| setInfluencers(result.referenceInfluencers || []); | |
| setCharacterConcept(result.characterConcept); | |
| toast.success("Análisis completado"); | |
| } else toast.error(result.error); | |
| } catch { toast.error("Error"); } | |
| finally { setInfluencerLoading(false); } | |
| }; | |
| return ( | |
| <div className="space-y-6"> | |
| <Card className="bg-slate-900/50 border-slate-800"> | |
| <CardHeader> | |
| <CardTitle className="flex items-center gap-2"><Users2 className="h-5 w-5 text-pink-400" />Análisis de Influencers IA Famosos</CardTitle> | |
| <CardDescription>Estudia los patrones de influencers IA exitosos para aplicarlos a tu contenido</CardDescription> | |
| </CardHeader> | |
| <CardContent className="space-y-4"> | |
| <div className="grid grid-cols-1 md:grid-cols-4 gap-4"> | |
| <div> | |
| <Label className="text-xs text-slate-400">Tu Nicho</Label> | |
| <Input placeholder="lifestyle, fashion..." value={influencerNiche} onChange={(e) => setInfluencerNiche(e.target.value)} className="bg-slate-800 border-slate-700 mt-1" /> | |
| </div> | |
| <div> | |
| <Label className="text-xs text-slate-400">Plataforma Objetivo</Label> | |
| <Select value={influencerPlatform} onValueChange={setInfluencerPlatform}> | |
| <SelectTrigger className="bg-slate-800 border-slate-700 mt-1"><SelectValue placeholder="Todas" /></SelectTrigger> | |
| <SelectContent> | |
| <SelectItem value="">Todas</SelectItem> | |
| <SelectItem value="instagram">Instagram</SelectItem> | |
| <SelectItem value="tiktok">TikTok</SelectItem> | |
| <SelectItem value="youtube">YouTube</SelectItem> | |
| </SelectContent> | |
| </Select> | |
| </div> | |
| <div className="flex items-end"> | |
| <div className="flex items-center gap-2 pb-2"> | |
| <Switch checked={influencerWithPets} onCheckedChange={setInfluencerWithPets} /> | |
| <Label className="text-sm text-slate-400">Con mascotas</Label> | |
| </div> | |
| </div> | |
| <div className="flex items-end"> | |
| <Button onClick={handleAnalyzeInfluencers} disabled={influencerLoading} className="w-full bg-pink-600 hover:bg-pink-700"> | |
| {influencerLoading ? <RefreshCw className="h-4 w-4 mr-2 animate-spin" /> : <Lightbulb className="h-4 w-4 mr-2" />}Analizar | |
| </Button> | |
| </div> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| {influencers.length > 0 && ( | |
| <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"> | |
| {influencers.map((inf, i) => ( | |
| <Card key={i} className="bg-slate-900/50 border-slate-800"> | |
| <CardContent className="p-4"> | |
| <div className="flex items-center gap-2 mb-2"> | |
| <div className="w-8 h-8 rounded-full bg-gradient-to-br from-pink-500 to-purple-500 flex items-center justify-center"> | |
| <Star className="h-4 w-4 text-white" /> | |
| </div> | |
| <div> | |
| <p className="font-medium text-sm">{inf.name}</p> | |
| <p className="text-xs text-slate-400">{inf.handle}</p> | |
| </div> | |
| </div> | |
| <div className="space-y-1 text-xs"> | |
| <p><span className="text-slate-400">Seguidores:</span> <span className="text-green-400">{(inf.followers / 1000000).toFixed(1)}M</span></p> | |
| <p><span className="text-slate-400">Engagement:</span> <span className="text-blue-400">{inf.engagement}%</span></p> | |
| <p><span className="text-slate-400">Nicho:</span> {inf.niche}</p> | |
| {inf.petCompanion && <Badge className="bg-amber-500/20 text-amber-400 mt-1"><PawPrint className="h-3 w-3 mr-1" />{inf.petType}</Badge>} | |
| </div> | |
| <div className="mt-2 pt-2 border-t border-slate-700"> | |
| <p className="text-xs text-slate-400">Lecciones:</p> | |
| <ul className="text-xs mt-1 space-y-1"> | |
| {inf.keyLessons.slice(0, 2).map((l, j) => ( | |
| <li key={j} className="text-slate-300">• {l}</li> | |
| ))} | |
| </ul> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| ))} | |
| </div> | |
| )} | |
| {characterConcept && ( | |
| <Card className="bg-slate-900/50 border-slate-800 border-violet-500/30"> | |
| <CardHeader> | |
| <CardTitle className="flex items-center gap-2 text-violet-400"><Sparkles className="h-5 w-5" />Concepto de Personaje Sugerido</CardTitle> | |
| </CardHeader> | |
| <CardContent> | |
| <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div> | |
| <h4 className="font-medium mb-2">Personaje</h4> | |
| <div className="p-3 rounded-lg bg-slate-800/50 text-sm"> | |
| {characterConcept.character && ( | |
| <> | |
| <p><strong>Nombre:</strong> {String(characterConcept.character.name || "")}</p> | |
| <p className="mt-1"><strong>Personalidad:</strong> {String(characterConcept.character.personality || "")}</p> | |
| <p className="mt-1"><strong>Historia:</strong> {String(characterConcept.character.backstory || "")}</p> | |
| </> | |
| )} | |
| </div> | |
| </div> | |
| <div> | |
| <h4 className="font-medium mb-2">Estilo Visual</h4> | |
| <div className="p-3 rounded-lg bg-slate-800/50 text-sm"> | |
| {characterConcept.visualStyle && ( | |
| <> | |
| <p><strong>Estética:</strong> {String(characterConcept.visualStyle.aesthetic || "")}</p> | |
| <p className="mt-1"><strong>Colores:</strong> {Array.isArray(characterConcept.visualStyle.colors) ? characterConcept.visualStyle.colors.join(", ") : ""}</p> | |
| </> | |
| )} | |
| </div> | |
| {Array.isArray(characterConcept.hashtags) && characterConcept.hashtags.length > 0 && ( | |
| <div className="mt-3 flex flex-wrap gap-1"> | |
| {characterConcept.hashtags.slice(0, 10).map((tag: string, i: number) => ( | |
| <Badge key={i} variant="outline" className="text-xs">{tag}</Badge> | |
| ))} | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| )} | |
| </div> | |
| ); | |
| } | |