import React, { useEffect, useState } from 'react'; import { Settings, Shield, DollarSign, CreditCard, Save, Info, Globe, SlidersHorizontal, Eye, EyeOff, Lock, Key, Cookie, Coins, Sparkles, Mail, Building2, Upload, Image as ImageIcon } from 'lucide-react'; import { toast } from 'react-toastify'; import adminPrivacyService, { CookieIntegrationSettings, CookiePolicySettings, CookiePolicySettingsResponse, } from '../../services/api/adminPrivacyService'; import systemSettingsService, { StripeSettingsResponse, UpdateStripeSettingsRequest, SmtpSettingsResponse, UpdateSmtpSettingsRequest, CompanySettingsResponse, UpdateCompanySettingsRequest, } from '../../services/api/systemSettingsService'; import { useCurrency } from '../../contexts/CurrencyContext'; import { Loading } from '../../components/common'; import { getCurrencySymbol } from '../../utils/format'; type SettingsTab = 'general' | 'cookie' | 'currency' | 'payment' | 'smtp' | 'company'; const SettingsPage: React.FC = () => { const { currency, supportedCurrencies, refreshCurrency } = useCurrency(); const [activeTab, setActiveTab] = useState('general'); // Cookie Settings State const [policy, setPolicy] = useState({ analytics_enabled: true, marketing_enabled: true, preferences_enabled: true, }); const [integrations, setIntegrations] = useState({ ga_measurement_id: '', fb_pixel_id: '', }); const [policyMeta, setPolicyMeta] = useState< Pick | null >(null); // Currency Settings State const [selectedCurrency, setSelectedCurrency] = useState(currency); // Stripe Settings State const [stripeSettings, setStripeSettings] = useState(null); const [formData, setFormData] = useState({ stripe_secret_key: '', stripe_publishable_key: '', stripe_webhook_secret: '', }); const [showSecretKey, setShowSecretKey] = useState(false); const [showWebhookSecret, setShowWebhookSecret] = useState(false); // SMTP Settings State const [smtpSettings, setSmtpSettings] = useState(null); const [smtpFormData, setSmtpFormData] = useState({ smtp_host: '', smtp_port: '', smtp_user: '', smtp_password: '', smtp_from_email: '', smtp_from_name: '', smtp_use_tls: true, }); const [showSmtpPassword, setShowSmtpPassword] = useState(false); const [testingEmail, setTestingEmail] = useState(false); const [testEmailAddress, setTestEmailAddress] = useState('email@example.com'); // Company Settings State const [companySettings, setCompanySettings] = useState(null); const [companyFormData, setCompanyFormData] = useState({ company_name: '', company_tagline: '', company_phone: '', company_email: '', company_address: '', }); const [logoPreview, setLogoPreview] = useState(null); const [faviconPreview, setFaviconPreview] = useState(null); const [uploadingLogo, setUploadingLogo] = useState(false); const [uploadingFavicon, setUploadingFavicon] = useState(false); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const currencyNames: Record = { VND: 'Vietnamese Dong', USD: 'US Dollar', EUR: 'Euro', GBP: 'British Pound', JPY: 'Japanese Yen', CNY: 'Chinese Yuan', KRW: 'South Korean Won', SGD: 'Singapore Dollar', THB: 'Thai Baht', AUD: 'Australian Dollar', CAD: 'Canadian Dollar', }; const getCurrencyDisplayName = (code: string): string => { const name = currencyNames[code] || code; const symbol = getCurrencySymbol(code); return `${name} (${symbol})`; }; // Load all settings useEffect(() => { loadAllSettings(); }, []); useEffect(() => { if (activeTab === 'smtp') { loadSmtpSettings(); } if (activeTab === 'company') { loadCompanySettings(); } }, [activeTab]); useEffect(() => { setSelectedCurrency(currency); }, [currency]); const loadAllSettings = async () => { try { setLoading(true); const [policyRes, integrationRes, currencyRes, stripeRes] = await Promise.all([ adminPrivacyService.getCookiePolicy(), adminPrivacyService.getIntegrations(), systemSettingsService.getPlatformCurrency(), systemSettingsService.getStripeSettings(), ]); setPolicy(policyRes.data); setPolicyMeta({ updated_at: policyRes.updated_at, updated_by: policyRes.updated_by, }); setIntegrations(integrationRes.data || {}); setSelectedCurrency(currencyRes.data.currency); setStripeSettings(stripeRes.data); setFormData({ stripe_secret_key: '', stripe_publishable_key: stripeRes.data.stripe_publishable_key || '', stripe_webhook_secret: '', }); } catch (error: any) { toast.error(error.message || 'Failed to load settings'); } finally { setLoading(false); } }; const loadSmtpSettings = async () => { try { const smtpRes = await systemSettingsService.getSmtpSettings(); setSmtpSettings(smtpRes.data); setSmtpFormData({ smtp_host: smtpRes.data.smtp_host || '', smtp_port: smtpRes.data.smtp_port || '', smtp_user: smtpRes.data.smtp_user || '', smtp_password: '', smtp_from_email: smtpRes.data.smtp_from_email || '', smtp_from_name: smtpRes.data.smtp_from_name || '', smtp_use_tls: smtpRes.data.smtp_use_tls, }); } catch (error: any) { toast.error(error.message || 'Failed to load SMTP settings'); } }; const loadCompanySettings = async () => { try { const companyRes = await systemSettingsService.getCompanySettings(); setCompanySettings(companyRes.data); setCompanyFormData({ company_name: companyRes.data.company_name || '', company_tagline: companyRes.data.company_tagline || '', company_phone: companyRes.data.company_phone || '', company_email: companyRes.data.company_email || '', company_address: companyRes.data.company_address || '', }); // Set previews if URLs exist if (companyRes.data.company_logo_url) { const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8000'; const logoUrl = companyRes.data.company_logo_url.startsWith('http') ? companyRes.data.company_logo_url : `${baseUrl}${companyRes.data.company_logo_url}`; setLogoPreview(logoUrl); } if (companyRes.data.company_favicon_url) { const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8000'; const faviconUrl = companyRes.data.company_favicon_url.startsWith('http') ? companyRes.data.company_favicon_url : `${baseUrl}${companyRes.data.company_favicon_url}`; setFaviconPreview(faviconUrl); } } catch (error: any) { toast.error(error.message || 'Failed to load company settings'); } }; // Cookie Settings Handlers const handleToggle = (key: keyof CookiePolicySettings) => { setPolicy((prev) => ({ ...prev, [key]: !prev[key], })); }; const handleSaveCookie = async () => { try { setSaving(true); const [policyRes, integrationRes] = await Promise.all([ adminPrivacyService.updateCookiePolicy(policy), adminPrivacyService.updateIntegrations(integrations), ]); setPolicy(policyRes.data); setPolicyMeta({ updated_at: policyRes.updated_at, updated_by: policyRes.updated_by, }); setIntegrations(integrationRes.data || {}); toast.success('Cookie policy and integrations updated successfully'); } catch (error: any) { toast.error(error.message || 'Failed to update cookie settings'); } finally { setSaving(false); } }; // Currency Settings Handlers const handleSaveCurrency = async () => { try { setSaving(true); await systemSettingsService.updatePlatformCurrency(selectedCurrency); await refreshCurrency(); await loadAllSettings(); toast.success('Platform currency updated successfully'); } catch (error: any) { toast.error(error.message || 'Failed to update platform currency'); } finally { setSaving(false); } }; // Stripe Settings Handlers const handleSaveStripe = async () => { try { setSaving(true); const updateData: UpdateStripeSettingsRequest = {}; if (formData.stripe_secret_key && formData.stripe_secret_key.trim()) { updateData.stripe_secret_key = formData.stripe_secret_key.trim(); } if (formData.stripe_publishable_key && formData.stripe_publishable_key.trim()) { updateData.stripe_publishable_key = formData.stripe_publishable_key.trim(); } if (formData.stripe_webhook_secret && formData.stripe_webhook_secret.trim()) { updateData.stripe_webhook_secret = formData.stripe_webhook_secret.trim(); } await systemSettingsService.updateStripeSettings(updateData); await loadAllSettings(); setFormData({ ...formData, stripe_secret_key: '', stripe_webhook_secret: '', }); toast.success('Stripe settings updated successfully'); } catch (error: any) { toast.error( error.response?.data?.message || error.response?.data?.detail || 'Failed to update Stripe settings' ); } finally { setSaving(false); } }; // SMTP Settings Handlers const handleSaveSmtp = async () => { try { setSaving(true); const updateData: UpdateSmtpSettingsRequest = {}; if (smtpFormData.smtp_host && smtpFormData.smtp_host.trim()) { updateData.smtp_host = smtpFormData.smtp_host.trim(); } if (smtpFormData.smtp_port && smtpFormData.smtp_port.trim()) { updateData.smtp_port = smtpFormData.smtp_port.trim(); } if (smtpFormData.smtp_user && smtpFormData.smtp_user.trim()) { updateData.smtp_user = smtpFormData.smtp_user.trim(); } if (smtpFormData.smtp_password && smtpFormData.smtp_password.trim()) { updateData.smtp_password = smtpFormData.smtp_password.trim(); } if (smtpFormData.smtp_from_email && smtpFormData.smtp_from_email.trim()) { updateData.smtp_from_email = smtpFormData.smtp_from_email.trim(); } if (smtpFormData.smtp_from_name && smtpFormData.smtp_from_name.trim()) { updateData.smtp_from_name = smtpFormData.smtp_from_name.trim(); } if (smtpFormData.smtp_use_tls !== undefined) { updateData.smtp_use_tls = smtpFormData.smtp_use_tls; } await systemSettingsService.updateSmtpSettings(updateData); await loadSmtpSettings(); setSmtpFormData({ ...smtpFormData, smtp_password: '', }); toast.success('SMTP settings updated successfully'); } catch (error: any) { toast.error( error.response?.data?.message || error.response?.data?.detail || 'Failed to update SMTP settings' ); } finally { setSaving(false); } }; // Test Email Handler const handleTestEmail = async () => { if (!testEmailAddress || !testEmailAddress.trim()) { toast.error('Please enter an email address'); return; } // Basic email validation const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(testEmailAddress.trim())) { toast.error('Please enter a valid email address'); return; } try { setTestingEmail(true); const response = await systemSettingsService.testSmtpEmail(testEmailAddress.trim()); toast.success(`Test email sent successfully to ${response.data.recipient}`); } catch (error: any) { toast.error( error.response?.data?.detail || error.response?.data?.message || 'Failed to send test email. Please check your SMTP settings.' ); } finally { setTestingEmail(false); } }; // Company Settings Handlers const handleSaveCompany = async () => { try { setSaving(true); await systemSettingsService.updateCompanySettings(companyFormData); await loadCompanySettings(); // Refresh company settings context to update all components if (typeof window !== 'undefined') { window.dispatchEvent(new CustomEvent('refreshCompanySettings')); } toast.success('Company settings updated successfully'); } catch (error: any) { toast.error( error.response?.data?.message || error.response?.data?.detail || 'Failed to update company settings' ); } finally { setSaving(false); } }; const handleLogoUpload = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; // Validate file type if (!file.type.startsWith('image/')) { toast.error('Please select an image file'); return; } // Validate file size (max 2MB) if (file.size > 2 * 1024 * 1024) { toast.error('Logo size must be less than 2MB'); return; } // Create preview const reader = new FileReader(); reader.onloadend = () => { setLogoPreview(reader.result as string); }; reader.readAsDataURL(file); try { setUploadingLogo(true); const response = await systemSettingsService.uploadCompanyLogo(file); if (response.status === 'success') { await loadCompanySettings(); // Refresh company settings context to update all components if (typeof window !== 'undefined') { window.dispatchEvent(new CustomEvent('refreshCompanySettings')); } toast.success('Logo uploaded successfully'); } } catch (error: any) { toast.error( error.response?.data?.detail || error.response?.data?.message || 'Failed to upload logo' ); setLogoPreview(null); } finally { setUploadingLogo(false); // Reset input e.target.value = ''; } }; const handleFaviconUpload = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; // Validate file type (ico, png, svg) const validTypes = ['image/x-icon', 'image/vnd.microsoft.icon', 'image/png', 'image/svg+xml']; const validExtensions = ['.ico', '.png', '.svg']; const fileExtension = file.name.toLowerCase().substring(file.name.lastIndexOf('.')); if (!validTypes.includes(file.type) && !validExtensions.includes(fileExtension)) { toast.error('Favicon must be .ico, .png, or .svg file'); return; } // Validate file size (max 500KB) if (file.size > 500 * 1024) { toast.error('Favicon size must be less than 500KB'); return; } // Create preview const reader = new FileReader(); reader.onloadend = () => { setFaviconPreview(reader.result as string); }; reader.readAsDataURL(file); try { setUploadingFavicon(true); const response = await systemSettingsService.uploadCompanyFavicon(file); if (response.status === 'success') { await loadCompanySettings(); // Refresh company settings context to update all components if (typeof window !== 'undefined') { window.dispatchEvent(new CustomEvent('refreshCompanySettings')); } toast.success('Favicon uploaded successfully'); // Update favicon in document const link = document.querySelector("link[rel~='icon']") as HTMLLinkElement; if (link) { link.href = response.data.full_url; } else { const newLink = document.createElement('link'); newLink.rel = 'icon'; newLink.href = response.data.full_url; document.head.appendChild(newLink); } } } catch (error: any) { toast.error( error.response?.data?.detail || error.response?.data?.message || 'Failed to upload favicon' ); setFaviconPreview(null); } finally { setUploadingFavicon(false); // Reset input e.target.value = ''; } }; if (loading) { return ; } const tabs = [ { id: 'general' as SettingsTab, label: 'Overview', icon: Settings }, { id: 'cookie' as SettingsTab, label: 'Privacy & Cookies', icon: Cookie }, { id: 'currency' as SettingsTab, label: 'Currency', icon: Coins }, { id: 'payment' as SettingsTab, label: 'Payment', icon: CreditCard }, { id: 'smtp' as SettingsTab, label: 'Email Server', icon: Mail }, { id: 'company' as SettingsTab, label: 'Company Info', icon: Building2 }, ]; return (
{/* Luxury Header */}
{/* Background decorative elements */}

Settings Dashboard

Centralized control center for all platform configurations and system settings

{/* Premium Tab Navigation */}
{tabs.map((tab) => { const Icon = tab.icon; const isActive = activeTab === tab.id; return ( ); })}
{/* General Overview Tab */} {activeTab === 'general' && (
setActiveTab('cookie')} className="group relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-blue-100/50 p-8 cursor-pointer transition-all duration-300 hover:shadow-2xl hover:scale-105 hover:border-blue-300/60 overflow-hidden" >

Privacy & Cookies

Manage cookie preferences, analytics integrations, and privacy controls

Last updated {policyMeta?.updated_at ? new Date(policyMeta.updated_at).toLocaleDateString() : 'Never'}
setActiveTab('currency')} className="group relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-emerald-100/50 p-8 cursor-pointer transition-all duration-300 hover:shadow-2xl hover:scale-105 hover:border-emerald-300/60 overflow-hidden" >

Currency

Configure platform-wide currency settings and display preferences

Current currency {currency}
setActiveTab('payment')} className="group relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-indigo-100/50 p-8 cursor-pointer transition-all duration-300 hover:shadow-2xl hover:scale-105 hover:border-indigo-300/60 overflow-hidden" >

