@@ -16,6 +16,7 @@ import {
1616 RectangleStackIcon ,
1717 ServerStackIcon ,
1818 Squares2X2Icon ,
19+ UsersIcon ,
1920} from "@heroicons/react/20/solid" ;
2021import { useLocation , useNavigation } from "@remix-run/react" ;
2122import { useEffect , useRef , useState , type ReactNode } from "react" ;
@@ -28,12 +29,14 @@ import { Avatar } from "~/components/primitives/Avatar";
2829import { type MatchedEnvironment } from "~/hooks/useEnvironment" ;
2930import { type MatchedOrganization } from "~/hooks/useOrganizations" ;
3031import { type MatchedProject } from "~/hooks/useProject" ;
32+ import { useHasAdminAccess } from "~/hooks/useUser" ;
3133import { type User } from "~/models/user.server" ;
3234import { useCurrentPlan } from "~/routes/_app.orgs.$organizationSlug/route" ;
3335import { type FeedbackType } from "~/routes/resources.feedback" ;
3436import { cn } from "~/utils/cn" ;
3537import {
3638 accountPath ,
39+ adminPath ,
3740 logoutPath ,
3841 newOrganizationPath ,
3942 newProjectPath ,
@@ -110,6 +113,7 @@ export function SideMenu({
110113 const currentPlan = useCurrentPlan ( ) ;
111114 const { isConnected } = useDevPresence ( ) ;
112115 const isFreeUser = currentPlan ?. v3Subscription ?. isPaying === false ;
116+ const isAdmin = useHasAdminAccess ( ) ;
113117
114118 useEffect ( ( ) => {
115119 const handleScroll = ( ) => {
@@ -143,6 +147,20 @@ export function SideMenu({
143147 project = { project }
144148 user = { user }
145149 />
150+ { isAdmin && ! user . isImpersonating ? (
151+ < TooltipProvider disableHoverableContent = { true } >
152+ < Tooltip >
153+ < TooltipTrigger >
154+ < LinkButton variant = "minimal/medium" to = { adminPath ( ) } TrailingIcon = { UsersIcon } />
155+ </ TooltipTrigger >
156+ < TooltipContent side = "bottom" className = { "text-xs" } >
157+ Admin dashboard
158+ </ TooltipContent >
159+ </ Tooltip >
160+ </ TooltipProvider >
161+ ) : isAdmin && user . isImpersonating ? (
162+ < ImpersonationBanner />
163+ ) : null }
146164 </ div >
147165 < div
148166 className = "overflow-hidden overflow-y-auto pt-2 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600"
@@ -325,10 +343,7 @@ function ProjectSelector({
325343 < PopoverArrowTrigger
326344 isOpen = { isOrgMenuOpen }
327345 overflowHidden
328- className = { cn (
329- "h-8 w-full justify-between py-1 pl-1.5" ,
330- user . isImpersonating && "border border-dashed border-amber-400"
331- ) }
346+ className = "h-8 w-full justify-between py-1 pl-1.5"
332347 >
333348 < span className = "flex items-center gap-1.5 overflow-hidden" >
334349 < Avatar avatar = { organization . avatar } size = { 1.25 } orgName = { organization . title } />
@@ -412,19 +427,24 @@ function ProjectSelector({
412427 < PopoverMenuItem to = { newProjectPath ( organization ) } title = "New project" icon = { PlusIcon } />
413428 </ div >
414429 < div className = "border-t border-charcoal-700 p-1" >
415- < SwitchOrganizations organizations = { organizations } organization = { organization } />
430+ { organizations . length > 1 ? (
431+ < SwitchOrganizations organizations = { organizations } organization = { organization } />
432+ ) : (
433+ < PopoverMenuItem
434+ to = { newOrganizationPath ( ) }
435+ title = "New organization"
436+ icon = { PlusIcon }
437+ leadingIconClassName = "text-text-dimmed"
438+ />
439+ ) }
416440 </ div >
417441 < div className = "border-t border-charcoal-700 p-1" >
418442 < PopoverMenuItem
419443 to = { accountPath ( ) }
420444 title = "Account"
421445 icon = { UserProfilePhoto }
422- leadingIconClassName = { cn (
423- "text-text-dimmed rounded-full border border-transparent" ,
424- user . isImpersonating && "rounded-full border-yellow-500"
425- ) }
446+ leadingIconClassName = "text-text-dimmed rounded-full border border-transparent"
426447 />
427- { user . isImpersonating && < ImpersonationBanner /> }
428448 </ div >
429449 < div className = "border-t border-charcoal-700 p-1" >
430450 < PopoverMenuItem
@@ -519,7 +539,7 @@ function SwitchOrganizations({
519539 < div className = "border-t border-charcoal-700 p-1" >
520540 < PopoverMenuItem
521541 to = { newOrganizationPath ( ) }
522- title = "New Organization "
542+ title = "New organization "
523543 icon = { PlusIcon }
524544 leadingIconClassName = "text-text-dimmed"
525545 />
0 commit comments