@@ -41,7 +41,7 @@ import { Label } from "~/components/primitives/Label";
4141import { NavBar , PageAccessories , PageTitle } from "~/components/primitives/PageHeader" ;
4242import { Paragraph } from "~/components/primitives/Paragraph" ;
4343import * as Property from "~/components/primitives/PropertyTable" ;
44- import { Select , SelectItem } from "~/components/primitives/Select" ;
44+ import { Select , SelectItem , SelectLinkItem } from "~/components/primitives/Select" ;
4545import { SpinnerWhite } from "~/components/primitives/Spinner" ;
4646import { SimpleTooltip } from "~/components/primitives/Tooltip" ;
4747import { cn } from "~/utils/cn" ;
@@ -52,16 +52,14 @@ import { removeTeamMember } from "~/models/member.server";
5252import { redirectWithSuccessMessage } from "~/models/message.server" ;
5353import { TeamPresenter } from "~/presenters/TeamPresenter.server" ;
5454import { rbac } from "~/services/rbac.server" ;
55- import {
56- dashboardAction ,
57- dashboardLoader ,
58- } from "~/services/routeBuilders/dashboardBuilder" ;
55+ import { dashboardAction , dashboardLoader } from "~/services/routeBuilders/dashboardBuilder" ;
5956import {
6057 inviteTeamMemberPath ,
6158 organizationRolesPath ,
6259 organizationTeamPath ,
6360 resendInvitePath ,
6461 revokeInvitePath ,
62+ selectPlanPath ,
6563 v3BillingPath ,
6664} from "~/utils/pathBuilder" ;
6765import { formatCurrency , formatNumber } from "~/utils/numberFormatter" ;
@@ -137,10 +135,7 @@ const PurchaseSchema = z.discriminatedUnion("action", [
137135 } ) ,
138136 z . object ( {
139137 action : z . literal ( "quota-increase" ) ,
140- amount : z . coerce
141- . number ( )
142- . int ( "Must be a whole number" )
143- . min ( 1 , "Amount must be greater than 0" ) ,
138+ amount : z . coerce . number ( ) . int ( "Must be a whole number" ) . min ( 1 , "Amount must be greater than 0" ) ,
144139 } ) ,
145140] ) ;
146141
@@ -339,7 +334,11 @@ export default function Page() {
339334 ) : requiresUpgrade ? (
340335 < SimpleTooltip
341336 button = {
342- < ButtonContent variant = "primary/small" LeadingIcon = { UserPlusIcon } className = "cursor-not-allowed opacity-50" >
337+ < ButtonContent
338+ variant = "primary/small"
339+ LeadingIcon = { UserPlusIcon }
340+ className = "cursor-not-allowed opacity-50"
341+ >
343342 Invite a team member
344343 </ ButtonContent >
345344 }
@@ -579,6 +578,7 @@ function RolePicker({
579578 assignableRoleIds : string [ ] ;
580579 canManageMembers : boolean ;
581580} ) {
581+ const organization = useOrganization ( ) ;
582582 const fetcher = useFetcher < { ok : boolean ; error ?: string } | { ok : true } > ( ) ;
583583 const assignable = new Set ( assignableRoleIds ) ;
584584 // With no RBAC plugin installed, the loader returns no roles —
@@ -587,13 +587,11 @@ function RolePicker({
587587
588588 const isSubmitting = fetcher . state === "submitting" ;
589589 const error =
590- fetcher . data && "error" in fetcher . data && fetcher . data . error
591- ? fetcher . data . error
592- : null ;
590+ fetcher . data && "error" in fetcher . data && fetcher . data . error ? fetcher . data . error : null ;
593591
594592 return (
595593 < div className = "flex flex-col items-end gap-1" >
596- < Select < string , Role >
594+ < Select
597595 defaultValue = { currentRoleId ?? "" }
598596 items = { roles }
599597 variant = "tertiary/small"
@@ -602,6 +600,12 @@ function RolePicker({
602600 text = { ( v ) => roles . find ( ( r ) => r . id === v ) ?. name ?? "No role" }
603601 setValue = { ( next ) => {
604602 if ( typeof next !== "string" || next === ( currentRoleId ?? "" ) ) return ;
603+ // Upgrade-link rows have a value too (Ariakit needs one to
604+ // make the row interactive — without it the Link inside
605+ // doesn't even register the click), but they shouldn't
606+ // submit the role-change form. The Link navigates the user
607+ // to the plan-selection page; we just bail here.
608+ if ( ! assignable . has ( next ) ) return ;
605609 fetcher . submit (
606610 { _formType : "set-role" , userId : memberUserId , roleId : next } ,
607611 { method : "post" }
@@ -611,11 +615,18 @@ function RolePicker({
611615 { ( items ) =>
612616 items . map ( ( role ) => {
613617 const isAssignable = assignable . has ( role . id ) ;
614- return (
615- < SelectItem key = { role . id } value = { role . id } disabled = { ! isAssignable } >
618+ return isAssignable ? (
619+ < SelectItem key = { role . id } value = { role . id } >
616620 { role . name }
617- { ! isAssignable ? " (upgrade)" : "" }
618621 </ SelectItem >
622+ ) : (
623+ < SelectLinkItem
624+ key = { role . id }
625+ value = { role . id }
626+ to = { selectPlanPath ( organization ) }
627+ >
628+ { role . name } (upgrade)
629+ </ SelectLinkItem >
619630 ) ;
620631 } )
621632 }
0 commit comments