Commit completed Torbat Pages admin frontend module, BFF proxy, routes, and validation artifacts for official platform deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
87 lines
3.4 KiB
TypeScript
87 lines
3.4 KiB
TypeScript
"use client";
|
||
|
||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||
import { toast } from "sonner";
|
||
import { useTenantId } from "@/hooks/useTenantId";
|
||
import { experienceApi } from "@/modules/experience/services/experience-api";
|
||
import { ExperiencePageLoader, ExperiencePageError } from "@/modules/experience/pages/shared";
|
||
import { ExperienceBreadcrumbs } from "@/modules/experience/components/ExperienceBreadcrumbs";
|
||
import { PageHeader, Button, Card, CardContent } from "@/components/ds";
|
||
import { ExperienceStatGrid } from "@/modules/experience/design-system";
|
||
|
||
export const AnalyticsDashboardPage = function ExperienceAnalyticsDashboard() {
|
||
const { tenantId } = useTenantId();
|
||
const qc = useQueryClient();
|
||
|
||
const defsQ = useQuery({
|
||
queryKey: ["experience", tenantId, "analytics-defs"],
|
||
queryFn: () => experienceApi.analyticsReportDefinitions.list(tenantId!),
|
||
enabled: !!tenantId,
|
||
});
|
||
|
||
const snapsQ = useQuery({
|
||
queryKey: ["experience", tenantId, "analytics-snaps"],
|
||
queryFn: () => experienceApi.analyticsSnapshots.list(tenantId!),
|
||
enabled: !!tenantId,
|
||
});
|
||
|
||
const refreshM = useMutation({
|
||
mutationFn: () => experienceApi.analyticsSnapshots.refresh(tenantId!, {}),
|
||
onSuccess: () => {
|
||
toast.success("اسنپشاتها بهروز شد");
|
||
qc.invalidateQueries({ queryKey: ["experience", tenantId, "analytics-snaps"] });
|
||
},
|
||
onError: (e: Error) => toast.error(e.message),
|
||
});
|
||
|
||
if (!tenantId || defsQ.isLoading || snapsQ.isLoading) return <ExperiencePageLoader />;
|
||
if (defsQ.error) return <ExperiencePageError error={defsQ.error} onRetry={() => defsQ.refetch()} />;
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
<ExperienceBreadcrumbs current="داشبورد آنالیتیکس" />
|
||
<PageHeader
|
||
title="داشبورد آنالیتیکس"
|
||
description="تعریف گزارش و اسنپشات متریک."
|
||
actions={
|
||
<Button onClick={() => refreshM.mutate()} loading={refreshM.isPending}>
|
||
بروزرسانی اسنپشاتها
|
||
</Button>
|
||
}
|
||
/>
|
||
<ExperienceStatGrid
|
||
stats={[
|
||
{ label: "تعاریف گزارش", value: String(defsQ.data?.length ?? 0) },
|
||
{ label: "اسنپشاتها", value: String(snapsQ.data?.length ?? 0) },
|
||
]}
|
||
/>
|
||
<div className="grid gap-4 lg:grid-cols-2">
|
||
<Card>
|
||
<CardContent className="p-4">
|
||
<h3 className="mb-2 font-semibold">آخرین اسنپشاتها</h3>
|
||
<ul className="space-y-1 text-sm">
|
||
{(snapsQ.data ?? []).slice(0, 8).map((s) => (
|
||
<li key={String(s.id)}>
|
||
{new Date(String(s.computed_at ?? s.created_at)).toLocaleString("fa-IR")} — {String(s.status)}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</CardContent>
|
||
</Card>
|
||
<Card>
|
||
<CardContent className="p-4">
|
||
<h3 className="mb-2 font-semibold">تعاریف گزارش</h3>
|
||
<ul className="space-y-1 text-sm">
|
||
{(defsQ.data ?? []).slice(0, 8).map((d) => (
|
||
<li key={String(d.id)}>{String(d.code ?? d.name ?? d.id)}</li>
|
||
))}
|
||
</ul>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default AnalyticsDashboardPage;
|