Files
ERP-core/Frontend/erp-system/lib/nav-routes.ts
T
Dhananjaya99 e7b1f270a5 feat: add vendor optional fields and configuration hooks
- Implemented VendorOptionalFields component to handle optional vendor details (mobile, email, address) with validation.
- Created useCustomerConfig hook to load optional customer field settings from Sales configuration.
- Developed useProcurementConfig hook to manage Procurement configuration flags.
- Introduced accessConfigApi for managing access configuration settings.
- Added openingBalancesApi for handling opening balances operations.
- Created procurementConfigApi for managing procurement configuration settings.
- Implemented nav-routes for permission-based routing.
- Developed PDF generation for purchase orders with dynamic vendor and item details.
- Added purchase-order tax helpers for tax calculations and formatting.
- Defined types for opening balances and related operations.
2026-10-18 12:46:31 +05:30

43 lines
2.0 KiB
TypeScript

// Which permission opens which page: the route guard in components/auth/AccessGate.tsx uses this so a role
// can't open a screen by typing its address (the sidebar only hides the link). Derived from the sidebar's own
// list, so a page and its menu entry can never disagree; the API enforces the same codes on every request, so this
// is a courtesy that replaces a wall of "Forbidden" toasts with one clear message — never the protection.
import { navItems } from "@/components/Layouts/AppSidebar"
interface RouteRule {
prefix: string
/** Any one of these opens the page. */
codes: string[]
}
/** Pages with no menu entry of their own, but that belong to a permission anyway. */
const EXTRA_RULES: RouteRule[] = [
{ prefix: "/dashboard/settings/audit-logs", codes: ["settings.audit-logs"] },
]
function buildRules(): RouteRule[] {
const rules: RouteRule[] = [...EXTRA_RULES]
for (const item of navItems) {
// The landing page and Help are open to everyone with a role (they hold no data of their own).
if (item.code !== "dashboard" && item.code !== "help") rules.push({ prefix: item.href, codes: [item.code] })
for (const child of item.children ?? []) {
rules.push({ prefix: child.href, codes: [child.code, ...(child.altCodes ?? [])] })
}
}
// Longest prefix first, so "/dashboard/procurement/purchase-orders/approvals" beats ".../purchase-orders".
return rules.sort((a, b) => b.prefix.length - a.prefix.length)
}
let cached: RouteRule[] | null = null
/**
* The permission codes that open `pathname` (any one suffices), or null when the page is unguarded
* (the landing page, Help, and anything not in the menu: those are protected by the API alone).
*/
export function requiredCodesFor(pathname: string): string[] | null {
cached ??= buildRules()
const path = pathname.length > 1 ? pathname.replace(/\/+$/, "") : pathname
const rule = cached.find((r) => path === r.prefix || path.startsWith(r.prefix + "/"))
return rule ? rule.codes : null
}