Payment Gateway

Manage Stripe payment processing credentials and webhook settings

Status {stripeSettings?.has_secret_key && stripeSettings?.has_publishable_key ? '✓ Configured' : 'Not configured'}
setActiveTab('smtp')} className="group relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-teal-100/50 p-8 cursor-pointer transition-all duration-300 hover:shadow-2xl hover:scale-105 hover:border-teal-300/60 overflow-hidden" >

Email Server

Configure SMTP server settings for platform-wide email delivery

Status {smtpSettings?.has_host && smtpSettings?.has_user && smtpSettings?.has_password ? '✓ Configured' : 'Not configured'}
setActiveTab('company')} className="group relative bg-white/90 backdrop-blur-xl rounded-2xl shadow-xl border border-purple-100/50 p-8 cursor-pointer transition-all duration-300 hover:shadow-2xl hover:scale-105 hover:border-purple-300/60 overflow-hidden" >

Company Info

Manage company branding, logo, favicon, and contact information

Status {companySettings?.company_name || companySettings?.company_logo_url ? '✓ Configured' : 'Not configured'}
)} {/* Cookie & Privacy Tab */} {activeTab === 'cookie' && (
{/* Section Header */}

Privacy & Cookie Controls

Define which cookie categories are allowed in the application. Control user consent preferences and analytics integrations.

{/* Info Card */}

How these settings affect the guest experience

Disabling a category here prevents it from being offered to guests as part of the cookie consent flow. For example, if marketing cookies are disabled, the website should not load marketing pixels even if a guest previously opted in.

{/* Cookie Toggles */}
{[ { key: 'analytics_enabled' as keyof CookiePolicySettings, label: 'Analytics Cookies', desc: 'Anonymous traffic and performance measurement', color: 'emerald' as const, icon: SlidersHorizontal }, { key: 'marketing_enabled' as keyof CookiePolicySettings, label: 'Marketing Cookies', desc: 'Personalised offers and remarketing campaigns', color: 'pink' as const, icon: SlidersHorizontal }, { key: 'preferences_enabled' as keyof CookiePolicySettings, label: 'Preference Cookies', desc: 'Remember guest choices like language and currency', color: 'indigo' as const, icon: SlidersHorizontal }, ].map(({ key, label, desc, color, icon: Icon }) => { const isEnabled = policy[key]; const colorClassesMap = { emerald: { bg: 'from-emerald-500 to-emerald-600', shadow: 'shadow-emerald-500/30', iconBg: 'bg-emerald-50 border-emerald-100', iconColor: 'text-emerald-600', }, pink: { bg: 'from-pink-500 to-pink-600', shadow: 'shadow-pink-500/30', iconBg: 'bg-pink-50 border-pink-100', iconColor: 'text-pink-600', }, indigo: { bg: 'from-indigo-500 to-indigo-600', shadow: 'shadow-indigo-500/30', iconBg: 'bg-indigo-50 border-indigo-100', iconColor: 'text-indigo-600', }, } as const; const colorClasses = colorClassesMap[color] || colorClassesMap.emerald; return (

{label}

{desc}

); })}
{/* Integration IDs */}

Third-Party Integrations

Configure IDs for supported analytics and marketing platforms. The application will only load these when both the policy and user consent allow it.

setIntegrations((prev) => ({ ...prev, ga_measurement_id: e.target.value || undefined, })) } placeholder="G-XXXXXXXXXX" className="w-full px-4 py-3 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Example: G-ABCDE12345

setIntegrations((prev) => ({ ...prev, fb_pixel_id: e.target.value || undefined, })) } placeholder="123456789012345" className="w-full px-4 py-3 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Numeric ID from your Meta Pixel configuration

)} {/* Currency Tab */} {activeTab === 'currency' && (
{/* Section Header */}

Platform Currency Settings

Set the default currency that will be displayed across all dashboards and pages throughout the platform

{/* Info Card */}

How platform currency works

The platform currency you select here will be used to display all prices, amounts, and financial information across the entire application. This includes customer-facing pages, admin dashboards, reports, and booking pages. All users will see prices in the selected currency.

{/* Currency Selection */}

Select Platform Currency

Choose the currency that will be used throughout the platform for displaying all monetary values

Current platform currency: {currency}
)} {/* Payment Tab */} {activeTab === 'payment' && (
{/* Section Header */}

Stripe Payment Settings

Configure your Stripe account credentials to enable secure card payments. All payments will be processed through your Stripe account.

{/* Info Card */}

How Stripe payments work

Stripe handles all card payments securely. You need to provide your Stripe API keys from your Stripe Dashboard. The secret key is used to process payments on the backend, while the publishable key is used in the frontend payment forms. The webhook secret is required to verify webhook events from Stripe.

Note: Leave fields empty to keep existing values. Only enter new values when you want to update them.

{/* Stripe Settings Form */}

Stripe API Keys

Get these keys from your{' '} Stripe Dashboard

{/* Secret Key */}
setFormData({ ...formData, stripe_secret_key: e.target.value }) } placeholder={ stripeSettings?.has_secret_key ? `Current: ${stripeSettings.stripe_secret_key_masked || '****'}` : 'sk_test_... or sk_live_...' } className="w-full px-4 py-3.5 pr-12 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm font-mono" />

Used to process payments on the backend. Must start with

sk_ {stripeSettings?.has_secret_key && ( Currently configured )}
{/* Publishable Key */}
setFormData({ ...formData, stripe_publishable_key: e.target.value, }) } placeholder="pk_test_... or pk_live_..." className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm font-mono" />

