From 16134f858d4c1d4fe214cd281c6db5c168b5a781 Mon Sep 17 00:00:00 2001 From: alorig <220087330+alorig@users.noreply.github.com> Date: Fri, 5 Dec 2025 13:22:19 +0500 Subject: [PATCH] Update AccountBillingPage.tsx --- .../src/pages/account/AccountBillingPage.tsx | 230 +++++++++++++++++- 1 file changed, 218 insertions(+), 12 deletions(-) diff --git a/frontend/src/pages/account/AccountBillingPage.tsx b/frontend/src/pages/account/AccountBillingPage.tsx index 89605644..233050a4 100644 --- a/frontend/src/pages/account/AccountBillingPage.tsx +++ b/frontend/src/pages/account/AccountBillingPage.tsx @@ -4,7 +4,7 @@ */ import { useState, useEffect } from 'react'; -import { Link } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import { CreditCard, Download, @@ -21,21 +21,29 @@ import { getInvoices, getPayments, getCreditBalance, + getCreditPackages, + getAvailablePaymentMethods, downloadInvoicePDF, type Invoice, type Payment, type CreditBalance, + type CreditPackage, + type PaymentMethod, } from '../../services/billing.api'; import { Card } from '../../components/ui/card'; import BillingRecentTransactions from '../../components/billing/BillingRecentTransactions'; +import PricingTable, { type PricingPlan } from '../../components/ui/pricing-table/PricingTable'; -type TabType = 'overview' | 'invoices' | 'payments'; +type TabType = 'overview' | 'plans' | 'invoices' | 'payments' | 'methods'; export default function AccountBillingPage() { + const navigate = useNavigate(); const [activeTab, setActiveTab] = useState('overview'); const [creditBalance, setCreditBalance] = useState(null); const [invoices, setInvoices] = useState([]); const [payments, setPayments] = useState([]); + const [creditPackages, setCreditPackages] = useState([]); + const [paymentMethods, setPaymentMethods] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); @@ -46,15 +54,19 @@ export default function AccountBillingPage() { const loadData = async () => { try { setLoading(true); - const [balanceRes, invoicesRes, paymentsRes] = await Promise.all([ + const [balanceRes, invoicesRes, paymentsRes, packagesRes, methodsRes] = await Promise.all([ getCreditBalance(), getInvoices(), getPayments(), + getCreditPackages(), + getAvailablePaymentMethods(), ]); setCreditBalance(balanceRes); setInvoices(invoicesRes.results); setPayments(paymentsRes.results); + setCreditPackages(packagesRes.results || []); + setPaymentMethods(methodsRes.results || []); } catch (err: any) { setError(err.message || 'Failed to load billing data'); console.error('Billing data load error:', err); @@ -82,11 +94,16 @@ export default function AccountBillingPage() { const getStatusBadge = (status: string) => { const styles: Record = { paid: { bg: 'bg-green-100', text: 'text-green-800', icon: CheckCircle }, - pending: { bg: 'bg-yellow-100', text: 'text-yellow-800', icon: Clock }, - failed: { bg: 'bg-red-100', text: 'text-red-800', icon: XCircle }, - void: { bg: 'bg-gray-100', text: 'text-gray-800', icon: XCircle }, + succeeded: { bg: 'bg-green-100', text: 'text-green-800', icon: CheckCircle }, completed: { bg: 'bg-green-100', text: 'text-green-800', icon: CheckCircle }, + pending: { bg: 'bg-yellow-100', text: 'text-yellow-800', icon: Clock }, pending_approval: { bg: 'bg-blue-100', text: 'text-blue-800', icon: Clock }, + processing: { bg: 'bg-blue-100', text: 'text-blue-800', icon: Clock }, + failed: { bg: 'bg-red-100', text: 'text-red-800', icon: XCircle }, + refunded: { bg: 'bg-gray-100', text: 'text-gray-800', icon: XCircle }, + cancelled: { bg: 'bg-gray-100', text: 'text-gray-800', icon: XCircle }, + void: { bg: 'bg-gray-100', text: 'text-gray-800', icon: XCircle }, + uncollectible: { bg: 'bg-gray-100', text: 'text-gray-800', icon: XCircle }, }; const style = styles[status] || styles.pending; @@ -114,11 +131,6 @@ export default function AccountBillingPage() {

Plans & Billing

- {/* Recent Transactions (moved from Credits & Billing overview) */} -
- -
-

Manage your subscription, credits, and billing

{[ { id: 'overview', label: 'Overview' }, + { id: 'plans', label: 'Plans & Credits' }, { id: 'invoices', label: 'Invoices' }, { id: 'payments', label: 'Payments' }, + { id: 'methods', label: 'Payment Methods' }, ].map((tab) => ( +
+ {/* Quick Actions */} @@ -239,6 +276,96 @@ export default function AccountBillingPage() { + + {/* Recent Transactions */} + +
+

Recent Transactions

+ + View usage details + +
+ +
+ + )} + + {/* Plans Tab */} + {activeTab === 'plans' && ( +
+
+ +
+
+

Choose a plan

+

Pick the package that fits your team.

+
+ +
+ {creditPackages.length === 0 ? ( +
+ + No packages available yet. Please check back soon. +
+ ) : ( + { + const plan: PricingPlan = { + id: pkg.id, + name: pkg.name, + price: Number(pkg.price), + period: '/one-time', + description: pkg.description, + features: [ + `${pkg.credits.toLocaleString()} credits`, + pkg.discount_percentage > 0 ? `${pkg.discount_percentage}% discount applied` : 'Standard pricing', + 'Manual & online payments supported', + ], + highlighted: pkg.is_featured, + buttonText: 'Select', + }; + return plan; + })} + onPlanSelect={() => navigate('/account/credits/purchase')} + /> + )} +
+ + +

Current plan

+
+
+
Plan
+
+ {creditBalance?.plan_credits_per_month ? 'Active Plan' : 'Pay as you go'} +
+
+
+
Monthly allocation
+
+ {creditBalance?.plan_credits_per_month?.toLocaleString() || '—'} +
+
+
+
+ Remaining this month:{' '} + + {creditBalance?.credits_remaining?.toLocaleString() ?? '—'} credits + +
+
+ + Buy more credits + +
+
+
)} @@ -370,6 +497,85 @@ export default function AccountBillingPage() { )} + + {/* Payment Methods Tab */} + {activeTab === 'methods' && ( +
+ +
+
+

Available payment methods

+

Use these options when purchasing credits.

+
+ + Go to purchase + +
+ + {paymentMethods.length === 0 ? ( +
+ + No payment methods available yet. +
+ ) : ( +
+ {paymentMethods.map((method) => ( +
+
+
+
{method.type}
+
{method.display_name || method.name}
+
+ + {method.is_enabled ? 'Enabled' : 'Disabled'} + +
+ {method.instructions && ( +

{method.instructions}

+ )} + {method.bank_details && ( +
+
+ Bank + {method.bank_details.bank_name} +
+
+ Account + {method.bank_details.account_number} +
+ {method.bank_details.routing_number && ( +
+ Routing + {method.bank_details.routing_number} +
+ )} +
+ )} + {method.wallet_details && ( +
+
+ Wallet + {method.wallet_details.wallet_type} +
+
+ ID + {method.wallet_details.wallet_id} +
+
+ )} +
+ ))} +
+ )} +
+
+ )} );