first
This commit is contained in:
commit
8538ab969a
434 changed files with 44051 additions and 0 deletions
|
|
@ -0,0 +1,160 @@
|
|||
"use client";
|
||||
import { config } from "@repo/config";
|
||||
import { useSession } from "@saas/auth/hooks/use-session";
|
||||
import { useActiveOrganization } from "@saas/organizations/hooks/use-active-organization";
|
||||
import { useOrganizationListQuery } from "@saas/organizations/lib/api";
|
||||
import { ActivePlanBadge } from "@saas/payments/components/ActivePlanBadge";
|
||||
import { UserAvatar } from "@shared/components/UserAvatar";
|
||||
import { useRouter } from "@shared/hooks/router";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@ui/components/dropdown-menu";
|
||||
import { ChevronsUpDownIcon, PlusIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import Link from "next/link";
|
||||
import { OrganizationLogo } from "./OrganizationLogo";
|
||||
|
||||
export function OrganzationSelect({ className }: { className?: string }) {
|
||||
const t = useTranslations();
|
||||
const { user } = useSession();
|
||||
const router = useRouter();
|
||||
const { activeOrganization, setActiveOrganization } =
|
||||
useActiveOrganization();
|
||||
const { data: allOrganizations } = useOrganizationListQuery();
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger className="flex w-full items-center justify-between gap-2 rounded-md border p-2 text-left outline-none focus-visible:bg-primary/10 focus-visible:ring-none">
|
||||
<div className="flex flex-1 items-center justify-start gap-2 text-sm overflow-hidden">
|
||||
{activeOrganization ? (
|
||||
<>
|
||||
<OrganizationLogo
|
||||
name={activeOrganization.name}
|
||||
logoUrl={activeOrganization.logo}
|
||||
className="hidden size-6 sm:block"
|
||||
/>
|
||||
<span className="block flex-1 truncate">
|
||||
{activeOrganization.name}
|
||||
</span>
|
||||
{config.organizations.enableBilling && (
|
||||
<ActivePlanBadge
|
||||
organizationId={activeOrganization.id}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<UserAvatar
|
||||
className="hidden size-6 sm:block"
|
||||
name={user.name ?? ""}
|
||||
avatarUrl={user.image}
|
||||
/>
|
||||
<span className="block truncate">
|
||||
{t(
|
||||
"organizations.organizationSelect.personalAccount",
|
||||
)}
|
||||
</span>
|
||||
{config.users.enableBilling && (
|
||||
<ActivePlanBadge />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<ChevronsUpDownIcon className="block size-4 opacity-50" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-full">
|
||||
{!config.organizations.requireOrganization && (
|
||||
<>
|
||||
<DropdownMenuRadioGroup
|
||||
value={activeOrganization?.id ?? user.id}
|
||||
onValueChange={(value: string) => {
|
||||
if (value === user.id) {
|
||||
router.replace("/app");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DropdownMenuLabel className="text-foreground/60 text-xs">
|
||||
{t(
|
||||
"organizations.organizationSelect.personalAccount",
|
||||
)}
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuRadioItem
|
||||
value={user.id}
|
||||
className="flex cursor-pointer items-center justify-center gap-2 pl-3"
|
||||
>
|
||||
<div className="flex flex-1 items-center justify-start gap-2">
|
||||
<UserAvatar
|
||||
className="size-8"
|
||||
name={user.name ?? ""}
|
||||
avatarUrl={user.image}
|
||||
/>
|
||||
{user.name}
|
||||
</div>
|
||||
</DropdownMenuRadioItem>
|
||||
</DropdownMenuRadioGroup>
|
||||
<DropdownMenuSeparator />
|
||||
</>
|
||||
)}
|
||||
<DropdownMenuRadioGroup
|
||||
value={activeOrganization?.slug}
|
||||
onValueChange={(organizationSlug: string) =>
|
||||
setActiveOrganization(organizationSlug)
|
||||
}
|
||||
>
|
||||
<DropdownMenuLabel className="text-foreground/60 text-xs">
|
||||
{t(
|
||||
"organizations.organizationSelect.organizations",
|
||||
)}
|
||||
</DropdownMenuLabel>
|
||||
{allOrganizations?.map((organization) => (
|
||||
<DropdownMenuRadioItem
|
||||
key={organization.slug}
|
||||
value={organization.slug}
|
||||
className="flex cursor-pointer items-center justify-center gap-2 pl-3"
|
||||
>
|
||||
<div className="flex flex-1 items-center justify-start gap-2">
|
||||
<OrganizationLogo
|
||||
className="size-8"
|
||||
name={organization.name}
|
||||
logoUrl={organization.logo}
|
||||
/>
|
||||
{organization.name}
|
||||
</div>
|
||||
</DropdownMenuRadioItem>
|
||||
))}
|
||||
</DropdownMenuRadioGroup>
|
||||
|
||||
{config.organizations.enableUsersToCreateOrganizations && (
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem
|
||||
asChild
|
||||
className="text-primary! cursor-pointer text-sm"
|
||||
>
|
||||
<Link href="/app/new-organization">
|
||||
<PlusIcon className="mr-2 size-6 rounded-md bg-primary/20 p-1" />
|
||||
{t(
|
||||
"organizations.organizationSelect.createNewOrganization",
|
||||
)}
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue