"use client" import { useState } from "react" import { toast } from "sonner" import { TrendingUp, TrendingDown, AlertTriangle, ShieldAlert, Wrench, Home, Zap, RefreshCw, Loader2, BarChart3, ArrowUpRight, ArrowDownRight, } from "lucide-react" import { formatCurrency } from "@/lib/utils" const typeConfig: Record = { revenue_forecast: { icon: TrendingUp, color: "text-emerald-400", bg: "bg-emerald-500/10", border: "border-emerald-500/20" }, occupancy_forecast: { icon: Home, color: "text-blue-400", bg: "bg-blue-500/10", border: "border-blue-500/20" }, cash_flow_risk: { icon: TrendingDown, color: "text-red-400", bg: "bg-red-500/10", border: "border-red-500/20" }, tenant_risk: { icon: AlertTriangle, color: "text-amber-400", bg: "bg-amber-500/10", border: "border-amber-500/20" }, maintenance_risk: { icon: Wrench, color: "text-orange-400", bg: "bg-orange-500/10", border: "border-orange-500/20" }, vacancy_risk: { icon: ShieldAlert, color: "text-red-400", bg: "bg-red-500/10", border: "border-red-500/20" }, growth_opportunity: { icon: Zap, color: "text-violet-400", bg: "bg-violet-500/10", border: "border-violet-500/20" }, } const riskBadge: Record = { critical: "text-red-400 bg-red-500/10 ring-red-500/20", high: "text-orange-400 bg-orange-500/10 ring-orange-500/20", medium: "text-amber-400 bg-amber-500/10 ring-amber-500/20", low: "text-emerald-400 bg-emerald-500/10 ring-emerald-500/20", } const confidenceBadge: Record = { high: "text-emerald-400", medium: "text-amber-400", low: "text-white/30", } export function PredictionsClient({ predictions: initial }: { predictions: any[] }) { const [predictions, setPredictions] = useState(initial) const [generating, setGenerating] = useState(false) const [filter, setFilter] = useState("") const riskItems = predictions.filter((p) => ["critical", "high"].includes(p.risk_level)) const filtered = filter ? predictions.filter((p) => p.type === filter) : predictions async function generate() { setGenerating(true) try { const res = await fetch("/api/ai/predictions", { method: "POST" }) const data = await res.json() if (!res.ok) { toast.error(data.error ?? "Failed to generate"); return } setPredictions(data) toast.success(`${data.length} predictions generated`) setFilter("") } catch { toast.error("Network error — please try again") } finally { setGenerating(false) } } return (
{/* Header */}

Predictive Analytics

AI-powered forecasts and risk alerts based on your portfolio trends {riskItems.length > 0 && ( {riskItems.length} risk alert{riskItems.length > 1 ? "s" : ""} )}

{/* Risk alerts banner */} {riskItems.length > 0 && (

{riskItems.length} Active Risk Alert{riskItems.length > 1 ? "s" : ""}

{riskItems.map((r) => (
{r.risk_level} {r.title} {r.timeframe}
))}
)} {/* Filter */} {predictions.length > 0 && (
{["revenue_forecast", "occupancy_forecast", "cash_flow_risk", "vacancy_risk", "growth_opportunity"].map((t) => { const count = predictions.filter((p) => p.type === t).length if (!count) return null return ( ) })}
)} {/* Cards */} {filtered.length === 0 ? (

No predictions yet

Click "Run Analysis" to generate AI-powered forecasts

) : (
{filtered.map((pred) => { const cfg = typeConfig[pred.type] ?? typeConfig.growth_opportunity const Icon = cfg.icon const changePercent = pred.data?.change_percent ?? 0 const isPositive = changePercent >= 0 const isRisk = ["cash_flow_risk", "tenant_risk", "maintenance_risk", "vacancy_risk"].includes(pred.type) return (

{pred.title}

{pred.timeframe}

{pred.risk_level}

{pred.prediction}

{pred.data?.metric && (

{pred.data.metric}

{typeof pred.data.current_value === "number" && pred.data.metric?.toLowerCase().includes("revenue") ? formatCurrency(pred.data.current_value) : `${pred.data.current_value}${pred.data.metric?.includes("%") || pred.data.metric?.toLowerCase().includes("rate") ? "%" : ""}`} {typeof pred.data.predicted_value === "number" && pred.data.metric?.toLowerCase().includes("revenue") ? formatCurrency(pred.data.predicted_value) : `${pred.data.predicted_value}${pred.data.metric?.includes("%") || pred.data.metric?.toLowerCase().includes("rate") ? "%" : ""}`}
{changePercent !== 0 && (
{isPositive ? : } {Math.abs(changePercent)}%
)}
)}
Confidence: {pred.confidence}
) })}
)}
) }