fix(topup-agent-management): fix wallet deposit fields
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Save, Key, Globe, DollarSign, Bell, Shield, Database } from 'lucide-react';
|
||||
import { Save, Key, Globe, DollarSign, Bell, Shield, Database, Ticket } from 'lucide-react';
|
||||
import { generalAPI } from '../services/api';
|
||||
import { ToastContainer, toast } from 'react-toastify';
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
import { getErrorMessage, getSuccessMessage } from '../utils/errorHandler';
|
||||
|
||||
const Settings = () => {
|
||||
const [settings, setSettings] = useState({
|
||||
@@ -21,12 +25,21 @@ const Settings = () => {
|
||||
}
|
||||
});
|
||||
|
||||
const [voucherConfig, setVoucherConfig] = useState({
|
||||
expireInDays: 0,
|
||||
refundUponVoucherExpiration: true,
|
||||
canPurchaseByAgentVouchers: true,
|
||||
canTopUpWithUserVouchers: true
|
||||
});
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [voucherLoading, setVoucherLoading] = useState(false);
|
||||
const [message, setMessage] = useState('');
|
||||
const [activeTab, setActiveTab] = useState('payment');
|
||||
|
||||
useEffect(() => {
|
||||
loadSettings();
|
||||
loadVoucherConfiguration();
|
||||
}, []);
|
||||
|
||||
const loadSettings = () => {
|
||||
@@ -36,6 +49,26 @@ const Settings = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const loadVoucherConfiguration = async () => {
|
||||
try {
|
||||
setVoucherLoading(true);
|
||||
const config = await generalAPI.getVoucherConfiguration();
|
||||
if (config) {
|
||||
setVoucherConfig({
|
||||
expireInDays: config.expireInDays ?? 0,
|
||||
refundUponVoucherExpiration: config.refundUponVoucherExpiration ?? true,
|
||||
canPurchaseByAgentVouchers: config.canPurchaseByAgentVouchers ?? true,
|
||||
canTopUpWithUserVouchers: config.canTopUpWithUserVouchers ?? true
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error loading voucher configuration:', err);
|
||||
toast.error(getErrorMessage(err));
|
||||
} finally {
|
||||
setVoucherLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleInputChange = (section, field, value) => {
|
||||
setSettings(prev => ({
|
||||
...prev,
|
||||
@@ -72,11 +105,32 @@ const Settings = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleVoucherSave = async () => {
|
||||
setVoucherLoading(true);
|
||||
try {
|
||||
const result = await generalAPI.updateVoucherConfiguration(voucherConfig);
|
||||
toast.success(getSuccessMessage(result) || 'Voucher configuration saved successfully');
|
||||
await loadVoucherConfiguration();
|
||||
} catch (err) {
|
||||
toast.error(getErrorMessage(err));
|
||||
} finally {
|
||||
setVoucherLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleVoucherChange = (field, value) => {
|
||||
setVoucherConfig(prev => ({
|
||||
...prev,
|
||||
[field]: value
|
||||
}));
|
||||
};
|
||||
|
||||
const tabs = [
|
||||
{ id: 'payment', label: 'Payment', icon: DollarSign },
|
||||
{ id: 'notifications', label: 'Notifications', icon: Bell },
|
||||
{ id: 'security', label: 'Security', icon: Shield },
|
||||
{ id: 'data', label: 'Data', icon: Database }
|
||||
{ id: 'data', label: 'Data', icon: Database },
|
||||
{ id: 'voucher', label: 'Voucher', icon: Ticket }
|
||||
];
|
||||
|
||||
const currencies = [
|
||||
@@ -90,6 +144,7 @@ const Settings = () => {
|
||||
|
||||
return (
|
||||
<div className="p-6">
|
||||
<ToastContainer position="top-right" autoClose={3000} />
|
||||
<div className="mb-8">
|
||||
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">Settings</h1>
|
||||
<p className="text-gray-600 dark:text-gray-400">Configure your payment system preferences</p>
|
||||
@@ -331,16 +386,105 @@ const Settings = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Voucher Settings */}
|
||||
{activeTab === 'voucher' && (
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-6">Voucher Configuration</h3>
|
||||
{voucherLoading ? (
|
||||
<div className="flex justify-center py-10">
|
||||
<div className="w-8 h-8 border-4 border-t-transparent border-primary-500 rounded-full animate-spin" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
Expire In Days
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
value={voucherConfig.expireInDays}
|
||||
onChange={(e) => handleVoucherChange('expireInDays', Number(e.target.value) || 0)}
|
||||
className="input-field w-32"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
Number of days before vouchers expire
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<label className="text-sm font-medium text-gray-700 dark:text-gray-300">Refund Upon Voucher Expiration</label>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400">Automatically refund when voucher expires</p>
|
||||
</div>
|
||||
<label className="relative inline-flex items-center cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={voucherConfig.refundUponVoucherExpiration}
|
||||
onChange={(e) => handleVoucherChange('refundUponVoucherExpiration', e.target.checked)}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-primary-300 dark:peer-focus:ring-primary-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-primary-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<label className="text-sm font-medium text-gray-700 dark:text-gray-300">Can Purchase By Agent Vouchers</label>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400">Allow purchases using agent-generated vouchers</p>
|
||||
</div>
|
||||
<label className="relative inline-flex items-center cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={voucherConfig.canPurchaseByAgentVouchers}
|
||||
onChange={(e) => handleVoucherChange('canPurchaseByAgentVouchers', e.target.checked)}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-primary-300 dark:peer-focus:ring-primary-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-primary-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<label className="text-sm font-medium text-gray-700 dark:text-gray-300">Can Top Up With User Vouchers</label>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400">Allow top-up using user-generated vouchers</p>
|
||||
</div>
|
||||
<label className="relative inline-flex items-center cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={voucherConfig.canTopUpWithUserVouchers}
|
||||
onChange={(e) => handleVoucherChange('canTopUpWithUserVouchers', e.target.checked)}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-primary-300 dark:peer-focus:ring-primary-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-primary-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Save Button */}
|
||||
<div className="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700">
|
||||
<button
|
||||
onClick={handleSave}
|
||||
disabled={loading}
|
||||
className="btn-primary flex items-center"
|
||||
>
|
||||
<Save className="h-4 w-4 mr-2" />
|
||||
{loading ? 'Saving...' : 'Save Settings'}
|
||||
</button>
|
||||
{activeTab === 'voucher' ? (
|
||||
<button
|
||||
onClick={handleVoucherSave}
|
||||
disabled={voucherLoading}
|
||||
className="btn-primary flex items-center"
|
||||
>
|
||||
<Save className="h-4 w-4 mr-2" />
|
||||
{voucherLoading ? 'Saving...' : 'Save Voucher Settings'}
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
onClick={handleSave}
|
||||
disabled={loading}
|
||||
className="btn-primary flex items-center"
|
||||
>
|
||||
<Save className="h-4 w-4 mr-2" />
|
||||
{loading ? 'Saving...' : 'Save Settings'}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user