Used in frontend payment forms. Must start with

pk_ {stripeSettings?.has_publishable_key && ( Currently configured )}
{/* Webhook Secret */}
setFormData({ ...formData, stripe_webhook_secret: e.target.value, }) } placeholder={ stripeSettings?.has_webhook_secret ? `Current: ${stripeSettings.stripe_webhook_secret_masked || '****'}` : 'whsec_...' } className="w-full px-4 py-3.5 pr-12 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm font-mono" />

Used to verify webhook events from Stripe. Must start with

whsec_ {stripeSettings?.has_webhook_secret && ( Currently configured )}
{/* Webhook URL Info */}

Webhook Endpoint URL

Configure this URL in your{' '} Stripe Webhooks Dashboard :

{window.location.origin}/api/payments/stripe/webhook

Make sure to subscribe to payment_intent.succeeded and{' '} payment_intent.payment_failed events.

)} {/* SMTP Email Server Tab */} {activeTab === 'smtp' && (
{/* Section Header */}

SMTP Email Server Settings

Configure your SMTP server settings for sending emails. These settings will be used platform-wide for all outgoing emails.

{/* Test Email Section */}

Test Email Configuration

Send a test email to verify that your SMTP settings are working correctly.

setTestEmailAddress(e.target.value)} placeholder="Enter email address to send test email" className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-teal-500/50 focus:border-teal-500 transition-all duration-200 text-sm" disabled={testingEmail} />

Enter the email address where you want to receive the test email

{/* Info Card */}

How SMTP settings work

The SMTP server configured here will be used for all outgoing emails across the platform, including welcome emails, password resets, booking confirmations, and notifications. Common SMTP services include Gmail, SendGrid, Mailgun, and AWS SES.

Note: Leave fields empty to keep existing values. Only enter new values when you want to update them. The password field will be masked for security.

{/* SMTP Settings Form */}

SMTP Server Configuration

Enter your SMTP server details. These are typically provided by your email service provider.

{/* SMTP Host */}
setSmtpFormData({ ...smtpFormData, smtp_host: e.target.value }) } placeholder={ smtpSettings?.has_host ? smtpSettings.smtp_host : 'smtp.gmail.com' } className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Server hostname (e.g., smtp.gmail.com, smtp.sendgrid.net)

