File size: 5,886 Bytes
83a54a9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { useState } from 'react';

const colorMap = {
  blue: { bg: 'bg-blue-500/10', border: 'border-blue-500/30', text: 'text-blue-400', glow: 'shadow-blue-500/20' },
  purple: { bg: 'bg-purple-500/10', border: 'border-purple-500/30', text: 'text-purple-400', glow: 'shadow-purple-500/20' },
  indigo: { bg: 'bg-indigo-500/10', border: 'border-indigo-500/30', text: 'text-indigo-400', glow: 'shadow-indigo-500/20' },
  green: { bg: 'bg-green-500/10', border: 'border-green-500/30', text: 'text-green-400', glow: 'shadow-green-500/20' },
  pink: { bg: 'bg-pink-500/10', border: 'border-pink-500/30', text: 'text-pink-400', glow: 'shadow-pink-500/20' },
  orange: { bg: 'bg-orange-500/10', border: 'border-orange-500/30', text: 'text-orange-400', glow: 'shadow-orange-500/20' },
  yellow: { bg: 'bg-yellow-500/10', border: 'border-yellow-500/30', text: 'text-yellow-400', glow: 'shadow-yellow-500/20' },
  cyan: { bg: 'bg-cyan-500/10', border: 'border-cyan-500/30', text: 'text-cyan-400', glow: 'shadow-cyan-500/20' },
  red: { bg: 'bg-red-500/10', border: 'border-red-500/30', text: 'text-red-400', glow: 'shadow-red-500/20' },
  teal: { bg: 'bg-teal-500/10', border: 'border-teal-500/30', text: 'text-teal-400', glow: 'shadow-teal-500/20' },
  violet: { bg: 'bg-violet-500/10', border: 'border-violet-500/30', text: 'text-violet-400', glow: 'shadow-violet-500/20' },
};

const statusConfig = {
  idle: { label: 'Idle', dot: 'bg-gray-600', bg: 'bg-gray-500/5' },
  active: { label: 'Active', dot: 'bg-yellow-500 animate-pulse', bg: '' },
  done: { label: 'Done', dot: 'bg-green-500', bg: '' },
  failed: { label: 'Failed', dot: 'bg-red-500', bg: '' },
};

export default function AgentGrid({ agents, statuses, currentPhase }) {
  const [selectedAgent, setSelectedAgent] = useState(null);

  const phaseNames = ['Planning', 'Execution', 'Validation', 'Documentation', 'Learning'];

  return (
    <div className="space-y-6">
      {/* Phase Indicator */}
      {currentPhase >= 0 && (
        <div className="glass-card p-4 animate-slide-up">
          <div className="flex items-center gap-3 mb-3">
            <div className="w-2 h-2 rounded-full bg-indigo-500 animate-pulse" />
            <span className="text-sm font-medium text-indigo-400">
              Current Phase: {phaseNames[currentPhase] || 'Unknown'}
            </span>
          </div>
          <div className="flex gap-2">
            {phaseNames.map((name, i) => (
              <div
                key={name}
                className={`flex-1 h-1.5 rounded-full transition-all duration-500 ${
                  i < currentPhase ? 'bg-green-500' :
                  i === currentPhase ? 'bg-indigo-500 animate-pulse' :
                  'bg-gray-800'
                }`}
              />
            ))}
          </div>
        </div>
      )}

      {/* Agent Grid */}
      <div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-4">
        {agents.map((agent, index) => {
          const colors = colorMap[agent.color];
          const status = statuses[agent.id] || 'idle';
          const statusInfo = statusConfig[status];
          const isSelected = selectedAgent === agent.id;

          return (
            <div
              key={agent.id}
              onClick={() => setSelectedAgent(isSelected ? null : agent.id)}
              className={`agent-card cursor-pointer animate-slide-up ${
                status === 'active' ? `${colors.bg} ${colors.border} shadow-lg ${colors.glow}` :
                status === 'done' ? 'border-green-500/20' :
                ''
              }`}
              style={{ animationDelay: `${index * 50}ms` }}
            >
              <div className="flex items-start gap-3">
                <div className={`w-10 h-10 rounded-xl ${colors.bg} flex items-center justify-center text-lg flex-shrink-0`}>
                  {agent.icon}
                </div>
                <div className="flex-1 min-w-0">
                  <div className="flex items-center justify-between gap-2">
                    <h3 className={`text-sm font-semibold ${colors.text} truncate`}>{agent.name}</h3>
                    <div className="flex items-center gap-1.5 flex-shrink-0">
                      <div className={`status-dot ${statusInfo.dot}`} />
                      <span className="text-xs text-gray-500">{statusInfo.label}</span>
                    </div>
                  </div>
                  <p className="text-xs text-gray-500 mt-1 line-clamp-2">{agent.description}</p>
                </div>
              </div>

              {isSelected && (
                <div className="mt-3 pt-3 border-t border-gray-800/50 animate-slide-up">
                  <div className="space-y-2">
                    <div className="flex items-center gap-2">
                      <span className="text-xs text-gray-500">Agent ID:</span>
                      <code className="text-xs text-gray-300 bg-gray-800/50 px-1.5 py-0.5 rounded">{agent.id}</code>
                    </div>
                    <div className="flex items-center gap-2">
                      <span className="text-xs text-gray-500">Status:</span>
                      <span className={`text-xs font-medium ${status === 'done' ? 'text-green-400' : status === 'active' ? 'text-yellow-400' : 'text-gray-400'}`}>
                        {status.toUpperCase()}
                      </span>
                    </div>
                    <div className="flex items-center gap-2">
                      <span className="text-xs text-gray-500">Phase:</span>
                      <span className="text-xs text-gray-300">
                        {currentPhase >= 0 ? phaseNames[currentPhase] : 'Waiting'}
                      </span>
                    </div>
                  </div>
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}