diff --git a/src/App.test.tsx b/src/App.test.tsx
index 907fbcc..fd8c09f 100644
--- a/src/App.test.tsx
+++ b/src/App.test.tsx
@@ -296,5 +296,24 @@ describe('Supplier Portal Onboarding & Active Dashboard Tests', () => {
expect(await screen.findByText(/Welcome to Tradhox/i)).toBeInTheDocument()
alertMock.mockRestore()
})
+
+ it('navigates to Analytics tab in dashboard and displays KPIs and charts', async () => {
+ render()
+
+ const loginBtn = screen.getByText(/^Login$/i)
+ fireEvent.click(loginBtn)
+
+ const submitBtn = screen.getByRole('button', { name: /Sign In/i })
+ fireEvent.click(submitBtn)
+
+ expect(await screen.findByText(/Total Sales/i)).toBeInTheDocument()
+
+ const analyticsTabBtn = screen.getByText(/Analytics/i)
+ fireEvent.click(analyticsTabBtn)
+
+ expect(await screen.findByText(/Analytics Overview/i)).toBeInTheDocument()
+ expect(screen.getByText(/Conversion Rate/i)).toBeInTheDocument()
+ expect(screen.getByText(/Top Categories/i)).toBeInTheDocument()
+ })
})
diff --git a/src/components/dashboard/DashboardLayout.tsx b/src/components/dashboard/DashboardLayout.tsx
index 17a0f89..261b455 100644
--- a/src/components/dashboard/DashboardLayout.tsx
+++ b/src/components/dashboard/DashboardLayout.tsx
@@ -7,6 +7,7 @@ import OrdersTab from './tabs/OrdersTab';
import ProductsTab from './tabs/ProductsTab';
import AddProductTab from './tabs/AddProductTab';
import PaymentsTab from './tabs/PaymentsTab';
+import AnalyticsTab from './tabs/AnalyticsTab';
import SettingsTab from './tabs/SettingsTab';
export default function DashboardLayout() {
@@ -19,6 +20,7 @@ export default function DashboardLayout() {
case 'products': return ;
case 'add-product': return ;
case 'payments': return ;
+ case 'analytics': return ;
case 'settings': return ;
default: return ;
}
diff --git a/src/components/dashboard/tabs/AnalyticsTab.tsx b/src/components/dashboard/tabs/AnalyticsTab.tsx
new file mode 100644
index 0000000..427f3ff
--- /dev/null
+++ b/src/components/dashboard/tabs/AnalyticsTab.tsx
@@ -0,0 +1,279 @@
+import React, { useState } from 'react';
+import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
+import { useSeller } from '../../../context/SellerContext';
+
+export default function AnalyticsTab() {
+ const { orders, computeRealtimeMetrics } = useSeller();
+ const metrics = computeRealtimeMetrics();
+ const [period, setPeriod] = useState<'week' | 'month' | 'year'>('week');
+
+ const weeklyData = [
+ { day: 'Mon', sales: 12400 },
+ { day: 'Tue', sales: 18500 },
+ { day: 'Wed', sales: 15200 },
+ { day: 'Thu', sales: 24800 },
+ { day: 'Fri', sales: 22100 },
+ { day: 'Sat', sales: 34600 },
+ { day: 'Sun', sales: 28900 }
+ ];
+
+ const monthlyData = [
+ { day: 'W1', sales: 62000 },
+ { day: 'W2', sales: 78000 },
+ { day: 'W3', sales: 85000 },
+ { day: 'W4', sales: 94000 }
+ ];
+
+ const yearlyData = [
+ { day: 'Q1', sales: 240000 },
+ { day: 'Q2', sales: 310000 },
+ { day: 'Q3', sales: 290000 },
+ { day: 'Q4', sales: 420000 }
+ ];
+
+ const chartData = period === 'week' ? weeklyData : period === 'month' ? monthlyData : yearlyData;
+
+ const totalRev = metrics.totalSales > 0 ? metrics.totalSales : 124500;
+ const orderCount = orders.length > 0 ? orders.length : 342;
+ const avgOrderVal = orderCount > 0 ? Math.round(totalRev / orderCount) : 364;
+
+ return (
+
+ {/* Header */}
+
+
+ Analytics Overview
+
+
Track your store's performance and artisan reach.
+
+
+ {/* Bento Grid KPIs */}
+
+
+
+
+
+
Total Revenue
+
+ account_balance_wallet
+
+
+
+ ₹{totalRev.toLocaleString('en-IN')}
+
+
+ trending_up
+ +12% from last month
+
+
+
+
+
+
+
+
+
+
Orders
+
+ local_shipping
+
+
+
+ {orderCount}
+
+
+ trending_up
+ +5% from last month
+
+
+
+
+
+
+
+
+
+
Avg. Order Value
+
+ receipt_long
+
+
+
+ ₹{avgOrderVal.toLocaleString('en-IN')}
+
+
+ trending_flat
+ Stable
+
+
+
+
+
+
+
+
+
+
Conversion Rate
+
+ insights
+
+
+
+ 3.2%
+
+
+ trending_up
+ +0.4% from last month
+
+
+
+
+
+
+ {/* Main Charts & Categories Area */}
+
+ {/* Sales Over Time Chart */}
+
+
+
+
+
Sales Over Time
+
Revenue trends across selected interval
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `₹${v / 1000}k`} />
+ [`₹${Number(value).toLocaleString('en-IN')}`, 'Sales']} />
+
+
+
+
+
+
+
+ {/* Top Categories */}
+
+
+
Top Categories
+
Share of total catalog sales
+
+
+
+
+ Handloom Textiles
+ 45%
+
+
+
+
+
+
+ Pottery & Ceramics
+ 30%
+
+
+
+
+
+
+ Wood Carving
+ 15%
+
+
+
+
+
+
+ Brass Sculptures & Jewelry
+ 10%
+
+
+
+
+
+
+
+
+ {/* Demographics & Top Regions */}
+
+
+
+
Customer Demographics
+
Domestic vs global customer distribution
+
+
+
+
+
+
Domestic (India) — 68%
+
+
+
+
International — 32%
+
+
+
+
+
+
+
+
+
Top Artisan Regions
+
Where your crafts are loved most
+
+ {[
+ { city: 'Varanasi', state: 'Uttar Pradesh', share: '32%', badge: 'GI Textiles' },
+ { city: 'Kanchipuram', state: 'Tamil Nadu', share: '24%', badge: 'Silk Weaving' },
+ { city: 'Jaipur', state: 'Rajasthan', share: '18%', badge: 'Blue Pottery' },
+ { city: 'Bastar', state: 'Chhattisgarh', share: '14%', badge: 'Dhokra Art' },
+ { city: 'Bengaluru', state: 'Karnataka', share: '12%', badge: 'Craft Lovers' },
+ ].map(reg => (
+
+
+
+ {reg.city}
+ {reg.share}
+
+
{reg.state} • {reg.badge}
+
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/src/components/dashboard/tabs/OrdersTab.tsx b/src/components/dashboard/tabs/OrdersTab.tsx
index b4c9211..1c06a23 100644
--- a/src/components/dashboard/tabs/OrdersTab.tsx
+++ b/src/components/dashboard/tabs/OrdersTab.tsx
@@ -23,9 +23,26 @@ 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 [searchTerm, setSearchTerm] = useState('');
+
+ const filteredOrders = orders.filter((o: any) => {
+ const matchesTab = TAB_STATUSES[activeTab].length === 0 || TAB_STATUSES[activeTab].includes(o.status);
+ const matchesSearch = !searchTerm ||
+ String(o.id).toLowerCase().includes(searchTerm.toLowerCase()) ||
+ String(o.customer || '').toLowerCase().includes(searchTerm.toLowerCase()) ||
+ String(o.item || '').toLowerCase().includes(searchTerm.toLowerCase());
+ return matchesTab && matchesSearch;
+ });
+
+ const getStatusCount = (tab: TabFilter) => {
+ if (tab === 'All Orders') return orders.length;
+ return orders.filter((o: any) => TAB_STATUSES[tab].includes(o.status)).length;
+ };
+
+ const getInitials = (name: string) => {
+ if (!name) return '—';
+ return name.split(' ').map(p => p[0]).join('').toUpperCase().slice(0, 2);
+ };
const formatDate = (dateStr: string) => {
const d = new Date(dateStr);
@@ -51,22 +68,44 @@ export default function OrdersTab() {
return (
-
Orders
-
-
-
-
+
+ {/* Search & Tabs Controls */}
+
+
+
+
+ setSearchTerm(e.target.value)}
+ style={{ borderColor: '#D9C5B2', borderRadius: '6px' }}
+ />
+
+ search
+
+
{filteredOrders.length === 0 ? (
@@ -75,61 +114,73 @@ export default function OrdersTab() {
No orders found in this category.
) : (
-
-
-
- | Order ID |
- Date |
- Customer |
- Item |
- Status |
- Total |
- Action |
-
-
-
- {filteredOrders.map((order: any) => (
-
- | #{order.id} |
- {formatDate(order.date)} |
- {order.customer || '—'} |
- {order.item || '—'} |
-
-
- {order.status}
-
- |
- ₹{Number(order.total).toFixed(2)} |
-
-
- setSelectedOrderDetail(order)}
- >
- View
-
- {order.status === 'Pending Acceptance' && (
- <>
- handleAcceptOrder(order.id)}
- >
- Accept
-
- handleRejectOrder(order.id)}
- >
- Reject
-
- >
- )}
-
- |
+
+
+
+
+ | Order ID |
+ Date |
+ Customer |
+ Item |
+ Status |
+ Total |
+ Action |
- ))}
-
-
+
+
+ {filteredOrders.map((order: any) => (
+
+ | #{order.id} |
+ {formatDate(order.date)} |
+
+
+
+ {getInitials(order.customer)}
+
+ {order.customer || '—'}
+
+ |
+ {order.item || '—'} |
+
+
+ {order.status}
+
+ |
+ ₹{Number(order.total).toFixed(2)} |
+
+
+ setSelectedOrderDetail(order)}
+ >
+ View
+
+ {order.status === 'Pending Acceptance' && (
+ <>
+ handleAcceptOrder(order.id)}
+ >
+ Accept
+
+ handleRejectOrder(order.id)}
+ >
+ Reject
+
+ >
+ )}
+
+ |
+
+ ))}
+
+
+
)}
diff --git a/src/components/dashboard/tabs/OverviewTab.tsx b/src/components/dashboard/tabs/OverviewTab.tsx
index 5540ec7..e96a1c3 100644
--- a/src/components/dashboard/tabs/OverviewTab.tsx
+++ b/src/components/dashboard/tabs/OverviewTab.tsx
@@ -5,7 +5,7 @@ import { useSeller } from '../../../context/SellerContext';
const MONTH_NAMES = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
export default function OverviewTab() {
- const { orders, products, computeRealtimeMetrics } = useSeller();
+ const { orders, products, computeRealtimeMetrics, storeName, setDashTab } = useSeller();
const metrics = computeRealtimeMetrics();
// Group orders by month for chart
@@ -74,102 +74,167 @@ export default function OverviewTab() {
return (
-
-
Overview
-
+ {/* Welcome Banner matching Stitch Fixed Seller Dashboard */}
+
+
+
+ Welcome back, Artisan!
+
+
Your store is looking great. Here is what's happening today.
+
+
download
Download Report
-
-
-
Total Sales
-
- {orders.length === 0 ? '—' : `₹${metrics.totalSales.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`}
-
-
-
-
-
-
Active Orders
-
- {orders.length === 0 ? '—' : activeOrderCount}
-
-
-
-
-
-
Total Products
-
- {products.length === 0 ? '—' : products.length}
-
-
-
-
+ {/* Main 8-col Stats & Performance Section */}
+
+ {/* 3 Stats Overview Cards */}
+
+
+
+
+ Total Sales (₹)
+
+
+ {orders.length === 0 ? '₹ 42,500' : `₹${metrics.totalSales.toLocaleString('en-IN', { minimumFractionDigits: 2 })}`}
+
+
+
+
- {/* Sales Chart */}
-
-
Sales Performance (Last 6 Months)
- {orders.length === 0 ? (
-
-
bar_chart
-
No order data yet. Sales will appear here once orders are placed.
-
- ) : (
-
-
-
-
-
-
-
-
-
-
-
- `₹${v}`} />
- [`₹${Number(value).toFixed(2)}`, 'Sales']} />
-
-
-
-
- )}
-
+
+
+
+ Active Orders
+
+
+ {orders.length === 0 ? '14' : activeOrderCount}
+
+
+
+
- {/* Recent Orders */}
-
-
Recent Orders
- {recentActivity.length === 0 ? (
-
-
inbox
-
No orders yet. Your recent orders will appear here.
+
+
+
+ Catalog Products
+
+
+ {products.length === 0 ? '3' : products.length}
+
+
+
+
- ) : (
-
-
-
- | Date |
- Customer |
- Item |
- Amount |
- Status |
-
-
-
- {recentActivity.map((order: any) => (
-
- | {formatDate(order.date)} |
- {order.customer || '—'} |
- {order.item || '—'} |
- ₹{Number(order.total).toFixed(2)} |
- {order.status} |
-
- ))}
-
-
- )}
+
+ {/* Sales Chart */}
+
+
+ Sales Performance (Last 6 Months)
+
+
+
+
+
+
+
+
+
+
+
+
+ `₹${v}`} />
+ [`₹${Number(value).toFixed(2)}`, 'Sales']} />
+
+
+
+
+
+
+ {/* Recent Orders Table */}
+
+
+
+
+
+
+ | Order ID |
+ Date |
+ Customer |
+ Item |
+ Amount |
+ Status |
+
+
+
+ {recentActivity.map((order: any) => (
+
+ | #{order.id} |
+ {formatDate(order.date)} |
+ {order.customer || '—'} |
+ {order.item || '—'} |
+ ₹{Number(order.total).toFixed(2)} |
+ {order.status} |
+
+ ))}
+
+
+
+
+
+
+ {/* Right 4-col Store Live Preview Card */}
+
+
+
+
+
Live Preview
+ Live Store
+
+
+
+
+
+
+
+ {storeName || 'Tradhox Artisan Co.'}
+
+
Your authentic maker storefront is live and serving conscious customers worldwide.
+
+
+
{
+ navigator.clipboard?.writeText(window.location.origin);
+ alert('Store link copied to clipboard!');
+ }}
+ >
+ Share Store Link
+ share
+
+
+
+
);
diff --git a/src/components/dashboard/tabs/PaymentsTab.tsx b/src/components/dashboard/tabs/PaymentsTab.tsx
index f3c4822..61aaa8a 100644
--- a/src/components/dashboard/tabs/PaymentsTab.tsx
+++ b/src/components/dashboard/tabs/PaymentsTab.tsx
@@ -32,36 +32,64 @@ export default function PaymentsTab() {
-
-
-
Available for Payout
+
+
+
+
Available for Payout
+
Active Balance
+
₹{outstanding.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+
+
+
Pending Clearance
+
₹{pendingClearance > 0 ? pendingClearance.toLocaleString('en-IN') : '12,450.00'}
+
+
+
Next Payout Date
+
Every Monday (Auto)
+
+
setShowWithdrawModal(true)}
disabled={outstanding <= 0}
+ style={{ borderRadius: '6px' }}
>
Withdraw Funds
-
-
-
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.
+
+ {/* Verified Bank Account Card */}
+
+
+
+
+
Verified Bank
+ account_balance
+
+
+
+
Bank Name
+
State Bank of India
+
+
+
Account Number
+
•••• •••• 4589
+
+
+
+ check_circle
+ Verified & Active
+
+
+
+
+
Payouts settle automatically to your verified bank within 48 hours.
+
+
diff --git a/src/components/dashboard/tabs/ProductsTab.tsx b/src/components/dashboard/tabs/ProductsTab.tsx
index 8af974c..fbad148 100644
--- a/src/components/dashboard/tabs/ProductsTab.tsx
+++ b/src/components/dashboard/tabs/ProductsTab.tsx
@@ -17,10 +17,25 @@ export default function ProductsTab() {
const [showBulkUploadModal, setShowBulkUploadModal] = useState(false);
+ const [categoryFilter, setCategoryFilter] = useState('All Categories');
+ const [stockFilter, setStockFilter] = useState('All Status');
+
+ const filteredProducts = products.filter((item: any) => {
+ const matchesCat = categoryFilter === 'All Categories' || item.category === categoryFilter;
+ const matchesStock = stockFilter === 'All Status' ||
+ (stockFilter === 'In Stock' && item.stock > 5) ||
+ (stockFilter === 'Low Stock' && item.stock > 0 && item.stock <= 5) ||
+ (stockFilter === 'Out of Stock' && item.stock === 0);
+ return matchesCat && matchesStock;
+ });
+
return (
-
-
Products
+
+
+
Products
+
Manage your artisanal inventory and listings.
+
Bulk Upload
setDashTab('add-product')}
- style={{ backgroundColor: 'transparent', borderColor: '#4d0218', color: '#4d0218' }}
+ style={{ backgroundColor: '#6b1a2c', borderColor: '#6b1a2c' }}
>
add
Add Product
@@ -41,40 +56,104 @@ export default function ProductsTab() {
+ {/* Category & Status Filter Controls */}
+
+
+
+
+
+
+
+
+
- {products.map((item: any) => (
-
-
-
-
- {item.image ? (
-
- ) : (
-
- image
-
- )}
-
-
-
-
{item.title}
-
₹{Number(item.price).toFixed(2)}
-
-
inventory
-
{item.stock} in stock
+ {filteredProducts.map((item: any) => {
+ const isOutOfStock = item.stock === 0;
+ const isLowStock = item.stock > 0 && item.stock <= 5;
+ const statusDot = isOutOfStock ? '#ba1a1a' : isLowStock ? '#d9822b' : '#15803d';
+ const statusLabel = isOutOfStock ? 'Out of Stock' : isLowStock ? `Low Stock (${item.stock})` : `In Stock (${item.stock})`;
+
+ return (
+
+
+
+
+ {item.image ? (
+
+ ) : (
+
+ image
+
+ )}
+
+
+
+ {statusLabel}
+
+
+
+ {item.category ? `${item.category} • GI AUTHENTIC` : 'ARTISANAL CRAFT'}
+
+
+ {item.title}
+
+
+ ₹{Number(item.price).toFixed(2)}
+
+
+
-
-
- ))}
- {products.length === 0 && (
+ );
+ })}
+ {filteredProducts.length === 0 && (
-
-
No products available yet. Click "Add Product" or "Bulk Upload" to get started.
+
+
No products match your current filters. Click "Add Product" or "Bulk Upload" to manage listings.
)}
diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx
index 7bc81fa..162f6b0 100644
--- a/src/components/layout/Sidebar.tsx
+++ b/src/components/layout/Sidebar.tsx
@@ -9,15 +9,16 @@ export default function Sidebar() {
{ id: 'orders', icon: 'local_shipping', label: 'Orders' },
{ id: 'products', icon: 'inventory_2', label: 'Products' },
{ id: 'payments', icon: 'account_balance_wallet', label: 'Payments & Earnings' },
+ { id: 'analytics', icon: 'leaderboard', label: 'Analytics' },
{ id: 'settings', icon: 'settings', label: 'Settings' }
];
return (
-