100 lines
3.8 KiB
TypeScript
100 lines
3.8 KiB
TypeScript
import React from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useAgents } from '@/api/automation';
|
|
import { Card } from '@/components/ui/Card';
|
|
import { Badge } from '@/components/ui/Badge';
|
|
import { Skeleton } from '@/components/ui/Skeleton';
|
|
import { EmptyState } from '@/components/ui/EmptyState';
|
|
import { Bot, Brain, Activity, AlertCircle } from 'lucide-react';
|
|
import type { AgentDefinition } from '@/types/automation';
|
|
|
|
function statusBadgeVariant(status: string): 'success' | 'warning' | 'secondary' {
|
|
if (status === 'active') return 'success';
|
|
if (status === 'inactive') return 'secondary';
|
|
return 'warning';
|
|
}
|
|
|
|
export function AgentsOverviewPage() {
|
|
const { t } = useTranslation();
|
|
const { data: agents, isLoading, isError, refetch } = useAgents();
|
|
|
|
return (
|
|
<div className="max-w-4xl mx-auto">
|
|
<h1 className="text-2xl font-bold text-secondary-900 mb-4">{t('agentsOverview.agentenübersicht')}</h1>
|
|
<p className="text-secondary-600 mb-6">
|
|
{t('agentsOverview.verwaltensiekiagentenführensie')}
|
|
</p>
|
|
|
|
{/* Loading */}
|
|
{isLoading && (
|
|
<div className="space-y-4">
|
|
{[1, 2, 3].map((i) => (
|
|
<Skeleton key={i} className="h-24 w-full" />
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
{/* Error */}
|
|
{isError && (
|
|
<Card className="p-6">
|
|
<div className="flex items-center gap-3 text-danger-600">
|
|
<AlertCircle className="h-5 w-5" />
|
|
<span>{t('common.errorLoading')}</span>
|
|
<button
|
|
onClick={() => refetch()}
|
|
className="ml-auto px-3 py-1.5 text-sm font-medium rounded-md bg-secondary-100 text-secondary-700 hover:bg-secondary-200 transition-colors min-h-touch"
|
|
>
|
|
{t('common.retry')}
|
|
</button>
|
|
</div>
|
|
</Card>
|
|
)}
|
|
|
|
{/* Empty State */}
|
|
{!isLoading && !isError && (!agents || agents.length === 0) && (
|
|
<EmptyState
|
|
title={t('agent.noAgents', 'Keine Agenten')}
|
|
description={t('agent.noAgentsDesc', 'Erstellen Sie Ihren ersten KI-Agenten, um zu starten.')}
|
|
icon={<Bot className="h-8 w-8" />}
|
|
/>
|
|
)}
|
|
|
|
{/* Agent List */}
|
|
{!isLoading && !isError && agents && agents.length > 0 && (
|
|
<div className="space-y-4">
|
|
{agents.map((agent: AgentDefinition) => (
|
|
<Card key={agent.id} className="p-4">
|
|
<div className="flex items-start justify-between">
|
|
<div className="flex-1">
|
|
<div className="flex items-center gap-3 mb-1">
|
|
<h3 className="text-lg font-semibold text-secondary-900">{agent.name}</h3>
|
|
<Badge variant={statusBadgeVariant(agent.active ? 'active' : 'inactive')}>
|
|
{agent.active ? t('agent.active', 'Aktiv') : t('agent.inactive', 'Inaktiv')}
|
|
</Badge>
|
|
<Badge variant={agent.mode === 'proactive' ? 'info' : 'secondary'}>
|
|
{agent.mode}
|
|
</Badge>
|
|
</div>
|
|
{agent.description && (
|
|
<p className="text-sm text-secondary-500 mb-2">{agent.description}</p>
|
|
)}
|
|
<div className="flex items-center gap-4 text-xs text-secondary-400">
|
|
<span className="flex items-center gap-1">
|
|
<Brain className="h-3 w-3" />
|
|
{agent.model}
|
|
</span>
|
|
<span className="flex items-center gap-1">
|
|
<Activity className="h-3 w-3" />
|
|
{agent.tools?.length || 0} tools
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|