"use client"; import { useGSAP } from "@gsap/react"; import gsap from "gsap"; import { Hash, Search, Sparkles, TrendingUp } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { useAmbient } from "@/components/ambient/ambient-context"; import { Avatar, Badge, GlassPanel, Input } from "@/components/primitives"; import { EmptyState, SectionHeader, SkeletonRows } from "@/components/shared"; import { useChannels, useMessageSearch, useTopReactors } from "@/hooks"; import { useStaggerReveal } from "@/hooks/use-gsap-animation"; import { aiTone } from "@/lib/ai-status"; import { formatDuration, getMessageChannelLabel, renderMessageContent, } from "@/lib/format"; if (typeof window !== "undefined") { gsap.registerPlugin(useGSAP); } export function AnalysisView() { const [query, setQuery] = useState(""); const search = useMessageSearch(query, query.trim().length >= 2); const { data: reactors } = useTopReactors(); const { data: channels } = useChannels(); const ambient = useAmbient(); const reactorsRef = useRef(null); const channelsRef = useRef(null); const resultsRef = useStaggerReveal(".search-result-card", { stagger: 0.03, y: 8, dependencies: [search.data?.length, query], }); useEffect(() => { ambient.set( query ? "amber" : "signal", 0.3, query ? "analyzing" : "search", ); }, [query, ambient]); // Count-up + bar-fill reveal for the reactor leaderboard — HUD gauge motif. useGSAP( () => { if (!reactorsRef.current) return; const bars = reactorsRef.current.querySelectorAll(".reactor-bar-fill"); const counters = reactorsRef.current.querySelectorAll(".reactor-count"); if (bars.length === 0) return; const prefersReduced = window.matchMedia( "(prefers-reduced-motion: reduce)", ).matches; if (prefersReduced) { gsap.set(bars, { scaleX: 1 }); return; } gsap.fromTo( bars, { scaleX: 0 }, { scaleX: 1, duration: 0.7, stagger: 0.06, ease: "power2.out", transformOrigin: "left center", }, ); counters.forEach((el) => { const target = Number(el.getAttribute("data-target") ?? "0"); const obj = { val: 0 }; gsap.to(obj, { val: target, duration: 0.8, ease: "power2.out", onUpdate: () => { el.textContent = `+${Math.round(obj.val)}`; }, }); }); }, { scope: reactorsRef, dependencies: [reactors] }, ); useGSAP( () => { if (!channelsRef.current) return; const rows = channelsRef.current.querySelectorAll(".channel-row"); if (rows.length === 0) return; const prefersReduced = window.matchMedia( "(prefers-reduced-motion: reduce)", ).matches; if (prefersReduced) { gsap.set(rows, { opacity: 1, x: 0 }); return; } gsap.fromTo( rows, { opacity: 0, x: -10 }, { opacity: 1, x: 0, duration: 0.35, stagger: 0.04, ease: "power2.out", clearProps: "transform", }, ); }, { scope: channelsRef, dependencies: [channels] }, ); return (
{/* Tactical HUD Header Bar */}

Deep Scan · Semantic Search & Telemetry Analysis

ENGINE: {query.trim().length >= 2 ? "SCANNING" : "STANDBY"}
{/* Hero Query Stage */}

Cross-Guild Archive Intelligence

Query vectorized messages, heuristic flags, and user behavior

setQuery(e.target.value)} autoFocus />
{/* Search Results Column */} {(search.data ?? []).length} results } /> {query.trim().length >= 2 && search.isLoading && ( )} {(search.data ?? []).length === 0 && !search.isLoading ? ( } title="No packets matched" description="Enter a query string above to scan across all captured guild communication." /> ) : (
{(search.data ?? []).map((m) => (
{m.username} {getMessageChannelLabel(m)} {m.ai_status && ( {m.ai_analysis_duration_ms && m.ai_analysis_duration_ms > 0 ? `${m.ai_status} · ${formatDuration(m.ai_analysis_duration_ms)}` : m.ai_status} )}
{renderMessageContent(m.content, m.metadata) || "(embed)"}
))}
)}
{/* Culture & Leaderboard Side Column */}
Top Reactors } />
{(reactors ?? []).slice(0, 6).map((r, i) => { const maxNet = reactors?.[0]?.net_count || 1; const pct = Math.max( 4, Math.round((r.net_count / maxNet) * 100), ); return (
0{i + 1} {r.username}
+0
); })} {(reactors ?? []).length === 0 && (
NO REACTOR DATA
)}
Top Active Channels } />
{(channels ?? []).slice(0, 6).map((c) => (
{c.channel_name ?? c.channel_id.slice(0, 10)} {c.total_messages.toLocaleString()} msgs
))} {(channels ?? []).length === 0 && (
NO CHANNEL DATA
)}
); }