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>
73 lines
2.7 KiB
TypeScript
73 lines
2.7 KiB
TypeScript
"use client";
|
||
|
||
import Link from "next/link";
|
||
import { AuthGuard } from "@/components/AuthGuard";
|
||
import { PageHeader, Card, CardContent, Button, LoadingState } from "@/components/ds";
|
||
import { SPORTS_CENTER_PORTALS } from "@/modules/sports-center/constants/portals";
|
||
import { useQuery } from "@tanstack/react-query";
|
||
import { sportsCenterApi } from "@/modules/sports-center/services/sports-center-api";
|
||
import { useTenantId } from "@/hooks/useTenantId";
|
||
|
||
export function SportsCenterHub() {
|
||
return (
|
||
<AuthGuard>
|
||
<SportsCenterHubInner />
|
||
</AuthGuard>
|
||
);
|
||
}
|
||
|
||
function SportsCenterHubInner() {
|
||
const { tenantId } = useTenantId();
|
||
const healthQ = useQuery({
|
||
queryKey: ["sports-center", "health"],
|
||
queryFn: () => sportsCenterApi.health(),
|
||
});
|
||
|
||
if (healthQ.isLoading) return <LoadingState label="در حال بارگذاری…" />;
|
||
|
||
return (
|
||
<div className="mx-auto max-w-6xl px-4 py-10 sm:px-6">
|
||
<PageHeader
|
||
title="مرکز ورزشی"
|
||
description="پلتفرم مدیریت حرفهای ورزش — پورتال مورد نظر را انتخاب کنید."
|
||
actions={
|
||
healthQ.data ? (
|
||
<span className="text-xs text-[var(--muted)]">v{healthQ.data.version}</span>
|
||
) : null
|
||
}
|
||
/>
|
||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||
{SPORTS_CENTER_PORTALS.map((portal) => {
|
||
const Icon = portal.icon;
|
||
return (
|
||
<Link key={portal.id} href={portal.basePath}>
|
||
<Card className="h-full transition-all hover:border-[var(--sports-accent)]/40 hover:shadow-[var(--shadow-md)]">
|
||
<CardContent className="flex h-full flex-col gap-4 pt-6">
|
||
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[var(--sports-accent-soft)] text-[var(--sports-accent)]">
|
||
<Icon className="h-6 w-6" />
|
||
</div>
|
||
<div>
|
||
<p className="text-lg font-semibold text-secondary">{portal.label}</p>
|
||
<p className="mt-1 text-sm text-[var(--muted)]">{portal.description}</p>
|
||
</div>
|
||
<span className="mt-auto text-xs text-[var(--sports-accent)]">ورود ←</span>
|
||
</CardContent>
|
||
</Card>
|
||
</Link>
|
||
);
|
||
})}
|
||
</div>
|
||
<div className="mt-8 flex flex-wrap gap-3">
|
||
<Link href="/dashboard">
|
||
<Button variant="ghost">workspace</Button>
|
||
</Link>
|
||
</div>
|
||
{!tenantId ? (
|
||
<p className="mt-6 text-sm text-[var(--muted)]">tenant فعال لازم است.</p>
|
||
) : null}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default SportsCenterHub;
|