{smtpSettings?.has_host && ( Currently configured )}
{/* SMTP Port */}
setSmtpFormData({ ...smtpFormData, smtp_port: e.target.value }) } placeholder={ smtpSettings?.smtp_port ? smtpSettings.smtp_port : '587' } className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Common ports: 587 (STARTTLS), 465 (SSL), 25 (Plain)

{/* SMTP User */}
setSmtpFormData({ ...smtpFormData, smtp_user: e.target.value }) } placeholder={ smtpSettings?.has_user ? smtpSettings.smtp_user : 'your-email@gmail.com' } className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Your SMTP login email or username

{smtpSettings?.has_user && ( Currently configured )}
{/* SMTP Password */}
setSmtpFormData({ ...smtpFormData, smtp_password: e.target.value }) } placeholder={ smtpSettings?.has_password ? `Current: ${smtpSettings.smtp_password_masked || '****'}` : 'Enter password' } className="w-full px-4 py-3.5 pr-12 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Your SMTP password or app password

{smtpSettings?.has_password && ( Currently configured )}
{/* From Email */}
setSmtpFormData({ ...smtpFormData, smtp_from_email: e.target.value }) } placeholder={ smtpSettings?.smtp_from_email ? smtpSettings.smtp_from_email : 'noreply@example.com' } className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Default sender email address (can be same as SMTP user)

