diff --git a/src/features/users/components/InternalTeamTab.tsx b/src/features/users/components/InternalTeamTab.tsx
new file mode 100644
index 0000000..9485ba9
--- /dev/null
+++ b/src/features/users/components/InternalTeamTab.tsx
@@ -0,0 +1,107 @@
+
+import { useState } from "react";
+import { Plus, MoreHorizontal, ShieldAlert, Key } from "lucide-react";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { Button } from "@/components/ui/button";
+import { Badge } from "@/components/ui/badge";
+import { mockInternalUsers } from "@/features/users/data/mockRbacData";
+import { toast } from "sonner";
+
+export function InternalTeamTab() {
+ const handleRevokeAccess = (name: string) => {
+ toast.success(`Access revoked for ${name}`);
+ };
+
+ return (
+
+
+
+
Internal Staff
+ {mockInternalUsers.length} Active
+
+
+
+
+
+
+
+
+ User
+ Role
+ Status
+ Last Active
+ Actions
+
+
+
+ {mockInternalUsers.map((user) => (
+
+
+
+
{user.name}
+
{user.email}
+
+
+
+
+ {user.role.replace('_', ' ')}
+
+
+
+ {user.status === 'Active' ? (
+
+ Active
+
+ ) : (
+
+ Inactive
+
+ )}
+
+ {user.lastActive}
+
+
+
+
+
+
+ Manage Access
+ Edit Role
+ View Audit Log
+
+
+ Reset Password
+
+ handleRevokeAccess(user.name)} className="text-error">
+ Revoke Access
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/src/features/users/components/PartnerAdminTab.tsx b/src/features/users/components/PartnerAdminTab.tsx
new file mode 100644
index 0000000..b3b4763
--- /dev/null
+++ b/src/features/users/components/PartnerAdminTab.tsx
@@ -0,0 +1,116 @@
+
+import { Search, MoreHorizontal, ShieldCheck, BadgePercent, Lock } from "lucide-react";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Badge } from "@/components/ui/badge";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { mockPartnerUsers } from "@/features/users/data/mockRbacData";
+import { toast } from "sonner";
+
+export function PartnerAdminTab() {
+ const handleToggleVerification = (name: string, currentStatus: boolean) => {
+ toast.success(`${name} verification status updated to ${!currentStatus}`);
+ };
+
+ return (
+
+
+
+
Partner Administration
+ B2B
+
+
+
+
+
+
+
+
+
+
+
+
+ Partner User
+ Organization
+ Role
+ Verification
+ Commission
+ Actions
+
+
+
+ {mockPartnerUsers.map((user) => (
+
+
+
+
{user.name}
+
{user.email}
+
+
+
+ {user.partnerName}
+
+
+ {user.role}
+
+
+ {user.isVerified ? (
+
+ Verified
+
+ ) : (
+
+ Unverified
+
+ )}
+
+
+ {user.commissionOverride ? (
+
+ {user.commissionOverride}% (VIP)
+
+ ) : (
+ Standard
+ )}
+
+
+
+
+
+
+
+ handleToggleVerification(user.partnerName, user.isVerified)}>
+ Toggle Verification
+
+
+ Set Custom Commission
+
+
+ Suspend Account
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/src/features/users/components/RoleMatrix.tsx b/src/features/users/components/RoleMatrix.tsx
new file mode 100644
index 0000000..390319d
--- /dev/null
+++ b/src/features/users/components/RoleMatrix.tsx
@@ -0,0 +1,97 @@
+
+import { useState } from "react";
+import { Check, Shield } from "lucide-react";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import { Checkbox } from "@/components/ui/checkbox";
+import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/ui/button";
+import { Role, Permission, roles as initialRoles, permissions } from "@/features/users/data/mockRbacData";
+import { toast } from "sonner";
+
+export function RoleMatrix() {
+ const [roles, setRoles] = useState(initialRoles);
+
+ const togglePermission = (roleId: string, permissionId: string) => {
+ setRoles(currentRoles =>
+ currentRoles.map(role => {
+ if (role.id !== roleId) return role;
+
+ const hasPermission = role.permissions.includes(permissionId);
+ return {
+ ...role,
+ permissions: hasPermission
+ ? role.permissions.filter(p => p !== permissionId)
+ : [...role.permissions, permissionId]
+ };
+ })
+ );
+ };
+
+ const handleSave = () => {
+ toast.success("Role permissions updated successfully");
+ };
+
+ return (
+
+
+
+
+
+ Role Definitions
+
+
Configure detailed permissions for each internal role.
+
+
+
+
+
+
+
+
+ Permission / Capability
+ {roles.map(role => (
+
+
+ {role.name}
+
+
+ ))}
+
+
+
+ {permissions.map(permission => (
+
+
+
+ {permission.name}
+ {permission.description}
+
+
+ {roles.map(role => (
+
+
+ togglePermission(role.id, permission.id)}
+ className="data-[state=checked]:bg-primary data-[state=checked]:border-primary"
+ />
+
+
+ ))}
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/src/features/users/components/UserBaseTab.tsx b/src/features/users/components/UserBaseTab.tsx
new file mode 100644
index 0000000..5d15335
--- /dev/null
+++ b/src/features/users/components/UserBaseTab.tsx
@@ -0,0 +1,120 @@
+
+import { Search, MoreHorizontal, UserX, KeyRound, Eye } from "lucide-react";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Badge } from "@/components/ui/badge";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { mockEndUsers } from "@/features/users/data/mockRbacData";
+import { toast } from "sonner";
+import { formatCurrency } from "@/data/mockData";
+
+export function UserBaseTab() {
+ const handleBanUser = (name: string) => {
+ toast.success(`User ${name} has been banned.`);
+ };
+
+ const handleImpersonate = (name: string) => {
+ toast.info(`Impersonating ${name}... (Dev Mode Only)`);
+ // In a real app this would store a token and redirect
+ };
+
+ return (
+
+
+
+
User Base
+ B2C
+
+
+
+
+
+
+
+
+
+ User Details
+ Contact
+ Bookings
+ Total Spent
+ Status
+ Actions
+
+
+
+ {mockEndUsers.map((user) => (
+
+
+
+
{user.name}
+
ID: {user.id}
+
+
+
+
+
{user.email}
+
{user.phone}
+
+
+
+ {user.bookingsCount}
+
+
+ {formatCurrency(user.totalSpent)}
+
+
+ {user.status === 'Active' ? (
+ Active
+ ) : (
+ Banned
+ )}
+
+
+
+
+
+
+
+ handleImpersonate(user.name)}>
+ Impersonate
+
+
+ Reset 2FA
+
+
+ handleBanUser(user.name)} className="text-error">
+ Ban User
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/src/features/users/data/mockRbacData.ts b/src/features/users/data/mockRbacData.ts
new file mode 100644
index 0000000..92e8876
--- /dev/null
+++ b/src/features/users/data/mockRbacData.ts
@@ -0,0 +1,100 @@
+
+export interface Permission {
+ id: string;
+ name: string;
+ description: string;
+}
+
+export interface Role {
+ id: string;
+ name: string;
+ permissions: string[]; // List of permission IDs
+ color: string;
+}
+
+export const permissions: Permission[] = [
+ { id: 'view_dashboard', name: 'View Dashboard', description: 'Access to the main dashboard stats' },
+ { id: 'manage_users', name: 'Manage Users', description: 'Create, edit, and delete user accounts' },
+ { id: 'manage_partners', name: 'Manage Partners', description: 'Onboard and verify partners' },
+ { id: 'manage_events', name: 'Manage Events', description: 'Approve, feature, and edit events' },
+ { id: 'view_financials', name: 'View Financials', description: 'Access revenue and transaction data' },
+ { id: 'manage_payouts', name: 'Manage Payouts', description: 'Process partner settlements' },
+ { id: 'manage_settings', name: 'Manage Settings', description: 'Configure platform settings' },
+ { id: 'manage_roles', name: 'Manage Roles', description: 'Edit role permissions' },
+];
+
+export const roles: Role[] = [
+ {
+ id: 'super_admin',
+ name: 'Super Admin',
+ permissions: permissions.map(p => p.id),
+ color: 'bg-purple-500/10 text-purple-600 border-purple-200'
+ },
+ {
+ id: 'support_agent',
+ name: 'Support Agent',
+ permissions: ['view_dashboard', 'manage_users', 'manage_events'],
+ color: 'bg-blue-500/10 text-blue-600 border-blue-200'
+ },
+ {
+ id: 'content_moderator',
+ name: 'Content Moderator',
+ permissions: ['view_dashboard', 'manage_events'],
+ color: 'bg-orange-500/10 text-orange-600 border-orange-200'
+ },
+ {
+ id: 'finance_manager',
+ name: 'Finance Manager',
+ permissions: ['view_dashboard', 'view_financials', 'manage_payouts'],
+ color: 'bg-green-500/10 text-green-600 border-green-200'
+ },
+];
+
+export interface InternalUser {
+ id: string;
+ name: string;
+ email: string;
+ role: string;
+ lastActive: string;
+ status: 'Active' | 'Inactive';
+}
+
+export const mockInternalUsers: InternalUser[] = [
+ { id: '1', name: 'Alex Admin', email: 'alex@eventify.com', role: 'super_admin', lastActive: 'Just now', status: 'Active' },
+ { id: '2', name: 'Sarah Support', email: 'sarah@eventify.com', role: 'support_agent', lastActive: '2h ago', status: 'Active' },
+ { id: '3', name: 'Mike Mod', email: 'mike@eventify.com', role: 'content_moderator', lastActive: '1d ago', status: 'Inactive' },
+];
+
+export interface PartnerUser {
+ id: string;
+ name: string;
+ email: string;
+ partnerName: string; // The organization they belong to
+ role: 'Partner Admin' | 'Staff';
+ isVerified: boolean;
+ commissionOverride?: number; // Optional override
+ status: 'Active' | 'Suspended';
+}
+
+export const mockPartnerUsers: PartnerUser[] = [
+ { id: 'p1', name: 'John Venue', email: 'john@neonarena.com', partnerName: 'Neon Arena', role: 'Partner Admin', isVerified: true, status: 'Active' },
+ { id: 'p2', name: 'Jane Staff', email: 'jane@neonarena.com', partnerName: 'Neon Arena', role: 'Staff', isVerified: true, status: 'Active' },
+ { id: 'p3', name: 'Bob Promoter', email: 'bob@toptier.com', partnerName: 'TopTier Promoters', role: 'Partner Admin', isVerified: false, commissionOverride: 5.0, status: 'Active' },
+];
+
+export interface EndUser {
+ id: string;
+ name: string;
+ email: string;
+ phone: string;
+ bookingsCount: number;
+ totalSpent: number;
+ lastLogin: string;
+ status: 'Active' | 'Banned';
+}
+
+export const mockEndUsers: EndUser[] = [
+ { id: 'u1', name: 'Alice Walker', email: 'alice@gmail.com', phone: '+91 9876543210', bookingsCount: 5, totalSpent: 12500, lastLogin: '1h ago', status: 'Active' },
+ { id: 'u2', name: 'Charlie Brown', email: 'charlie@yahoo.com', phone: '+91 8765432109', bookingsCount: 1, totalSpent: 500, lastLogin: '3d ago', status: 'Active' },
+ { id: 'u3', name: 'Dave Fraud', email: 'dave@suspicious.com', phone: '+91 7654321098', bookingsCount: 0, totalSpent: 0, lastLogin: 'Never', status: 'Banned' },
+];
diff --git a/src/pages/Users.tsx b/src/pages/Users.tsx
index c9bf537..fbf8a97 100644
--- a/src/pages/Users.tsx
+++ b/src/pages/Users.tsx
@@ -1,143 +1,85 @@
-import { User, Shield, UserCheck, Search, Plus } from 'lucide-react';
-import { AppLayout } from '@/components/layout/AppLayout';
-import { cn } from '@/lib/utils';
-const mockUsers = [
- { id: '1', name: 'Arjun Sharma', email: 'arjun@eventify.in', role: 'admin', status: 'active', lastActive: new Date() },
- { id: '2', name: 'Priya Patel', email: 'priya@eventify.in', role: 'support', status: 'active', lastActive: new Date(Date.now() - 1000 * 60 * 30) },
- { id: '3', name: 'Rahul Kumar', email: 'rahul@eventify.in', role: 'viewer', status: 'inactive', lastActive: new Date(Date.now() - 1000 * 60 * 60 * 24 * 3) },
-];
+import {
+ Shield,
+ Users,
+ BriefcaseBusiness,
+ Settings2,
+ ListFilter
+} from "lucide-react";
+import { AppLayout } from "@/components/layout/AppLayout";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
+import { InternalTeamTab } from "@/features/users/components/InternalTeamTab";
+import { PartnerAdminTab } from "@/features/users/components/PartnerAdminTab";
+import { UserBaseTab } from "@/features/users/components/UserBaseTab";
+import { RoleMatrix } from "@/features/users/components/RoleMatrix";
+import {
+ Sheet,
+ SheetContent,
+ SheetDescription,
+ SheetHeader,
+ SheetTitle,
+ SheetTrigger
+} from "@/components/ui/sheet";
+import { Button } from "@/components/ui/button";
export default function Users() {
return (
-
- {/* Quick Stats */}
-
+
+
- {/* Users Table */}
-
-
-
Platform Users
-
-
-
-
-
-
-
-
+
+
-
-
-
-
- | User |
- Role |
- Status |
- Last Active |
- Actions |
-
-
-
- {mockUsers.map((user) => (
-
-
-
-
-
- {user.name.split(' ').map(n => n[0]).join('')}
-
-
-
- {user.name}
- {user.email}
-
-
- |
-
-
- {user.role}
-
- |
-
-
-
- {user.status === 'active' ? 'Active' : 'Inactive'}
-
- |
-
- {user.lastActive.toLocaleDateString('en-IN', {
- day: 'numeric',
- month: 'short',
- hour: '2-digit',
- minute: '2-digit'
- })}
- |
-
-
- |
-
- ))}
-
-
-
+ {/* Main Navigation Tabs */}
+
+
+
+ Internal Team
+
+
+
+ Partners
+
+
+
+ User Base
+
+
+
+ {/* Quick Actions (Role Manager) */}
+
+
+
+
+
+
+ Role Permissions Matrix
+ Verify and modify capabilities for each internal system role.
+
+
+
+
+
+
+
+
);