All files / src/components/settings APIKeySection.tsx

100% Statements 3/3
100% Branches 10/10
100% Functions 2/2
100% Lines 3/3

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90                                                14x     14x                           3x                                                                                                
import { Key, Check, Loader2 } from 'lucide-react'
import type { AIStatus, AIModel } from '../../api/client'
import { useAPIKeyHandlers } from '../../hooks/useAPIKeyHandlers'
import AIStatusDisplay from './AIStatusDisplay'
 
interface APIKeySectionProps {
  aiStatus: AIStatus | null
  models: AIModel[]
  onAIStatusChange: (status: AIStatus) => void
  onModelsChange: (models: AIModel[]) => void
}
 
export default function APIKeySection({
  aiStatus,
  models,
  onAIStatusChange,
  onModelsChange,
}: APIKeySectionProps) {
  const {
    apiKey,
    setApiKey,
    testingKey,
    savingKey,
    handleTestApiKey,
    handleSaveApiKey,
  } = useAPIKeyHandlers({ onAIStatusChange, onModelsChange })
 
  return (
    <div className="rounded-lg border border-border bg-card p-4">
      <h2 className="mb-4 text-lg font-medium text-foreground">OpenRouter API</h2>
 
      <AIStatusDisplay aiStatus={aiStatus} models={models} />
 
      <div className="space-y-3">
        <label className="block">
          <span className="mb-1 block text-sm font-medium text-foreground">
            {aiStatus?.available ? 'Update API Key' : 'API Key'}
          </span>
          <input
            type="password"
            value={apiKey}
            onChange={(e) => setApiKey(e.target.value)}
            placeholder="sk-or-v1-..."
            className="w-full rounded-lg border border-border bg-input-background px-3 py-2 text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
          />
        </label>
 
        <div className="flex gap-2">
          <button
            onClick={handleTestApiKey}
            disabled={testingKey || !apiKey.trim()}
            className="flex items-center gap-2 rounded-lg border border-border bg-background px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50"
          >
            {testingKey ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <Check className="h-4 w-4" />
            )}
            Test Key
          </button>
          <button
            onClick={handleSaveApiKey}
            disabled={savingKey || !apiKey.trim()}
            className="flex items-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50"
          >
            {savingKey ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <Key className="h-4 w-4" />
            )}
            Save Key
          </button>
        </div>
      </div>
 
      <p className="mt-4 text-sm text-muted-foreground">
        Get your API key from{' '}
        <a
          href="https://openrouter.ai/keys"
          target="_blank"
          rel="noopener noreferrer"
          className="text-primary hover:underline"
        >
          openrouter.ai/keys
        </a>
      </p>
    </div>
  )
}
 
← Back to Dashboard