131 lines
6.3 KiB
TypeScript
131 lines
6.3 KiB
TypeScript
import React, { useMemo } from 'react';
|
|
|
|
export type Agent = {
|
|
id: string;
|
|
name: string;
|
|
color: string; // tailwind gradient colors
|
|
emoji: string;
|
|
};
|
|
|
|
interface AgentPanelProps {
|
|
agents: Agent[];
|
|
activeAgentId: string;
|
|
onChangeAgent: (id: string) => void;
|
|
}
|
|
|
|
const AgentPanel: React.FC<AgentPanelProps> = ({ agents, activeAgentId, onChangeAgent }) => {
|
|
const active = useMemo(() => agents.find(a => a.id === activeAgentId) || agents[0], [agents, activeAgentId]);
|
|
|
|
// 8 diverse agents for the 3D carousel
|
|
const carouselAgents = useMemo(() => [
|
|
{ id: 'hr', name: 'HR Command', emoji: '👥', color: 'from-luxury-gold/30 to-brass/30' },
|
|
{ id: 'finance', name: 'Finance Sage', emoji: '💰', color: 'from-bronze/30 to-luxury-gold/30' },
|
|
{ id: 'project', name: 'Project Sensei', emoji: '📊', color: 'from-brass/30 to-bronze/30' },
|
|
{ id: 'marketing', name: 'Marketing Genius', emoji: '🎯', color: 'from-luxury-gold/30 to-cream/30' },
|
|
{ id: 'analytics', name: 'Data Wizard', emoji: '📈', color: 'from-bronze/30 to-brass/30' },
|
|
{ id: 'security', name: 'Security Guard', emoji: '🛡️', color: 'from-deep-forest/40 to-luxury-gold/30' },
|
|
{ id: 'support', name: 'Support Hero', emoji: '🎧', color: 'from-brass/30 to-rich-brown/30' },
|
|
{ id: 'research', name: 'Research Bot', emoji: '🔍', color: 'from-luxury-gold/30 to-bronze/30' }
|
|
], []);
|
|
|
|
return (
|
|
<div className="h-full w-full rounded-xl bg-deep-forest/60 backdrop-blur-xl overflow-hidden flex flex-col shadow-inner">
|
|
{/* Removed heading & static active name per user request */}
|
|
|
|
<div className="relative flex-1">
|
|
<div className={`absolute inset-0 opacity-35 bg-gradient-to-br ${active.color}`} />
|
|
|
|
{/* Creative Orbital Agent Display */}
|
|
<div className="absolute inset-0 grid place-items-center">
|
|
{/* Central Hub */}
|
|
<div className="relative">
|
|
{/* Outer orbital ring */}
|
|
<div className="w-72 h-72 rounded-full border border-luxury-gold/15 relative">
|
|
{/* Orbital path indicator */}
|
|
<div className="absolute inset-4 rounded-full border border-luxury-gold/10"></div>
|
|
<div className="absolute inset-8 rounded-full border border-luxury-gold/5"></div>
|
|
|
|
{/* Rotating agents on the orbit */}
|
|
{carouselAgents.map((agent, index) => {
|
|
const angle = (index * 360) / carouselAgents.length;
|
|
const isActive = agent.id === activeAgentId;
|
|
const radian = (angle * Math.PI) / 180;
|
|
const radius = 130;
|
|
const x = Math.cos(radian) * radius;
|
|
const y = Math.sin(radian) * radius;
|
|
|
|
return (
|
|
<div key={agent.id} className="contents">
|
|
<button
|
|
onClick={() => onChangeAgent(agent.id)}
|
|
className={`absolute w-12 h-12 rounded-xl transition-all duration-300 hover:scale-125 focus:outline-none group ${
|
|
isActive
|
|
? 'bg-gradient-to-br from-luxury-gold/60 to-brass/60 border-2 border-luxury-gold shadow-[0_0_25px_rgba(197,157,89,0.8)] scale-110 z-10'
|
|
: 'bg-deep-forest/70 border border-luxury-gold/30 hover:border-luxury-gold/60 hover:bg-deep-forest/80'
|
|
}`}
|
|
style={{
|
|
left: '50%',
|
|
top: '50%',
|
|
transform: `translate(${x - 24}px, ${y - 24}px)`,
|
|
}}
|
|
title={agent.name}
|
|
>
|
|
<div className="flex flex-col items-center justify-center h-full">
|
|
<span className={`text-lg transition-all duration-300 ${isActive ? 'text-deep-forest' : 'text-cream'}`}>
|
|
{agent.emoji}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Connection line to center for active agent */}
|
|
{isActive && (
|
|
<div
|
|
className="absolute w-0.5 bg-gradient-to-r from-luxury-gold to-transparent opacity-60"
|
|
style={{
|
|
height: `${radius - 20}px`,
|
|
left: '50%',
|
|
top: '50%',
|
|
transformOrigin: 'top center',
|
|
transform: `translateX(-50%) rotate(${180 + angle}deg)`
|
|
}}
|
|
/>
|
|
)}
|
|
</button>
|
|
|
|
{/* Tooltip positioned outside rotating container */}
|
|
<div
|
|
className="absolute z-50 pointer-events-none"
|
|
style={{
|
|
left: '50%',
|
|
top: '50%',
|
|
transform: `translate(${x - 24}px, ${y + 40}px)`,
|
|
}}
|
|
>
|
|
<div className="opacity-0 group-hover:opacity-100 transition-opacity duration-150 bg-deep-forest/95 text-cream/90 text-[11px] px-2 py-1 rounded-md border border-luxury-gold/30 whitespace-nowrap font-montserrat font-medium shadow-[0_2px_4px_rgba(0,0,0,0.4)] -translate-x-1/2">
|
|
{agent.name}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
{/* Central Control Hub */}
|
|
<div className="absolute top-1/2 left-1/2 w-16 h-16 -translate-x-1/2 -translate-y-1/2 z-20">
|
|
<div className="w-full h-full rounded-full bg-gradient-to-br from-deep-forest/80 to-rich-brown/60 border border-luxury-gold/30 flex items-center justify-center group cursor-pointer">
|
|
<div className="text-center">
|
|
<div className="text-xl mb-0.5">🤖</div>
|
|
<div className="text-[10px] text-cream/80 font-montserrat font-medium">HUB</div>
|
|
</div>
|
|
</div>
|
|
{/* Removed pulsing rings for a calmer static display */}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/* Removed floating particle animations */}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AgentPanel;
|