Gate Roll Call behind the opt-in business module.
Super Admin can enable it per business; nav and pages stay hidden when off. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
c4e846564e
commit
b25f3cbea0
@@ -170,7 +170,7 @@ export function Sidebar({ open = false }: SidebarProps) {
|
|||||||
{ labelKey: 'nav.store.settings', to: '/store/settings' },
|
{ labelKey: 'nav.store.settings', to: '/store/settings' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
...(canAccessRollCall(user, getActiveBusinessId())
|
...(canAccessRollCall(user, getActiveBusinessId(), enabledModules)
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
type: 'group' as const,
|
type: 'group' as const,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import {
|
|||||||
type RollCallSummary,
|
type RollCallSummary,
|
||||||
type RollCallsListResponse,
|
type RollCallsListResponse,
|
||||||
} from '../services/rollCallService'
|
} from '../services/rollCallService'
|
||||||
|
import { useTenantBranding } from '../context/TenantBrandingContext'
|
||||||
import { canAccessRollCall } from '../utils/rollCallAccess'
|
import { canAccessRollCall } from '../utils/rollCallAccess'
|
||||||
import pageStyles from '../components/PageContent.module.css'
|
import pageStyles from '../components/PageContent.module.css'
|
||||||
import styles from './RollCallPage.module.css'
|
import styles from './RollCallPage.module.css'
|
||||||
@@ -102,8 +103,9 @@ export function RollCallPage() {
|
|||||||
const { locale } = useLocale()
|
const { locale } = useLocale()
|
||||||
const { showToast } = useToast()
|
const { showToast } = useToast()
|
||||||
const { user } = useAuth()
|
const { user } = useAuth()
|
||||||
|
const { enabledModules } = useTenantBranding()
|
||||||
const activeBusinessId = getActiveBusinessId()
|
const activeBusinessId = getActiveBusinessId()
|
||||||
const allowed = canAccessRollCall(user, activeBusinessId)
|
const allowed = canAccessRollCall(user, activeBusinessId, enabledModules)
|
||||||
|
|
||||||
const [data, setData] = useState<RollCallsListResponse | null>(null)
|
const [data, setData] = useState<RollCallsListResponse | null>(null)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export const BUSINESS_DASHBOARD_MODULE_IDS = [
|
|||||||
'workshops',
|
'workshops',
|
||||||
'finance',
|
'finance',
|
||||||
'multilanguage_data',
|
'multilanguage_data',
|
||||||
|
'roll_call',
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
/** Optional customer-dashboard modules. Always-on: home, profile, addresses, orders, favorites. */
|
/** Optional customer-dashboard modules. Always-on: home, profile, addresses, orders, favorites. */
|
||||||
@@ -57,7 +58,8 @@ export const DEFAULT_ENABLED_BUSINESS_MODULES: BusinessModuleId[] =
|
|||||||
(id) =>
|
(id) =>
|
||||||
id !== 'workshops' &&
|
id !== 'workshops' &&
|
||||||
id !== 'multilanguage_data' &&
|
id !== 'multilanguage_data' &&
|
||||||
id !== 'store_installments',
|
id !== 'store_installments' &&
|
||||||
|
id !== 'roll_call',
|
||||||
)
|
)
|
||||||
|
|
||||||
export const DEFAULT_HOME_CHARTS: [HomeChartId, HomeChartId] = [
|
export const DEFAULT_HOME_CHARTS: [HomeChartId, HomeChartId] = [
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import type { AuthUser } from '../types/auth'
|
import type { AuthUser } from '../types/auth'
|
||||||
|
import {
|
||||||
|
hasBusinessModule,
|
||||||
|
type BusinessModuleId,
|
||||||
|
} from './businessModules'
|
||||||
|
|
||||||
function membershipAllowsRollCall(membership: {
|
function membershipAllowsRollCall(membership: {
|
||||||
isOwner: boolean
|
isOwner: boolean
|
||||||
@@ -12,10 +16,16 @@ function membershipAllowsRollCall(membership: {
|
|||||||
return membership.permissions.includes('roll_calls.read')
|
return membership.permissions.includes('roll_calls.read')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show Roll Call when the business module is enabled and the user is
|
||||||
|
* staff (owner / admin) for the active tenant.
|
||||||
|
*/
|
||||||
export function canAccessRollCall(
|
export function canAccessRollCall(
|
||||||
user: AuthUser | null | undefined,
|
user: AuthUser | null | undefined,
|
||||||
activeBusinessId: string | null,
|
activeBusinessId: string | null,
|
||||||
|
enabledModules?: readonly BusinessModuleId[] | null,
|
||||||
): boolean {
|
): boolean {
|
||||||
|
if (!hasBusinessModule(enabledModules, 'roll_call')) return false
|
||||||
if (!user) return false
|
if (!user) return false
|
||||||
|
|
||||||
if (user.isSuperAdmin || user.roles.includes('super_admin')) {
|
if (user.isSuperAdmin || user.roles.includes('super_admin')) {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export function Sidebar({ open = false }: SidebarProps) {
|
|||||||
const displayName = brandName || fallbackBusinessName
|
const displayName = brandName || fallbackBusinessName
|
||||||
const showMyProducts = hasBusinessModule(enabledModules, 'customer_products')
|
const showMyProducts = hasBusinessModule(enabledModules, 'customer_products')
|
||||||
const activeBusinessId = getActiveBusinessId()
|
const activeBusinessId = getActiveBusinessId()
|
||||||
const showRollCall = canAccessRollCall(user, activeBusinessId)
|
const showRollCall = canAccessRollCall(user, activeBusinessId, enabledModules)
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ icon: Home, label: t('nav.home'), to: '/' },
|
{ icon: Home, label: t('nav.home'), to: '/' },
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
type RollCallSummary,
|
type RollCallSummary,
|
||||||
type RollCallsListResponse,
|
type RollCallsListResponse,
|
||||||
} from '../services/rollCallService'
|
} from '../services/rollCallService'
|
||||||
|
import { useTenantBranding } from '../context/TenantBrandingContext'
|
||||||
import { canAccessRollCall } from '../utils/rollCallAccess'
|
import { canAccessRollCall } from '../utils/rollCallAccess'
|
||||||
import pageStyles from '../components/PageContent.module.css'
|
import pageStyles from '../components/PageContent.module.css'
|
||||||
import styles from './RollCallPage.module.css'
|
import styles from './RollCallPage.module.css'
|
||||||
@@ -101,8 +102,9 @@ export function RollCallPage() {
|
|||||||
const { locale } = useLocale()
|
const { locale } = useLocale()
|
||||||
const { showToast } = useToast()
|
const { showToast } = useToast()
|
||||||
const { user } = useAuth()
|
const { user } = useAuth()
|
||||||
|
const { enabledModules } = useTenantBranding()
|
||||||
const activeBusinessId = getActiveBusinessId()
|
const activeBusinessId = getActiveBusinessId()
|
||||||
const allowed = canAccessRollCall(user, activeBusinessId)
|
const allowed = canAccessRollCall(user, activeBusinessId, enabledModules)
|
||||||
|
|
||||||
const [data, setData] = useState<RollCallsListResponse | null>(null)
|
const [data, setData] = useState<RollCallsListResponse | null>(null)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export const BUSINESS_MODULE_IDS = [
|
|||||||
'blog',
|
'blog',
|
||||||
'warehouse',
|
'warehouse',
|
||||||
'videos',
|
'videos',
|
||||||
|
'roll_call',
|
||||||
...CUSTOMER_MODULE_IDS,
|
...CUSTOMER_MODULE_IDS,
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import type { AuthUser } from '../types/auth'
|
import type { AuthUser } from '../types/auth'
|
||||||
|
import {
|
||||||
|
hasBusinessModule,
|
||||||
|
type BusinessModuleId,
|
||||||
|
} from './businessModules'
|
||||||
|
|
||||||
function membershipAllowsRollCall(membership: {
|
function membershipAllowsRollCall(membership: {
|
||||||
isOwner: boolean
|
isOwner: boolean
|
||||||
@@ -19,14 +23,15 @@ function sameId(a: string | number | null | undefined, b: string | number | null
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show Roll Call in the customer dashboard when the user is staff
|
* Show Roll Call when the business module is enabled and the user is
|
||||||
* (owner / admin) for the active tenant — same people who can open
|
* staff (owner / admin) for the active tenant.
|
||||||
* the business dashboard. No business module toggle is required.
|
|
||||||
*/
|
*/
|
||||||
export function canAccessRollCall(
|
export function canAccessRollCall(
|
||||||
user: AuthUser | null | undefined,
|
user: AuthUser | null | undefined,
|
||||||
activeBusinessId: string | null,
|
activeBusinessId: string | null,
|
||||||
|
enabledModules?: readonly BusinessModuleId[] | null,
|
||||||
): boolean {
|
): boolean {
|
||||||
|
if (!hasBusinessModule(enabledModules, 'roll_call')) return false
|
||||||
if (!user) return false
|
if (!user) return false
|
||||||
|
|
||||||
if (user.isSuperAdmin || user.roles.includes('super_admin')) {
|
if (user.isSuperAdmin || user.roles.includes('super_admin')) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export const BUSINESS_DASHBOARD_MODULE_IDS = [
|
|||||||
'workshops',
|
'workshops',
|
||||||
'finance',
|
'finance',
|
||||||
'multilanguage_data',
|
'multilanguage_data',
|
||||||
|
'roll_call',
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
/** Optional customer-dashboard modules. Always-on: home, profile, addresses, orders, favorites. */
|
/** Optional customer-dashboard modules. Always-on: home, profile, addresses, orders, favorites. */
|
||||||
@@ -42,6 +43,7 @@ export const BUSINESS_DASHBOARD_MODULE_LABELS: Record<
|
|||||||
workshops: 'Workshops',
|
workshops: 'Workshops',
|
||||||
finance: 'Finance',
|
finance: 'Finance',
|
||||||
multilanguage_data: 'MultiLanguage Data',
|
multilanguage_data: 'MultiLanguage Data',
|
||||||
|
roll_call: 'Roll Call',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CUSTOMER_MODULE_LABELS: Record<CustomerModuleId, string> = {
|
export const CUSTOMER_MODULE_LABELS: Record<CustomerModuleId, string> = {
|
||||||
@@ -87,7 +89,8 @@ export const DEFAULT_ENABLED_BUSINESS_MODULES: BusinessModuleId[] =
|
|||||||
(id) =>
|
(id) =>
|
||||||
id !== 'workshops' &&
|
id !== 'workshops' &&
|
||||||
id !== 'multilanguage_data' &&
|
id !== 'multilanguage_data' &&
|
||||||
id !== 'store_installments',
|
id !== 'store_installments' &&
|
||||||
|
id !== 'roll_call',
|
||||||
)
|
)
|
||||||
|
|
||||||
export const DEFAULT_HOME_CHARTS: [HomeChartId, HomeChartId] = [
|
export const DEFAULT_HOME_CHARTS: [HomeChartId, HomeChartId] = [
|
||||||
|
|||||||
Reference in New Issue
Block a user