diff --git a/src/App.test.tsx b/src/App.test.tsx index ec0196a..9a06f7f 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -148,6 +148,6 @@ describe('Supplier Portal Onboarding & Active Dashboard Tests', () => { fireEvent.click(walletTabBtn) expect(screen.getByText(/Available for Payout/i)).toBeInTheDocument() - expect(screen.getByText(/Recent Transactions/i)).toBeInTheDocument() + expect(screen.getByText(/Transaction History/i)).toBeInTheDocument() }) }) diff --git a/src/components/dashboard/tabs/OrdersTab.tsx b/src/components/dashboard/tabs/OrdersTab.tsx index 7655860..b4c9211 100644 --- a/src/components/dashboard/tabs/OrdersTab.tsx +++ b/src/components/dashboard/tabs/OrdersTab.tsx @@ -1,11 +1,58 @@ -import React from 'react'; +import React, { useState } from 'react'; +import { useSeller } from '../../../context/SellerContext'; + +type TabFilter = 'All Orders' | 'Pending' | 'Shipped' | 'Completed'; + +const TAB_STATUSES: Record = { + 'All Orders': [], + 'Pending': ['Pending Acceptance'], + 'Shipped': ['Ready to Ship', 'Shipped'], + 'Completed': ['Delivered', 'Cancelled', 'Rejected'], +}; + +const STATUS_TAG: Record = { + 'Pending Acceptance': 'is-warning is-light', + 'Ready to Ship': 'is-primary is-light', + 'Shipped': 'is-info is-light', + 'Delivered': 'is-success is-light', + 'Cancelled': 'is-danger is-light', + 'Rejected': 'is-danger is-light', +}; export default function OrdersTab() { + const { orders, handleAcceptOrder, handleRejectOrder, setSelectedOrderDetail } = useSeller(); + const [activeTab, setActiveTab] = useState('All Orders'); + + const filteredOrders = TAB_STATUSES[activeTab].length === 0 + ? orders + : orders.filter((o: any) => TAB_STATUSES[activeTab].includes(o.status)); + + const formatDate = (dateStr: string) => { + const d = new Date(dateStr); + if (isNaN(d.getTime())) return dateStr; + return d.toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric' }); + }; + + const handleExportCsv = () => { + const header = 'Order ID,Date,Customer,Item,Qty,Status,Total\n'; + const rows = orders.map((o: any) => + `${o.id},${o.date},${o.customer},${o.item},${o.quantity},${o.status},${o.total}` + ).join('\n'); + const blob = new Blob([header + rows], { type: 'text/csv;charset=utf-8;' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.setAttribute('href', url); + link.setAttribute('download', 'orders_export.csv'); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + return (

Orders

- @@ -14,42 +61,76 @@ export default function OrdersTab() {
- - - - - - - - - - - - - {[ - { id: '#1045', date: 'Oct 24, 2023', customer: 'Jane Doe', status: 'Processing', type: 'info', total: '$120.00' }, - { id: '#1044', date: 'Oct 22, 2023', customer: 'Alex Johnson', status: 'Shipped', type: 'warning', total: '$45.50' }, - { id: '#1043', date: 'Oct 20, 2023', customer: 'Sarah Williams', status: 'Completed', type: 'success', total: '$210.00' } - ].map(order => ( - - - - - - - + + {filteredOrders.length === 0 ? ( +
+ inventory_2 +

No orders found in this category.

+
+ ) : ( +
Order IDDateCustomerStatusTotalAction
{order.id}{order.date}{order.customer}{order.status}{order.total} - -
+ + + + + + + + + - ))} - -
Order IDDateCustomerItemStatusTotalAction
+ + + {filteredOrders.map((order: any) => ( + + #{order.id} + {formatDate(order.date)} + {order.customer || '—'} + {order.item || '—'} + + + {order.status} + + + ₹{Number(order.total).toFixed(2)} + +
+ + {order.status === 'Pending Acceptance' && ( + <> + + + + )} +
+ + + ))} + + + )}
); diff --git a/src/components/dashboard/tabs/PaymentsTab.tsx b/src/components/dashboard/tabs/PaymentsTab.tsx index aaf99d2..f3c4822 100644 --- a/src/components/dashboard/tabs/PaymentsTab.tsx +++ b/src/components/dashboard/tabs/PaymentsTab.tsx @@ -1,50 +1,146 @@ -import React from 'react'; +import React, { useState } from 'react'; +import { useSeller } from '../../../context/SellerContext'; export default function PaymentsTab() { + const { wallet, withdrawAmount, setWithdrawAmount, handleWithdrawRequest } = useSeller(); + + const outstanding = Number(wallet.outstanding || 0); + const withdrawn = Number(wallet.withdrawn || 0); + const transactions = wallet.transactions || wallet.history || []; + + // Pending = orders delivered but not yet in wallet (approximated as 0 unless backend provides it) + const pendingClearance = Number(wallet.pending_clearance || 0); + + const [showWithdrawModal, setShowWithdrawModal] = useState(false); + + const formatDate = (dateStr: string) => { + const d = new Date(dateStr); + if (isNaN(d.getTime())) return dateStr; + return d.toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric' }); + }; + + const handleWithdraw = async () => { + await handleWithdrawRequest(); + setShowWithdrawModal(false); + setWithdrawAmount(''); + }; + return (
-

Payments & Earnings

- +

+ Payments & Earnings +

+

Available for Payout

-

$1,240.00

- +

+ ₹{outstanding.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} +

+
-

Pending Clearance

-

$320.00

+

Total Withdrawn

+

+ ₹{withdrawn.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} +

+ {pendingClearance > 0 && ( + <> +

Pending Clearance

+

+ ₹{pendingClearance.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} +

+ + )}

Funds will be available in 3-5 business days after order delivery.

- + + {/* Withdraw Modal */} + {showWithdrawModal && ( +
+
setShowWithdrawModal(false)} /> +
+
+

Withdraw Funds

+
+
+

+ Available: ₹{outstanding.toLocaleString('en-IN', { minimumFractionDigits: 2 })} +

+
+ +
+ setWithdrawAmount(e.target.value)} + /> +
+
+
+
+ + +
+
+
+ )} +
-

Recent Transactions

- - - - - - - - - - - - - - - - - - - - -
DateDescriptionAmount
Oct 20, 2023Payout to Bank Account (...1234)-$500.00
Oct 19, 2023Order #1042 Revenue+$85.00
+

Transaction History

+ {transactions.length === 0 ? ( +
+ receipt_long +

No transactions yet.

+
+ ) : ( + + + + + + + + + + + {transactions.map((tx: any) => { + const amount = Number(tx.amount || 0); + const isDebit = tx.type === 'withdrawal' || amount < 0; + return ( + + + + + + + ); + })} + +
DateDescriptionAmountStatus
{formatDate(tx.date)}{tx.description || (isDebit ? 'Payout Withdrawal' : 'Order Revenue')} + {isDebit ? '-' : '+'}₹{Math.abs(amount).toFixed(2)} + + + {tx.status || 'Pending'} + +
+ )}
);