TorbatYar/frontend/modules/delivery/features/dashboard.tsx
Mortezakoohjani 7978970783 feat(delivery): add Torbat Driver frontend module with real API wiring.
Ship the delivery platform UI under modules/delivery with thin app routes, BFF proxy, CRUD for phase 10.0-10.1 APIs, and capability-gated future screens.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 12:02:01 +03:30

75 lines
3.3 KiB
TypeScript
Raw Permalink 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.

"use client";
import { useQuery } from "@tanstack/react-query";
import Link from "next/link";
import { deliveryApi } from "@/modules/delivery/services/delivery-api";
import { useTenantId } from "@/hooks/useTenantId";
import { useDeliveryCapabilities, useDeliveryMetrics } from "@/modules/delivery/hooks/useDeliveryCapabilities";
import { DeliveryPageLoader, DeliveryPageError } from "@/modules/delivery/pages/shared";
import { PageHeader, StatCard, Card, CardContent, Button, Badge } from "@/components/ds";
import { DeliveryBreadcrumbs } from "@/modules/delivery/components/DeliveryBreadcrumbs";
export const ExecutiveDashboard = function DeliveryExecutiveDashboard() {
const { tenantId } = useTenantId();
const caps = useDeliveryCapabilities();
const metrics = useDeliveryMetrics();
const countsQ = useQuery({
queryKey: ["delivery", tenantId, "dashboard-counts"],
queryFn: async () => {
const [orgs, hubs, drivers] = await Promise.all([
deliveryApi.organizations.list(tenantId!, { page: 1, page_size: 500 }),
deliveryApi.hubs.list(tenantId!, { page: 1, page_size: 500 }),
deliveryApi.drivers.list(tenantId!, { page: 1, page_size: 500 }),
]);
const driverItems = Array.isArray(drivers) ? drivers : drivers.items;
return {
organizations: orgs.length,
hubs: hubs.length,
drivers: driverItems.length,
driversActive: driverItems.filter((d) => d.status === "active").length,
};
},
enabled: !!tenantId,
});
if (!tenantId || countsQ.isLoading || caps.isLoading) return <DeliveryPageLoader />;
if (countsQ.error) return <DeliveryPageError error={countsQ.error} onRetry={() => countsQ.refetch()} />;
const c = countsQ.data!;
return (
<div className="space-y-6">
<DeliveryBreadcrumbs current="داشبورد اجرایی" />
<PageHeader
title="داشبورد اجرایی"
description="نمای کلی عملیات لجستیک، رانندگان و زیرساخت."
actions={<Badge tone="success">Torbat Driver v{caps.data?.version}</Badge>}
/>
<div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
<StatCard label="سازمان‌ها" value={String(c.organizations)} hint="Organizations" />
<StatCard label="شعب / هاب" value={String(c.hubs)} hint="Hubs" />
<StatCard label="رانندگان" value={String(c.drivers)} hint="Drivers" />
<StatCard label="راننده فعال" value={String(c.driversActive)} hint="Active" />
</div>
<Card>
<CardContent className="flex flex-wrap gap-2 p-4">
<Link href="/delivery/drivers"><Button variant="outline">رانندگان</Button></Link>
<Link href="/delivery/branches"><Button variant="outline">شعب</Button></Link>
<Link href="/delivery/maps/view"><Button variant="outline">نقشه</Button></Link>
<Link href="/delivery/capabilities"><Button variant="outline">قابلیتها</Button></Link>
</CardContent>
</Card>
{metrics.data ? (
<Card>
<CardContent className="p-4 text-xs text-[var(--muted)]">
فاز {metrics.data.phase} {metrics.data.note}
</CardContent>
</Card>
) : null}
</div>
);
};
export default ExecutiveDashboard;