changes on global catalogue

This commit is contained in:
2026-06-20 18:45:25 +05:30
parent 2e9ffb15bb
commit 8707004405
22 changed files with 3137 additions and 2070 deletions

View File

@@ -232,152 +232,7 @@ export default function DashboardView({ searchQuery, tenantId = FIESTA_TENANT_ID
})}
</div>
{/* Order status + store locations */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-gutter">
{/* Store Node Status donut (live) */}
<div className="bg-white border border-slate-200/70 rounded-2xl p-lg flex flex-col shadow-[0_1px_3px_rgba(16,24,40,0.05)]">
<div className="flex items-start gap-2.5">
<div className="h-9 w-9 rounded-xl bg-emerald-50 text-emerald-600 ring-1 ring-emerald-100 flex items-center justify-center shrink-0">
<Activity size={17} />
</div>
<div>
<h3 className="font-sans font-bold text-base text-slate-900 tracking-tight">Store Outlet Status</h3>
<p className="text-slate-500 text-xs font-sans mt-0.5">Active share of all registered nodes.</p>
</div>
</div>
<div className="my-lg flex justify-center items-center">
<div className="relative w-44 h-44 flex items-center justify-center">
{/* soft glow behind the ring */}
<div className="absolute w-32 h-32 rounded-full bg-emerald-400/10 blur-2xl" />
<svg className="w-full h-full transform -rotate-90 relative" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="transparent" stroke="#eef2f6" strokeWidth="9" />
<circle
cx="50"
cy="50"
r="40"
fill="transparent"
stroke="url(#dashGradient)"
strokeWidth="9"
strokeDasharray={circumference}
strokeDashoffset={dashOffset}
strokeLinecap="round"
className="transition-all duration-700"
/>
<defs>
<linearGradient id="dashGradient" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stopColor="#10b981" />
<stop offset="100%" stopColor="#0d9488" />
</linearGradient>
</defs>
</svg>
<div className="absolute inset-0 flex flex-col items-center justify-center">
<span className="font-sans font-extrabold text-4xl text-slate-900 tracking-tight">{activePct}%</span>
<span className="text-[10px] text-emerald-600 uppercase tracking-widest font-bold mt-1">Active</span>
</div>
</div>
</div>
<div className="divide-y divide-slate-100 text-xs">
{statusRows.map((r) => (
<div key={r.label} className="flex justify-between items-center py-2.5">
<span className="flex items-center gap-2 text-slate-500 font-medium">
<span className={`w-2.5 h-2.5 rounded-full ${r.dot}`} />
{r.label}
</span>
<span className="font-mono font-bold text-slate-700">{r.value.toLocaleString('en-IN')}</span>
</div>
))}
<div className="flex justify-between items-center pt-2.5">
<span className="text-slate-600 font-bold">Total Nodes</span>
<span className="font-mono font-extrabold text-purple-650">{totalStoresCount.toLocaleString('en-IN')}</span>
</div>
</div>
</div>
{/* Store locations (live) */}
<div className="lg:col-span-2 bg-white border border-slate-200/70 rounded-2xl p-lg shadow-[0_1px_3px_rgba(16,24,40,0.05)]">
<div className="flex justify-between items-center mb-md pb-sm border-b border-slate-100">
<h3 className="font-sans font-bold text-base text-slate-900 flex items-center gap-2.5 tracking-tight">
<span className="h-9 w-9 rounded-xl bg-purple-50 text-purple-650 ring-1 ring-purple-100 flex items-center justify-center">
<Store size={17} />
</span>
Store Locations
</h3>
<span className="text-[10px] text-purple-650 uppercase font-bold bg-purple-50 px-2.5 py-1 rounded-lg tracking-wide border border-purple-100">
{locationsQ.isLoading ? 'Loading' : `${locations.length} Outlet${locations.length === 1 ? '' : 's'}`}
</span>
</div>
{locationsQ.isLoading ? (
<div className="text-center py-xl text-slate-400 text-xs">Loading store locations…</div>
) : locations.length === 0 ? (
<div className="text-center py-xl text-slate-400 text-xs">No store locations found for this tenant.</div>
) : (
<div className="space-y-sm max-h-80 overflow-y-auto pr-1">
{locations.map((loc, i) => {
const sum = summaries.find((s) => s.locationid === Number(loc.locationid));
const deliveries = sum?.delivered ?? 0;
const orders = Math.max(sum?.delivered ?? 0, sum?.total ?? 0);
const isActive = str(loc.status).toLowerCase() === 'active';
const name = str(loc.locationname);
return (
<div
key={str(loc.locationid) || i}
className="group p-3.5 border border-slate-200/70 rounded-xl bg-slate-50/40 flex justify-between items-start gap-md hover:border-purple-200 hover:bg-white hover:shadow-[0_6px_18px_rgba(16,24,40,0.06)] transition-all animate-in fade-in"
>
<div className="flex items-start gap-3 min-w-0">
{/* Outlet initial badge */}
<div className="h-9 w-9 shrink-0 rounded-lg bg-gradient-to-br from-purple-500 to-indigo-500 text-white flex items-center justify-center font-bold text-xs uppercase shadow-sm">
{name.slice(0, 2) || ''}
</div>
<div className="min-w-0">
<p className="font-sans font-semibold text-sm text-slate-900 truncate">{name}</p>
<p className="text-[11px] text-slate-500 mt-0.5 flex items-center gap-1">
<MapPin size={11} className="shrink-0 text-slate-400" />
<span className="truncate">{str(loc.address) || `${str(loc.suburb)}, ${str(loc.city)}`}</span>
</p>
{str(loc.contactno) && (
<p className="text-[11px] text-slate-500 mt-0.5 flex items-center gap-1">
<Phone size={11} className="shrink-0 text-slate-400" />
{str(loc.contactno)}
</p>
)}
{/* Node-specific Orders and Dispatches */}
<div className="flex items-center gap-2 mt-2.5 flex-wrap">
<span className="text-[10px] bg-purple-50 text-purple-650 font-bold px-2 py-0.5 rounded-md border border-purple-100/60">
{orders} Orders
</span>
<span className="text-[10px] bg-emerald-50 text-emerald-700 font-bold px-2 py-0.5 rounded-md border border-emerald-100/60">
{deliveries} Dispatched
</span>
{orders > 0 && (
<span className="text-[10px] text-slate-400 font-semibold">
{Math.round((deliveries / orders) * 100)}% Fulfilled
</span>
)}
</div>
</div>
</div>
<span
className={`shrink-0 inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-[9px] font-bold uppercase tracking-wide ${
isActive
? 'text-emerald-600 bg-emerald-50 border border-emerald-100'
: 'text-slate-500 bg-slate-100 border border-slate-200'
}`}
>
<span className={`w-1.5 h-1.5 rounded-full ${isActive ? 'bg-emerald-500' : 'bg-slate-400'}`} />
{str(loc.status) || ''}
</span>
</div>
);
})}
</div>
)}
</div>
</div>
</div>
);
}