sofia-cloud / src /components /dashboard /TrendsTab.tsx
Gmagl
fix: correcciones críticas y refactorización de componentes
3eebcd0
Raw
History Blame Contribute Delete
9.67 kB
"use client";
import { useState, useEffect, useCallback } from "react";
import { Rocket, Flame, Target, Lightbulb, RefreshCw } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { toast } from "sonner";
import { apiFetch } from "./types";
export default function TrendsTab() {
const [trends, setTrends] = useState<any[]>([]);
const [viralStrategies, setViralStrategies] = useState<any[]>([]);
const [contentIdeas, setContentIdeas] = useState<any[]>([]);
const [trendAnalysis, setTrendAnalysis] = useState<any | null>(null);
const [trendLoading, setTrendLoading] = useState(false);
const [includePetInContent, setIncludePetInContent] = useState(false);
const loadTrends = useCallback(async () => {
try {
const result = await apiFetch(`/trends?includePets=${includePetInContent}`);
if (result.success) {
setTrends(result.trends);
setViralStrategies(result.viralStrategies);
setContentIdeas(result.contentIdeas);
}
} catch { toast.error("Error cargando tendencias"); }
}, [includePetInContent]);
useEffect(() => { loadTrends(); }, [loadTrends]);
const handleAnalyzeTrends = async () => {
setTrendLoading(true);
try {
const result = await apiFetch("/trends", {
method: "POST",
body: JSON.stringify({
niche: "lifestyle",
includePets: includePetInContent,
daysToViral: 14
}),
});
if (result.success) {
setTrendAnalysis(result.analysis);
toast.success("Análisis de tendencias completado");
} else toast.error(result.error);
} catch { toast.error("Error"); }
finally { setTrendLoading(false); }
};
return (
<div className="space-y-6">
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<Switch checked={includePetInContent} onCheckedChange={setIncludePetInContent} />
<Label className="text-sm text-slate-400">Incluir tendencias de mascotas</Label>
</div>
<Button onClick={handleAnalyzeTrends} disabled={trendLoading} className="bg-violet-600 hover:bg-violet-700">
{trendLoading ? <RefreshCw className="h-4 w-4 mr-2 animate-spin" /> : <Rocket className="h-4 w-4 mr-2" />}Analizar para Viralizar
</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
{trends.slice(0, 8).map((t, i) => (
<Card key={i} className="bg-slate-900/50 border-slate-800">
<CardContent className="p-4">
<div className="flex items-center justify-between mb-2">
<Badge variant="outline" className="text-xs">{String(t.platform || "")}</Badge>
<Flame className={`h-4 w-4 ${Number(t.growth) > 30 ? "text-red-400" : "text-orange-400"}`} />
</div>
<p className="font-semibold">{String(t.name)}</p>
<p className="text-green-400 text-sm">+{Number(t.growth).toFixed(1)}%</p>
<p className="text-xs text-slate-400 mt-1">{String(t.category || "")}</p>
</CardContent>
</Card>
))}
</div>
{viralStrategies.length > 0 && (
<Card className="bg-slate-900/50 border-slate-800">
<CardHeader><CardTitle className="flex items-center gap-2"><Rocket className="h-5 w-5 text-violet-400" />Estrategias Virales</CardTitle></CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
{viralStrategies.slice(0, 4).map((s, i) => (
<div key={i} className="p-3 rounded-lg bg-slate-800/50 border border-slate-700">
<div className="flex items-center justify-between mb-2">
<p className="font-medium text-sm">{String(s.name)}</p>
<Badge className="bg-green-500/20 text-green-400 text-xs">{String(s.successRate)}%</Badge>
</div>
<p className="text-xs text-slate-400 line-clamp-2">{String(s.description)}</p>
<div className="flex flex-wrap gap-1 mt-2">
{Array.isArray(s.platforms) && s.platforms.slice(0, 3).map((p: string, j: number) => (
<Badge key={j} variant="outline" className="text-xs">{p}</Badge>
))}
</div>
</div>
))}
</div>
</CardContent>
</Card>
)}
{contentIdeas.length > 0 && (
<Card className="bg-slate-900/50 border-slate-800">
<CardHeader><CardTitle className="flex items-center gap-2"><Lightbulb className="h-5 w-5 text-amber-400" />Ideas de Contenido Viral</CardTitle></CardHeader>
<CardContent>
<div className="space-y-3">
{contentIdeas.slice(0, 5).map((idea, i) => (
<div key={i} className="p-3 rounded-lg bg-slate-800/50 border border-slate-700">
<div className="flex items-center justify-between">
<div>
<p className="font-medium">{String(idea.title)}</p>
<p className="text-xs text-slate-400 mt-1">{String(idea.description)}</p>
{idea.hook && <p className="text-xs text-violet-400 mt-1">Hook: &quot;{String(idea.hook)}&quot;</p>}
</div>
<div className="text-right">
<Badge className="bg-violet-500/20 text-violet-400">{String(idea.format)}</Badge>
{idea.viralScore && <p className="text-xs text-green-400 mt-1">Score: {String(idea.viralScore)}</p>}
</div>
</div>
</div>
))}
</div>
</CardContent>
</Card>
)}
{trendAnalysis && (
<Card className="bg-slate-900/50 border-slate-800 border-violet-500/30">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-violet-400"><Target className="h-5 w-5" />Plan para Viralizar</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<h4 className="font-medium mb-2">Tendencias Emergentes</h4>
<div className="space-y-2">
{Array.isArray(trendAnalysis.emergingTrends) && trendAnalysis.emergingTrends.slice(0, 3).map((t: Record<string, unknown>, i: number) => (
<div key={i} className="p-2 rounded bg-slate-800/50 text-sm">
<p className="font-medium">{String(t.name)}</p>
<p className="text-xs text-slate-400">Potencial: {String(t.potential)}</p>
</div>
))}
</div>
</div>
<div>
<h4 className="font-medium mb-2">Recomendaciones</h4>
<div className="space-y-1">
{Array.isArray(trendAnalysis.recommendations) && trendAnalysis.recommendations.slice(0, 4).map((r: string, i: number) => (
<p key={i} className="text-sm text-slate-300">• {r}</p>
))}
</div>
{trendAnalysis.predictedViralPotential && (
<div className="mt-4 p-3 rounded-lg bg-violet-500/10 border border-violet-500/30">
<p className="text-sm">Potencial Viral Estimado:</p>
<p className="text-2xl font-bold text-violet-400">{String(trendAnalysis.predictedViralPotential)}%</p>
</div>
)}
</div>
</div>
</CardContent>
</Card>
)}
</div>
);
}