fix(impersonation): pointer-events + show all roles (§D.4-5)
Banner wrapper now uses pointer-events-none so it doesn't intercept clicks on the user-menu dropdown sitting underneath; the 'Return to Admin' button re-enables pointer events on itself only. Banner also lists every role the impersonated user holds (e.g. 'JURY MEMBER, MENTOR') instead of just the primary role, matching how multi-role users are surfaced everywhere else. Plan: docs/superpowers/plans/2026-04-28-pr6-multi-role-and-workspace-previews.md
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
'use client'
|
||||
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { trpc } from '@/lib/trpc/client'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { ArrowLeft, Loader2 } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import type { UserRole } from '@prisma/client'
|
||||
|
||||
export function ImpersonationBanner() {
|
||||
const { data: session, update } = useSession()
|
||||
const router = useRouter()
|
||||
const endImpersonation = trpc.user.endImpersonation.useMutation()
|
||||
|
||||
if (!session?.user?.impersonating) return null
|
||||
@@ -18,23 +17,29 @@ export function ImpersonationBanner() {
|
||||
try {
|
||||
await endImpersonation.mutateAsync()
|
||||
await update({ endImpersonation: true })
|
||||
// Full page navigation to ensure updated JWT cookie is sent
|
||||
window.location.href = '/admin/members'
|
||||
} catch (error) {
|
||||
toast.error(error instanceof Error ? error.message : 'Failed to end impersonation')
|
||||
}
|
||||
}
|
||||
|
||||
// Show every role the impersonated user holds (multi-role support).
|
||||
const roles = (session.user.roles as UserRole[] | undefined) ?? [session.user.role as UserRole]
|
||||
const rolesLabel = roles.map((r) => r.replace(/_/g, ' ')).join(', ')
|
||||
|
||||
return (
|
||||
<div className="fixed top-0 left-0 right-0 z-50 flex items-center justify-center gap-3 bg-red-600 px-4 py-1.5 text-sm text-white shadow-md">
|
||||
// pointer-events-none on the wrapper so the banner doesn't intercept clicks
|
||||
// on anything underneath (e.g., the user-menu dropdown). The button inside
|
||||
// re-enables pointer-events on itself only.
|
||||
<div className="pointer-events-none fixed top-0 left-0 right-0 z-50 flex items-center justify-center gap-3 bg-red-600 px-4 py-1.5 text-sm text-white shadow-md">
|
||||
<span>
|
||||
Impersonating <strong>{session.user.name || session.user.email}</strong>{' '}
|
||||
({session.user.role.replace('_', ' ')})
|
||||
({rolesLabel})
|
||||
</span>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="secondary"
|
||||
className="h-6 px-3 text-xs"
|
||||
className="pointer-events-auto h-6 px-3 text-xs"
|
||||
onClick={handleReturn}
|
||||
disabled={endImpersonation.isPending}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user