"use client"; import Link from "next/link"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@nextsparkjs/core/components/ui/card"; import { Button } from "@nextsparkjs/core/components/ui/button"; import { Badge } from "@nextsparkjs/core/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@nextsparkjs/core/components/ui/tabs"; import { ArrowLeft, Shield, Users, Lock, Eye, Key, CreditCard, Layers, Zap, } from "lucide-react"; import { APP_CONFIG_MERGED } from "@nextsparkjs/core/lib/config/config-sync"; import { PermissionService } from "@nextsparkjs/core/lib/services/permission.service"; import { PERMISSIONS_METADATA } from "@nextsparkjs/registries/permissions-registry"; import { getFullBillingMatrix } from "@nextsparkjs/core/lib/billing/queries"; import { RolesPermissionsMatrix } from "@nextsparkjs/core/components/superadmin/tables/RolesPermissionsMatrix"; import { PlanFeaturesMatrix } from "@nextsparkjs/core/components/superadmin/tables/PlanFeaturesMatrix"; import { getTemplateOrDefaultClient } from "@nextsparkjs/registries/template-registry.client"; /** * Team Roles & Permissions Page * * Displays two consolidated matrices: * 1. RBAC Matrix - Team roles and their permissions * 2. Plan Features Matrix - Billing plans and their features/limits * * Both use pre-computed data for O(1) runtime lookups. */ function TeamRolesPage() { const teamRolesConfig = APP_CONFIG_MERGED.teams.roles; const roles = teamRolesConfig.availableTeamRoles; const hierarchy = teamRolesConfig.hierarchy; // Get full RBAC matrix from pre-computed registry const { permissions, matrix } = PermissionService.getMatrix(); // Get full billing matrix from pre-computed registry const billingData = getFullBillingMatrix(); // Sort roles by hierarchy for display const sortedRoles = [...roles].sort( (a, b) => (hierarchy[b] ?? 0) - (hierarchy[a] ?? 0) ); // Convert FULL_MATRIX format to rolePermissions format for the matrix component const rolePermissions: Record = {}; for (const role of roles) { rolePermissions[role] = permissions .filter(p => matrix[p.id as keyof typeof matrix]?.[role]) .map(p => p.id); } // All permission IDs const allPermissions = permissions.map(p => p.id); // Count permissions per role const permissionCounts = sortedRoles.reduce( (acc, role) => { acc[role] = rolePermissions[role]?.length ?? 0; return acc; }, {} as Record ); // Get role badge variant based on hierarchy const getRoleBadgeVariant = (role: string) => { const h = hierarchy[role] ?? 0; if (h >= 100) return "destructive"; if (h >= 50) return "default"; if (h >= 10) return "secondary"; return "outline"; }; return (
{/* Header */}

Roles, Permissions & Plans

View team roles, permissions, and billing plan features

{/* Tabs for switching between matrices */} RBAC Matrix Plan Features {/* RBAC Matrix Tab */} {/* RBAC Stats Overview */}
Available Roles
{roles.length}

Team role types

Total Permissions
{PERMISSIONS_METADATA.totalPermissions}

{PERMISSIONS_METADATA.corePermissions} core + {PERMISSIONS_METADATA.featurePermissions} features + {PERMISSIONS_METADATA.entityPermissions} entity

Protected Role
owner

Cannot be removed

Default Role
{teamRolesConfig.defaultTeamRole}

For invitations

{/* Roles Hierarchy */} Team Roles Hierarchy Roles ordered by hierarchy level. Higher values have more permissions.
{sortedRoles.map((role) => (
{hierarchy[role] ?? 0}
{role}
{permissionCounts[role]} permissions
))}
{/* Permissions Matrix */} Permissions Matrix Complete view of which permissions each team role has access to. {/* RBAC Legend */} Legend
100 Owner (protected)
50 Admin
10 Member
1 Viewer
{/* RBAC Source Info */}

Source: Pre-computed permissions registry (build-time)

Roles config:{" "} APP_CONFIG_MERGED.teams.roles

Permissions registry:{" "} core/lib/registries/permissions-registry.ts

Generated at:{" "} {PERMISSIONS_METADATA.generatedAt}

{/* Plan Features Tab */} {/* Billing Stats Overview */}
Total Plans
{billingData.metadata.totalPlans}

{billingData.metadata.publicPlans} public

Features
{billingData.metadata.totalFeatures}

Defined features

Limits
{billingData.metadata.totalLimits}

Quota types

Theme
{billingData.metadata.theme}

Active theme

{/* Plan Cards Overview */} Available Plans Billing plans with their pricing and trial periods.
{billingData.plans.map((plan) => (
{plan.type}
{plan.slug}
{plan.type === "free" ? "Free forever" : plan.type === "enterprise" ? "Custom pricing" : plan.price ? `$${(plan.price.monthly / 100).toFixed(0)}/mo` : "Contact sales"} {plan.trialDays && plan.trialDays > 0 && ( ({plan.trialDays}d trial) )}
{plan.visibility === "hidden" && ( hidden )}
))}
{/* Plan Features Matrix */} Features & Limits Matrix Complete view of features and quotas included in each plan. {/* Plan Legend */} Legend
free Free tier
paid Subscription plan
enterprise Custom/unlimited
monthly Resets monthly
{/* Billing Source Info */}

Source: Pre-computed billing registry (module load)

Billing config:{" "} contents/themes/{billingData.metadata.theme}/billing/billing.config.ts

Billing registry:{" "} core/lib/registries/billing-registry.ts

{/* Three-Layer Model Info */} Three-Layer Permission Model

RESULT = Permission (RBAC) AND Feature (Plan) AND Quota (Limits)

  • Layer 1 - Permission (RBAC): Does the user's role allow this action?
  • Layer 2 - Feature (Plan): Does the subscription plan include this feature?
  • Layer 3 - Quota (Limits): Is there available quota for this action?
); } export default getTemplateOrDefaultClient( "app/superadmin/team-roles/page.tsx", TeamRolesPage );