'use client'; import { useState, useEffect } from 'react'; import { Button } from './ui/button'; import { Input } from './ui/input'; import { Toggle } from './ui/toggle'; import { ContextualHelpIcon } from './ContextualHelpIcon'; interface GeneralSettingsModalProps { isOpen: boolean; onClose: () => void; } export function GeneralSettingsModal({ isOpen, onClose }: GeneralSettingsModalProps) { const [activeTab, setActiveTab] = useState<'general' | 'github' | 'auth'>('general'); const [githubToken, setGithubToken] = useState(''); const [saveFilter, setSaveFilter] = useState(false); const [savedFilters, setSavedFilters] = useState(null); const [colorCodingEnabled, setColorCodingEnabled] = useState(false); const [isLoading, setIsLoading] = useState(false); const [isSaving, setIsSaving] = useState(false); const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); // Auth state const [authUsername, setAuthUsername] = useState(''); const [authPassword, setAuthPassword] = useState(''); const [authConfirmPassword, setAuthConfirmPassword] = useState(''); const [authEnabled, setAuthEnabled] = useState(false); const [authHasCredentials, setAuthHasCredentials] = useState(false); const [authSetupCompleted, setAuthSetupCompleted] = useState(false); const [authLoading, setAuthLoading] = useState(false); // Load existing settings when modal opens useEffect(() => { if (isOpen) { void loadGithubToken(); void loadSaveFilter(); void loadSavedFilters(); void loadAuthCredentials(); void loadColorCodingSetting(); } }, [isOpen]); const loadGithubToken = async () => { setIsLoading(true); try { const response = await fetch('/api/settings/github-token'); if (response.ok) { const data = await response.json(); setGithubToken((data.token as string) ?? ''); } } catch (error) { console.error('Error loading GitHub token:', error); } finally { setIsLoading(false); } }; const loadSaveFilter = async () => { try { const response = await fetch('/api/settings/save-filter'); if (response.ok) { const data = await response.json(); setSaveFilter((data.enabled as boolean) ?? false); } } catch (error) { console.error('Error loading save filter setting:', error); } }; const saveSaveFilter = async (enabled: boolean) => { try { const response = await fetch('/api/settings/save-filter', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ enabled }), }); if (response.ok) { setSaveFilter(enabled); setMessage({ type: 'success', text: 'Save filter setting updated!' }); // If disabling save filters, clear saved filters if (!enabled) { await clearSavedFilters(); } } else { const errorData = await response.json(); setMessage({ type: 'error', text: errorData.error ?? 'Failed to save setting' }); } } catch { setMessage({ type: 'error', text: 'Failed to save setting' }); } }; const loadSavedFilters = async () => { try { const response = await fetch('/api/settings/filters'); if (response.ok) { const data = await response.json(); setSavedFilters(data.filters); } } catch (error) { console.error('Error loading saved filters:', error); } }; const clearSavedFilters = async () => { try { const response = await fetch('/api/settings/filters', { method: 'DELETE', }); if (response.ok) { setSavedFilters(null); setMessage({ type: 'success', text: 'Saved filters cleared!' }); } else { const errorData = await response.json(); setMessage({ type: 'error', text: errorData.error ?? 'Failed to clear filters' }); } } catch { setMessage({ type: 'error', text: 'Failed to clear filters' }); } }; const saveGithubToken = async () => { setIsSaving(true); setMessage(null); try { const response = await fetch('/api/settings/github-token', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ token: githubToken }), }); if (response.ok) { setMessage({ type: 'success', text: 'GitHub token saved successfully!' }); } else { const errorData = await response.json(); setMessage({ type: 'error', text: errorData.error ?? 'Failed to save token' }); } } catch { setMessage({ type: 'error', text: 'Failed to save token' }); } finally { setIsSaving(false); } }; const loadColorCodingSetting = async () => { try { const response = await fetch('/api/settings/color-coding'); if (response.ok) { const data = await response.json(); setColorCodingEnabled(Boolean(data.enabled)); } } catch (error) { console.error('Error loading color coding setting:', error); } }; const saveColorCodingSetting = async (enabled: boolean) => { try { const response = await fetch('/api/settings/color-coding', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ enabled }), }); if (response.ok) { setColorCodingEnabled(enabled); setMessage({ type: 'success', text: 'Color coding setting saved successfully' }); setTimeout(() => setMessage(null), 3000); } else { setMessage({ type: 'error', text: 'Failed to save color coding setting' }); setTimeout(() => setMessage(null), 3000); } } catch (error) { console.error('Error saving color coding setting:', error); setMessage({ type: 'error', text: 'Failed to save color coding setting' }); setTimeout(() => setMessage(null), 3000); } }; const loadAuthCredentials = async () => { setAuthLoading(true); try { const response = await fetch('/api/settings/auth-credentials'); if (response.ok) { const data = await response.json() as { username: string; enabled: boolean; hasCredentials: boolean; setupCompleted: boolean }; setAuthUsername(data.username ?? ''); setAuthEnabled(data.enabled ?? false); setAuthHasCredentials(data.hasCredentials ?? false); setAuthSetupCompleted(data.setupCompleted ?? false); } } catch (error) { console.error('Error loading auth credentials:', error); } finally { setAuthLoading(false); } }; const saveAuthCredentials = async () => { if (authPassword !== authConfirmPassword) { setMessage({ type: 'error', text: 'Passwords do not match' }); return; } setAuthLoading(true); setMessage(null); try { const response = await fetch('/api/settings/auth-credentials', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username: authUsername, password: authPassword, enabled: authEnabled }), }); if (response.ok) { setMessage({ type: 'success', text: 'Authentication credentials updated successfully!' }); setAuthPassword(''); setAuthConfirmPassword(''); void loadAuthCredentials(); } else { const errorData = await response.json(); setMessage({ type: 'error', text: errorData.error ?? 'Failed to save credentials' }); } } catch { setMessage({ type: 'error', text: 'Failed to save credentials' }); } finally { setAuthLoading(false); } }; const toggleAuthEnabled = async (enabled: boolean) => { setAuthLoading(true); setMessage(null); try { const response = await fetch('/api/settings/auth-credentials', { method: 'PATCH', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ enabled }), }); if (response.ok) { setAuthEnabled(enabled); setMessage({ type: 'success', text: `Authentication ${enabled ? 'enabled' : 'disabled'} successfully!` }); } else { const errorData = await response.json(); setMessage({ type: 'error', text: errorData.error ?? 'Failed to update auth status' }); } } catch { setMessage({ type: 'error', text: 'Failed to update auth status' }); } finally { setAuthLoading(false); } }; if (!isOpen) return null; return (
{/* Header */}

