/**
* Sales Analytics Dashboard
* Complete sales dashboard with revenue KPIs, product charts, and customer tables
*/
import React, { useState, useEffect, useContext } from 'react';
import {
Card,
Grid,
Title,
Text,
Metric,
BadgeDelta,
AreaChart,
BarChart,
DonutChart,
Table,
TableHead,
TableRow,
TableHeaderCell,
TableBody,
TableCell,
DateRangePicker,
Select,
SelectItem,
MultiSelect,
MultiSelectItem
} from '@tremor/react';
// Dashboard Context for Global Filters
const DashboardContext = React.createContext({
filters: {
dateRange: { start: new Date(), end: new Date() },
regions: [],
products: [],
salesReps: []
},
setFilters: () => {},
refreshInterval: 30000
});
// Main Sales Dashboard Component
export function SalesDashboard() {
const [filters, setFilters] = useState({
dateRange: {
start: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
end: new Date()
},
regions: [],
products: [],
salesReps: []
});
const [dashboardData, setDashboardData] = useState(null);
const [loading, setLoading] = useState(true);
// Fetch dashboard data based on filters
useEffect(() => {
fetchDashboardData(filters).then(data => {
setDashboardData(data);
setLoading(false);
});
}, [filters]);
if (loading) {
return ;
}
return (
{/* Dashboard Header */}
Sales Analytics Dashboard
Track revenue, products, and customer metrics
{/* Global Filters */}
setFilters({ ...filters, dateRange: value })}
className="max-w-xs"
/>
setFilters({ ...filters, regions: value })}
>
North
South
East
West
setFilters({ ...filters, products: value })}
>
Product A
Product B
Product C
{/* KPI Cards */}
{/* Charts Row */}
{/* Sales by Region and Top Products */}
{/* Recent Transactions Table */}
Recent Transactions
);
}
// KPI Components
function RevenueKPI({ data }) {
return (
Total Revenue
${data.value.toLocaleString()}
0 ? 'increase' : 'decrease'}>
{data.trend > 0 ? '+' : ''}{data.trend}%
vs last period
);
}
function OrdersKPI({ data }) {
return (
Total Orders
{data.value.toLocaleString()}
0 ? 'increase' : 'decrease'}>
{data.trend > 0 ? '+' : ''}{data.trend}%
vs last period
);
}
function CustomersKPI({ data }) {
return (
New Customers
{data.value.toLocaleString()}
0 ? 'increase' : 'decrease'}>
{data.trend > 0 ? '+' : ''}{data.trend}%
vs last period
);
}
function ConversionKPI({ data }) {
return (
Conversion Rate
{data.value}%
0 ? 'increase' : 'decrease'}>
{data.trend > 0 ? '+' : ''}{data.trend} pp
vs last period
);
}
// Chart Components
function RevenueChart({ data }) {
const { filters } = useContext(DashboardContext);
return (
Revenue Trend
Daily revenue over selected period
`$${(value / 1000).toFixed(1)}k`}
showLegend
showGridLines
showAnimation
/>
);
}
function ProductPerformance({ data }) {
return (
Product Performance
Revenue by product category
`$${(value / 1000).toFixed(1)}k`}
showLegend
stack={false}
/>
);
}
function RegionalSales({ data }) {
return (
Sales by Region
`$${(value / 1000).toFixed(0)}k`}
colors={["blue", "cyan", "indigo", "violet"]}
showLabel
showAnimation
/>
{data.map((item) => (
{item.region}
${(item.sales / 1000).toFixed(0)}k
))}
);
}
function TopProducts({ data }) {
return (
Top Products
Product
Revenue
Growth
{data.slice(0, 5).map((item) => (
{item.name}
${(item.revenue / 1000).toFixed(1)}k
0 ? 'increase' : 'decrease'}>
{item.growth}%
))}
);
}
function SalesTeamPerformance({ data }) {
return (
Sales Team Performance
{data.slice(0, 5).map((rep) => (
{rep.name}
${(rep.sales / 1000).toFixed(0)}k
{((rep.sales / rep.target) * 100).toFixed(0)}% of target
))}
);
}
// Transactions Table
function TransactionsTable({ data }) {
const [page, setPage] = useState(0);
const pageSize = 10;
const paginatedData = data.slice(page * pageSize, (page + 1) * pageSize);
return (
<>
Transaction ID
Date
Customer
Product
Amount
Status
{paginatedData.map((transaction) => (
{transaction.id}
{new Date(transaction.date).toLocaleDateString()}
{transaction.customer}
{transaction.product}
${transaction.amount.toLocaleString()}
{transaction.status}
))}
{/* Pagination */}
Showing {page * pageSize + 1} to {Math.min((page + 1) * pageSize, data.length)} of {data.length}
>
);
}
// Loading Skeleton
function DashboardSkeleton() {
return (
{[1, 2, 3, 4].map((i) => (
))}
);
}
// Sparkline Component
function Sparkline({ data, className = '' }) {
const max = Math.max(...data);
const min = Math.min(...data);
const range = max - min || 1;
const points = data.map((value, index) => {
const x = (index / (data.length - 1)) * 100;
const y = 100 - ((value - min) / range) * 100;
return `${x},${y}`;
}).join(' ');
return (
);
}
// Badge Component
function Badge({ children, color = 'gray' }) {
const colors = {
green: 'bg-green-100 text-green-800',
yellow: 'bg-yellow-100 text-yellow-800',
red: 'bg-red-100 text-red-800',
gray: 'bg-gray-100 text-gray-800'
};
return (
{children}
);
}
// Progress Bar Component
function ProgressBar({ value, color = 'blue', className = '' }) {
return (
);
}
// Mock data fetching function
async function fetchDashboardData(filters) {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1000));
return {
revenue: {
value: 1245832,
trend: 15.3,
sparkline: [100, 120, 115, 140, 155, 145, 160, 180, 175, 190, 210, 205]
},
orders: {
value: 3421,
trend: 8.7
},
customers: {
value: 892,
trend: -2.3
},
conversion: {
value: 3.8,
trend: 0.5
},
revenueHistory: generateRevenueHistory(),
products: generateProductData(),
regions: generateRegionalData(),
topProducts: generateTopProducts(),
salesTeam: generateSalesTeamData(),
transactions: generateTransactions()
};
}
// Data generation helpers
function generateRevenueHistory() {
const data = [];
const now = new Date();
for (let i = 30; i >= 0; i--) {
const date = new Date(now);
date.setDate(date.getDate() - i);
data.push({
date: date.toISOString().split('T')[0],
revenue: Math.floor(Math.random() * 50000) + 30000,
target: 40000
});
}
return data;
}
function generateProductData() {
return [
{ product: 'Product A', revenue: 125000, units: 1250 },
{ product: 'Product B', revenue: 98000, units: 890 },
{ product: 'Product C', revenue: 87000, units: 1100 },
{ product: 'Product D', revenue: 65000, units: 450 }
];
}
function generateRegionalData() {
return [
{ region: 'North', sales: 425000 },
{ region: 'South', sales: 380000 },
{ region: 'East', sales: 290000 },
{ region: 'West', sales: 150832 }
];
}
function generateTopProducts() {
return [
{ id: 1, name: 'Premium Widget', revenue: 234000, growth: 23.5 },
{ id: 2, name: 'Standard Widget', revenue: 189000, growth: 15.2 },
{ id: 3, name: 'Basic Widget', revenue: 145000, growth: 8.7 },
{ id: 4, name: 'Deluxe Widget', revenue: 98000, growth: -5.3 },
{ id: 5, name: 'Compact Widget', revenue: 87000, growth: 12.1 }
];
}
function generateSalesTeamData() {
return [
{ id: 1, name: 'John Smith', sales: 145000, target: 150000 },
{ id: 2, name: 'Jane Doe', sales: 132000, target: 140000 },
{ id: 3, name: 'Mike Johnson', sales: 118000, target: 130000 },
{ id: 4, name: 'Sarah Williams', sales: 105000, target: 120000 },
{ id: 5, name: 'Tom Brown', sales: 95000, target: 110000 }
];
}
function generateTransactions() {
const transactions = [];
const products = ['Widget A', 'Widget B', 'Widget C', 'Widget D'];
const customers = ['Acme Corp', 'GlobalTech', 'MegaCorp', 'TechStart', 'Enterprise Inc'];
const statuses = ['completed', 'pending', 'completed', 'completed'];
for (let i = 0; i < 50; i++) {
transactions.push({
id: `TRX-${1000 + i}`,
date: new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000),
customer: customers[Math.floor(Math.random() * customers.length)],
product: products[Math.floor(Math.random() * products.length)],
amount: Math.floor(Math.random() * 5000) + 500,
status: statuses[Math.floor(Math.random() * statuses.length)]
});
}
return transactions.sort((a, b) => b.date - a.date);
}
export default SalesDashboard;