159 lines
5.2 KiB
TypeScript
159 lines
5.2 KiB
TypeScript
"use client";
|
|
|
|
import { motion } from "framer-motion";
|
|
import Panel from "./ui/Panel";
|
|
|
|
interface AnalystCard {
|
|
name: string;
|
|
role: string;
|
|
avatarType: string;
|
|
icon: string;
|
|
signal: "bullish" | "bearish" | "neutral";
|
|
signalText: string;
|
|
metrics: { label: string; value: string }[];
|
|
excerpt: string;
|
|
}
|
|
|
|
const analysts: AnalystCard[] = [
|
|
{
|
|
name: "Market Analyst",
|
|
role: "Technical Analysis",
|
|
avatarType: "market",
|
|
icon: "\u{1F4CA}",
|
|
signal: "bullish",
|
|
signalText: "Bullish \u2014 Uptrend Confirmed",
|
|
metrics: [
|
|
{ label: "Trend", value: "Strong Uptrend" },
|
|
{ label: "Momentum", value: "Accelerating" },
|
|
{ label: "Support", value: "$842.10" },
|
|
],
|
|
excerpt:
|
|
"MACD crossed above signal line with increasing histogram bars. RSI at 67.4 shows room before overbought. Price above all major moving averages with expanding volume.",
|
|
},
|
|
{
|
|
name: "Fundamentals",
|
|
role: "Financial Analysis",
|
|
avatarType: "fundamentals",
|
|
icon: "\u{1F4CB}",
|
|
signal: "bullish",
|
|
signalText: "Bullish \u2014 Strong Financials",
|
|
metrics: [
|
|
{ label: "Revenue Growth", value: "+122% YoY" },
|
|
{ label: "Gross Margin", value: "74.8%" },
|
|
{ label: "Free Cash Flow", value: "$27.1B" },
|
|
],
|
|
excerpt:
|
|
"Data center revenue surged 409% YoY driven by AI infrastructure demand. Operating margins expanding to 61.6%. Balance sheet shows $26B cash with manageable debt.",
|
|
},
|
|
{
|
|
name: "News Analyst",
|
|
role: "Macro & News",
|
|
avatarType: "news",
|
|
icon: "\u{1F4F0}",
|
|
signal: "bullish",
|
|
signalText: "Bullish \u2014 Favorable Headlines",
|
|
metrics: [
|
|
{ label: "Sentiment", value: "Positive (82%)" },
|
|
{ label: "Key Events", value: "3 Catalysts" },
|
|
{ label: "Risk Flags", value: "1 Moderate" },
|
|
],
|
|
excerpt:
|
|
"New Blackwell GPU architecture receiving strong OEM adoption. Sovereign AI investments from multiple nations. Minor concern: potential China export restrictions.",
|
|
},
|
|
{
|
|
name: "Social Media",
|
|
role: "Sentiment Analysis",
|
|
avatarType: "social",
|
|
icon: "\u{1F4AC}",
|
|
signal: "neutral",
|
|
signalText: "Neutral \u2014 Mixed Signals",
|
|
metrics: [
|
|
{ label: "Overall Score", value: "0.62 / 1.0" },
|
|
{ label: "Buzz Volume", value: "Very High" },
|
|
{ label: "Inst. Sentiment", value: "Positive" },
|
|
],
|
|
excerpt:
|
|
"Institutional sentiment strongly positive with multiple analyst upgrades. Retail shows FOMO \u2014 elevated put/call ratio suggests hedging. Insider selling noted.",
|
|
},
|
|
];
|
|
|
|
const avatarBg: Record<string, string> = {
|
|
market: "bg-cyan-dim border-cyan/20",
|
|
fundamentals: "bg-amber-dim border-amber/20",
|
|
news: "bg-blue-dim border-blue/20",
|
|
social: "bg-purple-dim border-purple/20",
|
|
};
|
|
|
|
const signalStyle: Record<string, string> = {
|
|
bullish: "bg-green-dim text-green",
|
|
bearish: "bg-red-dim text-red",
|
|
neutral: "bg-cyan-dim text-cyan",
|
|
};
|
|
|
|
export default function AnalystGrid() {
|
|
return (
|
|
<Panel
|
|
title="Analyst Reports"
|
|
badge="Updated"
|
|
badgeVariant="live"
|
|
className="col-span-2"
|
|
delay={0.25}
|
|
>
|
|
<div className="grid grid-cols-4 gap-2.5">
|
|
{analysts.map((a, i) => (
|
|
<motion.div
|
|
key={a.name}
|
|
initial={{ opacity: 0, y: 12 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{
|
|
duration: 0.5,
|
|
delay: 0.3 + i * 0.08,
|
|
ease: [0.22, 1, 0.36, 1],
|
|
}}
|
|
className="bg-bg-elevated border border-border-subtle rounded-lg p-3.5
|
|
transition-all duration-300 cursor-default
|
|
hover:border-border-medium hover:-translate-y-0.5 hover:shadow-[0_8px_30px_rgba(0,0,0,0.3)]"
|
|
>
|
|
<div className="flex items-center gap-2.5 mb-3">
|
|
<div
|
|
className={`w-8 h-8 rounded-lg grid place-items-center text-sm shrink-0 border ${avatarBg[a.avatarType]}`}
|
|
>
|
|
{a.icon}
|
|
</div>
|
|
<div>
|
|
<div className="font-display font-semibold text-xs text-text-primary">
|
|
{a.name}
|
|
</div>
|
|
<div className="text-[9px] text-text-tertiary uppercase tracking-[1px]">
|
|
{a.role}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
className={`flex items-center gap-1.5 mb-2.5 px-2.5 py-1.5 rounded text-[11px] font-medium ${signalStyle[a.signal]}`}
|
|
>
|
|
{a.signalText}
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-1.5">
|
|
{a.metrics.map((m) => (
|
|
<div key={m.label} className="flex justify-between items-center">
|
|
<span className="text-[10px] text-text-tertiary">{m.label}</span>
|
|
<span className="text-[11px] font-medium text-text-secondary">
|
|
{m.value}
|
|
</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div className="mt-2.5 pt-2.5 border-t border-border-subtle text-[11px] text-text-secondary leading-relaxed line-clamp-3">
|
|
{a.excerpt}
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</Panel>
|
|
);
|
|
}
|