import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { toast } from 'react-toastify'; import { ShieldAlert } from 'lucide-react'; import { Button, Input } from '../common'; import type { FeatureKey } from '../../services/featureFlags.service'; import { businessProfileService } from '../../services/businessProfile.service'; import { emailService, type EmailConfig } from '../../services/email.service'; // Features that need working SMTP to deliver anything. const EMAIL_FEATURES: FeatureKey[] = ['reminderEmails', 'incomingMail', 'whatsapp', 'bills']; interface Props { selectedFeatures: Set; onDone: () => void; } // Lean per-feature config, shown after the "How will you use PicPeak?" step. // Only the sections a selected feature actually needs are rendered; everything // else keeps its seeded defaults and is tunable later in Settings. Saving is // best-effort per section — a failure never traps the user on setup. export const SetupConfigStep: React.FC = ({ selectedFeatures, onDone }) => { const { t } = useTranslation(); const showInvoicing = selectedFeatures.has('bills'); const showEmail = EMAIL_FEATURES.some((f) => selectedFeatures.has(f)); const [saving, setSaving] = useState(false); const [inv, setInv] = useState({ companyName: '', addressLine1: '', postalCode: '', city: '', countryCode: '', vatId: '', taxId: '', defaultCurrency: 'CHF', iban: '', }); const [mail, setMail] = useState({ smtp_host: '', smtp_port: '587', smtp_user: '', smtp_pass: '', from_email: '', from_name: '', }); const invField = (k: keyof typeof inv) => (e: React.ChangeEvent) => setInv((p) => ({ ...p, [k]: e.target.value })); const mailField = (k: keyof typeof mail) => (e: React.ChangeEvent) => setMail((p) => ({ ...p, [k]: e.target.value })); const finish = async () => { setSaving(true); try { // Invoicing: only persist if they actually started filling it in. if (showInvoicing && inv.companyName.trim()) { await businessProfileService.update({ companyName: inv.companyName.trim(), addressLine1: inv.addressLine1.trim(), postalCode: inv.postalCode.trim(), city: inv.city.trim(), countryCode: inv.countryCode.trim(), vatId: inv.vatId.trim(), taxId: inv.taxId.trim(), defaultCurrency: inv.defaultCurrency.trim() || 'CHF', }); if (inv.iban.trim()) { await businessProfileService.createBankAccount({ iban: inv.iban.replace(/\s+/g, ''), accountHolder: inv.companyName.trim(), currency: inv.defaultCurrency.trim() || 'CHF', isDefault: true, }); } } // Email: only persist if a host was entered. if (showEmail && mail.smtp_host.trim()) { const port = parseInt(mail.smtp_port, 10) || 587; const config: EmailConfig = { smtp_host: mail.smtp_host.trim(), smtp_port: port, smtp_secure: port === 465, smtp_user: mail.smtp_user.trim(), smtp_pass: mail.smtp_pass, from_email: mail.from_email.trim(), from_name: mail.from_name.trim(), tls_reject_unauthorized: true, }; await emailService.updateConfig(config); } } catch (_) { toast.warn(t('setup.config.saveFailed', 'Some settings could not be saved — you can finish them in Settings.')); } finally { setSaving(false); onDone(); } }; return (

{t('setup.config.intro', 'A few details for the features you picked. Anything you skip keeps its default and can be set later in Settings.')}

{showInvoicing && (

{t('setup.config.invoicing', 'Invoicing details')}

{t('setup.config.invoicingDisclaimer', 'Used on your invoices. Bank/IBAN and VAT details are your responsibility — verify them with your bank and Treuhänder/tax advisor.')}

)} {showEmail && (

{t('setup.config.email', 'Email delivery (SMTP)')}

{t('setup.config.emailHint', 'Required to send reminders, invoices and notifications.')}

)}
); }; SetupConfigStep.displayName = 'SetupConfigStep';