Add frontend/modules/loyalty with types, API client, design system, feature pages and thin App Router routes under app/loyalty/. BFF proxy at app/api/loyalty/. Include loyalty frontend docs. Co-authored-by: Cursor <cursoragent@cursor.com>
68 lines
2.4 KiB
TypeScript
68 lines
2.4 KiB
TypeScript
"use client";
|
||
|
||
import { useQuery } from "@tanstack/react-query";
|
||
import { PageHeader, Button } from "@/components/ds";
|
||
import { loyaltyApi } from "@/modules/loyalty/services/loyalty-api";
|
||
import { useTenantId } from "@/hooks/useTenantId";
|
||
import { LoyaltyBreadcrumbs } from "@/modules/loyalty/components/LoyaltyBreadcrumbs";
|
||
import {
|
||
LoyaltyPageLoader,
|
||
LoyaltyPageError,
|
||
exportToCsv,
|
||
useLoyaltyCounts,
|
||
} from "@/modules/loyalty/pages/shared";
|
||
import { LoyaltyStatGrid, LoyaltyTablePage } from "@/modules/loyalty/design-system";
|
||
|
||
export default function ReportsPage() {
|
||
const { tenantId } = useTenantId();
|
||
const counts = useLoyaltyCounts(tenantId);
|
||
const membersQ = useQuery({
|
||
queryKey: ["loyalty", tenantId, "report-members"],
|
||
queryFn: () => loyaltyApi.members.list(tenantId!, { page: 1, page_size: 500 }),
|
||
enabled: !!tenantId,
|
||
});
|
||
if (!tenantId || counts.isLoading || membersQ.isLoading) return <LoyaltyPageLoader />;
|
||
if (counts.error) return <LoyaltyPageError error={counts.error} />;
|
||
const c = counts.data!;
|
||
return (
|
||
<div className="space-y-6">
|
||
<LoyaltyBreadcrumbs items={[{ label: "گزارشها" }]} />
|
||
<PageHeader
|
||
title="گزارشها"
|
||
description="گزارشهای عملیاتی از داده واقعی سرویس."
|
||
actions={
|
||
<Button
|
||
variant="outline"
|
||
onClick={() =>
|
||
exportToCsv(
|
||
"loyalty-members.csv",
|
||
(membersQ.data ?? []) as unknown as Record<string, unknown>[],
|
||
["membership_number", "display_name", "status", "email", "mobile"]
|
||
)
|
||
}
|
||
>
|
||
خروجی اعضا
|
||
</Button>
|
||
}
|
||
/>
|
||
<LoyaltyStatGrid
|
||
stats={[
|
||
{ label: "برنامه", value: c.programs },
|
||
{ label: "عضو", value: c.members },
|
||
{ label: "پاداش", value: c.rewards },
|
||
{ label: "کمپین", value: c.campaigns },
|
||
]}
|
||
/>
|
||
<LoyaltyTablePage
|
||
title="نمونه اعضا"
|
||
columns={[
|
||
{ key: "membership_number", header: "شماره" },
|
||
{ key: "display_name", header: "نام" },
|
||
{ key: "status", header: "وضعیت" },
|
||
]}
|
||
rows={(membersQ.data ?? []).slice(0, 50) as unknown as Record<string, unknown>[]}
|
||
/>
|
||
</div>
|
||
);
|
||
}
|