/* Copyright (C) 2025 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import React, { useEffect, useState, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { API, downloadTextAsFile, showError, showSuccess, renderQuota, getCurrencyConfig, } from '../../../../helpers'; import { quotaToDisplayAmount, displayAmountToQuota, } from '../../../../helpers/quota'; import { useIsMobile } from '../../../../hooks/common/useIsMobile'; import { Button, Modal, SideSheet, Space, Spin, Typography, Card, Tag, Form, Avatar, Row, Col, InputNumber, } from '@douyinfe/semi-ui'; import { IconCreditCard, IconSave, IconClose, IconGift, } from '@douyinfe/semi-icons'; const { Text, Title } = Typography; const EditRedemptionModal = (props) => { const { t } = useTranslation(); const isEdit = props.editingRedemption.id !== undefined; const [loading, setLoading] = useState(isEdit); const isMobile = useIsMobile(); const formApiRef = useRef(null); const [showQuotaInput, setShowQuotaInput] = useState(false); const getInitValues = () => ({ name: '', quota: 100000, amount: Number(quotaToDisplayAmount(100000).toFixed(6)), count: 1, expired_time: null, }); const handleCancel = () => { props.handleClose(); }; const loadRedemption = async () => { setLoading(true); let res = await API.get(`/api/redemption/${props.editingRedemption.id}`); const { success, message, data } = res.data; if (success) { if (data.expired_time === 0) { data.expired_time = null; } else { data.expired_time = new Date(data.expired_time * 1000); } data.amount = Number(quotaToDisplayAmount(data.quota || 0).toFixed(6)); formApiRef.current?.setValues({ ...getInitValues(), ...data }); } else { showError(message); } setLoading(false); }; useEffect(() => { if (formApiRef.current) { if (isEdit) { loadRedemption(); } else { formApiRef.current.setValues(getInitValues()); } } }, [props.editingRedemption.id]); const submit = async (values) => { let name = values.name; if (!isEdit && (!name || name === '')) { name = renderQuota(values.quota); } setLoading(true); let localInputs = { ...values }; localInputs.count = parseInt(localInputs.count) || 0; localInputs.quota = displayAmountToQuota(localInputs.amount); if (localInputs.quota <= 0) { showError(t('请输入金额')); setLoading(false); return; } localInputs.name = name; if (!localInputs.expired_time) { localInputs.expired_time = 0; } else { localInputs.expired_time = Math.floor( localInputs.expired_time.getTime() / 1000, ); } let res; if (isEdit) { res = await API.put(`/api/redemption/`, { ...localInputs, id: parseInt(props.editingRedemption.id), }); } else { res = await API.post(`/api/redemption/`, { ...localInputs, }); } const { success, message, data } = res.data; if (success) { if (isEdit) { showSuccess(t('兑换码更新成功!')); props.refresh(); props.handleClose(); } else { showSuccess(t('兑换码创建成功!')); props.refresh(); formApiRef.current?.setValues(getInitValues()); props.handleClose(); } } else { showError(message); } if (!isEdit && data) { let text = ''; for (let i = 0; i < data.length; i++) { text += data[i] + '\n'; } Modal.confirm({ title: t('兑换码创建成功'), content: (

{t('兑换码创建成功,是否下载兑换码?')}

{t('兑换码将以文本文件的形式下载,文件名为兑换码的名称。')}

), onOk: () => { downloadTextAsFile(text, `${localInputs.name}.txt`); }, }); } setLoading(false); }; return ( <> {isEdit ? ( {t('更新')} ) : ( {t('新建')} )} {isEdit ? t('更新兑换码信息') : t('创建新的兑换码')} } bodyStyle={{ padding: '0' }} visible={props.visiable} width={isMobile ? '100%' : 600} footer={
} closeIcon={null} onCancel={() => handleCancel()} >
(formApiRef.current = api)} onSubmit={submit} > {({ values }) => (
{/* Header: Basic Info */}
{t('基本信息')}
{t('设置兑换码的基本信息')}
{/* Header: Quota Settings */}
{t('额度设置')}
{t('设置兑换码的额度和数量')}
{ const amount = val === '' || val == null ? 0 : val; formApiRef.current?.setValue('amount', amount); formApiRef.current?.setValue( 'quota', displayAmountToQuota(amount), ); }} showClear />
setShowQuotaInput((v) => !v)} > {showQuotaInput ? `▾ ${t('收起原生额度输入')}` : `▸ ${t('使用原生额度输入')}`}
{ const num = parseInt(v, 10); return num > 0 ? Promise.resolve() : Promise.reject(t('额度必须大于0')); }, }, ]} onChange={(val) => { const quota = val === '' || val == null ? 0 : val; formApiRef.current?.setValue('quota', quota); formApiRef.current?.setValue( 'amount', Number(quotaToDisplayAmount(quota).toFixed(6)), ); }} style={{ width: '100%' }} showClear />
{!isEdit && ( { const num = parseInt(v, 10); return num > 0 ? Promise.resolve() : Promise.reject(t('生成数量必须大于0')); }, }, ]} style={{ width: '100%' }} showClear /> )}
)}
); }; export default EditRedemptionModal;