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>
73 lines
2.5 KiB
TypeScript
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>
|
|
);
|
|
}
|