// Ported from legacy henza_admin/src/layouts/components/vertical-nav-menu/navMenuItems.js // // Converted MECHANICALLY from the legacy file (see scratchpad/convert_menu.js) so // that every Farsi label, permissionId, url, slug and icon survives byte-exact. // The only edits are structural: the legacy `import {isBranch}` and the trailing // const menu = isBranch() ? branchMenu : adminMenu // are replaced by exporting both trees plus a getMenu() selector, so the choice // happens at the call site instead of at module load. // // Node shapes present in the legacy data (field census across 611 lines): // url x76, i18n x78, permissionId x74, slug x53, icon x33, submenu x19, header x2 // A "header" node is a section divider carrying `items`, not `submenu`. // // Legacy quirks preserved deliberately (see docs/ADMIN-PORT-PLAN.md): // - several nodes repeat the same permissionId or reuse another view's `name` // // Two further legacy quirks were fixed rather than preserved, since both were // bugs (not intentional behaviour) and each has since caused real confusion: // - banker-list / shopkeeper-list had their permissionId commented out, so // the items showed for everyone even though the backing endpoints // (admin/customers-omde/banker|shopkeeper/list) require // persons.list.client.omde and 403'd on an unauthorized click. Filled in. // - "newsletters.newsletters" never matched any rid in ALL_RIDS (the real // one is "newsletters"), so the item was invisible to every user, // including super-admin. Corrected to "newsletters". // "wallet.list" is a real, seeded rid (see acl.constants.ts) and was never // actually broken — the old note above was itself mistaken. import { isBranch } from '../utils'; export interface NavMenuNode { url?: string | null; name?: string; slug?: string; icon?: string; i18n?: string; tag?: string; tagColor?: string; permissionId?: string; /** Shown to the super admin only, whatever the rid (see utils/superAdmin.ts). */ superAdminOnly?: boolean; header?: string; items?: NavMenuNode[]; submenu?: NavMenuNode[]; } export const adminMenu: NavMenuNode[] = [ { // "آمار عمده فروشی" and "آمار تک فروشی" were two submenu entries behind // two rids, pointing at two near-duplicate dashboards. Merged into one // link behind one rid (dashboard.view) — see Dashboard.vue. url: '/dashboard/ecommerce', name: 'پیشخوان', // tag: '2', tagColor: 'warning', icon: 'HomeIcon', i18n: 'پیشخوان', permissionId:"dashboard.view", }, { header: 'Apps', icon: 'PackageIcon', i18n: 'کاربری', items: [ { url: null, name: 'User', icon: 'UserIcon', i18n: 'اشخاص', permissionId:"persons", submenu: [ // Restored per request: the add button on OmdeList only covers // wholesale customers, so removing this entry left no nav path to // the general "add person" form. { url: '/customer/add', name: 'AddCustomer', slug: 'add-customer', i18n: 'اضافه کردن شخص', permissionId:"persons.create" }, { url: '/customer/reagent-list', name: 'List', slug: 'raegentList', i18n: 'لیست کارشناسان فروش', permissionId:"persons.list.sellers" }, { url: '/customer/omde-list', name: 'List', slug: 'omde-customer-list', i18n: 'لیست مشتریان عمده', permissionId:"persons.list.client.omde" }, { url: '/customer/omde-non-verified-list', name: 'List', slug: 'omde-non-verified-list', i18n: 'لیست مشتریان در انتظار', permissionId:"persons.list.client.omde" }, { url: '/customer/omde-archived-list', name: 'List', slug: 'omde-archived-list', i18n: 'لیست مشتریان بایگانی', permissionId:"persons.list.client.omde" }, { url: '/customer/list', name: 'List', slug: 'app-user-list', i18n: 'لیست مشتریان تک', permissionId:"persons.list.client.single", superAdminOnly: true }, { url: '/customer/banker-list', name: 'List', slug: 'banker-list', i18n: 'لیست بنکداران', // Legacy left this rid commented out, so the item showed for // everyone regardless of permission — a bug, not a feature: the // API route it points at (admin/customers-omde/banker/list) is // gated on exactly this rid, so an unauthorized click 403'd. // Filled in to match what the server actually enforces. permissionId:"persons.list.client.omde", superAdminOnly: true }, { // legacy navMenuItems.js:90 spelled this with a capital S while the route // is '/customer/shopkeeper-list'. Case-sensitive in vue-router 4, so the // menu item dead-ended at the 404 page. Lowercased to match the route. url: '/customer/shopkeeper-list', name: 'List', slug: 'shopkeeper-list', i18n: 'لیست مغازه داران حضوری', // Same fix as banker-list above — the backing endpoint // (admin/customers-omde/shopkeeper/list) requires this rid. permissionId:"persons.list.client.omde", superAdminOnly: true }, ] }, { // Grouped per request: "شعب" and "کارگاه" used to be two separate // top-level entries; they are now one group with each nested inside // as its own submenu, same shape as the other grouped sections. url: null, name: 'branch and workshop', icon: 'GridIcon', i18n: 'شعب و کارگاه', superAdminOnly: true, submenu: [ { url: null, name: 'Branch', icon: 'GridIcon', i18n: 'شعب', permissionId:"branch", submenu: [ // 'افزودن شعب' removed: it is now the add button on the branch // list page. The /branch/add route still works. { url: '/branch/list', name: 'BranchList', slug: 'branch-list', i18n: 'لیست شعب', permissionId:"branch.list" }, ] }, { url: null, name: 'Workshop', icon: 'GridIcon', i18n: 'کارگاه', permissionId:"workshop", submenu: [ // 'افزودن کارگاه' removed: it is now the add button on the // workshop list page. The /workshop/add route still works. { url: '/workshop/list', name: 'WorkshopList', slug: 'workshop-list', i18n: 'لیست کارگاه ها', permissionId:"workshop.list" }, ] }, ] }, ///////////////////////////////////////////// { url: null, name: 'eCommerce', icon: 'ShoppingBagIcon', i18n: 'محصولات', permissionId:"product", submenu: [ { url: '/apps/product/add', name: 'AddProduct', slug: 'add-product', i18n: 'افزودن محصول', permissionId:"product.create" }, { url: '/apps/product/list', name: 'ProductList', slug: 'product-list', i18n: 'محصولات', permissionId:"product.list" }, { url: '/product/change/percent', name: 'changePercent', slug: 'change-Percent', i18n: 'تغییر درصد محصولات', permissionId:"product.percent" }, ] }, { url: null, name: 'order', icon: 'BoxIcon', i18n: 'سفارش ها', permissionId:"order", submenu: [ { url: '/order/create', name: 'orderOmdeList', slug: 'order-omde-list', i18n: 'ثبت سفارش تک', permissionId:"order.create", superAdminOnly: true }, { url: '/order/list', name: 'orderList', slug: 'order-list', i18n: 'لیست سفارش های تک', permissionId:"order.list", superAdminOnly: true }, { url: '/order/make', name: 'makeOrder', slug: 'order-makeOrder', i18n: 'سفارش های ساختنی', permissionId:"order.makeOrder" }, { url: '/order/omde-list', name: 'orderOmdeList', slug: 'order-omde-list', i18n: 'لیست سفارش های عمده', permissionId:"order.omde" }, { url: '/order/tamin-list', name: 'orderTaminList', slug: 'order-tamin-list', i18n: 'لیست تامین', permissionId:"order.tamin" } ] }, { url: null, name: 'users', icon: 'UserIcon', i18n: 'مدیران', permissionId:"user", submenu: [ { url: '/permission', name: 'permission', slug: 'user-permission', i18n: 'دسترسی ها', permissionId:"user.permission" }, // 'افزودن مدیر' removed: it is now the add button on the admin list // page (ListUser). The /user/create route still works. { url: '/user/list', name: 'UserList', slug: 'user-list', i18n: 'لیست مدیران', permissionId:"user.list" }, ] }, { url: null, name: 'report', icon: 'GiftIcon', i18n: 'تخفیفات', permissionId:"offers", submenu: [ // 'تعریف تخفیف تک' removed: it is now one of the two add buttons on // the promotions list page. The /major/promotion/tak/add route // still works. { url: '/major/promotion/autopromotion', name: 'major_promotion_list', slug: 'major_promotion_list', i18n: 'تخفیف اتوماتیک ', permissionId:"offers.autopromotion" }, // 'تعریف تخفیف عمده' removed: it is now the other add button on the // promotions list page. The /major/promotion/add route still works. { url: '/major/promotion/list', name: 'major_promotion_list', slug: 'major_promotion_list', i18n: 'لیست تخفیفات ', permissionId:"offers.list" }, // Moved under "تخفیفات" per request — was a top-level entry. { name: 'report', icon: 'SlashIcon', i18n: 'استثناعات تخفیف', permissionId:"offersIgnore", url: '/major/offersIgnore', slug: 'offersIgnore', }, ] }, { // Grouped per request: "اسناد مالی", "فاکتور انتقال" and "گزارشات" // used to be three separate top-level entries; they are now one // group ("گزارشات و اسناد مالی") with each of them nested inside it // as its own submenu, same 3-level shape as "پیکر بندی" below. url: null, name: 'reports and documents', icon: 'FileTextIcon', i18n: 'گزارشات و اسناد مالی', submenu: [ { url: null, name: 'finical', icon: 'DollarSignIcon', i18n: 'اسناد مالی', permissionId:"document", submenu: [ { url: '/finical/list', name: 'finical_list', slug: 'finical_list', i18n: 'لیست اسناد', permissionId:"document.list" }, // 'وارد کردن سند مالی مشتری' removed: it is now the add button // on the financial documents list page. The /add/findoc route // still works. ] }, { url: null, name: 'Invoice', icon: 'BookIcon', i18n: 'فاکتور انتقال', permissionId:"invoice", submenu: [ // 'افزودن فاکتور' removed: it is now the add button on the // invoice list page. The /invoice/add route still works. { url: '/invoice/list', name: 'InvoiceList', slug: 'invoice-list', i18n: 'لیست فاکتورها', permissionId:"invoice.list" }, ] }, { url: null, name: 'report', icon: 'FileTextIcon', i18n: 'گزارشات', permissionId:"report", submenu: [ { url: '/report/order_item', name: 'report_order_item', slug: 'report_ordedr_item', i18n: 'گزارش تجمیعی سفارش و اسناد', permissionId:"report.order.item" }, { url: '/report/product', name: 'report_product', slug: 'report_product', i18n: 'گزارش محصولات', permissionId:"report.product" }, ] }, ] }, { url: null, name: 'sms', icon: 'MailIcon', i18n: 'پیامک', permissionId:"sms", submenu: [ { url: '/sms/create', name: 'create sms', slug: 'create_sms', i18n: 'ارسال پیامک', permissionId:"sms.create", }, ] }, { url: '/statics', name: 'statics', icon: 'BarChartIcon', i18n: 'آمار', permissionId:"statics", }, { url: '/newsletters', name: 'newsletters', icon: 'FileTextIcon', i18n: 'خبرنامه', // Legacy typo'd this as "newsletters.newsletters", a rid that never // exists in ALL_RIDS — so the item was permanently invisible to // everyone, including super-admin. The route's own guard // (POST newsletter/list, admin-misc.controller.ts) requires the // plain "newsletters" rid; matched here. permissionId:"newsletters", }, ] }, { header: 'UI', icon: 'LayersIcon', i18n: 'مدیریت', items: [ { url: null, name: 'پیکر بندی', icon: 'SettingsIcon', i18n: 'پیکر بندی', permissionId:"config", submenu: [ { url: '/config/manage/const', name: 'Const Management', slug: 'manage-const', i18n: 'مدیریت ثابت ها', permissionId:"config.statics" }, { url: '/config/manage/report', name: 'report Management', slug: 'manage-report', i18n: 'گزارش', permissionId:"config.report" }, { url: '/config/manage/wallet', name: 'wallet Management', slug: 'manage-const', i18n: 'مدیریت کیف پول', permissionId:"config.wallet", superAdminOnly: true }, // D27 — Tahesab / Zarrin integration. { url: '/config/manage/accounting', name: 'accounting Integration', slug: 'manage-accounting', i18n: 'اتصال حسابداری', permissionId:"config.accounting" }, // MON-08 — the making-charge formula. { url: '/config/manage/wage', name: 'wage Formula', slug: 'manage-wage', i18n: 'اجرت', permissionId:"config.wage" }, // Moved under "پیکر بندی" per request — same node shape as before // (own submenu / plain leaf), just relocated in the tree. { url: null, name: 'category', icon: 'ListIcon', i18n: 'دسته بندی ها', permissionId:"collection", submenu: [ // 'افزودن دسته بندی' removed: it is now the add button on the // category list page. The /category/add route still works. { url: '/category/list', name: 'categoryList', slug: 'list-category', i18n: 'لیست دسته بندی ها', permissionId:"collection.list" } ] }, { url: null, name: 'wallet', icon: 'CreditCardIcon', i18n: 'کیف پول', permissionId:"wallet", submenu: [ { url: '/wallet', name: 'wallet', slug: 'wallet', i18n: 'لیست کیف پول های شارژ شده', permissionId:"wallet.list" }, ] }, { url: null, name: 'cities offer percent', // tagColor: 'warning', icon: 'PercentIcon', i18n: 'شهر ها', permissionId:"cities", submenu: [ // 'افزودن شهر' removed: it is now the add button on the city list // page. The /city/create route still works. { url: '/city/list', name: 'city list', slug: 'city_list', i18n: 'لیست شهر ها', permissionId:"cities.list" }, ] }, { url: '/comments', name: 'comments', // tagColor: 'warning', icon: 'MessageSquareIcon', i18n: 'دیدگاه ها', permissionId:"comment" }, { url: null, name: 'notify', icon: 'BellIcon', i18n: 'نوتیفیکیشن', permissionId:"notify", submenu: [ { url: '/notify/create', name: 'create notify', slug: 'create_notify', i18n: 'ارسال نوتیفیکیشن', permissionId:"notify.create", }, ] }, ] }, ] } ] export const branchMenu: NavMenuNode[] = [ { url: '/dashboard', name: 'dashboard', tagColor: 'warning', icon: 'HomeIcon', i18n: 'پیشخوان', permissionId:"dashboard", }, { url: null, name: 'User', icon: 'UserIcon', i18n: 'اشخاص', permissionId:"persons", submenu: [ { url: '/customer/add', name: 'AddCustomer', slug: 'add-customer', icon:'UserPlusIcon', i18n: 'اضافه کردن مشتری', permissionId:"persons.create" }, { url: '/customer/list', name: 'List', icon:'UsersIcon', slug: 'app-user-list', i18n: 'لیست مشتریان ', permissionId:"persons.list.client.single" }, ] }, { url: '/products', name: 'ProductList', slug: 'product-list', icon: 'ShoppingBagIcon', i18n: 'محصولات', permissionId:"product.list" }, { url: '/buy/order/list', name: 'ProductList', slug: 'product-list', icon: 'ShoppingBagIcon', i18n: 'فاکتور خرید', permissionId:"product.list" }, /*{ url: '/buy/order/list', name: 'ProductList', slug: 'product-list', icon: 'ShoppingBagIcon', i18n: 'فاکتور خرید', permissionId:"product.list" },*/ { url: null, name: 'order', icon: 'BoxIcon', i18n: 'سفارش ها', permissionId:"order", submenu: [ { url: '/order/create', name: 'orderOmdeList', icon:'InboxIcon', slug: 'order-omde-list', i18n: 'ثبت سفارش', permissionId:"order.create" }, { url: '/order/list', name: 'orderList', icon:'ListIcon', slug: 'order-list', i18n: 'لیست سفارش', permissionId:"order.list" }, ] }, ] /** Legacy: `const menu = isBranch() ? branchMenu : adminMenu`. */ export function getMenu(): NavMenuNode[] { return isBranch() ? branchMenu : adminMenu; } export default getMenu;