feat: add Proaktiv and KI Chat tabs to AI sidebar
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ChatWindow } from '@/components/ai/ChatWindow';
|
||||
import { ResizablePanel } from '@/components/ui/ResizablePanel';
|
||||
import { SuggestionList } from '@/components/ai/SuggestionSidebar';
|
||||
import { createSession, fetchSessions } from '@/api/ai';
|
||||
import { useUIStore } from '@/store/uiStore';
|
||||
|
||||
export function AISidebar() {
|
||||
const { aiSidebarCollapsed, toggleAISidebar } = useUIStore();
|
||||
const { aiSidebarCollapsed, toggleAISidebar, aiSidebarTab, setAISidebarTab } = useUIStore();
|
||||
const [sessionId, setSessionId] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
@@ -48,6 +49,65 @@ export function AISidebar() {
|
||||
);
|
||||
}
|
||||
|
||||
const renderTabContent = () => {
|
||||
if (aiSidebarTab === 'proactive') {
|
||||
return <SuggestionList />;
|
||||
}
|
||||
// chat tab
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full text-sm text-secondary-400">Laden...</div>
|
||||
);
|
||||
}
|
||||
if (sessionId) {
|
||||
return <ChatWindow sessionId={sessionId} compact className="h-full" />;
|
||||
}
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full text-sm text-red-500">
|
||||
Session konnte nicht erstellt werden
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const tabBar = (
|
||||
<div className="flex border-b border-secondary-200" role="tablist">
|
||||
<button
|
||||
onClick={() => setAISidebarTab('proactive')}
|
||||
className={`px-3 py-2 text-sm font-medium flex items-center gap-1.5 border-b-2 transition-colors ${
|
||||
aiSidebarTab === 'proactive'
|
||||
? 'text-primary-600 border-primary-500'
|
||||
: 'text-secondary-500 hover:text-secondary-700 border-transparent'
|
||||
}`}
|
||||
role="tab"
|
||||
aria-selected={aiSidebarTab === 'proactive'}
|
||||
aria-label="Proaktiv"
|
||||
data-testid="ai-sidebar-tab-proactive"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
|
||||
</svg>
|
||||
Proaktiv
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setAISidebarTab('chat')}
|
||||
className={`px-3 py-2 text-sm font-medium flex items-center gap-1.5 border-b-2 transition-colors ${
|
||||
aiSidebarTab === 'chat'
|
||||
? 'text-primary-600 border-primary-500'
|
||||
: 'text-secondary-500 hover:text-secondary-700 border-transparent'
|
||||
}`}
|
||||
role="tab"
|
||||
aria-selected={aiSidebarTab === 'chat'}
|
||||
aria-label="KI Chat"
|
||||
data-testid="ai-sidebar-tab-chat"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
|
||||
</svg>
|
||||
KI Chat
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
// Expanded: Mobile = full width overlay, Desktop = resizable panel
|
||||
return (
|
||||
<>
|
||||
@@ -70,16 +130,9 @@ export function AISidebar() {
|
||||
</button>
|
||||
<span className="text-sm font-medium text-secondary-700 ml-2">KI Assistent</span>
|
||||
</div>
|
||||
{tabBar}
|
||||
<div className="flex-1 overflow-hidden">
|
||||
{loading ? (
|
||||
<div className="flex items-center justify-center h-full text-sm text-secondary-400">Laden...</div>
|
||||
) : sessionId ? (
|
||||
<ChatWindow sessionId={sessionId} compact className="h-full" />
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-sm text-red-500">
|
||||
Session konnte nicht erstellt werden
|
||||
</div>
|
||||
)}
|
||||
{renderTabContent()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -105,16 +158,9 @@ export function AISidebar() {
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
{tabBar}
|
||||
<div className="flex-1 overflow-hidden">
|
||||
{loading ? (
|
||||
<div className="flex items-center justify-center h-full text-sm text-secondary-400">Laden...</div>
|
||||
) : sessionId ? (
|
||||
<ChatWindow sessionId={sessionId} compact className="h-full" />
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-sm text-red-500">
|
||||
Session konnte nicht erstellt werden
|
||||
</div>
|
||||
)}
|
||||
{renderTabContent()}
|
||||
</div>
|
||||
</div>
|
||||
</ResizablePanel>
|
||||
|
||||
@@ -4,14 +4,11 @@ import { Sidebar } from './Sidebar';
|
||||
import { TopBar } from './TopBar';
|
||||
import { PluginToolbar } from './PluginToolbar';
|
||||
import { AISidebar } from './AISidebar';
|
||||
import { SuggestionSidebar } from '@/components/ai/SuggestionSidebar';
|
||||
import { ToastContainer } from '@/components/ui/Toast';
|
||||
import { useUIStore } from '@/store/uiStore';
|
||||
import { useAIContext } from '@/hooks/useAIContext';
|
||||
|
||||
export function AppShell() {
|
||||
const location = useLocation();
|
||||
const { suggestionSidebarOpen, toggleSuggestionSidebar } = useUIStore();
|
||||
|
||||
// Track context for AI Proactive suggestions
|
||||
useAIContext();
|
||||
@@ -39,11 +36,6 @@ export function AppShell() {
|
||||
</div>
|
||||
{/* AI Sidebar — full height, right of TopBar and Toolbar */}
|
||||
{showAISidebar && <AISidebar />}
|
||||
{/* Suggestion Sidebar — overlays from right */}
|
||||
<SuggestionSidebar
|
||||
isOpen={suggestionSidebarOpen}
|
||||
onClose={() => toggleSuggestionSidebar()}
|
||||
/>
|
||||
<ToastContainer />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ export function TopBar() {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuthStore();
|
||||
const { toggleSidebar, toggleAISidebar, toggleSuggestionSidebar, aiSidebarCollapsed } = useUIStore();
|
||||
const { toggleSidebar, toggleAISidebar, openAISidebarProactive, aiSidebarCollapsed } = useUIStore();
|
||||
const { currentTenant, availableTenants, switchTenant, isSwitching } = useTenant();
|
||||
const logoutMutation = useLogout();
|
||||
|
||||
@@ -143,7 +143,7 @@ export function TopBar() {
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
{/* AI Suggestions Badge */}
|
||||
<SuggestionBadge onClick={toggleSuggestionSidebar} />
|
||||
<SuggestionBadge onClick={openAISidebarProactive} />
|
||||
|
||||
{/* Notifications */}
|
||||
<div ref={notifRef} className="relative">
|
||||
|
||||
Reference in New Issue
Block a user