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.
This commit is contained in:
@@ -67,7 +67,8 @@ import { useAuth } from "@/components/auth/AuthProvider"
|
||||
// `code` must match the seeded NavItem/SubNavItem codes in ERPCore
|
||||
// (Infra/Persistence/Configurations/NavItemConfiguration.cs / SubNavItemConfiguration.cs)
|
||||
// so role-based filtering (via GET /auth/me's navCodes) can match entries here.
|
||||
const navItems: {
|
||||
// Exported: lib/nav-routes.ts derives the page -> permission map (the route guard) from this same list.
|
||||
export const navItems: {
|
||||
title: string
|
||||
code: string
|
||||
href: string
|
||||
@@ -114,6 +115,7 @@ const navItems: {
|
||||
icon: ClipboardList,
|
||||
children: [
|
||||
{ title: "Purchase Orders", code: "procurement.purchase-orders", href: "/dashboard/procurement/purchase-orders", icon: ShoppingCart },
|
||||
{ title: "PO Approval Queue", code: "procurement.po-approvals", href: "/dashboard/procurement/purchase-orders/approvals", icon: ClipboardCheck },
|
||||
{ title: "Purchase Returns", code: "procurement.purchase-returns", href: "/dashboard/procurement/purchase-returns", icon: PackageX },
|
||||
{ title: "Vendors", code: "procurement.vendors", href: "/dashboard/vendors", icon: Truck },
|
||||
],
|
||||
@@ -215,6 +217,7 @@ const navItems: {
|
||||
{ title: "Expenses", code: "accounts.expenses", href: "/dashboard/accounts/expenses", icon: ReceiptText },
|
||||
{ title: "Expense Setup", code: "accounts.expense-setup", href: "/dashboard/accounts/expense-setup", icon: Tags },
|
||||
{ title: "Bank Deposits", code: "accounts.bank-deposits", href: "/dashboard/accounts/bank-deposits", icon: PiggyBank },
|
||||
{ title: "Opening Balances", code: "accounts.opening-balances", href: "/dashboard/accounts/opening-balances", icon: Scale },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -227,6 +230,7 @@ const navItems: {
|
||||
{ title: "Roles", code: "settings.roles", href: "/dashboard/settings/roles", icon: ShieldCheck },
|
||||
{ title: "Users", code: "settings.users", href: "/dashboard/settings/users", icon: Users },
|
||||
{ title: "Approvals", code: "settings.approvals", href: "/dashboard/settings/approvals", icon: ClipboardCheck },
|
||||
{ title: "Audit Log", code: "settings.audit-logs", href: "/dashboard/settings/audit-logs", icon: ScrollText },
|
||||
{ title: "Configuration", code: "products.configuration", href: "/dashboard/settings/configuration", icon: SlidersHorizontal },
|
||||
],
|
||||
},
|
||||
@@ -439,32 +443,19 @@ export function AppSidebar() {
|
||||
// While /auth/me hasn't resolved yet, show nothing rather than briefly
|
||||
// flashing the full menu to a restricted role. Once resolved, a nav item
|
||||
// is visible if its own code is granted, or (for parents) if any child is.
|
||||
//
|
||||
// "procurement", "hrm", "sales", "production" and "stock" are exempted from that check
|
||||
// (frontend-only): no role is currently seeded with NAV:procurement/NAV:hrm/NAV:production
|
||||
// or their children server-side (stock's children specifically have no SubNavItem rows at
|
||||
// all yet), which would hide the whole section for everyone. Remove each bypass once roles
|
||||
// are granted the permission properly (Settings → Roles → Sidebar permissions) or a backend
|
||||
// seed grants it. This is also flagged in 02-SECURITY.md as the AR-09 sidebar-visibility
|
||||
// stopgap for HRM's salary/PII data — it hides HRM from the UI but doesn't enforce
|
||||
// anything server-side.
|
||||
const bypassCodes = new Set(["procurement", "sales", "sales-returns", "hrm", "production", "stock"])
|
||||
|
||||
// Every section now has seeded nav rows (HRM and Sales Returns were the last gaps), so there is no
|
||||
// exemption list any more: what you see is exactly what your role grants (an administrator holds every code).
|
||||
const visibleItems = loading
|
||||
? []
|
||||
: navItems
|
||||
.filter(
|
||||
(item) =>
|
||||
bypassCodes.has(item.code) ||
|
||||
navCodes.includes(item.code) ||
|
||||
item.children?.some((c) => navCodes.includes(c.code) || c.altCodes?.some((ac) => navCodes.includes(ac)))
|
||||
)
|
||||
.map((item) => ({
|
||||
...item,
|
||||
children: (bypassCodes.has(item.code)
|
||||
? item.children
|
||||
: item.children?.filter((c) => navCodes.includes(c.code) || c.altCodes?.some((ac) => navCodes.includes(ac)))
|
||||
),
|
||||
children: item.children?.filter((c) => navCodes.includes(c.code) || c.altCodes?.some((ac) => navCodes.includes(ac))),
|
||||
}))
|
||||
|
||||
// Close mobile menu on route change
|
||||
|
||||
@@ -49,6 +49,7 @@ const PROCUREMENT_TITLES: Record<string, string> = {
|
||||
"/dashboard/procurement/rfqs/new": "New RFQ",
|
||||
"/dashboard/procurement/purchase-orders": "Purchase Orders",
|
||||
"/dashboard/procurement/purchase-orders/new": "New Purchase Order",
|
||||
"/dashboard/procurement/purchase-orders/approvals": "PO Approval Queue",
|
||||
"/dashboard/procurement/purchase-returns": "Purchase Returns",
|
||||
"/dashboard/procurement/purchase-returns/new": "New Purchase Return",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user