import { useEffect, useRef } from 'react' import { X, Loader2, AlertCircle } from 'lucide-react' import { useSettings, useUpdateSettings, useAvailableModels } from '../hooks/useProjects' interface SettingsModalProps { onClose: () => void } export function SettingsModal({ onClose }: SettingsModalProps) { const { data: settings, isLoading, isError, refetch } = useSettings() const { data: modelsData } = useAvailableModels() const updateSettings = useUpdateSettings() const modalRef = useRef(null) const closeButtonRef = useRef(null) // Focus trap - keep focus within modal useEffect(() => { const modal = modalRef.current if (!modal) return // Focus the close button when modal opens closeButtonRef.current?.focus() const focusableElements = modal.querySelectorAll( 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])' ) const firstElement = focusableElements[0] const lastElement = focusableElements[focusableElements.length - 1] const handleTabKey = (e: KeyboardEvent) => { if (e.key !== 'Tab') return if (e.shiftKey) { if (document.activeElement === firstElement) { e.preventDefault() lastElement?.focus() } } else { if (document.activeElement === lastElement) { e.preventDefault() firstElement?.focus() } } } const handleEscape = (e: KeyboardEvent) => { if (e.key === 'Escape') { onClose() } } document.addEventListener('keydown', handleTabKey) document.addEventListener('keydown', handleEscape) return () => { document.removeEventListener('keydown', handleTabKey) document.removeEventListener('keydown', handleEscape) } }, [onClose]) const handleYoloToggle = () => { if (settings && !updateSettings.isPending) { updateSettings.mutate({ yolo_mode: !settings.yolo_mode }) } } const handleModelChange = (modelId: string) => { if (!updateSettings.isPending) { updateSettings.mutate({ model: modelId }) } } const handleTestingRatioChange = (ratio: number) => { if (!updateSettings.isPending) { updateSettings.mutate({ testing_agent_ratio: ratio }) } } const handleCountTestingToggle = () => { if (settings && !updateSettings.isPending) { updateSettings.mutate({ count_testing_in_concurrency: !settings.count_testing_in_concurrency }) } } const models = modelsData?.models ?? [] const isSaving = updateSettings.isPending return (
e.stopPropagation()} role="dialog" aria-labelledby="settings-title" aria-modal="true" > {/* Header */}

Settings {isSaving && ( )}

{/* Loading State */} {isLoading && (
Loading settings...
)} {/* Error State */} {isError && (
Failed to load settings
)} {/* Settings Content */} {settings && !isLoading && (
{/* YOLO Mode Toggle */}

Skip testing for rapid prototyping

{/* Model Selection - Radio Group */}
{models.map((model) => ( ))}
{/* Testing Agent Ratio */}

Regression testing agents spawned per coding agent (0 = disabled)

{[0, 1, 2, 3].map((ratio) => ( ))}
{/* Count Testing in Concurrency Toggle */}

If enabled, testing agents count toward the concurrency limit

{/* Update Error */} {updateSettings.isError && (
Failed to save settings. Please try again.
)}
)}
) }