Purchase Dashboard functionality added.
This commit is contained in:
@@ -7,7 +7,9 @@ import {
|
||||
ArrowRight,
|
||||
Wallet,
|
||||
BarChart3,
|
||||
MessageSquare
|
||||
MessageSquare,
|
||||
Flame,
|
||||
TrendingUp
|
||||
} from 'lucide-react';
|
||||
import {
|
||||
AreaChart,
|
||||
@@ -114,7 +116,7 @@ const Dashboard = () => {
|
||||
);
|
||||
}
|
||||
|
||||
const { stats, storeOverview, hourlySales, insights } = data;
|
||||
const { stats, storeOverview, hourlySales, insights, trendingItems } = data;
|
||||
|
||||
const pieData = [
|
||||
{ name: 'Full Payment', value: stats.periodRevenue, color: '#8b5cf6' },
|
||||
@@ -316,11 +318,57 @@ const Dashboard = () => {
|
||||
<h4 className="text-[11px] font-black text-slate-400 uppercase tracking-widest leading-none">Total Expenses</h4>
|
||||
</div>
|
||||
<div className="text-center pb-2">
|
||||
<h2 className="text-3xl font-black text-slate-800 tracking-tighter">₹0</h2>
|
||||
<h2 className="text-3xl font-black text-slate-800 tracking-tighter">₹{stats.periodExpenses.toLocaleString()}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Trending Items Section */}
|
||||
<section>
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="p-2 bg-rose-50 text-rose-500 rounded-xl">
|
||||
<Flame size={20} />
|
||||
</div>
|
||||
<h3 className="text-sm font-black text-slate-800 tracking-tight uppercase tracking-[0.1em]">Best Selling Food</h3>
|
||||
</div>
|
||||
<div className="text-[10px] font-black text-slate-400 uppercase tracking-widest flex items-center gap-2">
|
||||
Performance Index <TrendingUp size={12} className="text-emerald-500" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{trendingItems.map((item: any, idx: number) => (
|
||||
<motion.div
|
||||
key={idx}
|
||||
whileHover={{ y: -5 }}
|
||||
className="bg-white p-5 rounded-[28px] border border-slate-100 shadow-sm hover:shadow-xl hover:border-indigo-500/20 transition-all group overflow-hidden relative cursor-default"
|
||||
>
|
||||
<div className="absolute top-4 right-4 bg-white/80 backdrop-blur-md px-2.5 py-1 rounded-lg text-[10px] font-black text-slate-900 border border-slate-100 z-10 shadow-sm">
|
||||
TOP #{idx+1}
|
||||
</div>
|
||||
<div className="w-full h-32 rounded-2xl mb-5 overflow-hidden bg-slate-50">
|
||||
<img
|
||||
src={item.imageUrl}
|
||||
alt={item.name}
|
||||
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700 opacity-90 group-hover:opacity-100"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-between items-start mb-2">
|
||||
<div>
|
||||
<h4 className="text-sm font-black text-slate-800 leading-tight mb-1 group-hover:text-indigo-600 transition-colors uppercase tracking-tight">{item.name}</h4>
|
||||
<p className="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{item.category}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between mt-4 pt-4 border-t border-slate-50">
|
||||
<div className="text-[10px] text-slate-400 font-black uppercase tracking-tight">Orders Count</div>
|
||||
<div className="text-lg font-black text-indigo-900 tracking-tighter">{item.orderCount} <span className="text-[10px] font-bold text-slate-300">Unit(s)</span></div>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Bottom Section */}
|
||||
<div className="grid grid-cols-12 gap-8 mt-4 pb-12">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import {
|
||||
ShoppingBag,
|
||||
@@ -21,14 +22,7 @@ import {
|
||||
Bar
|
||||
} from 'recharts';
|
||||
|
||||
const data = [
|
||||
{ month: 'Jan', purchases: 4500, orders: 12 },
|
||||
{ month: 'Feb', purchases: 5200, orders: 15 },
|
||||
{ month: 'Mar', purchases: 4800, orders: 14 },
|
||||
{ month: 'Apr', purchases: 6100, orders: 18 },
|
||||
{ month: 'May', purchases: 5500, orders: 16 },
|
||||
{ month: 'Jun', purchases: 6700, orders: 20 },
|
||||
];
|
||||
// Removed static data
|
||||
|
||||
const StatCard = ({ title, value, change, icon: Icon, color, delay }: any) => (
|
||||
<motion.div
|
||||
@@ -52,6 +46,43 @@ const StatCard = ({ title, value, change, icon: Icon, color, delay }: any) => (
|
||||
);
|
||||
|
||||
const VendorDashboard = () => {
|
||||
const [data, setData] = useState<any>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const response = await fetch('/api/dashboard/procurement');
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
setData(result);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching procurement data:', error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
if (isLoading || !data) {
|
||||
return (
|
||||
<div className="h-screen flex items-center justify-center bg-slate-50/50">
|
||||
<motion.div
|
||||
animate={{ scale: [1, 1.1, 1], opacity: [0.5, 1, 0.5] }}
|
||||
transition={{ repeat: Infinity, duration: 1.5 }}
|
||||
className="text-[#231651] font-black uppercase tracking-widest text-sm"
|
||||
>
|
||||
Analyzing Supply Chain...
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const { stats, trends, topVendors } = data;
|
||||
|
||||
return (
|
||||
<div className="p-8 space-y-8 animate-in fade-in duration-500">
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||
@@ -67,10 +98,10 @@ const VendorDashboard = () => {
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<StatCard title="Total Procurement" value="$28,450.00" change={12} icon={DollarSign} color="bg-blue-500" delay={0.1} />
|
||||
<StatCard title="Active Vendors" value="24" change={5} icon={Users} color="bg-emerald-500" delay={0.2} />
|
||||
<StatCard title="Pending POs" value="08" change={2} icon={Package} color="bg-amber-500" delay={0.3} />
|
||||
<StatCard title="Supply Fill Rate" value="94.2%" change={1.5} icon={TrendingUp} color="bg-violet-500" delay={0.4} />
|
||||
<StatCard title="Total Procurement" value={`₹${stats.totalProcurement.toLocaleString()}`} change={12} icon={DollarSign} color="bg-blue-500" delay={0.1} />
|
||||
<StatCard title="Active Vendors" value={stats.activeVendors} change={5} icon={Users} color="bg-emerald-500" delay={0.2} />
|
||||
<StatCard title="Pending POs" value={stats.pendingPOs.toString().padStart(2, '0')} change={2} icon={Package} color="bg-amber-500" delay={0.3} />
|
||||
<StatCard title="Supply Fill Rate" value={`${stats.fillRate}%`} change={1.5} icon={TrendingUp} color="bg-violet-500" delay={0.4} />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
@@ -87,7 +118,7 @@ const VendorDashboard = () => {
|
||||
</div>
|
||||
<div className="h-[300px] w-full">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<AreaChart data={data}>
|
||||
<AreaChart data={trends}>
|
||||
<defs>
|
||||
<linearGradient id="colorPurchases" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="5%" stopColor="#231651" stopOpacity={0.1}/>
|
||||
@@ -117,7 +148,7 @@ const VendorDashboard = () => {
|
||||
</div>
|
||||
<div className="h-[300px] w-full">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={data}>
|
||||
<BarChart data={trends}>
|
||||
<XAxis dataKey="month" axisLine={false} tickLine={false} tick={{fill: '#94a3b8', fontSize: 11, fontWeight: 700}} dy={10} />
|
||||
<YAxis axisLine={false} tickLine={false} tick={{fill: '#94a3b8', fontSize: 11, fontWeight: 700}} />
|
||||
<Tooltip />
|
||||
@@ -131,27 +162,27 @@ const VendorDashboard = () => {
|
||||
<div className="bg-white rounded-3xl border border-[#e2e8f0] shadow-sm p-6 overflow-hidden">
|
||||
<h3 className="text-lg font-bold text-[#1e293b] mb-6">Top Performing Vendors</h3>
|
||||
<div className="space-y-4">
|
||||
{[
|
||||
{ name: 'Fresh Foods Co.', orders: 45, volume: '$12,400', color: 'bg-blue-100 text-blue-600' },
|
||||
{ name: 'Dairy Plus', orders: 28, volume: '$8,200', color: 'bg-emerald-100 text-emerald-600' },
|
||||
{ name: 'Bakery World', orders: 15, volume: '$3,150', color: 'bg-amber-100 text-amber-600' },
|
||||
].map((v, i) => (
|
||||
<div key={i} className="flex items-center justify-between p-4 bg-gray-50/50 rounded-2xl hover:bg-gray-50 transition-all cursor-pointer group">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className={`w-10 h-10 rounded-xl ${v.color} flex items-center justify-center font-bold text-sm`}>
|
||||
{v.name.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-bold text-[#1e293b] group-hover:text-[#231651] transition-colors">{v.name}</p>
|
||||
<p className="text-[10px] font-bold text-[#94a3b8] uppercase tracking-wider">{v.orders} Orders this month</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="text-sm font-black text-[#1e293b]">{v.volume}</p>
|
||||
<p className="text-[10px] font-bold text-emerald-600 uppercase">Excellent Status</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{topVendors.length > 0 ? (
|
||||
topVendors.map((v: any, i: number) => (
|
||||
<div key={i} className="flex items-center justify-between p-4 bg-gray-50/50 rounded-2xl hover:bg-gray-50 transition-all cursor-pointer group">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className={`w-10 h-10 rounded-xl ${v.color || 'bg-indigo-100 text-indigo-600'} flex items-center justify-center font-bold text-sm`}>
|
||||
{v.name.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-bold text-[#1e293b] group-hover:text-[#231651] transition-colors">{v.name}</p>
|
||||
<p className="text-[10px] font-bold text-[#94a3b8] uppercase tracking-wider">{v.orders} Orders this month</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="text-sm font-black text-[#1e293b]">₹{v.volume.toLocaleString()}</p>
|
||||
<p className="text-[10px] font-bold text-emerald-600 uppercase">Excellent Status</p>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-center py-8 text-slate-400 font-medium italic">No vendor performance data available for this period.</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user