import type { FormEvent } from 'react'; import { useState, useEffect } from 'react'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import { toast } from 'sonner'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Switch } from '@/components/ui/switch'; import { useClient } from 'hooks/useClient'; import { useAuth } from 'hooks/useAuth'; import { useTranslation } from '@/lib/i18n'; type Provider = 'resend' | 'smtp' | 'mailhog'; type SmtpConfig = { provider: Provider; apiKey?: string; host?: string; port?: number; username?: string; password?: string; secure?: boolean; fromName: string; fromEmail: string; }; const PROVIDER_DEFAULTS: Record> = { mailhog: { host: 'localhost', port: 1025, secure: false, username: '', password: '' }, resend: { apiKey: '' }, smtp: { host: '', port: 587, secure: false, username: '', password: '' }, }; export const SMTPSection = () => { const { t } = useTranslation(); const client = useClient(); const queryClient = useQueryClient(); const { user } = useAuth(); const { data: config, isLoading } = useQuery({ queryKey: ['SMTP_CONFIG'], queryFn: () => client.get('/server-settings/smtp'), }); const [provider, setProvider] = useState('mailhog'); const [apiKey, setApiKey] = useState(''); const [host, setHost] = useState('localhost'); const [port, setPort] = useState('1025'); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [secure, setSecure] = useState(false); const [fromName, setFromName] = useState('officerdev'); const [fromEmail, setFromEmail] = useState('no-reply@officer.dev'); const [isSaving, setIsSaving] = useState(false); const [isTestingConnection, setIsTestingConnection] = useState(false); const [testEmail, setTestEmail] = useState(user?.email ?? ''); const [isTesting, setIsTesting] = useState(false); useEffect(() => { if (!config) return; setProvider(config.provider); setApiKey(config.apiKey ?? ''); setHost(config.host ?? ''); setPort(String(config.port ?? 587)); setUsername(config.username ?? ''); setPassword(config.password ?? ''); setSecure(config.secure ?? false); setFromName(config.fromName || 'officerdev'); setFromEmail(config.fromEmail || 'no-reply@officer.dev'); }, [config]); const handleProviderChange = (v: Provider) => { setProvider(v); const defaults = PROVIDER_DEFAULTS[v]; if (defaults.host !== undefined) setHost(defaults.host); if (defaults.port !== undefined) setPort(String(defaults.port)); if (defaults.secure !== undefined) setSecure(defaults.secure); if (defaults.username !== undefined) setUsername(defaults.username); if (defaults.password !== undefined) setPassword(defaults.password); if (defaults.apiKey !== undefined) setApiKey(defaults.apiKey); }; const buildConfig = (): SmtpConfig => ({ provider, fromName, fromEmail, ...(provider === 'resend' ? { apiKey } : { host, port: parseInt(port) || 587, username, password, secure }), }); const handleSave = async (ev?: FormEvent) => { ev?.preventDefault(); if (isSaving) return; setIsSaving(true); try { await client.put('/server-settings/smtp', buildConfig()); queryClient.invalidateQueries({ queryKey: ['SMTP_CONFIG'] }); toast.success(t('settings.server.smtp.saved')); } catch { toast.error(t('settings.server.smtp.saveFailed')); } finally { setIsSaving(false); } }; const handleTestConnection = async () => { if (isTestingConnection) return; setIsTestingConnection(true); try { await client.post('/server-settings/smtp/test-connection'); toast.success(t('settings.server.smtp.connected')); } catch (err: unknown) { const raw = (err as { message?: string })?.message; let msg = 'Connection failed'; try { if (raw) msg = JSON.parse(raw).error ?? msg; } catch { /* ignore */ } toast.error(msg); } finally { setIsTestingConnection(false); } }; const handleTest = async (ev?: FormEvent) => { ev?.preventDefault(); if (isTesting || !testEmail) return; setIsTesting(true); try { const result = await client.post<{ success?: boolean; error?: string }>('/server-settings/smtp/test', { ...buildConfig(), to: testEmail, }); if (result.error) { toast.error(result.error); } else { toast.success(t('settings.server.smtp.testSent', { email: testEmail })); } } catch (err: unknown) { const raw = (err as { message?: string })?.message; let msg = 'Failed to send test email'; try { if (raw) msg = JSON.parse(raw).error ?? msg; } catch { /* ignore */ } toast.error(msg); } finally { setIsTesting(false); } }; if (isLoading) return

{t('settings.server.loading')}

; const showSmtpFields = provider === 'smtp' || provider === 'mailhog'; return (
{provider === 'resend' && ( )} {showSmtpFields && ( <>
{provider === 'smtp' && ( <>
)} )}
{t('settings.server.smtp.sendTest')}
setTestEmail(ev.target.value)} />
); };