import { useEffect, useState, type FormEvent } from 'react' import { Eye, EyeOff } from 'lucide-react' import { Breadcrumbs } from '../components/Breadcrumbs' import { PageTitle } from '../components/PageTitle' import { Switch } from '../components/Switch' import { Tooltip } from '../components/Tooltip' import { useToast } from '../context/ToastContext' import { useT } from '../i18n/useT' import type { BusinessMessageKey } from '../i18n/messages' import { ApiError } from '../lib/api' import { DEFAULT_EPAYMENT_SETTINGS, getSettings, updateStoreSettings, type EPaymentSettings, type PaymentGatewayId, } from '../services/settingsService' import pageStyles from '../components/PageContent.module.css' import sharedStyles from './ProductSettingsPage.module.css' import fieldStyles from './AddNewProductPage.module.css' import styles from './SettingsPage.module.css' const COMING_SOON_GATEWAYS: { id: Exclude nameKey: BusinessMessageKey descKey: BusinessMessageKey }[] = [ { id: 'sep', nameKey: 'website.ePayment.gateway.sep', descKey: 'website.ePayment.gateway.sepDesc', }, { id: 'snappay', nameKey: 'website.ePayment.gateway.snappay', descKey: 'website.ePayment.gateway.snappayDesc', }, { id: 'digipay', nameKey: 'website.ePayment.gateway.digipay', descKey: 'website.ePayment.gateway.digipayDesc', }, ] function nextDefaultGateway( current: EPaymentSettings, gatewayId: PaymentGatewayId, enabled: boolean, ): PaymentGatewayId | null { if (enabled && !current.defaultGateway) return gatewayId if (!enabled && current.defaultGateway === gatewayId) { if (gatewayId !== 'mellat' && current.gateways.mellat.enabled) return 'mellat' if (gatewayId !== 'zarinpal' && current.gateways.zarinpal.enabled) { return 'zarinpal' } return null } return current.defaultGateway } export function SettingsPage() { const t = useT() const { showToast } = useToast() const [ePayment, setEPayment] = useState(DEFAULT_EPAYMENT_SETTINGS) const [passwordDraft, setPasswordDraft] = useState('') const [showPassword, setShowPassword] = useState(false) const [isLoading, setIsLoading] = useState(true) const [savingKey, setSavingKey] = useState(null) const [error, setError] = useState('') useEffect(() => { const controller = new AbortController() void loadSettings(controller.signal) return () => controller.abort() }, []) async function loadSettings(signal?: AbortSignal) { setIsLoading(true) setError('') try { const data = await getSettings(signal) setEPayment(data.settings.store.ePayment ?? DEFAULT_EPAYMENT_SETTINGS) setPasswordDraft('') } catch (err) { if (err instanceof DOMException && err.name === 'AbortError') return if (err instanceof ApiError) { setError(err.message) } else { setError(t('productSettings.errorLoad')) } } finally { setIsLoading(false) } } async function patchEPayment( saving: string, next: EPaymentSettings, password?: string, ) { setSavingKey(saving) setError('') try { const payload: EPaymentSettings = { ...next, gateways: { ...next.gateways, mellat: { ...next.gateways.mellat, password: password ?? '', }, zarinpal: { ...next.gateways.zarinpal, merchantId: next.gateways.zarinpal.merchantId.trim(), }, }, } const data = await updateStoreSettings({ ePayment: payload }) setEPayment(data.settings.store.ePayment ?? DEFAULT_EPAYMENT_SETTINGS) if (password) setPasswordDraft('') showToast(t('productSettings.saved'), 'success') } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError(t('productSettings.errorSave')) } } finally { setSavingKey(null) } } async function handleMasterToggle(checked: boolean) { await patchEPayment('master', { ...ePayment, enabled: checked, defaultGateway: checked ? ePayment.defaultGateway ?? (ePayment.gateways.mellat.enabled ? 'mellat' : ePayment.gateways.zarinpal.enabled ? 'zarinpal' : 'mellat') : ePayment.defaultGateway, }) } async function handleMellatToggle(checked: boolean) { await patchEPayment('mellat-enabled', { ...ePayment, gateways: { ...ePayment.gateways, mellat: { ...ePayment.gateways.mellat, enabled: checked }, }, defaultGateway: nextDefaultGateway(ePayment, 'mellat', checked), }) } async function handleZarinpalToggle(checked: boolean) { await patchEPayment('zarinpal-enabled', { ...ePayment, gateways: { ...ePayment.gateways, zarinpal: { ...ePayment.gateways.zarinpal, enabled: checked }, }, defaultGateway: nextDefaultGateway(ePayment, 'zarinpal', checked), }) } async function handleSaveMellatCredentials(event: FormEvent) { event.preventDefault() const terminalId = ePayment.gateways.mellat.terminalId.trim() const username = ePayment.gateways.mellat.username.trim() if (ePayment.gateways.mellat.enabled && (!terminalId || !username)) { setError(t('website.ePayment.error.credentials')) return } if ( ePayment.gateways.mellat.enabled && !ePayment.gateways.mellat.passwordSet && !passwordDraft.trim() ) { setError(t('website.ePayment.error.passwordRequired')) return } await patchEPayment( 'mellat-credentials', { ...ePayment, gateways: { ...ePayment.gateways, mellat: { ...ePayment.gateways.mellat, terminalId, username, }, }, }, passwordDraft.trim() || undefined, ) } async function handleSaveZarinpalCredentials(event: FormEvent) { event.preventDefault() const merchantId = ePayment.gateways.zarinpal.merchantId.trim() if (ePayment.gateways.zarinpal.enabled && !merchantId) { setError(t('website.ePayment.error.zarinpalMerchant')) return } await patchEPayment('zarinpal-credentials', { ...ePayment, gateways: { ...ePayment.gateways, zarinpal: { ...ePayment.gateways.zarinpal, merchantId, }, }, }) } return (
{t('title.settings')}

{t('settings.subtitle')}

{error ?
{error}
: null} {isLoading ? (

{t('productSettings.loading')}

) : (

{t('title.ePayment')}

{t('website.ePayment.masterDesc')}

void handleMasterToggle(checked)} />

{t('website.ePayment.gateway.mellat')}

{t('website.ePayment.gateway.mellatDesc')}

void handleMellatToggle(checked)} />
setEPayment((current) => ({ ...current, gateways: { ...current.gateways, mellat: { ...current.gateways.mellat, terminalId: e.target.value, }, }, })) } />
setEPayment((current) => ({ ...current, gateways: { ...current.gateways, mellat: { ...current.gateways.mellat, username: e.target.value, }, }, })) } />
setPasswordDraft(e.target.value)} />

{t('website.ePayment.gateway.zarinpal')}

{t('website.ePayment.gateway.zarinpalDesc')}

void handleZarinpalToggle(checked)} />
setEPayment((current) => ({ ...current, gateways: { ...current.gateways, zarinpal: { ...current.gateways.zarinpal, merchantId: e.target.value, }, }, })) } />

{t('website.ePayment.sandboxDesc')}

setEPayment((current) => ({ ...current, gateways: { ...current.gateways, zarinpal: { ...current.gateways.zarinpal, sandbox: checked, }, }, })) } />
{COMING_SOON_GATEWAYS.map((gateway) => (

{t(gateway.nameKey)}

{t(gateway.descKey)}

{t('website.ePayment.comingSoon')}
))}
)}
) }