From 16ade715984307e06ae8c52831dd7df0c461e816 Mon Sep 17 00:00:00 2001 From: adonis Date: Tue, 25 Aug 2026 14:19:26 +0330 Subject: [PATCH] feat(user): gate menus by SuperAdmin flags and show physical delivery Hide fund/earn/gift entries when access is off, add matching route guards, and surface physical delivery instead of price alert on mobile profile. Co-authored-by: Cursor --- src/app/setupRouter.ts | 28 ++++++++++++++ src/layouts/desktop/DesktopSidebar.vue | 17 +++++---- src/layouts/mobile/MobileOverflowMenu.vue | 16 +------- src/utils/superAdminMenuGates.ts | 37 +++++++++++++++++++ .../home/desktop/GhatrehHomeDesktopView.vue | 26 +++++++------ src/views/base/home/index.vue | 3 ++ .../base/user/composables/useUserPage.ts | 17 ++++++--- src/views/base/user/mobile/MobileUserView.vue | 29 +++------------ 8 files changed, 112 insertions(+), 61 deletions(-) create mode 100644 src/utils/superAdminMenuGates.ts diff --git a/src/app/setupRouter.ts b/src/app/setupRouter.ts index 108ce5a..8438964 100644 --- a/src/app/setupRouter.ts +++ b/src/app/setupRouter.ts @@ -99,6 +99,34 @@ export function setupRouterGuards() { } } + if ( + getToken() && + (to.name === 'piggy' || + to.name === 'fund' || + to.name === 'fund_info' || + to.name === 'fund_add') + ) { + const { useSettingsStore } = await import('@/store/settingsStore') + const settingsStore = useSettingsStore() + if (!settingsStore.loaded) { + await settingsStore.fetchSettings() + } + if (!settingsStore.isSettingTruthy('enable_product_funds')) { + return next({ name: (from.name as string) || 'home' }) + } + } + + if (to.name === 'earnMoney' && getToken()) { + const { useSettingsStore } = await import('@/store/settingsStore') + const settingsStore = useSettingsStore() + if (!settingsStore.loaded) { + await settingsStore.fetchSettings() + } + if (!settingsStore.isSettingTruthy('has_page_earn_money')) { + return next({ name: (from.name as string) || 'user' }) + } + } + if (isFirst) { isFirst = false diff --git a/src/layouts/desktop/DesktopSidebar.vue b/src/layouts/desktop/DesktopSidebar.vue index d1fa6b4..14ded3c 100644 --- a/src/layouts/desktop/DesktopSidebar.vue +++ b/src/layouts/desktop/DesktopSidebar.vue @@ -50,6 +50,7 @@ import { useTrackingSystemsFeature } from '@/composables/useTrackingSystemsFeatu import { useSettingsStore } from '@/store/settingsStore' import { getPrimaryNavItems, getSecondaryNavItems } from '../config/navigation' import { useAppNavigation } from '../composables/useAppNavigation' +import { featureSettingForRoute } from '@/utils/superAdminMenuGates' import DesktopNavItem from './DesktopNavItem.vue' import AppCreditLink from '@/components/AppCreditLink.vue' @@ -58,7 +59,13 @@ const authenticated = computed(() => isToken()) const navLogo = logoFull const { trackingSystemsEnabled } = useTrackingSystemsFeature() const settingsStore = useSettingsStore() -const primaryItems = computed(() => getPrimaryNavItems(authenticated.value)) +const primaryItems = computed(() => + getPrimaryNavItems(authenticated.value).filter((item) => { + const featureKey = featureSettingForRoute(item.routeName) + if (featureKey) return settingsStore.isSettingTruthy(featureKey) + return true + }), +) /** «لیست دریافتی‌ها» فقط در موبایل نمایش داده می‌شود */ const DESKTOP_HIDDEN_NAV_IDS = ['list'] const secondaryItems = computed(() => @@ -66,12 +73,8 @@ const secondaryItems = computed(() => includeRecoverySites: trackingSystemsEnabled.value, }).filter((item) => { if (DESKTOP_HIDDEN_NAV_IDS.includes(item.id)) return false - if (item.id === 'notifyTrigger') { - return settingsStore.isSettingTruthy('has_page_price_trigger') - } - if (item.id === 'giftCard') { - return settingsStore.isSettingTruthy('has_page_gift_card') - } + const featureKey = featureSettingForRoute(item.routeName) + if (featureKey) return settingsStore.isSettingTruthy(featureKey) return true }), ) diff --git a/src/layouts/mobile/MobileOverflowMenu.vue b/src/layouts/mobile/MobileOverflowMenu.vue index 1734193..d54d66d 100644 --- a/src/layouts/mobile/MobileOverflowMenu.vue +++ b/src/layouts/mobile/MobileOverflowMenu.vue @@ -34,18 +34,7 @@ >
-
دریافت طلای فیزیکی
-
- - -
- -
هشدار قیمت
+
تحویل فیزیکی
isToken()) const { trackingSystemsEnabled } = useTrackingSystemsFeature() const settingsStore = useSettingsStore() -const priceTriggerEnabled = computed(() => - settingsStore.isSettingTruthy('has_page_price_trigger'), -) const giftCardEnabled = computed(() => settingsStore.isSettingTruthy('has_page_gift_card'), ) diff --git a/src/utils/superAdminMenuGates.ts b/src/utils/superAdminMenuGates.ts new file mode 100644 index 0000000..5f2defc --- /dev/null +++ b/src/utils/superAdminMenuGates.ts @@ -0,0 +1,37 @@ +/** + * نگاشت منو/مسیر اپ کاربر → کلید دسترسی سوپرادمین. + * مقدار false/غایب = مخفی (پیش‌فرض امن). + */ +export const ROUTE_FEATURE_SETTING: Record = { + fund: 'enable_product_funds', + fund_info: 'enable_product_funds', + fund_add: 'enable_product_funds', + piggy: 'enable_product_funds', + earnMoney: 'has_page_earn_money', + giftCard: 'has_page_gift_card', + notifyTrigger: 'has_page_price_trigger', + appNotifications: 'has_page_notification', + conditionalOrder: 'enable_conditional_order', + permissions: 'permision__enabled', +} + +export const MENU_ID_FEATURE_SETTING: Record = { + fund: 'enable_product_funds', + piggy: 'enable_product_funds', + earnMoney: 'has_page_earn_money', + giftCard: 'has_page_gift_card', + notify: 'has_page_price_trigger', + notifyTrigger: 'has_page_price_trigger', + conditionalOrder: 'enable_conditional_order', + permissions: 'permision__enabled', +} + +export function featureSettingForRoute(routeName: string | null | undefined): string | null { + if (!routeName) return null + return ROUTE_FEATURE_SETTING[String(routeName)] ?? null +} + +export function featureSettingForMenuId(id: string | null | undefined): string | null { + if (!id) return null + return MENU_ID_FEATURE_SETTING[String(id)] ?? null +} diff --git a/src/views/base/home/desktop/GhatrehHomeDesktopView.vue b/src/views/base/home/desktop/GhatrehHomeDesktopView.vue index 3ec3f8a..8fe63ce 100644 --- a/src/views/base/home/desktop/GhatrehHomeDesktopView.vue +++ b/src/views/base/home/desktop/GhatrehHomeDesktopView.vue @@ -227,22 +227,26 @@ const mainActions = computed(() => { { name: 'buySell', icon: 'vuesax-linear:money-receive', label: 'خرید و فروش', handler: () => router.push({ name: 'gold' }) }, { name: 'deposit', icon: 'vuesax-linear:card-add', label: 'واریز نقدی', handler: () => router.push({ name: 'wallet', query: { state: 'deposit' } }) }, { name: 'balance', icon: 'vuesax-linear:receipt-item', label: 'موجودی', handler: () => emitBalance() }, - { name: 'fund', icon: 'vuesax-linear:archive-1', label: 'دارایی ها', handler: () => router.push({ name: 'fund' }) }, ] if (settingsStore.isSettingTruthy('enable_product_funds')) { + actions.push( + { name: 'fund', icon: 'vuesax-linear:archive-1', label: 'دارایی ها', handler: () => router.push({ name: 'fund' }) }, + { + name: 'piggy', + icon: 'vuesax-linear:safe-home', + label: 'قلک', + handler: () => router.push({ name: 'piggy' }), + }, + ) + } + if (settingsStore.isSettingTruthy('has_page_earn_money')) { actions.push({ - name: 'piggy', - icon: 'vuesax-linear:safe-home', - label: 'قلک', - handler: () => router.push({ name: 'piggy' }), + name: 'earn', + icon: 'vuesax-linear:dollar-circle', + label: 'کسب درآمد', + handler: () => router.push({ name: 'earnMoney' }), }) } - actions.push({ - name: 'earn', - icon: 'vuesax-linear:dollar-circle', - label: 'کسب درآمد', - handler: () => router.push({ name: 'earnMoney' }), - }) return actions }) diff --git a/src/views/base/home/index.vue b/src/views/base/home/index.vue index e891e39..5f7d542 100644 --- a/src/views/base/home/index.vue +++ b/src/views/base/home/index.vue @@ -99,6 +99,7 @@
موجودی
قلک
settingsStore.isSettingTruthy('enable_product_funds')) +const earnMoneyEnabled = computed(() => settingsStore.isSettingTruthy('has_page_earn_money')) const chartLoading = ref(false) const openModal = ref(false) const wholeBalanceVisible = ref(false) diff --git a/src/views/base/user/composables/useUserPage.ts b/src/views/base/user/composables/useUserPage.ts index ba134d5..ccbb5c1 100644 --- a/src/views/base/user/composables/useUserPage.ts +++ b/src/views/base/user/composables/useUserPage.ts @@ -113,11 +113,11 @@ export function useUserPage() { visible: true, }, { - id: 'notify', - label: 'هشدار قیمت', - icon: 'vuesax-linear:bill', - onClick: () => router.push({ name: 'notifyTrigger' }), - visible: settingsStore.isSettingTruthy('has_page_price_trigger'), + id: 'physicalReceive', + label: 'تحویل فیزیکی', + icon: 'vuesax-linear:direct-inbox', + onClick: () => router.push({ name: 'physicalReceive' }), + visible: true, }, { id: 'piggy', @@ -140,6 +140,13 @@ export function useUserPage() { onClick: () => router.push({ name: 'giftCard' }), visible: settingsStore.isSettingTruthy('has_page_gift_card'), }, + { + id: 'earnMoney', + label: 'کسب درآمد', + icon: 'vuesax-linear:dollar-circle', + onClick: () => router.push({ name: 'earnMoney' }), + visible: settingsStore.isSettingTruthy('has_page_earn_money'), + }, { id: 'support', label: 'پشتیبانی', diff --git a/src/views/base/user/mobile/MobileUserView.vue b/src/views/base/user/mobile/MobileUserView.vue index 81ea14f..4e899d1 100644 --- a/src/views/base/user/mobile/MobileUserView.vue +++ b/src/views/base/user/mobile/MobileUserView.vue @@ -100,14 +100,15 @@
-->
- -
هشدار قیمت
+ +
تحویل فیزیکی
سایت‌های ری‌گیری - - - - - - - - - - - - - settingsStore.isSettingTruthy('has_page_price_trigger'), -) const { editPassVisible, editPasswordVisible, copyCode, shareCode, requestLogout } = useUserPageContext()