Re_Figma_Code/src/components/admin/AIConfig/AIProviderSettings.tsx

219 lines
8.4 KiB
TypeScript

import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import { Switch } from '@/components/ui/switch';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Brain, Eye, EyeOff, Key } from 'lucide-react';
import { Button } from '@/components/ui/button';
interface AIProviderSettingsProps {
aiEnabled: boolean;
aiProvider: 'claude' | 'openai' | 'gemini';
claudeApiKey: string;
openaiApiKey: string;
geminiApiKey: string;
showApiKeys: Record<string, boolean>;
onAiEnabledChange: (enabled: boolean) => void;
onProviderChange: (provider: 'claude' | 'openai' | 'gemini') => void;
onClaudeApiKeyChange: (key: string) => void;
onOpenaiApiKeyChange: (key: string) => void;
onGeminiApiKeyChange: (key: string) => void;
onToggleApiKeyVisibility: (provider: 'claude' | 'openai' | 'gemini') => void;
maskApiKey: (key: string) => string;
}
const PROVIDERS = [
{ value: 'claude', label: 'Claude (Anthropic)', description: 'Advanced AI by Anthropic' },
{ value: 'openai', label: 'OpenAI (GPT-4)', description: 'GPT-4 by OpenAI' },
{ value: 'gemini', label: 'Gemini (Google)', description: 'Gemini by Google' }
];
export function AIProviderSettings({
aiEnabled,
aiProvider,
claudeApiKey,
openaiApiKey,
geminiApiKey,
showApiKeys,
onAiEnabledChange,
onProviderChange,
onClaudeApiKeyChange,
onOpenaiApiKeyChange,
onGeminiApiKeyChange,
onToggleApiKeyVisibility,
maskApiKey
}: AIProviderSettingsProps) {
return (
<Card className="border-0 shadow-sm">
<CardHeader className="pb-3">
<div className="flex items-center gap-2">
<Brain className="w-5 h-5 text-re-green" />
<CardTitle className="text-base font-semibold">AI Provider & API Keys</CardTitle>
</div>
<CardDescription className="text-sm">
Select your AI provider and configure API keys
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{/* Master Toggle */}
<div className="flex items-center justify-between p-4 bg-gray-50 border border-gray-200 rounded-md">
<div>
<p className="font-medium text-sm">Enable AI Features</p>
<p className="text-xs text-muted-foreground">
Master toggle to enable/disable all AI-powered features
</p>
</div>
<Switch
checked={aiEnabled}
onCheckedChange={onAiEnabledChange}
/>
</div>
{aiEnabled && (
<>
{/* Provider Selection */}
<div className="space-y-2">
<Label htmlFor="ai-provider" className="text-sm font-medium">
AI Provider
</Label>
<Select value={aiProvider} onValueChange={(value: any) => onProviderChange(value)}>
<SelectTrigger
id="ai-provider"
className="border-gray-200 focus:border-re-green focus:ring-2 focus:ring-re-green/20"
>
<SelectValue placeholder="Select AI provider" />
</SelectTrigger>
<SelectContent>
{PROVIDERS.map((provider) => (
<SelectItem key={provider.value} value={provider.value}>
<div className="flex items-center gap-2">
<span className="font-medium">{provider.label}</span>
<span className="text-xs text-muted-foreground">-</span>
<span className="text-xs text-muted-foreground">{provider.description}</span>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* API Keys for each provider */}
<div className="space-y-4 pt-2">
<Label className="text-sm font-medium flex items-center gap-2">
<Key className="w-4 h-4" />
API Keys
</Label>
{/* Claude API Key */}
<div className="space-y-2">
<Label htmlFor="claude-key" className="text-xs text-muted-foreground">
Claude API Key
</Label>
<div className="flex gap-2">
<Input
id="claude-key"
type={showApiKeys.claude ? 'text' : 'password'}
value={claudeApiKey}
onChange={(e) => onClaudeApiKeyChange(e.target.value)}
placeholder={showApiKeys.claude ? "sk-ant-..." : maskApiKey(claudeApiKey) || "sk-ant-..."}
className="border-gray-200 focus:border-re-green focus:ring-2 focus:ring-re-green/20 font-mono text-sm"
/>
<Button
type="button"
variant="outline"
size="icon"
onClick={() => onToggleApiKeyVisibility('claude')}
className="border-gray-200"
>
{showApiKeys.claude ? (
<EyeOff className="w-4 h-4" />
) : (
<Eye className="w-4 h-4" />
)}
</Button>
</div>
<p className="text-xs text-muted-foreground">
Get your API key from console.anthropic.com
</p>
</div>
{/* OpenAI API Key */}
<div className="space-y-2">
<Label htmlFor="openai-key" className="text-xs text-muted-foreground">
OpenAI API Key
</Label>
<div className="flex gap-2">
<Input
id="openai-key"
type={showApiKeys.openai ? 'text' : 'password'}
value={openaiApiKey}
onChange={(e) => onOpenaiApiKeyChange(e.target.value)}
placeholder={showApiKeys.openai ? "sk-..." : maskApiKey(openaiApiKey) || "sk-..."}
className="border-gray-200 focus:border-re-green focus:ring-2 focus:ring-re-green/20 font-mono text-sm"
/>
<Button
type="button"
variant="outline"
size="icon"
onClick={() => onToggleApiKeyVisibility('openai')}
className="border-gray-200"
>
{showApiKeys.openai ? (
<EyeOff className="w-4 h-4" />
) : (
<Eye className="w-4 h-4" />
)}
</Button>
</div>
<p className="text-xs text-muted-foreground">
Get your API key from platform.openai.com
</p>
</div>
{/* Gemini API Key */}
<div className="space-y-2">
<Label htmlFor="gemini-key" className="text-xs text-muted-foreground">
Gemini API Key
</Label>
<div className="flex gap-2">
<Input
id="gemini-key"
type={showApiKeys.gemini ? 'text' : 'password'}
value={geminiApiKey}
onChange={(e) => onGeminiApiKeyChange(e.target.value)}
placeholder={showApiKeys.gemini ? "AIza..." : maskApiKey(geminiApiKey) || "AIza..."}
className="border-gray-200 focus:border-re-green focus:ring-2 focus:ring-re-green/20 font-mono text-sm"
/>
<Button
type="button"
variant="outline"
size="icon"
onClick={() => onToggleApiKeyVisibility('gemini')}
className="border-gray-200"
>
{showApiKeys.gemini ? (
<EyeOff className="w-4 h-4" />
) : (
<Eye className="w-4 h-4" />
)}
</Button>
</div>
<p className="text-xs text-muted-foreground">
Get your API key from ai.google.dev
</p>
</div>
</div>
</>
)}
</CardContent>
</Card>
);
}