Dashboard made robust
This commit is contained in:
@@ -213,7 +213,7 @@ const ArchivedOrders: React.FC = () => {
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="text-[10px] text-slate-400 font-medium uppercase mb-0.5">Grand Total</div>
|
||||
<div className="text-lg font-black text-slate-900 leading-none">R{order.totalAmount.toFixed(2)}</div>
|
||||
<div className="text-lg font-black text-slate-900 leading-none">₹{order.totalAmount.toFixed(2)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -325,8 +325,8 @@ const ArchivedOrders: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="text-sm font-black text-slate-900">R{(item.price * item.quantity).toLocaleString()}</div>
|
||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-tighter">@ R{item.price}</div>
|
||||
<div className="text-sm font-black text-slate-900">₹{(item.price * item.quantity).toLocaleString()}</div>
|
||||
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-tighter">@ ₹{item.price}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
@@ -377,7 +377,7 @@ const ArchivedOrders: React.FC = () => {
|
||||
</div>
|
||||
<div className="text-right flex flex-col gap-1 min-w-[250px]">
|
||||
<div className="text-[10px] text-slate-500 uppercase font-black tracking-widest mb-1">Final Settlement</div>
|
||||
<div className="text-4xl font-black text-emerald-400 leading-none mb-1">R{selectedOrder.totalAmount.toLocaleString()}</div>
|
||||
<div className="text-4xl font-black text-emerald-400 leading-none mb-1">₹{selectedOrder.totalAmount.toLocaleString()}</div>
|
||||
<div className="text-[10px] text-slate-500 font-bold uppercase tracking-[0.2em]">Transaction Fully Reconciled</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -279,13 +279,13 @@ const Customers: React.FC = () => {
|
||||
<CircleDollarSign size={16} />
|
||||
</div>
|
||||
<span className="text-sm font-black text-[#231651]">
|
||||
R{user.ritzTokenBalance?.toLocaleString() || '0'}
|
||||
₹{user.ritzTokenBalance?.toLocaleString() || '0'}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4">
|
||||
<span className="text-sm font-bold text-[#231651]">
|
||||
R{user.ritzTokenBalance?.toLocaleString() || '0'}
|
||||
₹{user.ritzTokenBalance?.toLocaleString() || '0'}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-6 py-4">
|
||||
@@ -364,7 +364,7 @@ const Customers: React.FC = () => {
|
||||
RIT STUDENT
|
||||
</span>
|
||||
<span className="px-2 py-0.5 bg-indigo-50 text-indigo-600 text-[10px] font-bold rounded-lg border border-indigo-100 uppercase tracking-wider">
|
||||
R{user.ritzTokenBalance?.toLocaleString() || '0'} TOKENS
|
||||
₹{user.ritzTokenBalance?.toLocaleString() || '0'} TOKENS
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ const Dashboard = () => {
|
||||
</defs>
|
||||
<CartesianGrid strokeDasharray="3 3" vertical={false} stroke="#f1f5f9" />
|
||||
<XAxis dataKey="time" axisLine={false} tickLine={false} tick={{fill: '#94a3b8', fontSize: 10, fontWeight: 700}} />
|
||||
<YAxis axisLine={false} tickLine={false} tick={{fill: '#94a3b8', fontSize: 10, fontWeight: 700}} tickFormatter={(v) => v >= 1000 ? `R${v/1000}k` : `R${v}`} />
|
||||
<YAxis axisLine={false} tickLine={false} tick={{fill: '#94a3b8', fontSize: 10, fontWeight: 700}} tickFormatter={(v) => v >= 1000 ? `₹${v/1000}k` : `₹${v}`} />
|
||||
<Tooltip contentStyle={{ borderRadius: '12px', border: 'none', boxShadow: '0 10px 15px -3px rgb(0 0 0 / 0.1)' }} />
|
||||
<Area type="monotone" dataKey="value" stroke="#f43f5e" strokeWidth={3} fillOpacity={1} fill="url(#colorSalesMain)" />
|
||||
</AreaChart>
|
||||
@@ -262,9 +262,9 @@ const Dashboard = () => {
|
||||
</PieChart>
|
||||
</ResponsiveContainer>
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center">
|
||||
<h2 className="text-3xl font-black text-slate-800 tracking-tighter">R{(stats.periodRevenue || 0).toLocaleString()}</h2>
|
||||
<h2 className="text-3xl font-black text-slate-800 tracking-tighter">₹{(stats.periodRevenue || 0).toLocaleString()}</h2>
|
||||
<p className="text-[10px] font-black text-slate-400 uppercase tracking-widest mt-1">{timeRange === 'Today' ? 'Today' : timeRange}</p>
|
||||
<p className="text-[8px] font-bold text-slate-300 uppercase tracking-widest mt-0.5">Total: R{(stats.totalSales || 0).toLocaleString()}</p>
|
||||
<p className="text-[8px] font-bold text-slate-300 uppercase tracking-widest mt-0.5">Total: ₹{(stats.totalSales || 0).toLocaleString()}</p>
|
||||
</div>
|
||||
<div className="flex gap-6 mt-2">
|
||||
{pieData.map(item => (
|
||||
@@ -365,13 +365,17 @@ const Dashboard = () => {
|
||||
<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="w-full h-32 rounded-2xl mb-5 overflow-hidden bg-slate-50 flex items-center justify-center">
|
||||
{item.imageUrl ? (
|
||||
<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 className="w-full h-full bg-slate-50/50" />
|
||||
)}
|
||||
</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>
|
||||
@@ -401,7 +405,9 @@ const Dashboard = () => {
|
||||
key={idx}
|
||||
className={`p-5 rounded-2xl border transition-all cursor-default ${insight.color || 'border-slate-100 bg-slate-50/50 hover:bg-white hover:shadow-md hover:border-transparent'}`}
|
||||
>
|
||||
<p className="text-[11px] font-black text-slate-600 leading-relaxed uppercase tracking-tight">{insight.text || insight}</p>
|
||||
<p className="text-[11px] font-black text-slate-600 leading-relaxed uppercase tracking-tight">
|
||||
{(insight.text || insight).replace(/R(?=[0-9])/g, '₹')}
|
||||
</p>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
@@ -429,7 +435,7 @@ const Dashboard = () => {
|
||||
<div className="grid grid-cols-4 gap-4">
|
||||
<div className="space-y-1.5">
|
||||
<p className="text-[9px] font-black text-rose-500 uppercase tracking-widest opacity-60">Gross Sale</p>
|
||||
<p className="text-lg font-black text-slate-800 tracking-tighter">R{Number(store.sale).toLocaleString()}</p>
|
||||
<p className="text-lg font-black text-slate-800 tracking-tighter">₹{Number(store.sale).toLocaleString()}</p>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<p className="text-[9px] font-black text-blue-500 uppercase tracking-widest opacity-60">Volume</p>
|
||||
|
||||
@@ -465,7 +465,7 @@ const Orders: React.FC = () => {
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="text-[10px] text-slate-400 font-medium uppercase mb-0.5">Grand Total</div>
|
||||
<div className="text-lg font-black text-slate-900 leading-none">R{order.totalAmount.toFixed(2)}</div>
|
||||
<div className="text-lg font-black text-slate-900 leading-none">₹{order.totalAmount.toFixed(2)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -628,9 +628,9 @@ const Orders: React.FC = () => {
|
||||
</div>
|
||||
<div className="flex items-center gap-8">
|
||||
<div className="text-right">
|
||||
<div className="text-sm font-black text-slate-900">R{(item.price * item.quantity).toLocaleString()}</div>
|
||||
<div className="text-sm font-black text-slate-900">₹{(item.price * item.quantity).toLocaleString()}</div>
|
||||
<div className="text-[10px] font-bold text-slate-400">
|
||||
{item.quantity} x <span className="text-indigo-400 font-black">R{item.price}</span>
|
||||
{item.quantity} x <span className="text-indigo-400 font-black">₹{item.price}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -700,7 +700,7 @@ const Orders: React.FC = () => {
|
||||
|
||||
<div className="text-right flex flex-col gap-1 min-w-[250px]">
|
||||
<div className="text-[10px] text-indigo-400 uppercase font-black tracking-widest mb-1">Active Grand Total</div>
|
||||
<div className="text-4xl font-black text-emerald-400 leading-none mb-1">R{selectedOrder.totalAmount.toLocaleString()}</div>
|
||||
<div className="text-4xl font-black text-emerald-400 leading-none mb-1">₹{selectedOrder.totalAmount.toLocaleString()}</div>
|
||||
<div className="text-[10px] text-white/40 font-bold uppercase tracking-[0.2em]">Transaction Pending Approval</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -784,7 +784,7 @@ const Orders: React.FC = () => {
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-bold text-slate-800 text-sm">{item.productName}</div>
|
||||
<div className="text-[10px] font-black text-indigo-400 uppercase">R{item.price} each</div>
|
||||
<div className="text-[10px] font-black text-indigo-400 uppercase">₹{item.price} each</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -805,7 +805,7 @@ const Orders: React.FC = () => {
|
||||
</button>
|
||||
</div>
|
||||
<div className="text-right min-w-[80px]">
|
||||
<div className="text-sm font-black text-slate-900 leading-none mb-1">R{(item.price * item.quantity).toFixed(2)}</div>
|
||||
<div className="text-sm font-black text-slate-900 leading-none mb-1">₹{(item.price * item.quantity).toFixed(2)}</div>
|
||||
<button
|
||||
onClick={() => removeItem(idx)}
|
||||
className="text-[10px] font-black text-rose-400 hover:text-rose-600 uppercase tracking-widest transition-colors flex items-center gap-1 active:scale-95"
|
||||
@@ -848,7 +848,7 @@ const Orders: React.FC = () => {
|
||||
<div className="font-bold text-slate-800 text-sm group-hover:text-indigo-600 transition-colors">{product.name}</div>
|
||||
<div className="text-[10px] font-black text-slate-400 uppercase tracking-widest">{product.category}</div>
|
||||
</div>
|
||||
<div className="font-black text-emerald-600 text-xs">R{product.price}</div>
|
||||
<div className="font-black text-emerald-600 text-xs">₹{product.price}</div>
|
||||
</button>
|
||||
))
|
||||
) : editSearchQuery ? (
|
||||
@@ -866,7 +866,7 @@ const Orders: React.FC = () => {
|
||||
<div className="mt-8 pt-8 border-t border-slate-200">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<span className="text-[10px] font-black text-slate-400 uppercase tracking-widest">New Order Total</span>
|
||||
<span className="text-2xl font-black text-emerald-600 tracking-tighter">R{editTotal.toFixed(2)}</span>
|
||||
<span className="text-2xl font-black text-emerald-600 tracking-tighter">₹{editTotal.toFixed(2)}</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={saveOrderEdits}
|
||||
|
||||
@@ -395,7 +395,7 @@ const Products = () => {
|
||||
})()}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm font-bold text-[#1e293b]">R{product.price}</td>
|
||||
<td className="px-6 py-4 text-sm font-bold text-[#1e293b]">₹{product.price}</td>
|
||||
<td className="px-6 py-4">
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-bold w-fit ${product.active ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-600'}`}>
|
||||
|
||||
@@ -105,10 +105,10 @@ const Reports: React.FC = () => {
|
||||
|
||||
const summaryData = [
|
||||
['Metric', 'Value'],
|
||||
['Total Sales Revenue', `INR ${data.totalSales.toLocaleString()}`],
|
||||
['Total Sales Revenue', `₹ ${data.totalSales.toLocaleString()}`],
|
||||
['Total Orders Fulfilled', data.totalOrders.toString()],
|
||||
['Total Inventory Purchases', `INR ${data.totalPurchases.toLocaleString()}`],
|
||||
['Net Performance', `INR ${(data.totalSales - data.totalPurchases).toLocaleString()}`],
|
||||
['Total Inventory Purchases', `₹ ${data.totalPurchases.toLocaleString()}`],
|
||||
['Net Performance', `₹ ${(data.totalSales - data.totalPurchases).toLocaleString()}`],
|
||||
['Top Performing Vendor', data.topVendor]
|
||||
];
|
||||
|
||||
@@ -126,7 +126,7 @@ const Reports: React.FC = () => {
|
||||
autoTable(doc, {
|
||||
startY: finalY1 + 20,
|
||||
head: [['Product Name', 'Quantity Sold', 'Revenue']],
|
||||
body: data.topSellingItems.map(item => [item.name, item.quantity, `INR ${item.revenue.toLocaleString()}`]),
|
||||
body: data.topSellingItems.map(item => [item.name, item.quantity, `₹ ${item.revenue.toLocaleString()}`]),
|
||||
theme: 'grid'
|
||||
});
|
||||
|
||||
@@ -136,7 +136,7 @@ const Reports: React.FC = () => {
|
||||
autoTable(doc, {
|
||||
startY: finalY2 + 20,
|
||||
head: [['Vendor Name', 'Total Orders', 'Spend Amount']],
|
||||
body: data.vendorSummary.map(v => [v.name, v.orderCount, `INR ${v.amount.toLocaleString()}`]),
|
||||
body: data.vendorSummary.map(v => [v.name, v.orderCount, `₹ ${v.amount.toLocaleString()}`]),
|
||||
theme: 'striped'
|
||||
});
|
||||
|
||||
|
||||
@@ -639,7 +639,7 @@ const Stalls: React.FC = () => {
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-bold text-[#1e293b] text-sm">{product.name}</p>
|
||||
<p className="text-[10px] font-bold text-[#94a3b8] uppercase tracking-wider">R{product.price} • {product.category}</p>
|
||||
<p className="text-[10px] font-bold text-[#94a3b8] uppercase tracking-wider">₹{product.price} • {product.category}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`w-6 h-6 rounded flex items-center justify-center border-2 transition-all ${isSelected ? 'bg-[#231651] border-[#231651]' : 'border-slate-200 bg-white'}`}>
|
||||
|
||||
@@ -358,8 +358,12 @@ const StoreDashboard = () => {
|
||||
<tr key={idx} className="group cursor-pointer hover:bg-slate-50/50 transition-all">
|
||||
<td className="py-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 rounded-xl overflow-hidden bg-slate-100 border border-slate-50 group-hover:scale-105 transition-transform">
|
||||
<img src={item.image} alt={item.name} className="w-full h-full object-cover" />
|
||||
<div className="w-12 h-12 rounded-xl overflow-hidden bg-slate-100 border border-slate-50 group-hover:scale-105 transition-transform flex items-center justify-center">
|
||||
{item.imageUrl ? (
|
||||
<img src={item.imageUrl} alt={item.name} className="w-full h-full object-cover" />
|
||||
) : (
|
||||
<div className="w-full h-full bg-slate-100" />
|
||||
)}
|
||||
</div>
|
||||
<div className="space-y-0.5">
|
||||
<p className="text-[9px] font-black text-[#0f4475] uppercase tracking-widest brightness-110">{item.category}</p>
|
||||
@@ -368,7 +372,7 @@ const StoreDashboard = () => {
|
||||
</div>
|
||||
</td>
|
||||
<td className="py-4 text-right">
|
||||
<span className="text-sm font-black text-slate-800">{item.qty}</span>
|
||||
<span className="text-sm font-black text-slate-800">{item.orderCount}</span>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user