refactor(BillingManager): add tab navigation for subscriptions and payments, enhancing user experience and data visibility
Publish Fast Tabler Docker image / build-and-push-fast (push) Failing after 58s

This commit is contained in:
2026-02-16 21:28:58 +07:00
parent 5af5abb02d
commit 08a64b5be4
+33 -1
View File
@@ -54,6 +54,7 @@ function BillingManager() {
const [filterStatus, setFilterStatus] = useState(''); const [filterStatus, setFilterStatus] = useState('');
const [filterUrgency, setFilterUrgency] = useState(''); const [filterUrgency, setFilterUrgency] = useState('');
const [viewMode, setViewMode] = useState('cards'); // 'cards' | 'table' const [viewMode, setViewMode] = useState('cards'); // 'cards' | 'table'
const [activeTab, setActiveTab] = useState('subscriptions'); // 'subscriptions' | 'payments'
const pageSize = 15; const pageSize = 15;
// Модальные окна // Модальные окна
@@ -298,6 +299,10 @@ function BillingManager() {
return sum + convertToRUB(item.monthlyCost || 0, item.monthlyCostCurrency || 'USD'); return sum + convertToRUB(item.monthlyCost || 0, item.monthlyCostCurrency || 'USD');
}, 0); }, 0);
const totalPaymentsCount = billingData.reduce((sum, item) => {
return sum + ((item.payments && Array.isArray(item.payments) ? item.payments.length : 0));
}, 0);
const urgentPayments = billingData.filter(item => { const urgentPayments = billingData.filter(item => {
const nextPayment = new Date(item.nextPaymentDate); const nextPayment = new Date(item.nextPaymentDate);
const now = new Date(); const now = new Date();
@@ -578,6 +583,29 @@ function BillingManager() {
title="Биллинг" title="Биллинг"
icon={<IconCreditCard size={24} />} icon={<IconCreditCard size={24} />}
actions={ actions={
<div className="d-flex flex-column flex-sm-row align-items-stretch align-items-sm-center gap-2">
<div className="btn-group me-sm-2" role="group">
<button
className={`btn ${activeTab === 'subscriptions' ? 'btn-primary' : 'btn-outline-primary'}`}
onClick={() => setActiveTab('subscriptions')}
>
<IconServer size={16} className="me-1 d-none d-sm-inline" />
Подписки
<span className={`badge ms-1 ${activeTab === 'subscriptions' ? 'bg-white text-primary' : 'bg-primary-lt text-primary'}`}>
{billingData.length}
</span>
</button>
<button
className={`btn ${activeTab === 'payments' ? 'btn-primary' : 'btn-outline-primary'}`}
onClick={() => setActiveTab('payments')}
>
<IconHistory size={16} className="me-1 d-none d-sm-inline" />
История платежей
<span className={`badge ms-1 ${activeTab === 'payments' ? 'bg-white text-primary' : 'bg-primary-lt text-primary'}`}>
{totalPaymentsCount}
</span>
</button>
</div>
<PageHeaderActions <PageHeaderActions
loading={loading} loading={loading}
onRefresh={() => { fetchBillingData(); fetchServers(); }} onRefresh={() => { fetchBillingData(); fetchServers(); }}
@@ -587,6 +615,7 @@ function BillingManager() {
onSave={handleSaveChanges} onSave={handleSaveChanges}
disableSave={loading} disableSave={loading}
/> />
</div>
} }
/> />
@@ -656,7 +685,8 @@ function BillingManager() {
</div> </div>
</div> </div>
{/* Основная секция */} {/* Основная секция: Подписки */}
{activeTab === 'subscriptions' && (
<div className="card"> <div className="card">
<div className="card-header"> <div className="card-header">
<div className="d-flex align-items-center gap-3 flex-grow-1"> <div className="d-flex align-items-center gap-3 flex-grow-1">
@@ -927,8 +957,10 @@ function BillingManager() {
/> />
)} )}
</div> </div>
)}
{/* История платежей — компактная версия */} {/* История платежей — компактная версия */}
{activeTab === 'payments' && (
<div className="card mt-4"> <div className="card mt-4">
<div className="card-header"> <div className="card-header">
<h3 className="card-title d-flex align-items-center gap-2"> <h3 className="card-title d-flex align-items-center gap-2">