TorbatYar/frontend/app/accounting/layout.tsx
Mortezakoohjani 86b37c1de9 Speed up accounting sidebar navigation with shared session cache and prefetch.
Stop refetching /me on every page mount, warm shared accounting queries, prefetch nav routes, and keep the shell visible during soft SPA transitions.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 18:31:24 +03:30

73 lines
2.5 KiB
TypeScript

"use client";
import { AuthGuard } from "@/components/AuthGuard";
import { AccountingShell } from "@/components/accounting/AccountingShell";
import { RouteProgress } from "@/components/RouteProgress";
import { useMe } from "@/hooks/useMe";
import { accountingApi } from "@/lib/accounting-api";
import { useQuery } from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
import { LoadingState, ErrorState } from "@/components/ds";
/** Prefetch shared accounting lookups so sidebar hops skip cold API waits. */
function useWarmAccountingCache(tenantId: string | null) {
useQuery({
queryKey: ["accounting", tenantId, "accounts"],
queryFn: () => accountingApi.accounts.list(tenantId!),
enabled: !!tenantId,
staleTime: 60_000,
});
useQuery({
queryKey: ["accounting", tenantId, "fiscal-periods"],
queryFn: () => accountingApi.fiscal.listPeriods(tenantId!),
enabled: !!tenantId,
staleTime: 60_000,
});
useQuery({
queryKey: ["accounting", tenantId, "posting-policy"],
queryFn: () => accountingApi.setup.getPostingPolicy(tenantId!),
enabled: !!tenantId,
staleTime: 60_000,
});
}
function AccountingGate({ children }: { children: React.ReactNode }) {
const { me, loading, error, reload } = useMe();
const router = useRouter();
const tenantId = me?.current_tenant_id ?? null;
useWarmAccountingCache(tenantId);
useEffect(() => {
if (loading) return;
if (me?.onboarding_required) router.replace("/onboarding");
}, [me, loading, router]);
// Keep shell mounted once session is known — never blank the sidebar on soft nav.
if (loading && !me) return <LoadingState label="در حال آماده‌سازی ماژول حسابداری…" />;
if (error && !me) return <ErrorState message={error} onRetry={reload} />;
if (!loading && !me?.current_tenant_id) {
return (
<ErrorState message="برای استفاده از حسابداری باید یک workspace فعال داشته باشید." />
);
}
if (!me?.current_tenant_id) {
return <LoadingState label="در حال آماده‌سازی ماژول حسابداری…" />;
}
return (
<>
<RouteProgress />
<AccountingShell>{children}</AccountingShell>
</>
);
}
export default function AccountingLayout({ children }: { children: React.ReactNode }) {
return (
<AuthGuard>
<AccountingGate>{children}</AccountingGate>
</AuthGuard>
);
}