Spaces:
Sleeping
Sleeping
File size: 6,046 Bytes
ae4ceef | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | import React from 'react';
import {
Database, GitBranch, Bot, Globe, Server, ArrowRight,
Cpu, HardDrive, Share2
} from 'lucide-react';
import { motion } from 'framer-motion';
import { useTranslation } from 'react-i18next';
export default function ArchitectureMap() {
const { t } = useTranslation();
const nodes = [
{
id: 'data',
label: t('overview.arch.data_layer'),
icon: Database,
color: 'bg-emerald-500',
desc: t('overview.arch.data_desc'),
status: 'operational'
},
{
id: 'workflow',
label: t('overview.arch.orchestration'),
icon: GitBranch,
color: 'bg-blue-500',
desc: t('overview.arch.orch_desc'),
status: 'processing'
},
{
id: 'agent',
label: t('overview.arch.agent_core'),
icon: Bot,
color: 'bg-purple-500',
desc: t('overview.arch.agent_desc'),
status: 'operational'
},
{
id: 'app',
label: t('overview.arch.application'),
icon: Globe,
color: 'bg-orange-500',
desc: t('overview.arch.app_desc'),
status: 'active'
}
];
return (
<div className="bg-white p-6 rounded-3xl border border-zinc-200 shadow-sm mb-8 overflow-hidden relative">
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-emerald-500 via-blue-500 to-purple-500 opacity-20"></div>
<div className="flex items-center justify-between mb-6">
<h3 className="font-bold text-zinc-900 flex items-center gap-2">
<Share2 size={18} className="text-zinc-500" />
{t('overview.arch.title')}
</h3>
<span className="text-xs font-mono text-green-600 bg-green-50 px-2 py-1 rounded-full flex items-center gap-1">
<span className="w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse"></span>
{t('overview.arch.system_online')}
</span>
</div>
<div className="relative flex flex-col md:flex-row items-center justify-between gap-4 md:gap-0 px-4 py-4">
{/* Connecting Line (Desktop) */}
<div className="hidden md:block absolute top-1/2 left-10 right-10 h-0.5 bg-zinc-100 -z-0"></div>
{nodes.map((node, idx) => (
<React.Fragment key={node.id}>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: idx * 0.1 }}
className="relative z-10 flex flex-col items-center group cursor-pointer"
>
<div className={`
w-16 h-16 rounded-2xl flex items-center justify-center text-white shadow-lg mb-3 transition-all duration-300
${node.color} group-hover:scale-110 group-hover:shadow-xl
`}>
<node.icon size={28} />
{node.status === 'processing' && (
<span className="absolute -top-1 -right-1 flex h-3 w-3">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-white opacity-75"></span>
<span className="relative inline-flex rounded-full h-3 w-3 bg-white"></span>
</span>
)}
</div>
<div className="text-center">
<div className="font-bold text-zinc-800 text-sm">{node.label}</div>
<div className="text-[10px] text-zinc-400 font-medium mt-0.5">{node.desc}</div>
</div>
{/* Status Dot */}
<div className="mt-2 flex items-center gap-1">
<div className={`w-1.5 h-1.5 rounded-full ${node.status === 'operational' || node.status === 'active' || node.status === 'processing' ? 'bg-green-500' : 'bg-red-500'}`}></div>
<span className="text-[10px] text-zinc-400 uppercase">{t(`overview.arch.status.${node.status}`)}</span>
</div>
</motion.div>
{/* Arrow (except last) */}
{idx < nodes.length - 1 && (
<div className="md:hidden text-zinc-300">
<ArrowRight size={20} className="rotate-90 md:rotate-0" />
</div>
)}
{idx < nodes.length - 1 && (
<motion.div
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: idx * 0.1 + 0.2 }}
className="hidden md:flex items-center justify-center bg-white p-1 rounded-full border border-zinc-100 shadow-sm z-10 text-zinc-300"
>
<ArrowRight size={16} />
</motion.div>
)}
</React.Fragment>
))}
</div>
{/* Metrics Row */}
<div className="grid grid-cols-3 gap-4 mt-8 pt-6 border-t border-zinc-100 bg-zinc-50/50 -mx-6 -mb-6 px-6 pb-6">
<div className="flex items-center gap-3">
<div className="p-2 bg-zinc-200 rounded-lg text-zinc-500"><Server size={16} /></div>
<div>
<div className="text-[10px] text-zinc-400 font-bold uppercase">{t('overview.arch.load')}</div>
<div className="text-sm font-bold text-zinc-700">34%</div>
</div>
</div>
<div className="flex items-center gap-3">
<div className="p-2 bg-zinc-200 rounded-lg text-zinc-500"><Cpu size={16} /></div>
<div>
<div className="text-[10px] text-zinc-400 font-bold uppercase">{t('overview.arch.latency')}</div>
<div className="text-sm font-bold text-zinc-700">45ms</div>
</div>
</div>
<div className="flex items-center gap-3">
<div className="p-2 bg-zinc-200 rounded-lg text-zinc-500"><HardDrive size={16} /></div>
<div>
<div className="text-[10px] text-zinc-400 font-bold uppercase">{t('overview.arch.storage')}</div>
<div className="text-sm font-bold text-zinc-700">1.2GB</div>
</div>
</div>
</div>
</div>
);
}
|