Fix agent cards grid layout - clean code
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { Agent, AgentTeam, defaultTeams } from "@/lib/council/types";
|
||||
import { AgentTeam, defaultTeams } from "@/lib/council/types";
|
||||
import AgentModal from "./AgentModal";
|
||||
|
||||
const STORAGE_KEY = "horus:council";
|
||||
@@ -10,10 +10,7 @@ export default function Council() {
|
||||
const [teams, setTeams] = useState<AgentTeam[]>(defaultTeams);
|
||||
const [selectedTeam, setSelectedTeam] = useState<string | null>(null);
|
||||
const [selectedAgent, setSelectedAgent] = useState<string | null>(null);
|
||||
const [runningTask, setRunningTask] = useState<string>("");
|
||||
const [agentOutputs, setAgentOutputs] = useState<Record<string, string>>({});
|
||||
|
||||
// Load from localStorage
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
const saved = localStorage.getItem(STORAGE_KEY);
|
||||
@@ -24,13 +21,12 @@ export default function Council() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Save changes
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(teams));
|
||||
}, [teams]);
|
||||
|
||||
const getStatusColor = (status: Agent["status"]) => {
|
||||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case "working": return "text-yellow-400 bg-yellow-400/20";
|
||||
case "completed": return "text-green-400 bg-green-400/20";
|
||||
@@ -39,37 +35,6 @@ export default function Council() {
|
||||
}
|
||||
};
|
||||
|
||||
const spawnAgent = async (agent: Agent, task: string) => {
|
||||
if (!task.trim()) return;
|
||||
|
||||
// Update agent status
|
||||
setTeams(prev => prev.map(team => ({
|
||||
...team,
|
||||
agents: team.agents.map(a => a.id === agent.id ? { ...a, status: "working" as const, currentTask: task } : a)
|
||||
})));
|
||||
setRunningTask("");
|
||||
|
||||
// Simulate agent work (in reality this would call actual agents)
|
||||
const output = `[🤖 ${agent.name}] Starting task: "${task}"\n\n`;
|
||||
setAgentOutputs(prev => ({ ...prev, [agent.id]: output + "⏳ Processing...\n" }));
|
||||
|
||||
// Simulate completion after delay
|
||||
setTimeout(() => {
|
||||
const result = output + `✅ Task completed: ${task}\n\n💡 Result: Task processed successfully.`;
|
||||
setAgentOutputs(prev => ({ ...prev, [agent.id]: result }));
|
||||
|
||||
setTeams(prev => prev.map(team => ({
|
||||
...team,
|
||||
agents: team.agents.map(a => a.id === agent.id ? {
|
||||
...a,
|
||||
status: "completed" as const,
|
||||
lastRun: new Date().toISOString(),
|
||||
currentTask: undefined
|
||||
} : a)
|
||||
})));
|
||||
}, 3000 + Math.random() * 2000);
|
||||
};
|
||||
|
||||
const currentTeam = teams.find(t => t.id === selectedTeam);
|
||||
|
||||
return (
|
||||
@@ -104,11 +69,6 @@ export default function Council() {
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-white/60">{team.description}</p>
|
||||
<div className="mt-3 flex gap-1">
|
||||
{team.agents.slice(0, 4).map(a => (
|
||||
<span key={a.id} className={`w-2 h-2 rounded-full ${getStatusColor(a.status).split(' ')[1].replace('/', '-')}`} />
|
||||
))}
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
@@ -128,45 +88,29 @@ export default function Council() {
|
||||
</div>
|
||||
|
||||
{/* Agents - Grid Layout */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||
{currentTeam.agents.map((agent) => (
|
||||
<div key={agent.id} className="p-4 rounded-lg border border-white/10 bg-white/5">
|
||||
<button
|
||||
key={agent.id}
|
||||
onClick={() => setSelectedAgent(agent.id)}
|
||||
className="p-4 rounded-lg border border-white/10 bg-white/5 hover:bg-white/10 hover:border-brand-pink/50 transition text-left"
|
||||
>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className={`px-2 py-0.5 rounded text-xs font-medium ${getStatusColor(agent.status)}`}>
|
||||
{agent.status.toUpperCase()}
|
||||
</span>
|
||||
<span className="font-medium">{agent.name}</span>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-white/60 mb-3">{agent.role}</p>
|
||||
|
||||
{/* Open Agent Command Center */}
|
||||
<button
|
||||
onClick={() => setSelectedAgent(agent.id)}
|
||||
className="w-full px-3 py-2 bg-white/10 hover:bg-white/20 border border-white/20 rounded-lg text-sm text-center transition"
|
||||
>
|
||||
🧑💼 Open
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
type="text"
|
||||
value={runningTask}
|
||||
</div>
|
||||
<p className="font-medium">{agent.name}</p>
|
||||
<p className="text-xs text-white/50">{agent.role}</p>
|
||||
<div className="mt-3 pt-2 border-t border-white/10">
|
||||
<span className="text-xs text-brand-pink">🧑💼 Open →</span>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Horus Boss Note */}
|
||||
<div className="p-4 rounded-xl border border-brand-pink/30 bg-brand-pink/10">
|
||||
<p className="text-sm text-brand-pink">
|
||||
👁️ <strong>Note:</strong> I coordinate these agents. They run as sub-tasks within my sessions.
|
||||
In production, they'd be separate AI processes. Currently simulating — real agent spawning requires
|
||||
the OpenClaw sub-agent system to be configured.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Agent Modal */}
|
||||
{selectedAgent && (
|
||||
<AgentModal agentId={selectedAgent} onClose={() => setSelectedAgent(null)} />
|
||||
|
||||
Reference in New Issue
Block a user