Settings

{/* Tabs */}
{/* Content */}
{activeTab === 'general' && (

General Settings

Configure general application preferences and behavior.

Save Filters

Save your configured script filters.

{saveFilter && (

Saved Filters

{savedFilters ? 'Filters are currently saved' : 'No filters saved yet'}

{savedFilters && (
Search: {savedFilters.searchQuery ?? 'None'}
Types: {savedFilters.selectedTypes?.length ?? 0} selected
Sort: {savedFilters.sortBy} ({savedFilters.sortOrder})
)}
{savedFilters && ( )}
)}

Server Color Coding

Enable color coding for servers to visually distinguish them throughout the application.

)} {activeTab === 'github' && (

GitHub Integration

Configure GitHub integration for script management and updates.

GitHub Personal Access Token

Save a GitHub Personal Access Token to circumvent GitHub API rate limits.

) => setGithubToken(e.target.value)} disabled={isLoading || isSaving} className="w-full" />
{message && (
{message.text}
)}
)} {activeTab === 'auth' && (

Authentication Settings

Configure authentication to secure access to your application.

Authentication Status

{authSetupCompleted ? (authHasCredentials ? `Authentication is ${authEnabled ? 'enabled' : 'disabled'}. Current username: ${authUsername}` : `Authentication is ${authEnabled ? 'enabled' : 'disabled'}. No credentials configured.`) : 'Authentication setup has not been completed yet.' }

Enable Authentication

{authEnabled ? 'Authentication is required on every page load' : 'Authentication is optional' }

Update Credentials

Change your username and password for authentication.

) => setAuthUsername(e.target.value)} disabled={authLoading} className="w-full" minLength={3} />
) => setAuthPassword(e.target.value)} disabled={authLoading} className="w-full" minLength={6} />
) => setAuthConfirmPassword(e.target.value)} disabled={authLoading} className="w-full" minLength={6} />
{message && (
{message.text}
)}
)}
); }