44 lines
1.7 KiB
TypeScript
44 lines
1.7 KiB
TypeScript
|
|
import { eq } from 'drizzle-orm';
|
||
|
|
|
||
|
|
import { db } from '@/lib/db';
|
||
|
|
import { ports as portsTable } from '@/lib/db/schema/ports';
|
||
|
|
import { isExpensesModuleEnabled } from '@/lib/services/expenses-module.service';
|
||
|
|
import { ModuleDisabledPage } from '@/components/shared/module-disabled-page';
|
||
|
|
|
||
|
|
interface ExpensesLayoutProps {
|
||
|
|
children: React.ReactNode;
|
||
|
|
params: Promise<{ portSlug: string }>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Layout-level gate for the entire /expenses subtree (list, scan,
|
||
|
|
* detail). When the port has expenses_module_enabled = false, every
|
||
|
|
* route under /expenses renders the ModuleDisabledPage instead of the
|
||
|
|
* real content. This is the route-level half of the "hybrid hide+block"
|
||
|
|
* model (the sidebar entries are independently hidden via
|
||
|
|
* expensesModuleByPort on the SSR-resolved sidebar prop).
|
||
|
|
*
|
||
|
|
* Using a layout rather than per-page guards means: (a) one place to
|
||
|
|
* change the gate logic, (b) nested routes (scan, [id]) are covered
|
||
|
|
* automatically, (c) the children subtree never mounts when disabled,
|
||
|
|
* so its data-fetching effects don't fire.
|
||
|
|
*/
|
||
|
|
export default async function ExpensesLayout({ children, params }: ExpensesLayoutProps) {
|
||
|
|
const { portSlug } = await params;
|
||
|
|
const port = await db.query.ports.findFirst({
|
||
|
|
where: eq(portsTable.slug, portSlug),
|
||
|
|
columns: { id: true },
|
||
|
|
});
|
||
|
|
if (!port) return children;
|
||
|
|
const enabled = await isExpensesModuleEnabled(port.id);
|
||
|
|
if (enabled) return children;
|
||
|
|
return (
|
||
|
|
<ModuleDisabledPage
|
||
|
|
moduleName="Expenses"
|
||
|
|
description="Expense tracking and receipt upload are turned off for this port. Previously-recorded expense rows are preserved and will reappear when the module is re-enabled."
|
||
|
|
settingsHref={`/${portSlug}/admin/settings`}
|
||
|
|
fallbackHref={`/${portSlug}/dashboard`}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
}
|