Header.tsx 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. "use client";
  2. import { Button } from "@app/components/ui/button";
  3. import {
  4. Command,
  5. CommandEmpty,
  6. CommandGroup,
  7. CommandInput,
  8. CommandItem,
  9. CommandList,
  10. CommandSeparator
  11. } from "@app/components/ui/command";
  12. import {
  13. Popover,
  14. PopoverContent,
  15. PopoverTrigger
  16. } from "@app/components/ui/popover";
  17. import { useEnvContext } from "@app/hooks/useEnvContext";
  18. import { cn } from "@app/lib/cn";
  19. import { ListOrgsResponse } from "@server/routers/org";
  20. import { Check, ChevronsUpDown, Plus } from "lucide-react";
  21. import Link from "next/link";
  22. import { useRouter } from "next/navigation";
  23. import { useState } from "react";
  24. import { useUserContext } from "@app/hooks/useUserContext";
  25. import ProfileIcon from "./ProfileIcon";
  26. type HeaderProps = {
  27. orgId?: string;
  28. orgs?: ListOrgsResponse["orgs"];
  29. };
  30. export function Header({ orgId, orgs }: HeaderProps) {
  31. const { user, updateUser } = useUserContext();
  32. const [open, setOpen] = useState(false);
  33. const router = useRouter();
  34. const { env } = useEnvContext();
  35. return (
  36. <>
  37. <div className="flex items-center justify-between">
  38. <ProfileIcon />
  39. <div className="flex items-center">
  40. <div className="hidden md:block">
  41. <div className="flex items-center gap-4 mr-4">
  42. <Link
  43. href="https://docs.fossorial.io/Pangolin/overview"
  44. target="_blank"
  45. rel="noopener noreferrer"
  46. className="text-muted-foreground hover:text-foreground"
  47. >
  48. Documentation
  49. </Link>
  50. <a
  51. href="mailto:support@fossorial.io"
  52. className="text-muted-foreground hover:text-foreground"
  53. >
  54. Support
  55. </a>
  56. </div>
  57. </div>
  58. {orgs && (
  59. <Popover open={open} onOpenChange={setOpen}>
  60. <PopoverTrigger asChild>
  61. <Button
  62. variant="outline"
  63. size="lg"
  64. role="combobox"
  65. aria-expanded={open}
  66. className="w-full md:w-[200px] h-12 px-3 py-4 bg-neutral hover:bg-neutral"
  67. >
  68. <div className="flex items-center justify-between w-full">
  69. <div className="flex flex-col items-start">
  70. <span className="font-bold text-sm">
  71. Organization
  72. </span>
  73. <span className="text-sm text-muted-foreground">
  74. {orgId
  75. ? orgs?.find(
  76. (org) =>
  77. org.orgId ===
  78. orgId
  79. )?.name
  80. : "None selected"}
  81. </span>
  82. </div>
  83. <ChevronsUpDown className="h-4 w-4 shrink-0 opacity-50" />
  84. </div>
  85. </Button>
  86. </PopoverTrigger>
  87. <PopoverContent className="[100px] md:w-[180px] p-0">
  88. <Command>
  89. <CommandInput placeholder="Search..." />
  90. <CommandEmpty>
  91. No organizations found.
  92. </CommandEmpty>
  93. {(!env.flags.disableUserCreateOrg ||
  94. user.serverAdmin) && (
  95. <>
  96. <CommandGroup heading="Create">
  97. <CommandList>
  98. <CommandItem
  99. onSelect={(
  100. currentValue
  101. ) => {
  102. router.push(
  103. "/setup"
  104. );
  105. }}
  106. >
  107. <Plus className="mr-2 h-4 w-4" />
  108. New Organization
  109. </CommandItem>
  110. </CommandList>
  111. </CommandGroup>
  112. <CommandSeparator />
  113. </>
  114. )}
  115. <CommandGroup heading="Organizations">
  116. <CommandList>
  117. {orgs.map((org) => (
  118. <CommandItem
  119. key={org.orgId}
  120. onSelect={(
  121. currentValue
  122. ) => {
  123. router.push(
  124. `/${org.orgId}/settings`
  125. );
  126. }}
  127. >
  128. <Check
  129. className={cn(
  130. "mr-2 h-4 w-4",
  131. orgId === org.orgId
  132. ? "opacity-100"
  133. : "opacity-0"
  134. )}
  135. />
  136. {org.name}
  137. </CommandItem>
  138. ))}
  139. </CommandList>
  140. </CommandGroup>
  141. </Command>
  142. </PopoverContent>
  143. </Popover>
  144. )}
  145. </div>
  146. </div>
  147. </>
  148. );
  149. }
  150. export default Header;