feat: Kunden-Panel zeigt Agents + API-Keys nebeneinander

This commit is contained in:
cynfo3000 2026-03-10 00:20:56 +01:00
parent ebd8f1ebb8
commit 4a79305eee

View File

@ -1,7 +1,7 @@
import { useEffect, useState } from 'react'
import api from '../api/client'
import { copyToClipboard } from '../utils/clipboard'
import { Plus, Trash2, Edit2, X, Check, ChevronDown, ChevronRight, Copy, Key } from 'lucide-react'
import { Plus, Trash2, Edit2, X, Check, ChevronDown, ChevronRight, Copy, Key, Monitor } from 'lucide-react'
const PERM_LABELS = {
agent: { label: 'Agent', color: 'text-blue-400 bg-blue-900/30 border-blue-700/50' },
@ -198,10 +198,12 @@ export default function Customers() {
function CustomerKeyPanel({ customerId }) {
const [keys, setKeys] = useState(null)
const [agents, setAgents] = useState(null)
const [copied, setCopied] = useState(null)
useEffect(() => {
api.getCustomerAPIKeys(customerId).then(setKeys)
api.getCustomerAgents(customerId).then(setAgents)
}, [customerId])
const copyKey = (key, id) => {
@ -210,34 +212,56 @@ function CustomerKeyPanel({ customerId }) {
setTimeout(() => setCopied(null), 2000)
}
if (keys === null) {
const loading = keys === null || agents === null
if (loading) {
return <div className="px-8 py-3 text-gray-500 text-xs bg-gray-800/20 border-t border-gray-800">Laden...</div>
}
if (keys.length === 0) {
return (
<div className="px-8 py-3 text-gray-500 text-xs bg-gray-800/20 border-t border-gray-800 flex items-center gap-2">
<Key className="w-3.5 h-3.5" />
Keine API-Keys fuer diesen Kunden
</div>
)
}
// Agent-Key fuer diesen Kunden ermitteln (zum Abgleich welcher Agent ihn nutzt)
const agentKey = keys.find(k => k.permissions === 'agent')
return (
<div className="bg-gray-800/20 border-t border-gray-800 px-8 py-3 space-y-1.5">
<div className="bg-gray-800/20 border-t border-gray-800 px-8 py-3 grid grid-cols-1 md:grid-cols-2 gap-x-10 gap-y-3">
{/* Agents */}
<div className="space-y-1.5">
<div className="flex items-center gap-2 mb-2">
<Monitor className="w-3.5 h-3.5 text-gray-500" />
<span className="text-xs text-gray-500 font-medium">Agents ({agents.length})</span>
</div>
{agents.length === 0 ? (
<div className="text-xs text-gray-600">Keine Agents zugeordnet</div>
) : (
agents.map((a) => (
<div key={a.id} className="flex items-center gap-2.5">
<span className={`w-1.5 h-1.5 rounded-full flex-shrink-0 ${
a.status === 'online' ? 'bg-green-400' :
a.status === 'stale' ? 'bg-yellow-400' : 'bg-gray-600'
}`} />
<span className="text-xs text-gray-300 flex-1 min-w-0 truncate">{a.name}</span>
<span className="text-[10px] text-gray-600 font-mono flex-shrink-0">{a.agent_version || '—'}</span>
</div>
))
)}
</div>
{/* API-Keys */}
<div className="space-y-1.5">
<div className="flex items-center gap-2 mb-2">
<Key className="w-3.5 h-3.5 text-gray-500" />
<span className="text-xs text-gray-500 font-medium">API-Keys</span>
</div>
{keys.map((k) => {
{keys.length === 0 ? (
<div className="text-xs text-gray-600">Keine Keys</div>
) : (
keys.map((k) => {
const perm = PERM_LABELS[k.permissions] || PERM_LABELS.read
return (
<div key={k.id} className="flex items-center gap-3">
<div key={k.id} className="flex items-center gap-2.5">
<span className={`text-[10px] font-bold px-1.5 py-0.5 rounded border leading-none w-16 text-center flex-shrink-0 ${perm.color}`}>
{perm.label}
</span>
<span className="text-xs text-gray-400 flex-1 min-w-0 truncate">{k.name}</span>
<code className="text-xs text-gray-500 font-mono flex-shrink-0">
<code className="text-xs text-gray-500 font-mono flex-1 min-w-0 truncate">
{k.key.substring(0, 8)}...{k.key.substring(k.key.length - 4)}
</code>
<button
@ -252,7 +276,10 @@ function CustomerKeyPanel({ customerId }) {
</button>
</div>
)
})}
})
)}
</div>
</div>
)
}