fix(i-d): Geister-Komponenten eliminiert — AIAssistant-Seite erstellt (Agent-Auswahl + AgentChat, STATIC_COMPONENT_MAP registriert nach C3-Pattern); 5 Ghost-Contact-Detail-Tabs aus Backend-Manifesten entfernt; Production-Build mit AIAssistant-Chunk verifiziert (AIAssistant-DVb66TSo.js); tsc exit=0; ruff clean
Check Cross-Plugin Imports / check (push) Has been cancelled
Check Cross-Plugin Imports / check (push) Has been cancelled
This commit is contained in:
@@ -118,8 +118,8 @@ function normalizeModule(m: ComponentModule): { default: React.ComponentType<any
|
||||
const STATIC_COMPONENT_MAP: Record<string, LazyComponentFactory> = {
|
||||
// Pages
|
||||
'@/pages/AgentDashboard': () => import('@/pages/AgentDashboard').then(normalizeModule),
|
||||
// NOTE: @/pages/AIAssistant is declared in the backend manifest but does
|
||||
// not exist as a frontend page — ghost component, see PROGRESS.md.
|
||||
// BUG (ghost page) fixed in Block I-D: page now exists.
|
||||
'@/pages/AIAssistant': () => import('@/pages/AIAssistant').then(normalizeModule),
|
||||
'@/pages/AISettings': () => import('@/pages/AISettings').then(normalizeModule),
|
||||
'@/pages/AutomationDashboard': () => import('@/pages/AutomationDashboard').then(normalizeModule),
|
||||
'@/pages/AutomationSettings': () => import('@/pages/AutomationSettings').then(normalizeModule),
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAgents } from '@/api/automation';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import { AgentChat } from '@/components/agents/AgentChat';
|
||||
|
||||
/**
|
||||
* AI Assistant page (BUG: ghost page fixed — was declared in the backend
|
||||
* manifest but did not exist, see PROGRESS.md "Ghost components").
|
||||
*
|
||||
* Minimal implementation: pick an agent, chat with it. Full agent management
|
||||
* lives in the Agent Dashboard.
|
||||
*/
|
||||
export default function AIAssistant() {
|
||||
const { t } = useTranslation();
|
||||
const { data: agents, isLoading } = useAgents();
|
||||
const [selectedAgentId, setSelectedAgentId] = useState('');
|
||||
|
||||
const selectedAgent = agents?.find((a) => a.id === selectedAgentId);
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-4" aria-label={t('ai.assistant', 'AI Assistant')}>
|
||||
<h1 className="text-xl font-semibold text-secondary-900">
|
||||
{t('ai.assistant', 'AI Assistant')}
|
||||
</h1>
|
||||
|
||||
<Card className="p-4">
|
||||
<label
|
||||
htmlFor="assistant-agent-select"
|
||||
className="block text-sm font-medium text-secondary-700 mb-1"
|
||||
>
|
||||
{t('agent.targetAgent', 'Target agent')}
|
||||
</label>
|
||||
<select
|
||||
id="assistant-agent-select"
|
||||
value={selectedAgentId}
|
||||
onChange={(e) => setSelectedAgentId(e.target.value)}
|
||||
className="w-full rounded-lg border border-secondary-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary-500"
|
||||
>
|
||||
<option value="">{t('agent.selectTargetAgent', 'Select an agent…')}</option>
|
||||
{(agents ?? []).map((agent) => (
|
||||
<option key={agent.id} value={agent.id}>
|
||||
{agent.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{!isLoading && (agents ?? []).length === 0 && (
|
||||
<p className="mt-2 text-sm text-secondary-500">
|
||||
{t(
|
||||
'agent.noAgentsHint',
|
||||
'No agents yet — create one in the Agent Dashboard.'
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{selectedAgent && (
|
||||
<Card className="p-4">
|
||||
<AgentChat agentId={selectedAgent.id} agentName={selectedAgent.name} />
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user