Spaces:
Runtime error
Runtime error
| import { useState, useEffect } from 'react'; | |
| import { X, Settings, Save } from 'lucide-react'; | |
| export default function ConfigModal({ isOpen, onClose, onSave, initialConfig }) { | |
| const [spotifyId, setSpotifyId] = useState(''); | |
| const [spotifySecret, setSpotifySecret] = useState(''); | |
| const [aiProvider, setAiProvider] = useState('openai'); | |
| const [aiApiKey, setAiApiKey] = useState(''); | |
| const [aiModel, setAiModel] = useState('gpt-3.5-turbo'); | |
| useEffect(() => { | |
| if (initialConfig) { | |
| setSpotifyId(initialConfig.spotifyId || ''); | |
| setSpotifySecret(initialConfig.spotifySecret || ''); | |
| setAiProvider(initialConfig.aiProvider || 'openai'); | |
| setAiApiKey(initialConfig.aiApiKey || ''); | |
| setAiModel(initialConfig.aiModel || 'gpt-3.5-turbo'); | |
| } | |
| }, [initialConfig, isOpen]); | |
| if (!isOpen) return null; | |
| const handleSave = () => { | |
| onSave({ spotifyId, spotifySecret, aiProvider, aiApiKey, aiModel }); | |
| onClose(); | |
| }; | |
| return ( | |
| <div className="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center z-50 p-4"> | |
| <div className="bg-[#282828] rounded-xl w-full max-w-md border border-white/10 shadow-2xl"> | |
| <div className="flex justify-between items-center p-5 border-b border-white/10"> | |
| <div className="flex items-center gap-2"> | |
| <Settings className="w-5 h-5 text-spotify-green" /> | |
| <h2 className="text-lg font-bold">Configuration</h2> | |
| </div> | |
| <button | |
| onClick={onClose} | |
| className="text-gray-400 hover:text-white transition-colors" | |
| > | |
| <X className="w-5 h-5" /> | |
| </button> | |
| </div> | |
| <div className="p-6 space-y-5 max-h-[70vh] overflow-y-auto"> | |
| <div className="space-y-3"> | |
| <h3 className="text-sm font-semibold text-spotify-green uppercase tracking-wider">Spotify Credentials</h3> | |
| <p className="text-xs text-gray-400"> | |
| Create an app at <a href="https://developer.spotify.com/dashboard" target="_blank" rel="noreferrer" className="underline hover:text-white">Spotify Dashboard</a> to get these. | |
| </p> | |
| <div> | |
| <label className="block text-sm font-medium text-gray-300 mb-1">Client ID</label> | |
| <input | |
| type="text" | |
| value={spotifyId} | |
| onChange={(e) => setSpotifyId(e.target.value)} | |
| placeholder="Enter Spotify Client ID" | |
| className="w-full bg-black/40 border border-white/20 rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-spotify-green transition-colors" | |
| /> | |
| </div> | |
| <div> | |
| <label className="block text-sm font-medium text-gray-300 mb-1">Client Secret</label> | |
| <input | |
| type="password" | |
| value={spotifySecret} | |
| onChange={(e) => setSpotifySecret(e.target.value)} | |
| placeholder="Enter Spotify Client Secret" | |
| className="w-full bg-black/40 border border-white/20 rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-spotify-green transition-colors" | |
| /> | |
| </div> | |
| </div> | |
| <div className="space-y-3 pt-4 border-t border-white/10"> | |
| <h3 className="text-sm font-semibold text-purple-400 uppercase tracking-wider">AI Configuration</h3> | |
| <div> | |
| <label className="block text-sm font-medium text-gray-300 mb-1">Provider</label> | |
| <select | |
| value={aiProvider} | |
| onChange={(e) => setAiProvider(e.target.value)} | |
| className="w-full bg-black/40 border border-white/20 rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-purple-400 transition-colors" | |
| > | |
| <option value="openai">OpenAI</option> | |
| <option value="anthropic">Anthropic (Claude)</option> | |
| <option value="custom">Custom Endpoint</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label className="block text-sm font-medium text-gray-300 mb-1">API Key</label> | |
| <input | |
| type="password" | |
| value={aiApiKey} | |
| onChange={(e) => setAiApiKey(e.target.value)} | |
| placeholder="sk-..." | |
| className="w-full bg-black/40 border border-white/20 rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-purple-400 transition-colors" | |
| /> | |
| </div> | |
| <div> | |
| <label className="block text-sm font-medium text-gray-300 mb-1">Model Name</label> | |
| <input | |
| type="text" | |
| value={aiModel} | |
| onChange={(e) => setAiModel(e.target.value)} | |
| placeholder="e.g. gpt-4, claude-3-opus" | |
| className="w-full bg-black/40 border border-white/20 rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-purple-400 transition-colors" | |
| /> | |
| </div> | |
| </div> | |
| </div> | |
| <div className="p-5 border-t border-white/10 bg-black/20 rounded-b-xl flex justify-end"> | |
| <button | |
| onClick={handleSave} | |
| className="flex items-center gap-2 bg-spotify-green hover:bg-green-500 text-black font-semibold px-5 py-2 rounded-full transition-all transform active:scale-95" | |
| > | |
| <Save className="w-4 h-4" /> | |
| Save Configuration | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } |