Vitron-Front/app/components/admin/OrdersBarChart.tsx
Arda Samadi 0360780411 feat(admin): admin-panel foundation shell + overview (slice 0)
- /admin opted out of shopper chrome in MyLayout; /admin added to server
  protectedRoutes; useRequireAdmin() gates to superusers (UserProfile.isSuperuser).
- Admin shell (admin.tsx) with sidebar nav (Overview live; other sections stubbed)
  and a mobile top bar; Overview dashboard (KPI cards + 14-day orders chart) via
  use-admin-hooks.ts hitting /api/adminpanel/v1/overview/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 12:00:49 +03:30

62 lines
1.9 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Dependency-free 14-day orders bar chart for the admin overview.
* (A richer charting lib can replace this in a later slice.)
*/
interface Point {
date: string;
orders: number;
revenue: number;
}
function faNum(n: number): string {
return Math.round(n).toLocaleString("fa-IR");
}
function dayLabel(iso: string): string {
// day-of-month in Persian digits
try {
const d = new Date(iso);
return d.toLocaleDateString("fa-IR", { day: "numeric" });
} catch {
return "";
}
}
export function OrdersBarChart({ data }: { data: Point[] }) {
const max = Math.max(1, ...data.map((d) => d.orders));
return (
<div className="rounded-2xl border border-WHITE3 bg-WHITE p-4">
<div className="flex items-center justify-between mb-4">
<h3 className="font-bold text-[15px]">سفارشهای ۱۴ روز اخیر</h3>
<span className="text-[12px] text-GRAY">
مجموع: {faNum(data.reduce((s, d) => s + d.orders, 0))} سفارش
</span>
</div>
<div className="flex items-end gap-1.5 h-[160px]" dir="ltr">
{data.map((d) => (
<div
key={d.date}
className="flex-1 h-full flex flex-col items-center justify-end gap-1 group"
title={`${dayLabel(d.date)}${faNum(d.orders)} سفارش، ${faNum(
d.revenue
)} تومان`}
>
<div className="w-full flex-1 flex items-end">
<div
className="w-full rounded-t-md bg-VITROWN_BLUE/80 group-hover:bg-VITROWN_BLUE transition-colors min-h-[2px]"
style={{ height: `${(d.orders / max) * 100}%` }}
/>
</div>
<span className="text-[10px] text-GRAY tabular-nums">
{dayLabel(d.date)}
</span>
</div>
))}
</div>
</div>
);
}
export default OrdersBarChart;