- Cash Floats: ledger card (opening balance, top-ups, slips), manual entries, slip photos - Office access level; clock app Slips tab (photograph a slip, popup for supplier/cost code/comments/amount); only Office sees it; per-role route table in lib/clock-access - Job cards: Machine Service PDF (with Oil block), JC numbers, manual Close job, Delete - Hide Expenses > Vehicle Costs and Finance (Bastion) from the menu Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
42 lines
2.4 KiB
TypeScript
42 lines
2.4 KiB
TypeScript
import type { UserAccess } from "./auth-policy";
|
|
|
|
/**
|
|
* What each access level may reach inside the Plant Clock app (/clock and /api/clock).
|
|
*
|
|
* full everything in the main app, and Employees / Fuel / Job cards in the clock app (not Slips)
|
|
* clock clock-in user: Employees, Fuel, Job cards
|
|
* mechanic Fuel and Job cards only — no clock in/out
|
|
* office Slips only (photo of a cash-card slip) — and ONLY office sees Slips
|
|
*
|
|
* Pure and dependency-free so the proxy, the bottom nav and the tests share one rule.
|
|
*/
|
|
export type ClockTab = { href: string; label: string };
|
|
|
|
export const CLOCK_TABS: Record<UserAccess, ClockTab[]> = {
|
|
full: [{ href: "/clock", label: "Employees" }, { href: "/clock/stock", label: "Fuel" }, { href: "/clock/job-cards", label: "Job cards" }],
|
|
clock: [{ href: "/clock", label: "Employees" }, { href: "/clock/stock", label: "Fuel" }, { href: "/clock/job-cards", label: "Job cards" }],
|
|
mechanic: [{ href: "/clock/stock", label: "Fuel" }, { href: "/clock/job-cards", label: "Job cards" }],
|
|
office: [{ href: "/clock/slips", label: "Slips" }],
|
|
};
|
|
|
|
/** Where a user lands when they open the clock app. */
|
|
export const clockHome = (access: UserAccess): string => (access === "mechanic" ? "/clock/job-cards" : access === "office" ? "/clock/slips" : "/clock");
|
|
|
|
const under = (path: string, base: string) => path === base || path.startsWith(`${base}/`);
|
|
|
|
// Pages and APIs a restricted role may use, besides the sign-in / password screens.
|
|
const ALLOWED: Partial<Record<UserAccess, string[]>> = {
|
|
mechanic: ["/clock/stock", "/clock/job-cards", "/api/clock/stock-out", "/api/clock/oil-out", "/api/clock/job-start", "/api/clock/job-finish"],
|
|
office: ["/clock/slips", "/api/clock/slip", "/api/clock/cash-float"],
|
|
};
|
|
// The slip scanner belongs to the Office role alone. (The cash-float opening-balance call is also
|
|
// open to full users, because the main Cash Floats page makes it.)
|
|
const SLIPS = ["/clock/slips", "/api/clock/slip"];
|
|
const ALWAYS = ["/clock/login", "/clock/change-password"];
|
|
|
|
export function clockPathAllowed(access: UserAccess, path: string): boolean {
|
|
if (ALWAYS.some((p) => under(path, p))) return true;
|
|
if (access === "full") return !SLIPS.some((p) => under(path, p));
|
|
if (access === "clock") return ![...SLIPS, "/api/clock/cash-float"].some((p) => under(path, p));
|
|
return (ALLOWED[access] ?? []).some((p) => under(path, p));
|
|
}
|