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:
Alireza Hassani
2026-10-07 14:15:46 +03:30
co-authored by Cursor
parent c4e846564e
commit b25f3cbea0
9 changed files with 34 additions and 9 deletions
+1 -1
View File
@@ -170,7 +170,7 @@ export function Sidebar({ open = false }: SidebarProps) {
{ labelKey: 'nav.store.settings', to: '/store/settings' },
],
},
...(canAccessRollCall(user, getActiveBusinessId())
...(canAccessRollCall(user, getActiveBusinessId(), enabledModules)
? [
{
type: 'group' as const,
+3 -1
View File
@@ -28,6 +28,7 @@ import {
type RollCallSummary,
type RollCallsListResponse,
} from '../services/rollCallService'
import { useTenantBranding } from '../context/TenantBrandingContext'
import { canAccessRollCall } from '../utils/rollCallAccess'
import pageStyles from '../components/PageContent.module.css'
import styles from './RollCallPage.module.css'
@@ -102,8 +103,9 @@ export function RollCallPage() {
const { locale } = useLocale()
const { showToast } = useToast()
const { user } = useAuth()
const { enabledModules } = useTenantBranding()
const activeBusinessId = getActiveBusinessId()
const allowed = canAccessRollCall(user, activeBusinessId)
const allowed = canAccessRollCall(user, activeBusinessId, enabledModules)
const [data, setData] = useState<RollCallsListResponse | null>(null)
const [loading, setLoading] = useState(false)
+3 -1
View File
@@ -11,6 +11,7 @@ export const BUSINESS_DASHBOARD_MODULE_IDS = [
'workshops',
'finance',
'multilanguage_data',
'roll_call',
] as const
/** Optional customer-dashboard modules. Always-on: home, profile, addresses, orders, favorites. */
@@ -57,7 +58,8 @@ export const DEFAULT_ENABLED_BUSINESS_MODULES: BusinessModuleId[] =
(id) =>
id !== 'workshops' &&
id !== 'multilanguage_data' &&
id !== 'store_installments',
id !== 'store_installments' &&
id !== 'roll_call',
)
export const DEFAULT_HOME_CHARTS: [HomeChartId, HomeChartId] = [
+10
View File
@@ -1,4 +1,8 @@
import type { AuthUser } from '../types/auth'
import {
hasBusinessModule,
type BusinessModuleId,
} from './businessModules'
function membershipAllowsRollCall(membership: {
isOwner: boolean
@@ -12,10 +16,16 @@ function membershipAllowsRollCall(membership: {
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(
user: AuthUser | null | undefined,
activeBusinessId: string | null,
enabledModules?: readonly BusinessModuleId[] | null,
): boolean {
if (!hasBusinessModule(enabledModules, 'roll_call')) return false
if (!user) return false
if (user.isSuperAdmin || user.roles.includes('super_admin')) {