import { ChevronDown } from 'lucide-react' import Link from 'next/link' import { parseAsString, useQueryState } from 'nuqs' import { useMemo, useState } from 'react' import { Badge, Button, Card, CardHeader, CardTitle, Input } from 'ui' import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader' import { ButtonTooltip } from './ButtonTooltip' import { useFreeProjectLimitCheckQuery } from '@/data/organizations/free-project-limit-check-query' import { useOrganizationsQuery } from '@/data/organizations/organizations-query' import type { Organization } from '@/types' export interface ProjectClaimChooseOrgProps { onSelect: (orgSlug: string) => void maxOrgsToShow?: number canCreateNewOrg: boolean } const OrganizationCard = ({ org, onSelect, }: { org: Organization onSelect: (orgSlug: string) => void }) => { const isFreePlan = org.plan?.id === 'free' const { data: membersExceededLimit, isSuccess } = useFreeProjectLimitCheckQuery( { slug: org.slug }, { enabled: isFreePlan } ) const hasMembersExceedingFreeTierLimit = (membersExceededLimit || []).length > 0 const freePlanWithExceedingLimits = isFreePlan && hasMembersExceedingFreeTierLimit return ( {org.name} {org.plan?.name}

The following members have reached their maximum limits for the number of active free plan projects within organizations where they are an administrator or owner:

    {membersExceededLimit.map((member, idx: number) => (
  • {member.username || member.primary_email} (Limit:{' '} {member.free_project_limit} free projects)
  • ))}

These members will need to either delete, pause, or upgrade one or more of these projects before you're able to create a free project within this organization.

) : undefined, }, }} size="small" onClick={() => { onSelect(org.slug) }} className="shrink-0" disabled={isSuccess && freePlanWithExceedingLimits} > Choose
) } export function OrganizationSelector({ onSelect, maxOrgsToShow = 5, canCreateNewOrg, }: ProjectClaimChooseOrgProps) { const { data: organizations = [], isPending: isLoadingOrgs, isSuccess: isSuccessOrgs, isError: isErrorOrgs, } = useOrganizationsQuery() const [search, setSearch] = useQueryState( 'org', parseAsString.withDefault('').withOptions({ clearOnDefault: true }) ) const [showAll, setShowAll] = useState(false) const filteredOrgs = useMemo(() => { if (!search) { return showAll ? organizations : organizations.slice(0, maxOrgsToShow) } return organizations.filter((org) => org.name.toLowerCase().includes(search.toLowerCase())) }, [organizations, search, showAll, maxOrgsToShow]) const searchParams = new URLSearchParams(location.search) let pathname = location.pathname const basePath = process.env.NEXT_PUBLIC_BASE_PATH if (basePath) { pathname = pathname.replace(basePath, '') } searchParams.set('returnTo', pathname) const onSelectOrg = (orgSlug: string) => { onSelect(orgSlug) setSearch('') } return (
{isLoadingOrgs ? ( ) : isErrorOrgs ? (
Error
) : isSuccessOrgs && organizations.length === 0 ? ( It seems you don't have any organizations yet. ) : ( <> setSearch(e.target.value)} placeholder="Search..." />
{filteredOrgs.length === 0 && (
No organizations found.
)} {filteredOrgs.map((org) => ( ))} {organizations.length > maxOrgsToShow && !showAll && !search && (
)}
)} {canCreateNewOrg && ( Need a new organization? )}
) }