{/* From Name */}
setSmtpFormData({ ...smtpFormData, smtp_from_name: e.target.value }) } placeholder={ smtpSettings?.smtp_from_name ? smtpSettings.smtp_from_name : 'Hotel Booking' } className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Display name for outgoing emails

{/* TLS/SSL Toggle */}

Enable for port 465 (SSL/TLS), disable for port 587 (STARTTLS)

{/* Common Providers Info */}

Common SMTP Settings

Gmail: smtp.gmail.com:587 (STARTTLS) or 465 (SSL) - Requires App Password

SendGrid: smtp.sendgrid.net:587 - Use API key as password

Mailgun: smtp.mailgun.org:587 or 465 - Use SMTP credentials from dashboard

AWS SES: email-smtp.[region].amazonaws.com:587 or 465 - Use SMTP credentials

)} {/* Company Info Tab */} {activeTab === 'company' && (
{/* Section Header */}

Company Information

Manage your company branding, logo, favicon, and contact information. These will be displayed across the platform and in email notifications.

{/* Logo & Favicon Upload Section */}
{/* Logo Upload */}

Company Logo

Upload your company logo. This will be displayed in the header, emails, and across the platform. (Max 2MB)

{logoPreview && (
Logo preview
)} {uploadingLogo && (
Uploading logo...
)}
{/* Favicon Upload */}

Favicon

Upload your favicon (site icon). This appears in browser tabs and bookmarks. (Max 500KB, .ico, .png, or .svg)

{faviconPreview && (
Favicon preview
)} {uploadingFavicon && (
Uploading favicon...
)}
{/* Company Information Form */}

Company Details

Enter your company information. This will be used in email notifications, invoices, and displayed across the platform.

{/* Company Name */}
setCompanyFormData({ ...companyFormData, company_name: e.target.value }) } placeholder="Luxury Hotel" className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Your company or hotel name as it should appear in emails and invoices

{/* Company Tagline */}
setCompanyFormData({ ...companyFormData, company_tagline: e.target.value }) } placeholder="Excellence Redefined" className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

A short tagline that appears below your company name in the header and footer

{/* Phone */}
setCompanyFormData({ ...companyFormData, company_phone: e.target.value }) } placeholder="+1 (555) 123-4567" className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Contact phone number for customers

{/* Email */}
setCompanyFormData({ ...companyFormData, company_email: e.target.value }) } placeholder="info@hotel.com" className="w-full px-4 py-3.5 bg-white border border-gray-300 rounded-xl shadow-sm focus:ring-2 focus:ring-amber-500/50 focus:border-amber-500 transition-all duration-200 text-sm" />

Contact email address for customers

{/* Address */}