import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { vaultCategoryPermissionsOptions, vaultCategoryMutations, vaultKeys } from '@/api/vault' import { roleListOptions } from '@/api/rbac' import { userListOptions } from '@/api/users' import type { UserRecord } from '@/api/users' import type { Role } from '@/types/rbac' import type { VaultCategoryPermission } from '@/types/vault' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { Label } from '@/components/ui/label' import { Switch } from '@/components/ui/switch' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Trash2, Shield, Users, User } from 'lucide-react' import { toast } from 'sonner' interface Props { categoryId: string categoryName: string isPublic: boolean open: boolean onOpenChange: (open: boolean) => void } const ACCESS_LEVELS = [ { value: 'view', label: 'View', variant: 'secondary' as const }, { value: 'edit', label: 'Edit', variant: 'default' as const }, { value: 'admin', label: 'Admin', variant: 'destructive' as const }, ] export function CategoryPermissionsDialog({ categoryId, categoryName, isPublic, open, onOpenChange }: Props) { const queryClient = useQueryClient() const [assigneeType, setAssigneeType] = useState<'role' | 'user'>('role') const [assigneeId, setAssigneeId] = useState('') const [accessLevel, setAccessLevel] = useState('view') const { data: permissionsData, isLoading: permsLoading } = useQuery({ ...vaultCategoryPermissionsOptions(categoryId), enabled: open && !!categoryId, }) const { data: rolesData } = useQuery({ ...roleListOptions(), enabled: open }) const { data: usersData } = useQuery({ ...userListOptions({ page: 1, limit: 100, order: 'asc' }), enabled: open && assigneeType === 'user', }) const permissions = permissionsData?.data ?? [] const roles = rolesData?.data ?? [] const users = usersData?.data ?? [] const togglePublicMutation = useMutation({ mutationFn: (newIsPublic: boolean) => vaultCategoryMutations.update(categoryId, { isPublic: newIsPublic }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: vaultKeys.categories }) queryClient.invalidateQueries({ queryKey: vaultKeys.categoryDetail(categoryId) }) toast.success(isPublic ? 'Category set to private' : 'Category set to public') }, onError: (err) => toast.error(err.message), }) const addPermissionMutation = useMutation({ mutationFn: () => vaultCategoryMutations.addPermission(categoryId, { ...(assigneeType === 'role' ? { roleId: assigneeId } : { userId: assigneeId }), accessLevel, }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: vaultKeys.categoryPermissions(categoryId) }) setAssigneeId('') setAccessLevel('view') toast.success('Permission added') }, onError: (err) => toast.error(err.message), }) const removePermissionMutation = useMutation({ mutationFn: (permId: string) => vaultCategoryMutations.removePermission(permId), onSuccess: () => { queryClient.invalidateQueries({ queryKey: vaultKeys.categoryPermissions(categoryId) }) toast.success('Permission removed') }, onError: (err) => toast.error(err.message), }) function getPermissionLabel(perm: VaultCategoryPermission) { if (perm.roleId) { const role = roles.find((r: Role) => r.id === perm.roleId) return { icon: Users, name: role?.name ?? 'Unknown role' } } const user = users.find((u: UserRecord) => u.id === perm.userId) return { icon: User, name: user ? `${user.firstName} ${user.lastName}` : 'Unknown user' } } return ( Permissions — {categoryName}

Public categories are viewable by all users with vault access

togglePublicMutation.mutate(checked)} disabled={togglePublicMutation.isPending} />
{permsLoading ? (

Loading...

) : permissions.length === 0 ? (

No specific permissions assigned

) : ( permissions.map((perm) => { const { icon: Icon, name } = getPermissionLabel(perm) const level = ACCESS_LEVELS.find((l) => l.value === perm.accessLevel) return (
{name}
{level?.label ?? perm.accessLevel}
) }) )}
{ e.preventDefault(); if (assigneeId) addPermissionMutation.mutate() }} className="space-y-3">
) }