import { useState } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { Mail, Send, Lock, Unlock, AlertTriangle, CheckCircle, Loader2 } from 'lucide-react'; import { api } from '../api/client'; import type { SMTPSettings, TestSMTPRequest } from '../api/client'; import { Card, CardContent, CardHeader } from './Card'; import { Button } from './Button'; import { useToast } from '../contexts/ToastContext'; import { useEffect } from 'react'; import { useAuth } from '../contexts/AuthContext'; const SECURITY_PORT_MAP: Record = { starttls: 587, ssl: 465, none: 25, }; const PORT_SECURITY_MAP: Record = { 587: 'starttls', 465: 'ssl', 25: 'none', }; export function EmailSettings() { const { t } = useTranslation(); const { showToast } = useToast(); const queryClient = useQueryClient(); const [smtpSettings, setSMTPSettings] = useState({ smtp_host: '', smtp_port: 587, smtp_username: '', smtp_password: '', smtp_security: 'starttls', smtp_auth_enabled: true, smtp_from_email: '', smtp_from_name: 'BamBuddy', }); const [testEmail, setTestEmail] = useState(''); // Fetch SMTP settings const { data: existingSettings, isLoading } = useQuery({ queryKey: ['smtpSettings'], queryFn: () => api.getSMTPSettings(), }); // Fetch global auth status const { authEnabled } = useAuth(); // Fetch advanced auth status const { data: advancedAuthStatus } = useQuery({ queryKey: ['advancedAuthStatus'], queryFn: () => api.getAdvancedAuthStatus(), }); // Load existing settings when fetched useEffect(() => { if (existingSettings) { setSMTPSettings({ ...existingSettings, smtp_password: '', // Never show password }); } }, [existingSettings]); const handleSecurityChange = (security: 'starttls' | 'ssl' | 'none') => { setSMTPSettings({ ...smtpSettings, smtp_security: security, smtp_port: SECURITY_PORT_MAP[security], }); }; const handlePortChange = (port: number) => { const matchedSecurity = PORT_SECURITY_MAP[port]; setSMTPSettings({ ...smtpSettings, smtp_port: port, ...(matchedSecurity ? { smtp_security: matchedSecurity as 'starttls' | 'ssl' | 'none' } : {}), }); }; const handleAuthChange = (enabled: boolean) => { setSMTPSettings({ ...smtpSettings, smtp_auth_enabled: enabled, ...(!enabled ? { smtp_username: '', smtp_password: '' } : {}), }); }; // Save SMTP settings const saveMutation = useMutation({ mutationFn: (settings: SMTPSettings) => api.saveSMTPSettings(settings), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['smtpSettings'] }); queryClient.invalidateQueries({ queryKey: ['advancedAuthStatus'] }); showToast(t('settings.email.success.settingsSaved'), 'success'); }, onError: (error: Error) => { showToast(error.message, 'error'); }, }); // Test SMTP connection const testMutation = useMutation({ mutationFn: (request: TestSMTPRequest) => api.testSMTP(request), onSuccess: (data) => { showToast(data.message, data.success ? 'success' : 'error'); }, onError: (error: Error) => { showToast(error.message, 'error'); }, }); // Toggle advanced auth const toggleAdvancedAuthMutation = useMutation({ mutationFn: (enabled: boolean) => enabled ? api.enableAdvancedAuth() : api.disableAdvancedAuth(), onSuccess: (data) => { queryClient.invalidateQueries({ queryKey: ['advancedAuthStatus'] }); showToast(data.message, 'success'); }, onError: (error: Error) => { showToast(error.message, 'error'); }, }); const handleSave = () => { // Validate required fields if (!smtpSettings.smtp_host || !smtpSettings.smtp_from_email) { showToast(t('settings.email.errors.requiredFields'), 'error'); return; } // Validate auth fields when authentication is enabled if (smtpSettings.smtp_auth_enabled && (!smtpSettings.smtp_username)) { showToast(t('settings.email.errors.usernameRequired'), 'error'); return; } saveMutation.mutate(smtpSettings); }; const handleTest = () => { if (!testEmail) { showToast(t('settings.email.errors.enterTestEmail'), 'error'); return; } testMutation.mutate({ test_recipient: testEmail, }); }; const handleToggleAdvancedAuth = () => { if (!authEnabled) { showToast(t('settings.email.errors.enableAuthFirst'), 'error'); return; } if (!advancedAuthStatus?.advanced_auth_enabled && !advancedAuthStatus?.smtp_configured) { showToast(t('settings.email.errors.configureSmtpFirst'), 'error'); return; } toggleAdvancedAuthMutation.mutate(!advancedAuthStatus?.advanced_auth_enabled); }; if (isLoading) { return (
); } const advancedEnabled = advancedAuthStatus?.advanced_auth_enabled ?? false; const inputClasses = "w-full px-3 py-2 bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-lg text-white placeholder-bambu-gray focus:outline-none focus:ring-2 focus:ring-bambu-green/50 focus:border-bambu-green transition-colors"; const disabledInputClasses = "w-full px-3 py-2 bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-lg text-white/40 placeholder-bambu-gray/40 cursor-not-allowed"; return (
{/* Advanced Authentication Toggle - Always visible */}

{t('settings.email.advancedAuth') || 'Advanced Authentication'}

{advancedEnabled ? (

{t('settings.email.advancedAuthEnabled') || 'Advanced Authentication is enabled'}

  • {t('settings.email.feature1') || 'Passwords are auto-generated and emailed to new users'}
  • {t('settings.email.feature2') || 'Users can login with username or email'}
  • {t('settings.email.feature3') || 'Forgot password feature is available'}
  • {t('settings.email.feature4') || 'Admins can reset user passwords via email'}
) : (

{t('settings.email.advancedAuthDisabled') || 'Advanced Authentication is disabled'}

{t('settings.email.advancedAuthDisabledDesc') || 'Enable advanced authentication to activate email-based features for user management.'}

)}
{/* SMTP Config + Test SMTP side-by-side on lg+ */}

{t('settings.email.smtpSettings') || 'SMTP Configuration'}

{/* Authentication - at the top */}
{/* Username / Password - dimmed when auth disabled */}
setSMTPSettings({ ...smtpSettings, smtp_username: e.target.value })} placeholder="your.email@gmail.com" disabled={!smtpSettings.smtp_auth_enabled} className={smtpSettings.smtp_auth_enabled ? inputClasses : disabledInputClasses} />
setSMTPSettings({ ...smtpSettings, smtp_password: e.target.value })} placeholder={existingSettings ? '••••••••' : 'App password'} disabled={!smtpSettings.smtp_auth_enabled} className={smtpSettings.smtp_auth_enabled ? inputClasses : disabledInputClasses} />
{/* SMTP Server / Port */}
setSMTPSettings({ ...smtpSettings, smtp_host: e.target.value })} placeholder="smtp.gmail.com" className={inputClasses} />
handlePortChange(parseInt(e.target.value) || 587)} placeholder="587" className={inputClasses} />
{/* Security */}
{/* From Email / Name */}
setSMTPSettings({ ...smtpSettings, smtp_from_email: e.target.value })} placeholder="your@email.com" className={inputClasses} />
setSMTPSettings({ ...smtpSettings, smtp_from_name: e.target.value })} placeholder="BamBuddy" className={inputClasses} />
{/* Test SMTP */}

{t('settings.email.testConnection') || 'Test SMTP Connection'}

setTestEmail(e.target.value)} placeholder="test@example.com" className={inputClasses} />
); }