feat: multi-provider AI support with auto-detection
- Added support for Google Gemini, OpenAI, Anthropic, and Azure OpenAI - Implemented API key validation with auto model detection - Added Error Boundary for better error handling - Migrated PDF generation to native jsPDF (better quality) - Added PWA support with offline capabilities - Implemented tests with Vitest - Fixed language consistency (PT-BR) - Improved accessibility (ARIA)
This commit is contained in:
51
components/ModelSelector.tsx
Normal file
51
components/ModelSelector.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { PROVIDERS, type AIProvider } from '../types/providers';
|
||||
|
||||
interface ModelSelectorProps {
|
||||
provider: AIProvider;
|
||||
onModelChange: (model: string) => void;
|
||||
apiKey: string;
|
||||
}
|
||||
|
||||
export const ModelSelector: React.FC<ModelSelectorProps> = ({ provider, onModelChange, apiKey }) => {
|
||||
const [selectedModel, setSelectedModel] = useState<string>('');
|
||||
const providerConfig = PROVIDERS.find(p => p.id === provider);
|
||||
|
||||
useEffect(() => {
|
||||
if (providerConfig) {
|
||||
const saved = localStorage.getItem(`model-${provider}`);
|
||||
if (saved && providerConfig.models.includes(saved)) {
|
||||
setSelectedModel(saved);
|
||||
onModelChange(saved);
|
||||
} else {
|
||||
setSelectedModel(providerConfig.defaultModel);
|
||||
onModelChange(providerConfig.defaultModel);
|
||||
}
|
||||
}
|
||||
}, [provider, providerConfig, onModelChange]);
|
||||
|
||||
const handleChange = (model: string) => {
|
||||
setSelectedModel(model);
|
||||
localStorage.setItem(`model-${provider}`, model);
|
||||
onModelChange(model);
|
||||
};
|
||||
|
||||
if (!providerConfig) return null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wider mb-2">
|
||||
Modelo
|
||||
</label>
|
||||
<select
|
||||
value={selectedModel}
|
||||
onChange={(e) => handleChange(e.target.value)}
|
||||
className="w-full px-4 py-3 bg-white/50 dark:bg-slate-700/50 border border-slate-300 dark:border-slate-600 rounded-xl shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all text-slate-700 dark:text-slate-200"
|
||||
>
|
||||
{providerConfig.models.map((model) => (
|
||||
<option key={model} value={model}>{model}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user