'use client' import { useState, useEffect } from 'react' interface AIStatus { provider: string model: string is_available: boolean is_mock: boolean error?: string | null } interface LLMProviderToggleProps { aiStatus: AIStatus | null onStatusChange?: () => void } /** * LLM Provider Toggle Component * * Allows developers to switch between: * - Anthropic Claude API (Cloud, kostenpflichtig) * - Self-Hosted Ollama (Lokal auf Mac Mini, kostenlos, DSGVO-konform) */ export default function LLMProviderToggle({ aiStatus, onStatusChange }: LLMProviderToggleProps) { const [switching, setSwitching] = useState(false) const [showDetails, setShowDetails] = useState(false) const [error, setError] = useState(null) const BACKEND_URL = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000' const isAnthropicActive = aiStatus?.provider === 'anthropic' const isSelfHostedActive = aiStatus?.provider === 'self_hosted' const isMockActive = aiStatus?.provider === 'mock' const switchProvider = async (newProvider: 'anthropic' | 'self_hosted') => { setSwitching(true) setError(null) try { const res = await fetch(`${BACKEND_URL}/api/v1/compliance/ai/switch-provider`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ provider: newProvider }), }) if (res.ok) { const result = await res.json() console.log('Provider switched:', result) onStatusChange?.() } else { const errorText = await res.text() setError(`Fehler: ${errorText}`) } } catch (err) { console.error('Failed to switch provider:', err) setError('Verbindung zum Backend fehlgeschlagen') } finally { setSwitching(false) } } // Determine the badge color based on provider const getBadgeColor = () => { if (isMockActive) return 'bg-gray-100 text-gray-700 border-gray-300' if (isSelfHostedActive) return 'bg-green-100 text-green-700 border-green-300' if (isAnthropicActive) return 'bg-purple-100 text-purple-700 border-purple-300' return 'bg-gray-100 text-gray-600 border-gray-200' } const getProviderIcon = () => { if (isSelfHostedActive) { // Local/Server icon return ( ) } if (isAnthropicActive) { // Cloud icon return ( ) } // Mock/Unknown icon return ( ) } return (
{/* Toggle Button */} {/* Dropdown Panel */} {showDetails && (
{/* Header */}

KI-Provider Einstellungen

Wechseln Sie zwischen Cloud-API und lokalem Modell

{/* Current Status */}
Aktuell: {aiStatus?.provider || 'Unbekannt'} | {aiStatus?.model || 'Kein Modell'}
{/* Provider Options */}
{/* Self-Hosted Option */} {/* Anthropic Option */}
{/* Error Message */} {error && (

{error}

)} {/* Footer Info */}

Hinweis: Die Umschaltung gilt nur fuer diese Session. Fuer permanente Aenderungen docker-compose.yml anpassen.

)} {/* Click outside to close */} {showDetails && (
setShowDetails(false)} /> )}
) }