@@ -3,16 +3,87 @@ import Link from 'next/link'
33import { useMemo , useState } from 'react'
44
55import ShimmeringLoader from 'components/ui/ShimmeringLoader'
6+ import { useFreeProjectLimitCheckQuery } from 'data/organizations/free-project-limit-check-query'
67import { useOrganizationsQuery } from 'data/organizations/organizations-query'
78import { parseAsString , useQueryState } from 'nuqs'
89import { Organization } from 'types'
910import { Badge , Button , Card , CardHeader , CardTitle , Input_Shadcn_ } from 'ui'
11+ import { ButtonTooltip } from './ButtonTooltip'
1012
1113export interface ProjectClaimChooseOrgProps {
12- onSelect : ( org : Organization ) => void
14+ onSelect : ( orgSlug : string ) => void
1315 maxOrgsToShow ?: number
1416}
1517
18+ const OrganizationCard = ( {
19+ org,
20+ onSelect,
21+ } : {
22+ org : Organization
23+ onSelect : ( orgSlug : string ) => void
24+ } ) => {
25+ const isFreePlan = org . plan ?. id === 'free'
26+ const { data : membersExceededLimit , isSuccess } = useFreeProjectLimitCheckQuery (
27+ { slug : org . slug } ,
28+ { enabled : isFreePlan }
29+ )
30+ const hasMembersExceedingFreeTierLimit = ( membersExceededLimit || [ ] ) . length > 0
31+ const freePlanWithExceedingLimits = isFreePlan && hasMembersExceedingFreeTierLimit
32+
33+ return (
34+ < Card
35+ key = { org . id }
36+ className = "hover:bg-surface-200 rounded-none first:rounded-t-lg last:rounded-b-lg -mb-px"
37+ >
38+ < CardHeader className = "flex flex-row justify-between border-none space-y-0 space-x-2" >
39+ < CardTitle className = "flex items-center gap-2 min-w-0 flex-1" >
40+ < span className = "truncate min-w-0" title = { org . name } >
41+ { org . name }
42+ </ span >
43+ < Badge className = "shrink-0" > { org . plan ?. name } </ Badge >
44+ </ CardTitle >
45+ < ButtonTooltip
46+ tooltip = { {
47+ content : {
48+ text :
49+ isSuccess && freePlanWithExceedingLimits ? (
50+ < div className = "space-y-3 w-96 p-2" >
51+ < p className = "text-sm leading-normal" >
52+ The following members have reached their maximum limits for the number of
53+ active free plan projects within organizations where they are an administrator
54+ or owner:
55+ </ p >
56+ < ul className = "pl-5 list-disc" >
57+ { membersExceededLimit . map ( ( member , idx : number ) => (
58+ < li key = { `member-${ idx } ` } >
59+ { member . username || member . primary_email } (Limit:{ ' ' }
60+ { member . free_project_limit } free projects)
61+ </ li >
62+ ) ) }
63+ </ ul >
64+ < p className = "text-sm leading-normal" >
65+ These members will need to either delete, pause, or upgrade one or more of
66+ these projects before you're able to create a free project within this
67+ organization.
68+ </ p >
69+ </ div >
70+ ) : undefined ,
71+ } ,
72+ } }
73+ size = "small"
74+ onClick = { ( ) => {
75+ onSelect ( org . slug )
76+ } }
77+ className = "shrink-0"
78+ disabled = { isSuccess && freePlanWithExceedingLimits }
79+ >
80+ Choose
81+ </ ButtonTooltip >
82+ </ CardHeader >
83+ </ Card >
84+ )
85+ }
86+
1687export function OrganizationSelector ( { onSelect, maxOrgsToShow = 5 } : ProjectClaimChooseOrgProps ) {
1788 const {
1889 data : organizations = [ ] ,
@@ -43,6 +114,11 @@ export function OrganizationSelector({ onSelect, maxOrgsToShow = 5 }: ProjectCla
43114
44115 searchParams . set ( 'returnTo' , pathname )
45116
117+ const onSelectOrg = ( orgSlug : string ) => {
118+ onSelect ( orgSlug )
119+ setSearch ( '' )
120+ }
121+
46122 return (
47123 < div className = "w-full flex flex-col gap-y-4" >
48124 { isLoadingOrgs ? (
@@ -66,29 +142,7 @@ export function OrganizationSelector({ onSelect, maxOrgsToShow = 5 }: ProjectCla
66142 < div className = "text-center text-foreground-light py-6" > No organizations found.</ div >
67143 ) }
68144 { filteredOrgs . map ( ( org ) => (
69- < Card
70- key = { org . id }
71- className = "hover:bg-surface-200 rounded-none first:rounded-t-lg last:rounded-b-lg -mb-px"
72- >
73- < CardHeader className = "flex flex-row justify-between border-none space-y-0 space-x-2" >
74- < CardTitle className = "flex items-center gap-2 min-w-0 flex-1" >
75- < span className = "truncate min-w-0" title = { org . name } >
76- { org . name }
77- </ span >
78- < Badge className = "shrink-0" > { org . plan ?. name } </ Badge >
79- </ CardTitle >
80- < Button
81- size = "small"
82- onClick = { ( ) => {
83- onSelect ( org )
84- setSearch ( '' )
85- } }
86- className = "shrink-0"
87- >
88- Choose
89- </ Button >
90- </ CardHeader >
91- </ Card >
145+ < OrganizationCard key = { org . id } org = { org } onSelect = { onSelectOrg } />
92146 ) ) }
93147 { organizations . length > maxOrgsToShow && ! showAll && ! search && (
94148 < div className = "flex justify-center py-2" >
0 commit comments