TorbatYar/frontend/modules/experience/features/analyticsDashboard.tsx
Mortezakoohjani 0eec9f729b feat(experience): deploy Experience frontend FE-11.0-11.5 portal
Commit completed Torbat Pages admin frontend module, BFF proxy, routes, and validation artifacts for official platform deploy.

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

87 lines
3.4 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 { 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;