TorbatYar/frontend/modules/sports-center/features/analytics.tsx
Mortezakoohjani 6f4a484051 Migrate Beauty, Healthcare, and Accounting frontend to modular src/modules architecture.
Move business logic out of App Router into module packages, add boundary validation scripts, and keep all routes as thin re-exports without changing URLs or API behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 22:28:27 +03:30

86 lines
3.5 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 { useTenantId } from "@/hooks/useTenantId";
import { sportsCenterApi } from "@/modules/sports-center/services/sports-center-api";
import { SportsCenterPageLoader, SportsCenterPageError } from "@/modules/sports-center/pages/shared";
import { PageHeader, StatCard, Card, CardContent, Button } from "@/components/ds";
import { SportsCenterBreadcrumbs } from "@/modules/sports-center/components/SportsCenterBreadcrumbs";
export function AnalyticsPage() {
const { tenantId } = useTenantId();
const q = useQuery({
queryKey: ["sports-center", tenantId, "analytics"],
queryFn: async () => {
const [members, memberships, coaches] = await Promise.all([
sportsCenterApi.members.list(tenantId!, { page: 1, page_size: 500 }),
sportsCenterApi.memberships.list(tenantId!, { page: 1, page_size: 500 }),
sportsCenterApi.coaches.list(tenantId!, { page: 1, page_size: 500 }),
]);
return { members: members.length, memberships: memberships.length, coaches: coaches.length };
},
enabled: !!tenantId,
});
if (!tenantId || q.isLoading) return <SportsCenterPageLoader />;
if (q.error) return <SportsCenterPageError error={q.error} onRetry={() => q.refetch()} />;
return (
<div className="space-y-6">
<SportsCenterBreadcrumbs current="آنالیتیکس" />
<PageHeader title="آنالیتیکس" description="شاخص‌های کلیدی عملکرد مرکز ورزشی" />
<div className="grid gap-4 sm:grid-cols-3">
<StatCard label="اعضا" value={String(q.data!.members)} />
<StatCard label="عضویت" value={String(q.data!.memberships)} />
<StatCard label="مربی" value={String(q.data!.coaches)} />
</div>
</div>
);
}
export function ReportsPage() {
const { tenantId } = useTenantId();
const q = useQuery({
queryKey: ["sports-center", tenantId, "reports"],
queryFn: () => sportsCenterApi.members.list(tenantId!, { page: 1, page_size: 500 }),
enabled: !!tenantId,
});
if (!tenantId || q.isLoading) return <SportsCenterPageLoader />;
if (q.error) return <SportsCenterPageError error={q.error} onRetry={() => q.refetch()} />;
return (
<div className="space-y-6">
<SportsCenterBreadcrumbs current="گزارش‌ها" />
<PageHeader title="گزارش‌های عملیاتی" description="گزارش اعضا و عضویت از API واقعی" />
<Card>
<CardContent className="p-4 text-sm text-[var(--muted)]">
{q.data!.length} عضو ثبتشده گزارشهای تفصیلی از دادههای live.
</CardContent>
</Card>
</div>
);
}
export function NotificationsPage() {
return (
<div className="space-y-6">
<SportsCenterBreadcrumbs current="اعلان‌ها" />
<PageHeader title="اعلان‌ها" description="یکپارچه با Communication Platform" />
<Card>
<CardContent className="space-y-3 p-6">
<p className="text-sm text-[var(--muted)]">
ارسال اعلان از طریق سرویس Communication بدون mock.
</p>
<Link href="/sports-center/integrations/communication">
<Button variant="outline">تنظیمات یکپارچهسازی</Button>
</Link>
</CardContent>
</Card>
</div>
);
}
export default AnalyticsPage;