import { useEffect, useState, type FormEvent } from 'react' import { Eye, EyeOff } from 'lucide-react' import { Switch } from './Switch' import { Tooltip } from './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 sharedStyles from '../pages/ProductSettingsPage.module.css' import fieldStyles from '../pages/AddNewProductPage.module.css' import styles from '../pages/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 EPaymentSettingsSection() { 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 = { enabled: next.enabled, defaultGateway: next.defaultGateway, gateways: { mellat: { enabled: next.gateways.mellat.enabled, terminalId: next.gateways.mellat.terminalId, username: next.gateways.mellat.username, password: password ?? '', }, sep: { enabled: next.gateways.sep.enabled }, snappay: { enabled: next.gateways.snappay.enabled }, digipay: { enabled: next.gateways.digipay.enabled }, zarinpal: { enabled: next.gateways.zarinpal.enabled, merchantId: next.gateways.zarinpal.merchantId.trim(), sandbox: next.gateways.zarinpal.sandbox, }, }, } 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, enabled: checked ? true : ePayment.enabled, gateways: { ...ePayment.gateways, mellat: { ...ePayment.gateways.mellat, enabled: checked }, }, defaultGateway: nextDefaultGateway(ePayment, 'mellat', checked), }) } async function handleZarinpalToggle(checked: boolean) { await patchEPayment('zarinpal-enabled', { ...ePayment, enabled: checked ? true : ePayment.enabled, 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 } 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, }, }, }) } if (isLoading) { return

{t('productSettings.loading')}

} return (
{error ?
{error}
: null}

{t('title.ePayment')}

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

void handleMasterToggle(checked)} />
{!ePayment.enabled && (ePayment.gateways.mellat.enabled || ePayment.gateways.zarinpal.enabled) ? (

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

) : null}

{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, }, }, })) } />
{COMING_SOON_GATEWAYS.map((gateway) => (

{t(gateway.nameKey)}

{t(gateway.descKey)}

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