'use client' import { useEffect, useState } from 'react' import { apiFetch } from '@/lib/api' import { useDashboardI18n } from '@/components/I18nProvider' interface BrandSettings { displayName: string tagline: string | null primaryColor: string accentColor?: string | null publicEmail: string | null publicPhone: string | null publicAddress?: string | null publicCity: string | null publicCountry?: string | null subdomain: string logoUrl?: string | null heroImageUrl?: string | null websiteUrl?: string | null whatsappNumber?: string | null paypalEmail: string | null amanpayMerchantId: string | null amanpaySecretKey?: string | null paypalMerchantId?: string | null customDomain?: string | null customDomainVerified?: boolean defaultLocale?: string defaultCurrency?: string isListedOnMarketplace: boolean } interface ContractSettings { fuelPolicyType: string fuelPolicyNote: string | null additionalDriverCharge: 'FREE' | 'PER_DAY' | 'FLAT' additionalDriverDailyRate: number additionalDriverFlatRate: number damagePolicy: string } interface InsurancePolicy { id: string name: string type: string chargeType: string chargeValue: number isRequired: boolean isActive: boolean } interface PricingRule { id: string name: string type: string condition: string conditionValue: number adjustmentType: string adjustmentValue: number isActive: boolean } interface AccountingSettings { reportingPeriod: string accountantEmail: string | null accountantName: string | null autoSendReport: boolean reportFormat: string } const emptyInsurance = { name: '', type: 'BASIC', chargeType: 'PER_DAY', chargeValue: 0, isRequired: false, isActive: true } const emptyRule = { name: '', type: 'SURCHARGE', condition: 'AGE_LESS_THAN', conditionValue: 25, adjustmentType: 'PERCENTAGE', adjustmentValue: 0, isActive: true } export default function SettingsPage() { const { language } = useDashboardI18n() const copy = { en: { title: 'Advanced settings', subtitle: 'Manage insurance, additional-driver rules, pricing adjustments, and reporting defaults.', save: 'Saving…', saveBrand: 'Save brand', brandProfile: 'Brand and public profile', brandProfileDesc: 'Control how your company appears on the marketplace and public booking site.', payments: 'Rental payment methods', paymentsDesc: 'Configure how renters pay your company on the public booking site.', savePayments: 'Save payments', customDomain: 'Custom domain', customDomainDesc: 'Point your own domain to the branded booking site.', saveDomain: 'Save domain', removeDomain: 'Remove custom domain', contractPolicies: 'Contract and driver policies', savePolicies: 'Save policies', insurancePolicies: 'Insurance policies', pricingRules: 'Pricing rules', accounting: 'Accounting and exports', saveAccounting: 'Save accounting', displayName: 'Display name', tagline: 'Tagline', publicEmail: 'Public email', publicPhone: 'Public phone', city: 'City', country: 'Country', websiteUrl: 'Website URL', contractLanguage: 'Contract language', whatsapp: 'WhatsApp number', brandColor: 'Brand color', listedMarketplace: 'Listed on marketplace', logoUpload: 'Logo upload', heroUpload: 'Hero image upload', uploading: 'Uploading…', logoUploaded: 'Logo uploaded', noLogo: 'No logo uploaded yet', heroUploaded: 'Hero image uploaded', noHero: 'No hero image uploaded yet', subdomain: 'Subdomain', customDomainLabel: 'Custom domain', domainPlaceholder: 'cars.example.com', status: 'Status', verified: 'Verified', pendingDns: 'Pending DNS verification', notConfigured: 'Not configured', fuelPolicyType: 'Fuel policy type', additionalDriverCharge: 'Additional driver charge', dailyDriverRate: 'Daily driver rate', flatDriverRate: 'Flat driver rate', fuelPolicyNote: 'Fuel policy note', damagePolicy: 'Damage policy', active: 'Active', inactive: 'Inactive', noInsurance: 'No insurance policies configured yet.', policyName: 'Policy name', chargeValue: 'Charge value', required: 'Required', addPolicy: 'Add policy', noRules: 'No pricing rules configured yet.', ruleName: 'Rule name', addRule: 'Add rule', reportingPeriod: 'Reporting period', reportFormat: 'Report format', accountantName: 'Accountant name', accountantEmail: 'Accountant email', autoSend: 'Auto-send reports to the accountant', amanpayMerchantId: 'AmanPay merchant ID', amanpaySecretKey: 'AmanPay secret key', paypalEmail: 'PayPal business email', noPaymentConfigured: 'If no payment method is configured, renters can still submit reservation requests and pay on pickup.', fuelPolicyLabels: { FULL_TO_FULL: 'Full to full', FULL_TO_EMPTY: 'Full to empty', SAME_TO_SAME: 'Same to same', PREPAID: 'Prepaid', FREE: 'Included' } as Record, driverChargeLabels: { FREE: 'Free', PER_DAY: 'Per day', FLAT: 'Flat' } as Record, reportingPeriodLabels: { WEEKLY: 'Weekly', MONTHLY: 'Monthly', QUARTERLY: 'Quarterly', ANNUAL: 'Annual' } as Record, reportFormatLabels: { CSV: 'CSV', PDF: 'PDF', BOTH: 'Both' } as Record, }, fr: { title: 'Paramètres avancés', subtitle: 'Gérez les assurances, règles conducteurs, ajustements tarifaires et paramètres de reporting.', save: 'Enregistrement…', saveBrand: 'Enregistrer la marque', brandProfile: 'Marque et profil public', brandProfileDesc: 'Contrôlez l’affichage de votre entreprise sur la marketplace et le site de réservation.', payments: 'Méthodes de paiement location', paymentsDesc: 'Configurez comment les clients paient votre entreprise.', savePayments: 'Enregistrer les paiements', customDomain: 'Domaine personnalisé', customDomainDesc: 'Pointez votre propre domaine vers le site de réservation.', saveDomain: 'Enregistrer le domaine', removeDomain: 'Supprimer le domaine', contractPolicies: 'Contrat et politiques conducteur', savePolicies: 'Enregistrer les politiques', insurancePolicies: 'Polices d’assurance', pricingRules: 'Règles tarifaires', accounting: 'Comptabilité et exports', saveAccounting: 'Enregistrer la comptabilité', displayName: 'Nom affiché', tagline: 'Slogan', publicEmail: 'E-mail public', publicPhone: 'Téléphone public', city: 'Ville', country: 'Pays', websiteUrl: 'URL du site', contractLanguage: 'Langue du contrat', whatsapp: 'Numéro WhatsApp', brandColor: 'Couleur de marque', listedMarketplace: 'Publié sur la marketplace', logoUpload: 'Logo', heroUpload: 'Image principale', uploading: 'Téléversement…', logoUploaded: 'Logo téléversé', noLogo: 'Aucun logo téléversé', heroUploaded: 'Image principale téléversée', noHero: 'Aucune image principale téléversée', subdomain: 'Sous-domaine', customDomainLabel: 'Domaine personnalisé', domainPlaceholder: 'voitures.exemple.com', status: 'Statut', verified: 'Vérifié', pendingDns: 'Vérification DNS en attente', notConfigured: 'Non configuré', fuelPolicyType: 'Type de politique carburant', additionalDriverCharge: 'Supplément conducteur additionnel', dailyDriverRate: 'Tarif conducteur/jour', flatDriverRate: 'Tarif conducteur fixe', fuelPolicyNote: 'Note sur la politique carburant', damagePolicy: 'Politique dommages', active: 'Actif', inactive: 'Inactif', noInsurance: 'Aucune police d’assurance configurée.', policyName: 'Nom de la police', chargeValue: 'Valeur de facturation', required: 'Obligatoire', addPolicy: 'Ajouter la police', noRules: 'Aucune règle tarifaire configurée.', ruleName: 'Nom de la règle', addRule: 'Ajouter la règle', reportingPeriod: 'Période de reporting', reportFormat: 'Format de rapport', accountantName: 'Nom du comptable', accountantEmail: 'E-mail du comptable', autoSend: 'Envoyer automatiquement les rapports au comptable', amanpayMerchantId: 'ID marchand AmanPay', amanpaySecretKey: 'Clé secrète AmanPay', paypalEmail: 'Email business PayPal', noPaymentConfigured: 'Si aucun moyen de paiement n’est configuré, les clients peuvent envoyer une demande puis payer à la prise du véhicule.', fuelPolicyLabels: { FULL_TO_FULL: 'Plein à plein', FULL_TO_EMPTY: 'Plein à vide', SAME_TO_SAME: 'Même niveau', PREPAID: 'Prépayé', FREE: 'Inclus' } as Record, driverChargeLabels: { FREE: 'Gratuit', PER_DAY: 'Par jour', FLAT: 'Forfait' } as Record, reportingPeriodLabels: { WEEKLY: 'Hebdomadaire', MONTHLY: 'Mensuel', QUARTERLY: 'Trimestriel', ANNUAL: 'Annuel' } as Record, reportFormatLabels: { CSV: 'CSV', PDF: 'PDF', BOTH: 'Les deux' } as Record, }, ar: { title: 'الإعدادات المتقدمة', subtitle: 'إدارة التأمين وقواعد السائق الإضافي وتعديلات التسعير وإعدادات التقارير.', save: 'جارٍ الحفظ…', saveBrand: 'حفظ العلامة', brandProfile: 'العلامة والملف العام', brandProfileDesc: 'تحكم في ظهور شركتك في السوق وموقع الحجز العام.', payments: 'طرق دفع الإيجار', paymentsDesc: 'تهيئة طريقة دفع العملاء لشركتك في موقع الحجز.', savePayments: 'حفظ الدفع', customDomain: 'نطاق مخصص', customDomainDesc: 'ربط نطاقك الخاص بموقع الحجز.', saveDomain: 'حفظ النطاق', removeDomain: 'إزالة النطاق المخصص', contractPolicies: 'العقد وسياسات السائق', savePolicies: 'حفظ السياسات', insurancePolicies: 'سياسات التأمين', pricingRules: 'قواعد التسعير', accounting: 'المحاسبة والتصدير', saveAccounting: 'حفظ المحاسبة', displayName: 'اسم العرض', tagline: 'الشعار', publicEmail: 'البريد الإلكتروني العام', publicPhone: 'الهاتف العام', city: 'المدينة', country: 'الدولة', websiteUrl: 'رابط الموقع', contractLanguage: 'لغة العقد', whatsapp: 'رقم واتساب', brandColor: 'لون العلامة', listedMarketplace: 'مدرج في السوق', logoUpload: 'رفع الشعار', heroUpload: 'رفع صورة الواجهة', uploading: 'جارٍ الرفع…', logoUploaded: 'تم رفع الشعار', noLogo: 'لم يتم رفع شعار بعد', heroUploaded: 'تم رفع صورة الواجهة', noHero: 'لم يتم رفع صورة واجهة بعد', subdomain: 'النطاق الفرعي', customDomainLabel: 'النطاق المخصص', domainPlaceholder: 'cars.example.com', status: 'الحالة', verified: 'موثق', pendingDns: 'بانتظار التحقق من DNS', notConfigured: 'غير مُعدّ', fuelPolicyType: 'نوع سياسة الوقود', additionalDriverCharge: 'رسوم السائق الإضافي', dailyDriverRate: 'تعرفة السائق اليومية', flatDriverRate: 'تعرفة السائق الثابتة', fuelPolicyNote: 'ملاحظة سياسة الوقود', damagePolicy: 'سياسة الأضرار', active: 'نشط', inactive: 'غير نشط', noInsurance: 'لا توجد سياسات تأمين مهيأة.', policyName: 'اسم السياسة', chargeValue: 'قيمة الرسوم', required: 'إلزامي', addPolicy: 'إضافة سياسة', noRules: 'لا توجد قواعد تسعير مهيأة.', ruleName: 'اسم القاعدة', addRule: 'إضافة قاعدة', reportingPeriod: 'فترة التقرير', reportFormat: 'تنسيق التقرير', accountantName: 'اسم المحاسب', accountantEmail: 'بريد المحاسب', autoSend: 'إرسال التقارير تلقائياً إلى المحاسب', amanpayMerchantId: 'معرّف التاجر AmanPay', amanpaySecretKey: 'المفتاح السري AmanPay', paypalEmail: 'بريد أعمال PayPal', noPaymentConfigured: 'إذا لم يتم إعداد وسيلة دفع، لا يزال بإمكان العملاء إرسال طلب حجز والدفع عند الاستلام.', fuelPolicyLabels: { FULL_TO_FULL: 'ممتلئ إلى ممتلئ', FULL_TO_EMPTY: 'ممتلئ إلى فارغ', SAME_TO_SAME: 'نفس المستوى', PREPAID: 'مدفوع مسبقاً', FREE: 'مشمول' } as Record, driverChargeLabels: { FREE: 'مجاني', PER_DAY: 'يومي', FLAT: 'ثابت' } as Record, reportingPeriodLabels: { WEEKLY: 'أسبوعي', MONTHLY: 'شهري', QUARTERLY: 'ربع سنوي', ANNUAL: 'سنوي' } as Record, reportFormatLabels: { CSV: 'CSV', PDF: 'PDF', BOTH: 'كلاهما' } as Record, }, }[language] const [brand, setBrand] = useState(null) const [contractSettings, setContractSettings] = useState(null) const [insurancePolicies, setInsurancePolicies] = useState([]) const [pricingRules, setPricingRules] = useState([]) const [accountingSettings, setAccountingSettings] = useState(null) const [newInsurance, setNewInsurance] = useState(emptyInsurance) const [newRule, setNewRule] = useState(emptyRule) const [customDomain, setCustomDomain] = useState('') const [uploadingAsset, setUploadingAsset] = useState<'logo' | 'hero' | null>(null) const [error, setError] = useState(null) const [saving, setSaving] = useState(false) async function load() { try { const [brandData, contractData, insuranceData, ruleData, accountingData] = await Promise.all([ apiFetch('/companies/me/brand'), apiFetch('/companies/me/contract-settings'), apiFetch('/companies/me/insurance-policies'), apiFetch('/companies/me/pricing-rules'), apiFetch('/companies/me/accounting-settings'), ]) setBrand(brandData) setCustomDomain(brandData?.customDomain ?? '') setContractSettings(contractData ?? { fuelPolicyType: 'FULL_TO_FULL', fuelPolicyNote: '', additionalDriverCharge: 'FREE', additionalDriverDailyRate: 0, additionalDriverFlatRate: 0, damagePolicy: '', }) setInsurancePolicies(insuranceData) setPricingRules(ruleData) setAccountingSettings(accountingData ?? { reportingPeriod: 'MONTHLY', accountantEmail: '', accountantName: '', autoSendReport: false, reportFormat: 'CSV', }) setError(null) } catch (err: any) { setError(err.message ?? 'Failed to load settings') } } async function saveBrandSettings() { if (!brand) return setSaving(true) setError(null) try { const updated = await apiFetch('/companies/me/brand', { method: 'PATCH', body: JSON.stringify({ displayName: brand.displayName, tagline: brand.tagline || undefined, primaryColor: brand.primaryColor, accentColor: brand.accentColor || undefined, publicEmail: brand.publicEmail || undefined, publicPhone: brand.publicPhone || undefined, publicAddress: brand.publicAddress || undefined, publicCity: brand.publicCity || undefined, publicCountry: brand.publicCountry || undefined, websiteUrl: brand.websiteUrl || undefined, defaultLocale: brand.defaultLocale || undefined, whatsappNumber: brand.whatsappNumber || undefined, paypalEmail: brand.paypalEmail || undefined, amanpayMerchantId: brand.amanpayMerchantId || undefined, amanpaySecretKey: brand.amanpaySecretKey || undefined, paypalMerchantId: brand.paypalMerchantId || undefined, defaultCurrency: brand.defaultCurrency || undefined, isListedOnMarketplace: brand.isListedOnMarketplace, }), }) setBrand(updated) } catch (err: any) { setError(err.message ?? 'Failed to save brand settings') } finally { setSaving(false) } } async function uploadBrandAsset(kind: 'logo' | 'hero', file: File | null) { if (!file) return setUploadingAsset(kind) setError(null) try { const formData = new FormData() formData.append('file', file) const updated = await apiFetch(`/companies/me/brand/${kind}`, { method: 'POST', body: formData, }) setBrand(updated) } catch (err: any) { setError(err.message ?? `Failed to upload ${kind}`) } finally { setUploadingAsset(null) } } async function saveCustomDomain() { setSaving(true) setError(null) try { await apiFetch('/companies/me/brand/custom-domain', { method: 'POST', body: JSON.stringify({ customDomain }), }) await load() } catch (err: any) { setError(err.message ?? 'Failed to save custom domain') } finally { setSaving(false) } } async function removeCustomDomain() { setSaving(true) setError(null) try { await apiFetch('/companies/me/brand/custom-domain', { method: 'DELETE', }) setCustomDomain('') await load() } catch (err: any) { setError(err.message ?? 'Failed to remove custom domain') } finally { setSaving(false) } } useEffect(() => { load() }, []) async function saveContractSettings() { if (!contractSettings) return setSaving(true) setError(null) try { await apiFetch('/companies/me/contract-settings', { method: 'PATCH', body: JSON.stringify(contractSettings), }) } catch (err: any) { setError(err.message ?? 'Failed to save contract settings') } finally { setSaving(false) } } async function saveAccountingSettings() { if (!accountingSettings) return setSaving(true) setError(null) try { await apiFetch('/companies/me/accounting-settings', { method: 'PATCH', body: JSON.stringify(accountingSettings), }) } catch (err: any) { setError(err.message ?? 'Failed to save accounting settings') } finally { setSaving(false) } } async function createInsurance() { setSaving(true) setError(null) try { await apiFetch('/companies/me/insurance-policies', { method: 'POST', body: JSON.stringify(newInsurance), }) setNewInsurance(emptyInsurance) await load() } catch (err: any) { setError(err.message ?? 'Failed to create insurance policy') } finally { setSaving(false) } } async function toggleInsurance(policy: InsurancePolicy) { try { await apiFetch(`/companies/me/insurance-policies/${policy.id}`, { method: 'PATCH', body: JSON.stringify({ isActive: !policy.isActive }), }) await load() } catch (err: any) { setError(err.message ?? 'Failed to update insurance policy') } } async function createRule() { setSaving(true) setError(null) try { await apiFetch('/companies/me/pricing-rules', { method: 'POST', body: JSON.stringify(newRule), }) setNewRule(emptyRule) await load() } catch (err: any) { setError(err.message ?? 'Failed to create pricing rule') } finally { setSaving(false) } } async function toggleRule(rule: PricingRule) { try { await apiFetch(`/companies/me/pricing-rules/${rule.id}`, { method: 'PATCH', body: JSON.stringify({ isActive: !rule.isActive }), }) await load() } catch (err: any) { setError(err.message ?? 'Failed to update pricing rule') } } return (

{copy.title}

{copy.subtitle}

{error &&
{error}
} {brand && (

{copy.brandProfile}

{copy.brandProfileDesc}

setBrand((current) => current ? { ...current, displayName: event.target.value } : current)} />
setBrand((current) => current ? { ...current, tagline: event.target.value } : current)} />
setBrand((current) => current ? { ...current, publicEmail: event.target.value } : current)} />
setBrand((current) => current ? { ...current, publicPhone: event.target.value } : current)} />
setBrand((current) => current ? { ...current, publicCity: event.target.value } : current)} />
setBrand((current) => current ? { ...current, publicCountry: event.target.value } : current)} />
setBrand((current) => current ? { ...current, websiteUrl: event.target.value } : current)} />
setBrand((current) => current ? { ...current, whatsappNumber: event.target.value } : current)} />
setBrand((current) => current ? { ...current, primaryColor: event.target.value } : current)} />

{copy.payments}

{copy.paymentsDesc}

setBrand((current) => current ? { ...current, amanpayMerchantId: event.target.value } : current)} />
setBrand((current) => current ? { ...current, amanpaySecretKey: event.target.value } : current)} />
setBrand((current) => current ? { ...current, paypalEmail: event.target.value } : current)} />
{copy.noPaymentConfigured}

{copy.customDomain}

{copy.customDomainDesc}

{brand.subdomain}.RentalDriveGo.com
setCustomDomain(event.target.value)} />
{copy.status}: {brand.customDomain ? (brand.customDomainVerified ? copy.verified : copy.pendingDns) : copy.notConfigured}
{brand.customDomain ? ( ) : null}
)} {contractSettings && (

{copy.contractPolicies}

setContractSettings((current) => current ? { ...current, additionalDriverDailyRate: Number(event.target.value) } : current)} />
setContractSettings((current) => current ? { ...current, additionalDriverFlatRate: Number(event.target.value) } : current)} />