@apptimate/core-lib 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -7
- package/package.json +16 -16
- package/src/client.ts +10 -0
- package/src/common/interfaces/ICommon.ts +6 -6
- package/src/constants/iconRegistry.ts +189 -0
- package/src/constants/menus.ts +975 -0
- package/src/constants/storageKeys.ts +14 -9
- package/src/index.ts +3 -8
- package/src/server.ts +12 -0
- package/src/utils/bem.ts +13 -13
- package/src/utils/bootstrapConfig.ts +80 -0
- package/src/utils/cn.ts +9 -9
- package/src/utils/commonService.ts +46 -26
- package/src/utils/cookiesHandler.ts +64 -64
- package/src/utils/httpClient.ts +185 -161
- package/src/utils/localStorageHandler.ts +59 -49
|
@@ -0,0 +1,975 @@
|
|
|
1
|
+
export interface SubMenuItem {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
path: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface SubMenuGroup {
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
items: SubMenuItem[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface MainMenuItem {
|
|
14
|
+
id: string;
|
|
15
|
+
label: string;
|
|
16
|
+
iconName: string;
|
|
17
|
+
groups: SubMenuGroup[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A secondary item in a saved menu config.
|
|
22
|
+
* Can be a plain registry key (backward compat) or an enriched object
|
|
23
|
+
* with optional label/group overrides.
|
|
24
|
+
*/
|
|
25
|
+
export type SecondaryItemConfig = string | {
|
|
26
|
+
key: string;
|
|
27
|
+
/** Override the default label from the registry */
|
|
28
|
+
label?: string;
|
|
29
|
+
/** Override the default group from the registry */
|
|
30
|
+
group?: string;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** Normalize a SecondaryItemConfig to its key string. */
|
|
34
|
+
export function secondaryItemKey(item: SecondaryItemConfig): string {
|
|
35
|
+
return typeof item === 'string' ? item : item.key;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Normalize a SecondaryItemConfig to the enriched shape. */
|
|
39
|
+
export function normalizeSecondaryItem(item: SecondaryItemConfig): { key: string; label?: string; group?: string } {
|
|
40
|
+
return typeof item === 'string' ? { key: item } : item;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ─── MASTER REGISTRY ─────────────────────────────────────────────
|
|
44
|
+
// Every possible secondary menu item across all modules.
|
|
45
|
+
// These are the building blocks that can be assembled into custom menus.
|
|
46
|
+
|
|
47
|
+
export interface RegistryItem {
|
|
48
|
+
/** Unique key used for selection, e.g. "core__users" */
|
|
49
|
+
key: string;
|
|
50
|
+
/** Human-readable label */
|
|
51
|
+
label: string;
|
|
52
|
+
/** URL path */
|
|
53
|
+
path: string;
|
|
54
|
+
/** Which module this belongs to */
|
|
55
|
+
module: string;
|
|
56
|
+
/** Default group label when added to a menu */
|
|
57
|
+
defaultGroup: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const MENU_ITEM_REGISTRY: RegistryItem[] = [
|
|
61
|
+
// ── Core Module ──
|
|
62
|
+
{ key: 'core__users', label: 'Users', path: '/users', module: 'Core', defaultGroup: 'User Management' },
|
|
63
|
+
{ key: 'core__roles', label: 'Roles', path: '/roles', module: 'Core', defaultGroup: 'User Management' },
|
|
64
|
+
{ key: 'core__organizations', label: 'Organizations', path: '/organizations', module: 'Core', defaultGroup: 'User Management' },
|
|
65
|
+
{ key: 'core__design_system', label: 'Design System', path: '/design-system', module: 'Core', defaultGroup: 'Temporary' },
|
|
66
|
+
{ key: 'core__activity_logs', label: 'Activity Logs', path: '/activity-logs', module: 'Core', defaultGroup: 'System Auditing' },
|
|
67
|
+
{ key: 'core__api_requests', label: 'API Requests', path: '/system/api-requests', module: 'Core', defaultGroup: 'System Auditing' },
|
|
68
|
+
{ key: 'core__feature_access_logs', label: 'Feature Access Logs', path: '/system/feature-access-logs', module: 'Core', defaultGroup: 'System Auditing' },
|
|
69
|
+
{ key: 'core__issue_logs', label: 'Issue Logs', path: '/system/issue-logs', module: 'Core', defaultGroup: 'System Auditing' },
|
|
70
|
+
{ key: 'core__feature_registry', label: 'Feature Registry', path: '/system/features', module: 'Core', defaultGroup: 'System Auditing' },
|
|
71
|
+
{ key: 'core__menu_config', label: 'Menu Configuration', path: '/menu-config', module: 'Core', defaultGroup: 'System' },
|
|
72
|
+
|
|
73
|
+
// ── Inventory Module ──
|
|
74
|
+
{ key: 'inv__items', label: 'Items', path: '/inventory/items', module: 'Inventory', defaultGroup: 'Catalog' },
|
|
75
|
+
{ key: 'inv__categories', label: 'Categories', path: '/inventory/categories', module: 'Inventory', defaultGroup: 'Catalog' },
|
|
76
|
+
{ key: 'inv__units', label: 'Units', path: '/inventory/units', module: 'Inventory', defaultGroup: 'Catalog' },
|
|
77
|
+
{ key: 'inv__supplier_items', label: 'Supplier Items', path: '/inventory/supplier-items', module: 'Inventory', defaultGroup: 'Catalog' },
|
|
78
|
+
{ key: 'inv__documents', label: 'Stock Documents', path: '/inventory/documents', module: 'Inventory', defaultGroup: 'Stock Control' },
|
|
79
|
+
{ key: 'inv__warehouses', label: 'Warehouses', path: '/inventory/warehouses', module: 'Inventory', defaultGroup: 'Stock Control' },
|
|
80
|
+
{ key: 'inv__lots', label: 'Lots & Serials', path: '/inventory/lots', module: 'Inventory', defaultGroup: 'Stock Control' },
|
|
81
|
+
{ key: 'inv__stock_counts', label: 'Stock Counts', path: '/inventory/stock-counts', module: 'Inventory', defaultGroup: 'Stock Control' },
|
|
82
|
+
{ key: 'inv__reservations', label: 'Reservations', path: '/inventory/reservations', module: 'Inventory', defaultGroup: 'Stock Control' },
|
|
83
|
+
{ key: 'inv__inspection', label: 'Inspection', path: '/inventory/inspection', module: 'Inventory', defaultGroup: 'Quality & Alerts' },
|
|
84
|
+
{ key: 'inv__alerts', label: 'Stock Alerts', path: '/inventory/alerts', module: 'Inventory', defaultGroup: 'Quality & Alerts' },
|
|
85
|
+
{ key: 'inv__opening_balances', label: 'Opening Balances', path: '/inventory/opening-balances', module: 'Inventory', defaultGroup: 'Operations' },
|
|
86
|
+
{ key: 'inv__transfer_requests', label: 'Transfer Requests', path: '/inventory/transfer-requests', module: 'Inventory', defaultGroup: 'Transfers' },
|
|
87
|
+
{ key: 'inv__transfer_orders', label: 'Transfer Orders', path: '/inventory/transfer-orders', module: 'Inventory', defaultGroup: 'Transfers' },
|
|
88
|
+
{ key: 'inv__consignment', label: 'Consignment', path: '/inventory/consignment', module: 'Inventory', defaultGroup: 'Operations' },
|
|
89
|
+
{ key: 'inv__write_offs', label: 'Write-Offs', path: '/inventory/write-offs', module: 'Inventory', defaultGroup: 'Operations' },
|
|
90
|
+
{ key: 'inv__dashboard', label: 'Dashboard', path: '/inventory/dashboard', module: 'Inventory', defaultGroup: 'Reports' },
|
|
91
|
+
{ key: 'inv__balances', label: 'Stock Balances', path: '/inventory/balances', module: 'Inventory', defaultGroup: 'Reports' },
|
|
92
|
+
{ key: 'inv__reports', label: 'All Reports', path: '/inventory/reports', module: 'Inventory', defaultGroup: 'Reports' },
|
|
93
|
+
|
|
94
|
+
// ── Sales Module: POS channel (current implementation) ──
|
|
95
|
+
{ key: 'pos__dashboard', label: 'POS Dashboard', path: '/pos', module: 'Sales', defaultGroup: 'POS Overview' },
|
|
96
|
+
{ key: 'pos__sell', label: 'Sell Screen', path: '/pos/sell', module: 'Sales', defaultGroup: 'POS Overview' },
|
|
97
|
+
{ key: 'pos__quick_sell', label: 'Quick Sell', path: '/pos/quick-sell', module: 'Sales', defaultGroup: 'POS Overview' },
|
|
98
|
+
{ key: 'pos__terminals', label: 'Terminals', path: '/pos/terminals', module: 'Sales', defaultGroup: 'POS Configuration' },
|
|
99
|
+
{ key: 'pos__sessions', label: 'Sessions', path: '/pos/sessions', module: 'Sales', defaultGroup: 'POS Operations' },
|
|
100
|
+
{ key: 'pos__invoices', label: 'Invoices', path: '/pos/invoices', module: 'Sales', defaultGroup: 'POS Transactions' },
|
|
101
|
+
{ key: 'pos__returns', label: 'Returns', path: '/pos/returns', module: 'Sales', defaultGroup: 'POS Transactions' },
|
|
102
|
+
{ key: 'pos__reports', label: 'Sales Reports', path: '/pos/reports', module: 'Sales', defaultGroup: 'POS Reports' },
|
|
103
|
+
|
|
104
|
+
// ── Finance Module ──
|
|
105
|
+
{ key: 'fin__dashboard', label: 'Dashboard', path: '/finance', module: 'Finance', defaultGroup: 'Overview' },
|
|
106
|
+
{ key: 'fin__settings', label: 'Settings', path: '/finance/settings', module: 'Finance', defaultGroup: 'Setup' },
|
|
107
|
+
{ key: 'fin__chart_of_accounts', label: 'Chart of Accounts', path: '/finance/accounts', module: 'Finance', defaultGroup: 'General Ledger' },
|
|
108
|
+
{ key: 'fin__fiscal_periods', label: 'Fiscal Periods', path: '/finance/fiscal-periods', module: 'Finance', defaultGroup: 'General Ledger' },
|
|
109
|
+
{ key: 'fin__journal_entries', label: 'Journal Entries', path: '/finance/journals', module: 'Finance', defaultGroup: 'General Ledger' },
|
|
110
|
+
{ key: 'fin__gl_transactions', label: 'GL Transactions', path: '/finance/gl-transactions', module: 'Finance', defaultGroup: 'General Ledger' },
|
|
111
|
+
{ key: 'fin__receipts', label: 'Receipts', path: '/finance/receipts', module: 'Finance', defaultGroup: 'Receivables' },
|
|
112
|
+
{ key: 'fin__customers', label: 'Customers (AR)', path: '/finance/customers', module: 'Finance', defaultGroup: 'Receivables' },
|
|
113
|
+
{ key: 'fin__payments', label: 'Payments', path: '/finance/payments', module: 'Finance', defaultGroup: 'Payables' },
|
|
114
|
+
{ key: 'fin__vendors', label: 'Vendors (AP)', path: '/finance/vendors', module: 'Finance', defaultGroup: 'Payables' },
|
|
115
|
+
{ key: 'fin__bank_accounts', label: 'Bank Accounts', path: '/finance/bank/accounts', module: 'Finance', defaultGroup: 'Banking' },
|
|
116
|
+
{ key: 'fin__bank_transactions', label: 'Bank Transactions', path: '/finance/bank/transactions', module: 'Finance', defaultGroup: 'Banking' },
|
|
117
|
+
{ key: 'fin__bank_reconciliation', label: 'Bank Reconciliation', path: '/finance/bank/reconciliation', module: 'Finance', defaultGroup: 'Banking' },
|
|
118
|
+
{ key: 'fin__cheques', label: 'Cheque Management', path: '/finance/cheques', module: 'Finance', defaultGroup: 'Banking' },
|
|
119
|
+
{ key: 'fin__expense_income', label: 'Expense / Income', path: '/finance/expense-income', module: 'Finance', defaultGroup: 'Expense & Income' },
|
|
120
|
+
{ key: 'fin__tax_codes', label: 'Tax Codes', path: '/finance/tax/codes', module: 'Finance', defaultGroup: 'Tax' },
|
|
121
|
+
{ key: 'fin__tax_returns', label: 'Tax Returns', path: '/finance/tax/returns', module: 'Finance', defaultGroup: 'Tax' },
|
|
122
|
+
{ key: 'fin__events', label: 'Accounting Events', path: '/finance/events', module: 'Finance', defaultGroup: 'System' },
|
|
123
|
+
{ key: 'fin__reports', label: 'Reports', path: '/finance/reports', module: 'Finance', defaultGroup: 'Reports' },
|
|
124
|
+
{ key: 'fin__assets', label: 'Fixed Assets', path: '/finance/assets', module: 'Finance', defaultGroup: 'Assets' },
|
|
125
|
+
{ key: 'fin__budgets', label: 'Budgets', path: '/finance/budgets', module: 'Finance', defaultGroup: 'Budgets' },
|
|
126
|
+
{ key: 'fin__period_close', label: 'Period Close', path: '/finance/period-close', module: 'Finance', defaultGroup: 'System' },
|
|
127
|
+
|
|
128
|
+
// ── Sales Module (umbrella / back-office) ──
|
|
129
|
+
{ key: 'sales__orders', label: 'Sales Orders', path: '/sales/orders', module: 'Sales', defaultGroup: 'Orders' },
|
|
130
|
+
{ key: 'sales__invoices', label: 'Sales Invoices', path: '/sales/invoices', module: 'Sales', defaultGroup: 'Billing' },
|
|
131
|
+
{ key: 'sales__customers', label: 'Customers', path: '/sales/customers', module: 'Sales', defaultGroup: 'Customers' },
|
|
132
|
+
{ key: 'sales__quotations', label: 'Quotations', path: '/sales/quotations', module: 'Sales', defaultGroup: 'Pre-Sales' },
|
|
133
|
+
{ key: 'sales__pos', label: 'POS Workspace', path: '/pos', module: 'Sales', defaultGroup: 'Channels' },
|
|
134
|
+
{ key: 'sales__returns', label: 'Returns', path: '/sales/returns', module: 'Sales', defaultGroup: 'Returns' },
|
|
135
|
+
{ key: 'sales__reports', label: 'Sales Reports', path: '/sales/reports', module: 'Sales', defaultGroup: 'Reports' },
|
|
136
|
+
|
|
137
|
+
// ── Procurement Module ──
|
|
138
|
+
{ key: 'purch__dashboard', label: 'Dashboard', path: '/procurement', module: 'Procurement', defaultGroup: 'Overview' },
|
|
139
|
+
{ key: 'purch__suppliers', label: 'Suppliers', path: '/procurement/suppliers', module: 'Procurement', defaultGroup: 'Suppliers' },
|
|
140
|
+
{ key: 'purch__requisitions', label: 'Requisitions', path: '/procurement/requisitions', module: 'Procurement', defaultGroup: 'Purchasing' },
|
|
141
|
+
{ key: 'purch__orders', label: 'Purchase Orders', path: '/procurement/purchase-orders', module: 'Procurement', defaultGroup: 'Purchasing' },
|
|
142
|
+
{ key: 'purch__grn', label: 'Goods Receipts (GRN)', path: '/procurement/grns', module: 'Procurement', defaultGroup: 'Receiving' },
|
|
143
|
+
{ key: 'purch__returns', label: 'Purchase Returns', path: '/procurement/returns', module: 'Procurement', defaultGroup: 'Receiving' },
|
|
144
|
+
{ key: 'purch__invoices', label: 'Supplier Invoices', path: '/procurement/invoices', module: 'Procurement', defaultGroup: 'Invoicing' },
|
|
145
|
+
{ key: 'purch__consignment', label: 'Consignment', path: '/procurement/consignment', module: 'Procurement', defaultGroup: 'Consignment' },
|
|
146
|
+
{ key: 'purch__settlements', label: 'Settlements', path: '/procurement/consignment/settlements', module: 'Procurement', defaultGroup: 'Consignment' },
|
|
147
|
+
|
|
148
|
+
// ── Manufacturing Module (future) ──
|
|
149
|
+
{ key: 'mfg__bom', label: 'Bill of Materials', path: '/manufacturing/bom', module: 'Manufacturing', defaultGroup: 'Engineering' },
|
|
150
|
+
{ key: 'mfg__work_orders', label: 'Work Orders', path: '/manufacturing/work-orders', module: 'Manufacturing', defaultGroup: 'Production' },
|
|
151
|
+
{ key: 'mfg__routing', label: 'Routing', path: '/manufacturing/routing', module: 'Manufacturing', defaultGroup: 'Engineering' },
|
|
152
|
+
{ key: 'mfg__reports', label: 'Production Reports', path: '/manufacturing/reports', module: 'Manufacturing', defaultGroup: 'Reports' },
|
|
153
|
+
|
|
154
|
+
// ── HR Module (future) ──
|
|
155
|
+
{ key: 'hr__employees', label: 'Employees', path: '/hr/employees', module: 'HR', defaultGroup: 'Workforce' },
|
|
156
|
+
{ key: 'hr__attendance', label: 'Attendance', path: '/hr/attendance', module: 'HR', defaultGroup: 'Workforce' },
|
|
157
|
+
{ key: 'hr__payroll', label: 'Payroll', path: '/hr/payroll', module: 'HR', defaultGroup: 'Compensation' },
|
|
158
|
+
{ key: 'hr__leave', label: 'Leave Management', path: '/hr/leave', module: 'HR', defaultGroup: 'Workforce' },
|
|
159
|
+
{ key: 'hr__reports', label: 'HR Reports', path: '/hr/reports', module: 'HR', defaultGroup: 'Reports' },
|
|
160
|
+
|
|
161
|
+
// ── Jewelry Module ──
|
|
162
|
+
{ key: 'jwl__dashboard', label: 'Dashboard', path: '/jewelry', module: 'Jewelry', defaultGroup: 'Overview' },
|
|
163
|
+
{ key: 'jwl__metal_rates', label: 'Metal Rates', path: '/jewelry/metal-rates', module: 'Jewelry', defaultGroup: 'Setup' },
|
|
164
|
+
{ key: 'jwl__master_metals', label: 'Metal Types', path: '/jewelry/master/metals', module: 'Jewelry', defaultGroup: 'Setup' },
|
|
165
|
+
{ key: 'jwl__master_purities', label: 'Purity Master', path: '/jewelry/master/purities', module: 'Jewelry', defaultGroup: 'Setup' },
|
|
166
|
+
{ key: 'jwl__items', label: 'Jewelry Items', path: '/jewelry/items', module: 'Jewelry', defaultGroup: 'Catalog' },
|
|
167
|
+
{ key: 'jwl__stones', label: 'Loose Stones', path: '/jewelry/stones', module: 'Jewelry', defaultGroup: 'Catalog' },
|
|
168
|
+
{ key: 'jwl__certifications', label: 'Certifications', path: '/jewelry/certifications', module: 'Jewelry', defaultGroup: 'Catalog' },
|
|
169
|
+
{ key: 'jwl__karigars', label: 'Karigars', path: '/jewelry/karigars', module: 'Jewelry', defaultGroup: 'Operations' },
|
|
170
|
+
{ key: 'jwl__custom_orders', label: 'Custom Orders', path: '/jewelry/custom-orders', module: 'Jewelry', defaultGroup: 'Operations' },
|
|
171
|
+
{ key: 'jwl__repairs', label: 'Repairs', path: '/jewelry/repairs', module: 'Jewelry', defaultGroup: 'Operations' },
|
|
172
|
+
{ key: 'jwl__melting', label: 'Old Gold / Melting', path: '/jewelry/melting', module: 'Jewelry', defaultGroup: 'Operations' },
|
|
173
|
+
{ key: 'jwl__tags', label: 'Tag Printing', path: '/jewelry/tags', module: 'Jewelry', defaultGroup: 'Operations' },
|
|
174
|
+
{ key: 'jwl__refinery', label: 'Refinery Batches', path: '/jewelry/refinery', module: 'Jewelry', defaultGroup: 'Manufacturing' },
|
|
175
|
+
{ key: 'jwl__metal_issues', label: 'Metal Issues', path: '/jewelry/metal-issues', module: 'Jewelry', defaultGroup: 'Manufacturing' },
|
|
176
|
+
{ key: 'jwl__designs', label: 'Design Library', path: '/jewelry/designs', module: 'Jewelry', defaultGroup: 'Manufacturing' },
|
|
177
|
+
{ key: 'jwl__dealers', label: 'Wholesale Dealers', path: '/jewelry/dealers', module: 'Jewelry', defaultGroup: 'Sales & Billing' },
|
|
178
|
+
{ key: 'jwl__installments', label: 'Installments', path: '/jewelry/installments', module: 'Jewelry', defaultGroup: 'Sales & Billing' },
|
|
179
|
+
{ key: 'jwl__vouchers', label: 'Gift Vouchers', path: '/jewelry/vouchers', module: 'Jewelry', defaultGroup: 'Sales & Billing' },
|
|
180
|
+
{ key: 'jwl__reservations', label: 'Reservations', path: '/jewelry/reservations', module: 'Jewelry', defaultGroup: 'Sales & Billing' },
|
|
181
|
+
{ key: 'jwl__warranties', label: 'Warranties', path: '/jewelry/warranties', module: 'Jewelry', defaultGroup: 'Sales & Billing' },
|
|
182
|
+
{ key: 'jwl__notifications', label: 'Notifications Queue', path: '/jewelry/notifications', module: 'Jewelry', defaultGroup: 'System' },
|
|
183
|
+
{ key: 'jwl__reports', label: 'Reports', path: '/jewelry/reports', module: 'Jewelry', defaultGroup: 'Reports' },
|
|
184
|
+
{ key: 'jwl__pos_sell', label: 'POS Sell', path: '/jewelry/pos/sell', module: 'Jewelry', defaultGroup: 'Sales & Billing' },
|
|
185
|
+
{ key: 'jwl__pos_sales', label: 'View Sales', path: '/jewelry/pos/sales', module: 'Jewelry', defaultGroup: 'Sales & Billing' },
|
|
186
|
+
{ key: 'jwl__stone_procurement', label: 'Stone Procurement', path: '/jewelry/stone-procurement', module: 'Jewelry', defaultGroup: 'Procurement' },
|
|
187
|
+
{ key: 'jwl__consignment', label: 'Consignment Stock', path: '/jewelry/consignment', module: 'Jewelry', defaultGroup: 'Procurement' },
|
|
188
|
+
{ key: 'jwl__procurement', label: 'Purchase Orders', path: '/jewelry/procurement', module: 'Jewelry', defaultGroup: 'Procurement' },
|
|
189
|
+
{ key: 'jwl__purchase_pos', label: 'Purchase POS', path: '/jewelry/purchases', module: 'Jewelry', defaultGroup: 'Procurement' },
|
|
190
|
+
{ key: 'jwl__processing', label: 'Inventory Processing', path: '/jewelry/purchases/processing', module: 'Jewelry', defaultGroup: 'Procurement' },
|
|
191
|
+
{ key: 'jwl__purchase_returns', label: 'Purchase Returns', path: '/jewelry/purchases/returns', module: 'Jewelry', defaultGroup: 'Procurement' },
|
|
192
|
+
{ key: 'jwl__repositories', label: 'Metal Repositories', path: '/jewelry/repositories', module: 'Jewelry', defaultGroup: 'Operations' },
|
|
193
|
+
{ key: 'jwl__repository_settings', label: 'Repository Settings', path: '/jewelry/repository-settings', module: 'Jewelry', defaultGroup: 'Setup' },
|
|
194
|
+
|
|
195
|
+
// ── AI Intelligence Module ──
|
|
196
|
+
{ key: 'ai__recommendations', label: 'Recommendations', path: '/jewelry/ai/recommendations', module: 'AI', defaultGroup: 'Intelligence' },
|
|
197
|
+
{ key: 'ai__reports', label: 'AI Reports', path: '/jewelry/ai/reports', module: 'AI', defaultGroup: 'Intelligence' },
|
|
198
|
+
{ key: 'ai__anomalies', label: 'Anomalies', path: '/jewelry/ai/anomalies', module: 'AI', defaultGroup: 'Intelligence' },
|
|
199
|
+
{ key: 'ai__predictions', label: 'Predictions', path: '/jewelry/ai/predictions', module: 'AI', defaultGroup: 'Intelligence' },
|
|
200
|
+
{ key: 'ai__usage', label: 'Usage', path: '/jewelry/ai/usage', module: 'AI', defaultGroup: 'Intelligence' },
|
|
201
|
+
];
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get all unique module names from the registry.
|
|
205
|
+
*/
|
|
206
|
+
export function getRegistryModules(): string[] {
|
|
207
|
+
const modules = new Set(MENU_ITEM_REGISTRY.map(item => item.module));
|
|
208
|
+
return Array.from(modules);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Get registry items filtered by module.
|
|
213
|
+
*/
|
|
214
|
+
export function getRegistryItemsByModule(module: string): RegistryItem[] {
|
|
215
|
+
return MENU_ITEM_REGISTRY.filter(item => item.module === module);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Resolve secondary item configs into MainMenuItem groups.
|
|
220
|
+
* Accepts both plain string keys (legacy) and enriched objects with
|
|
221
|
+
* optional label / group overrides.
|
|
222
|
+
*/
|
|
223
|
+
export function resolveRegistryKeys(items: SecondaryItemConfig[]): SubMenuGroup[] {
|
|
224
|
+
const groupMap = new Map<string, SubMenuItem[]>();
|
|
225
|
+
// Track insertion order of groups
|
|
226
|
+
const groupOrder: string[] = [];
|
|
227
|
+
|
|
228
|
+
for (const raw of items) {
|
|
229
|
+
const cfg = normalizeSecondaryItem(raw);
|
|
230
|
+
const reg = MENU_ITEM_REGISTRY.find(r => r.key === cfg.key);
|
|
231
|
+
if (!reg) continue;
|
|
232
|
+
|
|
233
|
+
const groupLabel = cfg.group || reg.defaultGroup;
|
|
234
|
+
|
|
235
|
+
if (!groupMap.has(groupLabel)) {
|
|
236
|
+
groupMap.set(groupLabel, []);
|
|
237
|
+
groupOrder.push(groupLabel);
|
|
238
|
+
}
|
|
239
|
+
groupMap.get(groupLabel)!.push({
|
|
240
|
+
id: cfg.key,
|
|
241
|
+
label: cfg.label || reg.label,
|
|
242
|
+
path: reg.path,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return groupOrder.map(label => ({
|
|
247
|
+
id: label.toLowerCase().replace(/[^a-z0-9]+/g, '_'),
|
|
248
|
+
label,
|
|
249
|
+
items: groupMap.get(label)!,
|
|
250
|
+
}));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
// ─── PRESET MENU CONFIGURATIONS ──────────────────────────────────
|
|
255
|
+
// These are the default/example configs for different business types.
|
|
256
|
+
|
|
257
|
+
export interface MenuPreset {
|
|
258
|
+
id: string;
|
|
259
|
+
label: string;
|
|
260
|
+
description: string;
|
|
261
|
+
primaryMenus: {
|
|
262
|
+
id: string;
|
|
263
|
+
label: string;
|
|
264
|
+
iconName: string;
|
|
265
|
+
secondaryItems: string[]; // registry keys
|
|
266
|
+
}[];
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export const MENU_PRESETS: MenuPreset[] = [
|
|
270
|
+
{
|
|
271
|
+
id: 'default_full',
|
|
272
|
+
label: 'Full ERP',
|
|
273
|
+
description: 'All modules visible — suitable for large enterprises',
|
|
274
|
+
primaryMenus: [
|
|
275
|
+
{
|
|
276
|
+
id: 'core',
|
|
277
|
+
label: 'Core',
|
|
278
|
+
iconName: 'Settings',
|
|
279
|
+
secondaryItems: [
|
|
280
|
+
'core__users', 'core__roles', 'core__organizations',
|
|
281
|
+
'core__activity_logs', 'core__api_requests', 'core__feature_access_logs',
|
|
282
|
+
'core__issue_logs', 'core__feature_registry', 'core__menu_config',
|
|
283
|
+
],
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
id: 'inventory',
|
|
287
|
+
label: 'Inventory',
|
|
288
|
+
iconName: 'Package',
|
|
289
|
+
secondaryItems: [
|
|
290
|
+
'inv__items', 'inv__categories', 'inv__units', 'inv__supplier_items',
|
|
291
|
+
'inv__documents', 'inv__warehouses', 'inv__lots', 'inv__stock_counts', 'inv__reservations',
|
|
292
|
+
'inv__inspection', 'inv__alerts',
|
|
293
|
+
'inv__opening_balances',
|
|
294
|
+
'inv__dashboard', 'inv__balances', 'inv__reports',
|
|
295
|
+
],
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
id: 'sales',
|
|
299
|
+
label: 'Sales',
|
|
300
|
+
iconName: 'ShoppingCart',
|
|
301
|
+
secondaryItems: [
|
|
302
|
+
'pos__dashboard', 'pos__sell',
|
|
303
|
+
'pos__terminals', 'pos__sessions',
|
|
304
|
+
'pos__invoices', 'pos__returns',
|
|
305
|
+
'pos__reports',
|
|
306
|
+
],
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
id: 'finance',
|
|
310
|
+
label: 'Finance',
|
|
311
|
+
iconName: 'Landmark',
|
|
312
|
+
secondaryItems: [
|
|
313
|
+
'fin__dashboard', 'fin__settings',
|
|
314
|
+
'fin__chart_of_accounts', 'fin__fiscal_periods', 'fin__journal_entries', 'fin__gl_transactions',
|
|
315
|
+
'fin__customers', 'fin__vendors',
|
|
316
|
+
'fin__bank_accounts', 'fin__tax_codes',
|
|
317
|
+
],
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
id: 'procurement',
|
|
321
|
+
label: 'Procurement',
|
|
322
|
+
iconName: 'Truck',
|
|
323
|
+
secondaryItems: [
|
|
324
|
+
'purch__dashboard', 'purch__suppliers',
|
|
325
|
+
'purch__requisitions', 'purch__orders',
|
|
326
|
+
'purch__grn', 'purch__returns',
|
|
327
|
+
'purch__invoices',
|
|
328
|
+
'purch__consignment', 'purch__settlements',
|
|
329
|
+
],
|
|
330
|
+
},
|
|
331
|
+
],
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
id: 'small_retail',
|
|
335
|
+
label: 'Small Retail / Jewelry Shop',
|
|
336
|
+
description: 'Sales, stock, finance — simplified for small retail businesses',
|
|
337
|
+
primaryMenus: [
|
|
338
|
+
{
|
|
339
|
+
id: 'sales',
|
|
340
|
+
label: 'Sales',
|
|
341
|
+
iconName: 'ShoppingCart',
|
|
342
|
+
secondaryItems: [
|
|
343
|
+
'sales__orders', 'sales__invoices', 'sales__customers',
|
|
344
|
+
'sales__returns', 'sales__reports',
|
|
345
|
+
'pos__dashboard', 'pos__sell',
|
|
346
|
+
'pos__terminals', 'pos__sessions',
|
|
347
|
+
'pos__invoices', 'pos__returns',
|
|
348
|
+
'pos__reports',
|
|
349
|
+
],
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
id: 'stock',
|
|
353
|
+
label: 'Stock',
|
|
354
|
+
iconName: 'Package',
|
|
355
|
+
secondaryItems: [
|
|
356
|
+
'inv__items', 'inv__categories',
|
|
357
|
+
'inv__documents', 'inv__warehouses',
|
|
358
|
+
'inv__alerts', 'inv__balances',
|
|
359
|
+
],
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
id: 'purchases',
|
|
363
|
+
label: 'Purchases',
|
|
364
|
+
iconName: 'Truck',
|
|
365
|
+
secondaryItems: [
|
|
366
|
+
'purch__orders', 'purch__grn', 'purch__suppliers', 'purch__reports',
|
|
367
|
+
],
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
id: 'finance',
|
|
371
|
+
label: 'Finance',
|
|
372
|
+
iconName: 'Landmark',
|
|
373
|
+
secondaryItems: [
|
|
374
|
+
'fin__chart_of_accounts', 'fin__journal_entries',
|
|
375
|
+
'fin__invoices', 'fin__payments', 'fin__reports',
|
|
376
|
+
],
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
id: 'settings',
|
|
380
|
+
label: 'Settings',
|
|
381
|
+
iconName: 'Settings',
|
|
382
|
+
secondaryItems: [
|
|
383
|
+
'core__users', 'core__roles', 'core__organizations', 'core__menu_config',
|
|
384
|
+
],
|
|
385
|
+
},
|
|
386
|
+
],
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
id: 'enterprise_mfg',
|
|
390
|
+
label: 'Enterprise / Manufacturing',
|
|
391
|
+
description: 'Full modules with procurement, manufacturing, and inventory',
|
|
392
|
+
primaryMenus: [
|
|
393
|
+
{
|
|
394
|
+
id: 'inventory',
|
|
395
|
+
label: 'Inventory',
|
|
396
|
+
iconName: 'Warehouse',
|
|
397
|
+
secondaryItems: [
|
|
398
|
+
'inv__items', 'inv__categories', 'inv__units', 'inv__supplier_items',
|
|
399
|
+
'inv__documents', 'inv__warehouses', 'inv__lots', 'inv__stock_counts', 'inv__reservations',
|
|
400
|
+
'inv__inspection', 'inv__alerts', 'inv__opening_balances',
|
|
401
|
+
'inv__dashboard', 'inv__balances', 'inv__reports',
|
|
402
|
+
],
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
id: 'procurement',
|
|
406
|
+
label: 'Procurement',
|
|
407
|
+
iconName: 'Truck',
|
|
408
|
+
secondaryItems: [
|
|
409
|
+
'purch__requisitions', 'purch__orders', 'purch__grn',
|
|
410
|
+
'purch__suppliers', 'purch__contracts', 'purch__reports',
|
|
411
|
+
],
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
id: 'manufacturing',
|
|
415
|
+
label: 'Manufacturing',
|
|
416
|
+
iconName: 'Factory',
|
|
417
|
+
secondaryItems: [
|
|
418
|
+
'mfg__bom', 'mfg__work_orders', 'mfg__routing', 'mfg__reports',
|
|
419
|
+
],
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
id: 'finance',
|
|
423
|
+
label: 'Finance',
|
|
424
|
+
iconName: 'Landmark',
|
|
425
|
+
secondaryItems: [
|
|
426
|
+
'fin__chart_of_accounts', 'fin__journal_entries',
|
|
427
|
+
'fin__bank_accounts', 'fin__reconciliation',
|
|
428
|
+
'fin__invoices', 'fin__payments', 'fin__reports',
|
|
429
|
+
],
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
id: 'hr',
|
|
433
|
+
label: 'HR',
|
|
434
|
+
iconName: 'Users',
|
|
435
|
+
secondaryItems: [
|
|
436
|
+
'hr__employees', 'hr__attendance', 'hr__payroll', 'hr__leave', 'hr__reports',
|
|
437
|
+
],
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
id: 'admin',
|
|
441
|
+
label: 'Admin',
|
|
442
|
+
iconName: 'Settings',
|
|
443
|
+
secondaryItems: [
|
|
444
|
+
'core__users', 'core__roles', 'core__organizations',
|
|
445
|
+
'core__activity_logs', 'core__menu_config',
|
|
446
|
+
],
|
|
447
|
+
},
|
|
448
|
+
],
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
id: 'services_company',
|
|
452
|
+
label: 'Services Company',
|
|
453
|
+
description: 'HR, finance, and client management for service businesses',
|
|
454
|
+
primaryMenus: [
|
|
455
|
+
{
|
|
456
|
+
id: 'clients',
|
|
457
|
+
label: 'Clients',
|
|
458
|
+
iconName: 'Handshake',
|
|
459
|
+
secondaryItems: [
|
|
460
|
+
'sales__customers', 'sales__quotations', 'sales__orders',
|
|
461
|
+
'sales__invoices', 'sales__reports',
|
|
462
|
+
],
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
id: 'team',
|
|
466
|
+
label: 'Team',
|
|
467
|
+
iconName: 'Users',
|
|
468
|
+
secondaryItems: [
|
|
469
|
+
'hr__employees', 'hr__attendance', 'hr__leave', 'hr__payroll', 'hr__reports',
|
|
470
|
+
],
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
id: 'finance',
|
|
474
|
+
label: 'Finance',
|
|
475
|
+
iconName: 'Landmark',
|
|
476
|
+
secondaryItems: [
|
|
477
|
+
'fin__chart_of_accounts', 'fin__journal_entries',
|
|
478
|
+
'fin__invoices', 'fin__payments', 'fin__reports',
|
|
479
|
+
],
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
id: 'settings',
|
|
483
|
+
label: 'Settings',
|
|
484
|
+
iconName: 'Settings',
|
|
485
|
+
secondaryItems: [
|
|
486
|
+
'core__users', 'core__roles', 'core__organizations', 'core__menu_config',
|
|
487
|
+
],
|
|
488
|
+
},
|
|
489
|
+
],
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
id: 'jewelry_shop',
|
|
493
|
+
label: 'Jewelry Shop',
|
|
494
|
+
description: 'Specialized for jewelry retail with metal rates, stones, karigars, and custom orders',
|
|
495
|
+
primaryMenus: [
|
|
496
|
+
{
|
|
497
|
+
id: 'dashboard',
|
|
498
|
+
label: 'Dashboard',
|
|
499
|
+
iconName: 'LayoutDashboard',
|
|
500
|
+
secondaryItems: [
|
|
501
|
+
'jwl__dashboard', 'jwl__metal_rates',
|
|
502
|
+
'jwl__reports', 'jwl__notifications',
|
|
503
|
+
'ai__recommendations', 'ai__reports', 'ai__anomalies', 'ai__predictions', 'ai__usage',
|
|
504
|
+
],
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
id: 'catalog',
|
|
508
|
+
label: 'Catalog',
|
|
509
|
+
iconName: 'Gem',
|
|
510
|
+
secondaryItems: [
|
|
511
|
+
'jwl__items', 'jwl__stones', 'jwl__certifications',
|
|
512
|
+
'jwl__master_metals', 'jwl__master_purities',
|
|
513
|
+
'jwl__tags', 'jwl__designs',
|
|
514
|
+
'inv__categories', 'inv__units',
|
|
515
|
+
],
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
id: 'sales',
|
|
519
|
+
label: 'Sales & POS',
|
|
520
|
+
iconName: 'ShoppingCart',
|
|
521
|
+
secondaryItems: [
|
|
522
|
+
'jwl__pos_sell', 'jwl__pos_sales',
|
|
523
|
+
'jwl__dealers', 'jwl__installments',
|
|
524
|
+
'jwl__vouchers', 'jwl__reservations',
|
|
525
|
+
'jwl__warranties', 'jwl__melting',
|
|
526
|
+
],
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
id: 'orders',
|
|
530
|
+
label: 'Orders',
|
|
531
|
+
iconName: 'ClipboardList',
|
|
532
|
+
secondaryItems: [
|
|
533
|
+
'jwl__custom_orders', 'jwl__repairs',
|
|
534
|
+
'jwl__karigars',
|
|
535
|
+
],
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
id: 'manufacturing',
|
|
539
|
+
label: 'Manufacturing',
|
|
540
|
+
iconName: 'Factory',
|
|
541
|
+
secondaryItems: [
|
|
542
|
+
'jwl__refinery', 'jwl__metal_issues', 'jwl__repositories',
|
|
543
|
+
],
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
id: 'procurement',
|
|
547
|
+
label: 'Procurement',
|
|
548
|
+
iconName: 'Truck',
|
|
549
|
+
secondaryItems: [
|
|
550
|
+
'jwl__purchase_pos', 'jwl__processing', 'jwl__purchase_returns',
|
|
551
|
+
'jwl__stone_procurement', 'jwl__consignment', 'jwl__procurement',
|
|
552
|
+
'purch__suppliers', 'purch__orders', 'purch__grn',
|
|
553
|
+
'purch__consignment', 'purch__settlements',
|
|
554
|
+
],
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
id: 'stock',
|
|
558
|
+
label: 'Stock',
|
|
559
|
+
iconName: 'Package',
|
|
560
|
+
secondaryItems: [
|
|
561
|
+
'inv__items', 'inv__documents', 'inv__warehouses', 'inv__lots',
|
|
562
|
+
'inv__alerts', 'inv__balances', 'inv__reports',
|
|
563
|
+
],
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
id: 'finance',
|
|
567
|
+
label: 'Finance',
|
|
568
|
+
iconName: 'Landmark',
|
|
569
|
+
secondaryItems: [
|
|
570
|
+
'fin__chart_of_accounts', 'fin__journal_entries',
|
|
571
|
+
'fin__customers', 'fin__vendors',
|
|
572
|
+
'fin__bank_accounts', 'fin__tax_codes',
|
|
573
|
+
],
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
id: 'settings',
|
|
577
|
+
label: 'Settings',
|
|
578
|
+
iconName: 'Settings',
|
|
579
|
+
secondaryItems: [
|
|
580
|
+
'core__users', 'core__roles', 'core__organizations', 'core__menu_config',
|
|
581
|
+
'jwl__repository_settings',
|
|
582
|
+
],
|
|
583
|
+
},
|
|
584
|
+
],
|
|
585
|
+
},
|
|
586
|
+
];
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
// ─── DEFAULT APP MENUS (legacy / fallback) ───────────────────────
|
|
590
|
+
// This is the current static config, used when no custom config exists.
|
|
591
|
+
|
|
592
|
+
export const APP_MENUS: MainMenuItem[] = [
|
|
593
|
+
{
|
|
594
|
+
id: "core",
|
|
595
|
+
label: "Core",
|
|
596
|
+
iconName: "Settings", // Translates to Settings icon from lucide-react
|
|
597
|
+
groups: [
|
|
598
|
+
{
|
|
599
|
+
id: "core_users",
|
|
600
|
+
label: "User Management",
|
|
601
|
+
items: [
|
|
602
|
+
{ id: "users", label: "Users", path: "/users" },
|
|
603
|
+
{ id: "roles", label: "Roles", path: "/roles" },
|
|
604
|
+
{ id: "organizations", label: "Organizations", path: "/organizations" },
|
|
605
|
+
],
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
id: "core_system",
|
|
609
|
+
label: "System",
|
|
610
|
+
items: [
|
|
611
|
+
{ id: "menu_config", label: "Menu Configuration", path: "/menu-config" },
|
|
612
|
+
],
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
id: "core_audit",
|
|
616
|
+
label: "System Auditing",
|
|
617
|
+
items: [
|
|
618
|
+
{ id: "activity_logs", label: "Activity Logs", path: "/activity-logs" },
|
|
619
|
+
{ id: "api_requests", label: "API Requests", path: "/system/api-requests" },
|
|
620
|
+
{ id: "feature_access_logs", label: "Feature Access Logs", path: "/system/feature-access-logs" },
|
|
621
|
+
{ id: "issue_logs", label: "Issue Logs", path: "/system/issue-logs" },
|
|
622
|
+
{ id: "feature_registry", label: "Feature Registry", path: "/system/features" },
|
|
623
|
+
],
|
|
624
|
+
},
|
|
625
|
+
],
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
id: "inventory",
|
|
629
|
+
label: "Inventory",
|
|
630
|
+
iconName: "Package", // Translates to Package icon from lucide-react
|
|
631
|
+
groups: [
|
|
632
|
+
{
|
|
633
|
+
id: "inv_catalog",
|
|
634
|
+
label: "Catalog",
|
|
635
|
+
items: [
|
|
636
|
+
{ id: "items", label: "Items", path: "/inventory/items" },
|
|
637
|
+
{ id: "categories", label: "Categories", path: "/inventory/categories" },
|
|
638
|
+
{ id: "units", label: "Units", path: "/inventory/units" },
|
|
639
|
+
{ id: "supplier_items", label: "Supplier Items", path: "/inventory/supplier-items" },
|
|
640
|
+
],
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
id: "inv_stock",
|
|
644
|
+
label: "Stock Control",
|
|
645
|
+
items: [
|
|
646
|
+
{ id: "documents", label: "Stock Documents", path: "/inventory/documents" },
|
|
647
|
+
{ id: "warehouses", label: "Warehouses", path: "/inventory/warehouses" },
|
|
648
|
+
{ id: "lots", label: "Lots & Serials", path: "/inventory/lots" },
|
|
649
|
+
{ id: "stock_counts", label: "Stock Counts", path: "/inventory/stock-counts" },
|
|
650
|
+
{ id: "reservations", label: "Reservations", path: "/inventory/reservations" },
|
|
651
|
+
],
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
id: "inv_transfers",
|
|
655
|
+
label: "Transfers",
|
|
656
|
+
items: [
|
|
657
|
+
{ id: "transfer_requests", label: "Transfer Requests", path: "/inventory/transfer-requests" },
|
|
658
|
+
{ id: "transfer_orders", label: "Transfer Orders", path: "/inventory/transfer-orders" },
|
|
659
|
+
],
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
id: "inv_quality",
|
|
663
|
+
label: "Quality & Alerts",
|
|
664
|
+
items: [
|
|
665
|
+
{ id: "inspection", label: "Inspection", path: "/inventory/inspection" },
|
|
666
|
+
{ id: "alerts", label: "Stock Alerts", path: "/inventory/alerts" },
|
|
667
|
+
],
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
id: "inv_operations",
|
|
671
|
+
label: "Operations",
|
|
672
|
+
items: [
|
|
673
|
+
{ id: "opening_balances", label: "Opening Balances", path: "/inventory/opening-balances" },
|
|
674
|
+
{ id: "write_offs", label: "Write-Offs", path: "/inventory/write-offs" },
|
|
675
|
+
{ id: "consignment", label: "Consignment", path: "/inventory/consignment" },
|
|
676
|
+
],
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
id: "inv_reports",
|
|
680
|
+
label: "Reports",
|
|
681
|
+
items: [
|
|
682
|
+
{ id: "dashboard", label: "Dashboard", path: "/inventory/dashboard" },
|
|
683
|
+
{ id: "balances", label: "Stock Balances", path: "/inventory/balances" },
|
|
684
|
+
{ id: "reports", label: "All Reports", path: "/inventory/reports" },
|
|
685
|
+
],
|
|
686
|
+
},
|
|
687
|
+
],
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
id: "sales",
|
|
691
|
+
label: "Sales",
|
|
692
|
+
iconName: "ShoppingCart",
|
|
693
|
+
groups: [
|
|
694
|
+
{
|
|
695
|
+
id: "sales_pos_overview",
|
|
696
|
+
label: "POS Overview",
|
|
697
|
+
items: [
|
|
698
|
+
{ id: "pos_dashboard", label: "POS Dashboard", path: "/pos" },
|
|
699
|
+
{ id: "pos_sell", label: "Sell Screen", path: "/pos/sell" },
|
|
700
|
+
{ id: "pos_quick_sell", label: "Quick Sell", path: "/pos/quick-sell" },
|
|
701
|
+
],
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
id: "sales_pos_ops",
|
|
705
|
+
label: "POS Operations",
|
|
706
|
+
items: [
|
|
707
|
+
{ id: "pos_terminals", label: "Terminals", path: "/pos/terminals" },
|
|
708
|
+
{ id: "pos_sessions", label: "Sessions", path: "/pos/sessions" },
|
|
709
|
+
],
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
id: "sales_pos_transactions",
|
|
713
|
+
label: "POS Transactions",
|
|
714
|
+
items: [
|
|
715
|
+
{ id: "pos_invoices", label: "Invoices", path: "/pos/invoices" },
|
|
716
|
+
{ id: "pos_returns", label: "Returns", path: "/pos/returns" },
|
|
717
|
+
],
|
|
718
|
+
},
|
|
719
|
+
{
|
|
720
|
+
id: "sales_pos_reports",
|
|
721
|
+
label: "POS Reports",
|
|
722
|
+
items: [
|
|
723
|
+
{ id: "pos_reports", label: "Sales Reports", path: "/pos/reports" },
|
|
724
|
+
],
|
|
725
|
+
},
|
|
726
|
+
],
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
id: "finance",
|
|
730
|
+
label: "Finance",
|
|
731
|
+
iconName: "Landmark",
|
|
732
|
+
groups: [
|
|
733
|
+
{
|
|
734
|
+
id: "fin_overview",
|
|
735
|
+
label: "Overview",
|
|
736
|
+
items: [
|
|
737
|
+
{ id: "fin_dashboard", label: "Dashboard", path: "/finance" },
|
|
738
|
+
{ id: "fin_settings", label: "Settings", path: "/finance/settings" },
|
|
739
|
+
],
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
id: "fin_gl",
|
|
743
|
+
label: "General Ledger",
|
|
744
|
+
items: [
|
|
745
|
+
{ id: "chart_of_accounts", label: "Chart of Accounts", path: "/finance/accounts" },
|
|
746
|
+
{ id: "fiscal_periods", label: "Fiscal Periods", path: "/finance/fiscal-periods" },
|
|
747
|
+
{ id: "journals", label: "Journal Entries", path: "/finance/journals" },
|
|
748
|
+
{ id: "gl_transactions", label: "GL Transactions", path: "/finance/gl-transactions" },
|
|
749
|
+
],
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
id: "fin_receivables",
|
|
753
|
+
label: "Receivables (AR)",
|
|
754
|
+
items: [
|
|
755
|
+
{ id: "receipts", label: "Receipts", path: "/finance/receipts" },
|
|
756
|
+
{ id: "customers", label: "Customers", path: "/finance/customers" },
|
|
757
|
+
],
|
|
758
|
+
},
|
|
759
|
+
{
|
|
760
|
+
id: "fin_payables",
|
|
761
|
+
label: "Payables (AP)",
|
|
762
|
+
items: [
|
|
763
|
+
{ id: "payments", label: "Payments", path: "/finance/payments" },
|
|
764
|
+
{ id: "vendors", label: "Vendors", path: "/finance/vendors" },
|
|
765
|
+
],
|
|
766
|
+
},
|
|
767
|
+
{
|
|
768
|
+
id: "fin_banking",
|
|
769
|
+
label: "Banking",
|
|
770
|
+
items: [
|
|
771
|
+
{ id: "bank_accounts", label: "Bank Accounts", path: "/finance/bank/accounts" },
|
|
772
|
+
{ id: "bank_transactions", label: "Bank Transactions", path: "/finance/bank/transactions" },
|
|
773
|
+
{ id: "bank_reconciliation", label: "Reconciliation", path: "/finance/bank/reconciliation" },
|
|
774
|
+
{ id: "cheques", label: "Cheque Management", path: "/finance/cheques" },
|
|
775
|
+
],
|
|
776
|
+
},
|
|
777
|
+
{
|
|
778
|
+
id: "fin_expense_income",
|
|
779
|
+
label: "Expense & Income",
|
|
780
|
+
items: [
|
|
781
|
+
{ id: "expense_income", label: "Categories & Transactions", path: "/finance/expense-income" },
|
|
782
|
+
],
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
id: "fin_tax",
|
|
786
|
+
label: "Tax",
|
|
787
|
+
items: [
|
|
788
|
+
{ id: "tax_codes", label: "Tax Codes", path: "/finance/tax/codes" },
|
|
789
|
+
{ id: "tax_returns", label: "Tax Returns", path: "/finance/tax/returns" },
|
|
790
|
+
],
|
|
791
|
+
},
|
|
792
|
+
{
|
|
793
|
+
id: "fin_advanced",
|
|
794
|
+
label: "Advanced",
|
|
795
|
+
items: [
|
|
796
|
+
{ id: "assets", label: "Fixed Assets", path: "/finance/assets" },
|
|
797
|
+
{ id: "budgets", label: "Budgets", path: "/finance/budgets" },
|
|
798
|
+
{ id: "events", label: "Accounting Events", path: "/finance/events" },
|
|
799
|
+
{ id: "reports", label: "Reports", path: "/finance/reports" },
|
|
800
|
+
{ id: "period_close", label: "Period Close", path: "/finance/period-close" },
|
|
801
|
+
],
|
|
802
|
+
},
|
|
803
|
+
],
|
|
804
|
+
},
|
|
805
|
+
{
|
|
806
|
+
id: "procurement",
|
|
807
|
+
label: "Procurement",
|
|
808
|
+
iconName: "Truck",
|
|
809
|
+
groups: [
|
|
810
|
+
{
|
|
811
|
+
id: "purch_overview",
|
|
812
|
+
label: "Overview",
|
|
813
|
+
items: [
|
|
814
|
+
{ id: "purch_dashboard", label: "Dashboard", path: "/procurement" },
|
|
815
|
+
],
|
|
816
|
+
},
|
|
817
|
+
{
|
|
818
|
+
id: "purch_suppliers",
|
|
819
|
+
label: "Suppliers",
|
|
820
|
+
items: [
|
|
821
|
+
{ id: "suppliers", label: "Suppliers", path: "/procurement/suppliers" },
|
|
822
|
+
],
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
id: "purch_purchasing",
|
|
826
|
+
label: "Purchasing",
|
|
827
|
+
items: [
|
|
828
|
+
{ id: "requisitions", label: "Requisitions", path: "/procurement/requisitions" },
|
|
829
|
+
{ id: "purchase_orders", label: "Purchase Orders", path: "/procurement/purchase-orders" },
|
|
830
|
+
],
|
|
831
|
+
},
|
|
832
|
+
{
|
|
833
|
+
id: "purch_receiving",
|
|
834
|
+
label: "Receiving",
|
|
835
|
+
items: [
|
|
836
|
+
{ id: "grns", label: "Goods Receipts (GRN)", path: "/procurement/grns" },
|
|
837
|
+
{ id: "returns", label: "Purchase Returns", path: "/procurement/returns" },
|
|
838
|
+
],
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
id: "purch_invoicing",
|
|
842
|
+
label: "Invoicing",
|
|
843
|
+
items: [
|
|
844
|
+
{ id: "invoices", label: "Supplier Invoices", path: "/procurement/invoices" },
|
|
845
|
+
],
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
id: "purch_consignment",
|
|
849
|
+
label: "Consignment",
|
|
850
|
+
items: [
|
|
851
|
+
{ id: "consignment", label: "Agreements", path: "/procurement/consignment" },
|
|
852
|
+
{ id: "settlements", label: "Settlements", path: "/procurement/consignment/settlements" },
|
|
853
|
+
],
|
|
854
|
+
},
|
|
855
|
+
],
|
|
856
|
+
},
|
|
857
|
+
{
|
|
858
|
+
id: "jewelry",
|
|
859
|
+
label: "Jewelry",
|
|
860
|
+
iconName: "Gem",
|
|
861
|
+
groups: [
|
|
862
|
+
{
|
|
863
|
+
id: "jwl_overview",
|
|
864
|
+
label: "Overview",
|
|
865
|
+
items: [
|
|
866
|
+
{ id: "jwl_dashboard", label: "Dashboard", path: "/jewelry" },
|
|
867
|
+
{ id: "jwl_metal_rates", label: "Metal Rates", path: "/jewelry/metal-rates" },
|
|
868
|
+
],
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
id: "jwl_setup",
|
|
872
|
+
label: "Master Data",
|
|
873
|
+
items: [
|
|
874
|
+
{ id: "jwl_master_metals", label: "Metal Types", path: "/jewelry/master/metals" },
|
|
875
|
+
{ id: "jwl_master_purities", label: "Purity Master", path: "/jewelry/master/purities" },
|
|
876
|
+
{ id: "jwl_repo_settings", label: "Repository Settings", path: "/jewelry/repository-settings" },
|
|
877
|
+
],
|
|
878
|
+
},
|
|
879
|
+
{
|
|
880
|
+
id: "jwl_catalog",
|
|
881
|
+
label: "Catalog",
|
|
882
|
+
items: [
|
|
883
|
+
{ id: "jwl_items", label: "Jewelry Items", path: "/jewelry/items" },
|
|
884
|
+
{ id: "jwl_stones", label: "Loose Stones", path: "/jewelry/stones" },
|
|
885
|
+
{ id: "jwl_certifications", label: "Certifications", path: "/jewelry/certifications" },
|
|
886
|
+
],
|
|
887
|
+
},
|
|
888
|
+
{
|
|
889
|
+
id: "jwl_operations",
|
|
890
|
+
label: "Operations",
|
|
891
|
+
items: [
|
|
892
|
+
{ id: "jwl_karigars", label: "Karigars", path: "/jewelry/karigars" },
|
|
893
|
+
{ id: "jwl_custom_orders", label: "Custom Orders", path: "/jewelry/custom-orders" },
|
|
894
|
+
{ id: "jwl_repairs", label: "Repairs", path: "/jewelry/repairs" },
|
|
895
|
+
{ id: "jwl_melting", label: "Old Gold / Melting", path: "/jewelry/melting" },
|
|
896
|
+
],
|
|
897
|
+
},
|
|
898
|
+
{
|
|
899
|
+
id: "jwl_manufacturing",
|
|
900
|
+
label: "Manufacturing",
|
|
901
|
+
items: [
|
|
902
|
+
{ id: "jwl_refinery", label: "Refinery Batches", path: "/jewelry/refinery" },
|
|
903
|
+
{ id: "jwl_metal_issues", label: "Metal Issues", path: "/jewelry/metal-issues" },
|
|
904
|
+
{ id: "jwl_designs", label: "Design Library", path: "/jewelry/designs" },
|
|
905
|
+
{ id: "jwl_repositories", label: "Metal Repositories", path: "/jewelry/repositories" },
|
|
906
|
+
],
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
id: "jwl_procurement",
|
|
910
|
+
label: "Procurement",
|
|
911
|
+
items: [
|
|
912
|
+
{ id: "jwl_purchase_pos", label: "Purchase POS", path: "/jewelry/purchases" },
|
|
913
|
+
{ id: "jwl_processing", label: "Inventory Processing", path: "/jewelry/purchases/processing" },
|
|
914
|
+
{ id: "jwl_purchase_returns", label: "Purchase Returns", path: "/jewelry/purchases/returns" },
|
|
915
|
+
{ id: "jwl_stone_procurement", label: "Stone Procurement", path: "/jewelry/stone-procurement" },
|
|
916
|
+
{ id: "jwl_consignment", label: "Consignment Stock", path: "/jewelry/consignment" },
|
|
917
|
+
{ id: "jwl_procurement_orders", label: "Purchase Orders", path: "/jewelry/procurement" },
|
|
918
|
+
],
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
id: "jwl_sales_billing",
|
|
922
|
+
label: "Sales & Billing",
|
|
923
|
+
items: [
|
|
924
|
+
{ id: "jwl_pos_sell", label: "POS Sell", path: "/jewelry/pos/sell" },
|
|
925
|
+
{ id: "jwl_pos_sales", label: "View Sales", path: "/jewelry/pos/sales" },
|
|
926
|
+
{ id: "jwl_dealers", label: "Wholesale Dealers", path: "/jewelry/dealers" },
|
|
927
|
+
{ id: "jwl_installments", label: "Installments", path: "/jewelry/installments" },
|
|
928
|
+
{ id: "jwl_vouchers", label: "Gift Vouchers", path: "/jewelry/vouchers" },
|
|
929
|
+
{ id: "jwl_reservations", label: "Reservations", path: "/jewelry/reservations" },
|
|
930
|
+
{ id: "jwl_warranties", label: "Warranties", path: "/jewelry/warranties" },
|
|
931
|
+
],
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
id: "jwl_reports",
|
|
935
|
+
label: "Reports",
|
|
936
|
+
items: [
|
|
937
|
+
{ id: "jwl_reports", label: "Reports & Analytics", path: "/jewelry/reports" },
|
|
938
|
+
],
|
|
939
|
+
},
|
|
940
|
+
{
|
|
941
|
+
id: "jwl_system",
|
|
942
|
+
label: "System",
|
|
943
|
+
items: [
|
|
944
|
+
{ id: "jwl_notifications", label: "Notifications Queue", path: "/jewelry/notifications" },
|
|
945
|
+
],
|
|
946
|
+
},
|
|
947
|
+
{
|
|
948
|
+
id: "jwl_ai",
|
|
949
|
+
label: "AI Intelligence",
|
|
950
|
+
items: [
|
|
951
|
+
{ id: "ai_recommendations", label: "Recommendations", path: "/jewelry/ai/recommendations" },
|
|
952
|
+
{ id: "ai_reports", label: "AI Reports", path: "/jewelry/ai/reports" },
|
|
953
|
+
{ id: "ai_anomalies", label: "Anomalies", path: "/jewelry/ai/anomalies" },
|
|
954
|
+
{ id: "ai_predictions", label: "Predictions", path: "/jewelry/ai/predictions" },
|
|
955
|
+
{ id: "ai_usage", label: "Usage", path: "/jewelry/ai/usage" },
|
|
956
|
+
],
|
|
957
|
+
},
|
|
958
|
+
],
|
|
959
|
+
},
|
|
960
|
+
];
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* Builds MainMenuItem[] from a saved menu config (from the API).
|
|
964
|
+
* Supports both legacy string[] and enriched SecondaryItemConfig[] formats.
|
|
965
|
+
*/
|
|
966
|
+
export function buildMenusFromConfig(config: {
|
|
967
|
+
primaryMenus: { id: string; label: string; iconName: string; secondaryItems: SecondaryItemConfig[] }[];
|
|
968
|
+
}): MainMenuItem[] {
|
|
969
|
+
return config.primaryMenus.map(pm => ({
|
|
970
|
+
id: pm.id,
|
|
971
|
+
label: pm.label,
|
|
972
|
+
iconName: pm.iconName,
|
|
973
|
+
groups: resolveRegistryKeys(pm.secondaryItems),
|
|
974
|
+
}));
|
|
975
|
+
}
|