Spaces:
Sleeping
Sleeping
| import { useState, useEffect } from 'react'; | |
| import { Key, Eye, EyeOff, Save, Trash } from 'lucide-react'; | |
| export default function Settings() { | |
| const [apiKey, setApiKey] = useState(''); | |
| const [showKey, setShowKey] = useState(false); | |
| const [status, setStatus] = useState<string | null>(null); | |
| useEffect(() => { | |
| const savedKey = localStorage.getItem('sandbox_gemini_api_key') || ''; | |
| setApiKey(savedKey); | |
| }, []); | |
| const handleSave = () => { | |
| if (apiKey.trim()) { | |
| localStorage.setItem('sandbox_gemini_api_key', apiKey.trim()); | |
| setStatus('API Key saved successfully!'); | |
| } else { | |
| localStorage.removeItem('sandbox_gemini_api_key'); | |
| setStatus('API Key cleared.'); | |
| } | |
| setTimeout(() => setStatus(null), 3000); | |
| }; | |
| const handleClear = () => { | |
| localStorage.removeItem('sandbox_gemini_api_key'); | |
| setApiKey(''); | |
| setStatus('API Key cleared.'); | |
| setTimeout(() => setStatus(null), 3000); | |
| }; | |
| return ( | |
| <div className="w-full h-full bg-[#fdf8e1] p-6 flex flex-col gap-5 select-none font-sans text-ink-black overflow-y-auto custom-scrollbar"> | |
| <div className="flex flex-col gap-2"> | |
| <h3 className="font-headline-md font-bold text-sm m-0 flex items-center gap-2"> | |
| <span className="material-symbols-outlined text-lg text-[#0ea5e9]">key</span> | |
| CUSTOM GEMINI API CONFIG | |
| </h3> | |
| <p className="text-[9px] text-trash-gray font-bold leading-normal m-0 uppercase font-arcade"> | |
| Configure a custom Gemini API key for Sandbox Mode AI evaluations & explanations. | |
| </p> | |
| </div> | |
| <div className="bg-white border-[3px] border-ink-black p-4 shadow-[4px_4px_0px_0px_rgba(30,41,59,1)] flex flex-col gap-4"> | |
| <div> | |
| <label className="block text-xs font-bold text-ink-black uppercase tracking-wider mb-2 font-headline-md"> | |
| Gemini API Key | |
| </label> | |
| <div className="relative"> | |
| <Key className="absolute left-3.5 top-1/2 -translate-y-1/2 w-4 h-4 text-ink-black" /> | |
| <input | |
| type={showKey ? 'text' : 'password'} | |
| value={apiKey} | |
| onChange={(e) => setApiKey(e.target.value)} | |
| placeholder="AIzaSy..." | |
| className="w-full bg-white border-[3px] border-ink-black rounded-lg py-2.5 pl-10 pr-10 text-ink-black placeholder-trash-gray focus:outline-none focus:bg-white text-xs font-code-mono shadow-[inset_2px_2px_0px_rgba(0,0,0,0.1)]" | |
| /> | |
| <button | |
| type="button" | |
| onClick={() => setShowKey(!showKey)} | |
| className="absolute right-3.5 top-1/2 -translate-y-1/2 text-trash-gray hover:text-ink-black cursor-pointer bg-transparent border-0 outline-none" | |
| > | |
| {showKey ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />} | |
| </button> | |
| </div> | |
| <span className="text-[9px] text-trash-gray mt-2 block font-medium leading-normal"> | |
| Your key is stored locally in your browser's localStorage and is only sent to the local server in request headers. | |
| </span> | |
| </div> | |
| {status && ( | |
| <div className="p-3 border-[3px] border-ink-black bg-emerald-100 border-emerald-500 text-emerald-700 text-xs font-bold font-arcade leading-relaxed shadow-[2px_2px_0px_0px_rgba(30,41,59,1)]"> | |
| {status} | |
| </div> | |
| )} | |
| <div className="flex flex-col sm:flex-row gap-3 pt-2 border-t border-slate-200"> | |
| <button | |
| onClick={handleSave} | |
| className="flex-1 flex items-center justify-center gap-2 py-2.5 border-[3px] border-ink-black bg-[#ffe24c] hover:bg-yellow-300 text-xs font-bold text-ink-black shadow-[3px_3px_0px_0px_#1E293B] active:translate-y-0.5 active:shadow-none transition-all cursor-pointer text-center uppercase" | |
| > | |
| <Save className="w-4 h-4" /> | |
| Save Key | |
| </button> | |
| <button | |
| onClick={handleClear} | |
| className="flex-1 flex items-center justify-center gap-2 py-2.5 border-[3px] border-ink-black bg-white hover:bg-slate-100 text-xs font-bold text-ink-black shadow-[3px_3px_0px_0px_#1E293B] active:translate-y-0.5 active:shadow-none transition-all cursor-pointer text-center uppercase" | |
| > | |
| <Trash className="w-4 h-4 text-rose-500" /> | |
| Clear Key | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |