/** * ProviderSelector Component * * Wiederverwendbare Komponente zur Auswahl von AICore-Providern. * Kann im Chat Playground und Automation Editor verwendet werden. * * Features: * - Dropdown für Einzelauswahl * - Checkbox-Liste für Mehrfachauswahl * - Lädt verfügbare Provider aus dem Billing-System */ import React, { useEffect, useMemo, useState } from 'react'; import { useBilling } from '../../hooks/useBilling'; import styles from './ProviderSelector.module.css'; // Provider display names const PROVIDER_LABELS: Record = { anthropic: 'Anthropic (Claude)', openai: 'OpenAI (GPT)', perplexity: 'Perplexity', tavily: 'Tavily (Web Search)', internal: 'Internal', }; // Provider icons (emojis for simplicity) const PROVIDER_ICONS: Record = { anthropic: '🤖', openai: '💬', perplexity: '🔍', tavily: '🌐', internal: '🏠', }; // ============================================================================ // SINGLE SELECT COMPONENT // ============================================================================ interface ProviderSelectProps { value: string; onChange: (provider: string) => void; disabled?: boolean; className?: string; label?: string; showLabel?: boolean; } export const ProviderSelect: React.FC = ({ value, onChange, disabled = false, className, label = 'AI-Provider', showLabel = true, }) => { const { allowedProviders, loadAllowedProviders, loading } = useBilling(); useEffect(() => { if (allowedProviders.length === 0 && !loading) { loadAllowedProviders(); } }, []); const providerOptions = useMemo(() => { return allowedProviders.map((provider) => ({ value: provider, label: `${PROVIDER_ICONS[provider] || '🔌'} ${PROVIDER_LABELS[provider] || provider}`, })); }, [allowedProviders]); return (
{showLabel && }
); }; // ============================================================================ // MULTI SELECT COMPONENT (Checkbox List) // ============================================================================ interface ProviderMultiSelectProps { selectedProviders: string[]; onChange: (providers: string[]) => void; disabled?: boolean; className?: string; label?: string; showLabel?: boolean; defaultExpanded?: boolean; } export const ProviderMultiSelect: React.FC = ({ selectedProviders, onChange, disabled = false, className, label = 'AI-Provider', showLabel = true, defaultExpanded = false, }) => { const [isExpanded, setIsExpanded] = useState(defaultExpanded); const { allowedProviders, loadAllowedProviders, loading } = useBilling(); useEffect(() => { if (allowedProviders.length === 0 && !loading) { loadAllowedProviders(); } }, []); const handleToggle = (provider: string) => { if (selectedProviders.includes(provider)) { onChange(selectedProviders.filter((p) => p !== provider)); } else { onChange([...selectedProviders, provider]); } }; const handleSelectAll = () => { onChange(allowedProviders); }; const handleSelectNone = () => { onChange([]); }; // Summary text for collapsed view const summaryText = useMemo(() => { if (selectedProviders.length === 0) { return 'Alle Provider'; } if (selectedProviders.length === 1) { return PROVIDER_LABELS[selectedProviders[0]] || selectedProviders[0]; } return `${selectedProviders.length} Provider`; }, [selectedProviders]); // Summary icons for collapsed view const summaryIcons = useMemo(() => { if (selectedProviders.length === 0) { return '🤖'; } return selectedProviders.slice(0, 3).map(p => PROVIDER_ICONS[p] || '🔌').join(''); }, [selectedProviders]); return (
{/* Collapsible Header */} {/* Expandable Content */} {isExpanded && (
{showLabel && }
{loading ? (
Lade Provider...
) : (
{allowedProviders.map((provider) => ( ))}
)} {selectedProviders.length === 0 && !loading && (
Wenn keine Provider ausgewählt sind, werden alle erlaubten Provider verwendet.
)}
)}
); }; // ============================================================================ // COMPACT PROVIDER BADGE LIST // ============================================================================ interface ProviderBadgesProps { providers: string[]; className?: string; } export const ProviderBadges: React.FC = ({ providers, className, }) => { if (providers.length === 0) { return Alle Provider; } return (
{providers.map((provider) => ( {PROVIDER_ICONS[provider] || '🔌'} {PROVIDER_LABELS[provider] || provider} ))}
); }; // Default export export default ProviderSelect;