@carlonicora/nextjs-jsonapi 1.7.1 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BlockNoteEditor-M6TUP3NT.mjs → BlockNoteEditor-GJURWDIH.mjs} +3 -3
- package/dist/{BlockNoteEditor-IJASTIUZ.js → BlockNoteEditor-WEQLDXRK.js} +13 -13
- package/dist/{BlockNoteEditor-IJASTIUZ.js.map → BlockNoteEditor-WEQLDXRK.js.map} +1 -1
- package/dist/{chunk-U4NADAHN.js → chunk-BYMZEX5B.js} +7 -3
- package/dist/chunk-BYMZEX5B.js.map +1 -0
- package/dist/{chunk-4U5CJA44.mjs → chunk-JPHVDI2C.mjs} +7 -3
- package/dist/chunk-JPHVDI2C.mjs.map +1 -0
- package/dist/{chunk-4L7OWJ2P.js → chunk-ODZ2X6Y3.js} +358 -358
- package/dist/{chunk-4L7OWJ2P.js.map → chunk-ODZ2X6Y3.js.map} +1 -1
- package/dist/{chunk-TW4QRJ7D.mjs → chunk-RRNBQ3LY.mjs} +3 -3
- package/dist/client/index.js +3 -3
- package/dist/client/index.mjs +2 -2
- package/dist/components/index.js +3 -3
- package/dist/components/index.mjs +2 -2
- package/dist/contexts/index.js +3 -3
- package/dist/contexts/index.mjs +2 -2
- package/dist/core/index.js +2 -2
- package/dist/core/index.mjs +1 -1
- package/dist/index.js +2 -2
- package/dist/index.mjs +1 -1
- package/dist/server/index.js +9 -5
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +7 -3
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client/JsonApiClient.ts +6 -2
- package/src/server/JsonApiServer.ts +6 -2
- package/dist/chunk-4U5CJA44.mjs.map +0 -1
- package/dist/chunk-U4NADAHN.js.map +0 -1
- /package/dist/{BlockNoteEditor-M6TUP3NT.mjs.map → BlockNoteEditor-GJURWDIH.mjs.map} +0 -0
- /package/dist/{chunk-TW4QRJ7D.mjs.map → chunk-RRNBQ3LY.mjs.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-4L7OWJ2P.js","../src/components/navigations/Breadcrumb.tsx","../src/hooks/TableGeneratorRegistry.ts","../src/hooks/url.rewriter.ts","../src/hooks/usePageUrlGenerator.ts","../src/hooks/useDataListRetriever.ts","../src/hooks/useDebounce.ts","../src/hooks/useTableGenerator.ts","../src/hooks/useCustomD3Graph.tsx","../src/hooks/useNotificationSync.ts","../src/features/company/contexts/CompanyContext.tsx","../src/features/user/contexts/CurrentUserContext.tsx","../src/features/user/contexts/UserContext.tsx","../src/features/user/components/forms/RoleUserAdd.tsx","../src/features/user/components/forms/UserAvatarEditor.tsx","../src/shadcnui/ui/accordion.tsx","../src/shadcnui/ui/alert.tsx","../src/shadcnui/ui/alert-dialog.tsx","../src/shadcnui/ui/button.tsx","../src/shadcnui/ui/avatar.tsx","../src/shadcnui/ui/badge.tsx","../src/shadcnui/ui/breadcrumb.tsx","../src/shadcnui/ui/calendar.tsx","../src/shadcnui/ui/card.tsx","../src/shadcnui/ui/carousel.tsx","../src/shadcnui/ui/chart.tsx","../src/shadcnui/ui/checkbox.tsx","../src/shadcnui/ui/collapsible.tsx","../src/shadcnui/ui/command.tsx","../src/shadcnui/ui/dialog.tsx","../src/shadcnui/ui/context-menu.tsx","../src/shadcnui/ui/drawer.tsx","../src/shadcnui/ui/dropdown-menu.tsx","../src/shadcnui/ui/form.tsx","../src/shadcnui/ui/label.tsx","../src/shadcnui/ui/hover-card.tsx","../src/shadcnui/ui/input.tsx","../src/shadcnui/ui/navigation-menu.tsx","../src/shadcnui/ui/popover.tsx","../src/shadcnui/ui/progress.tsx","../src/shadcnui/ui/radio-group.tsx","../src/shadcnui/ui/resizable.tsx","../src/shadcnui/ui/scroll-area.tsx","../src/shadcnui/ui/select.tsx","../src/shadcnui/ui/separator.tsx","../src/shadcnui/ui/sheet.tsx","../src/shadcnui/ui/sidebar.tsx","../src/shadcnui/ui/skeleton.tsx","../src/shadcnui/ui/tooltip.tsx","../src/shadcnui/ui/slider.tsx","../src/shadcnui/ui/sonner.tsx","../src/shadcnui/ui/switch.tsx","../src/shadcnui/ui/table.tsx","../src/shadcnui/ui/tabs.tsx","../src/shadcnui/ui/textarea.tsx","../src/shadcnui/ui/toggle.tsx","../src/shadcnui/custom/kanban.tsx","../src/shadcnui/custom/link.tsx","../src/shadcnui/custom/multi-select.tsx","../src/features/user/components/forms/UserDeleter.tsx","../src/features/user/components/forms/UserEditor.tsx","../src/features/user/components/forms/UserMultiSelect.tsx","../src/features/user/components/forms/UserReactivator.tsx","../src/features/user/components/forms/UserResentInvitationEmail.tsx","../src/features/user/components/forms/UserSelector.tsx","../src/features/user/components/widgets/UserAvatar.tsx","../src/features/user/components/containers/UserContainer.tsx","../src/features/user/components/details/UserDetails.tsx","../src/features/user/components/details/UserIndexDetails.tsx","../src/features/user/components/containers/UserIndexContainer.tsx","../src/features/user/components/containers/UsersListContainer.tsx","../src/features/user/components/lists/AdminUsersList.tsx","../src/features/user/components/lists/CompanyUsersList.tsx","../src/features/user/components/lists/ContributorsList.tsx","../src/features/user/components/lists/RelevantUsersList.tsx","../src/features/user/components/lists/RoleUsersList.tsx","../src/features/user/components/lists/UserListInAdd.tsx","../src/features/user/components/lists/UsersList.tsx","../src/features/user/components/lists/UsersListByContentIds.tsx","../src/features/company/components/details/CompanyDetails.tsx","../src/features/company/components/containers/AdminCompanyContainer.tsx","../src/features/company/components/containers/CompanyContainer.tsx","../src/features/company/components/forms/CompanyConfigurationEditor.tsx","../src/features/company/components/forms/CompanyConfigurationSecurityForm.tsx","../src/features/company/components/forms/CompanyDeleter.tsx","../src/features/company/components/forms/CompanyEditor.tsx","../src/features/company/components/forms/CompanyLicense.tsx","../src/features/company/components/lists/CompaniesList.tsx","../src/features/notification/contexts/NotificationContext.tsx","../src/features/notification/components/notifications/Notification.tsx","../src/features/role/contexts/RoleContext.tsx","../src/contexts/CommonContext.tsx","../src/contexts/SharedContext.tsx","../src/contexts/SocketContext.tsx","../src/atoms/recentPagesAtom.ts","../src/hooks/usePageTracker.ts","../src/hooks/usePushNotifications.ts","../src/hooks/useSocket.ts","../src/components/navigations/ContentTitle.tsx","../src/components/navigations/Header.tsx","../src/components/navigations/ModeToggleSwitch.tsx","../src/components/navigations/PageSection.tsx","../src/components/navigations/RecentPagesNavigator.tsx","../src/components/containers/PageContainer.tsx","../src/components/containers/ReactMarkdownContainer.tsx","../src/components/containers/TabsContainer.tsx","../src/components/contents/AttributeElement.tsx","../src/components/details/AllowedUsersDetails.tsx","../src/components/editors/BlockNoteEditorContainer.tsx","../src/components/errors/ErrorDetails.tsx","../src/components/errors/errorToast.ts","../src/components/forms/CommonAssociationForm.tsx","../src/components/forms/CommonDeleter.tsx","../src/components/forms/CommonEditorButtons.tsx","../src/components/forms/CommonEditorHeader.tsx","../src/components/forms/CommonEditorTrigger.tsx","../src/components/forms/DatePickerPopover.tsx","../src/components/forms/DateRangeSelector.tsx","../src/components/forms/FileUploader.tsx","../src/components/forms/FormCheckbox.tsx","../src/components/forms/FormContainerGeneric.tsx","../src/components/forms/FormDate.tsx","../src/components/forms/FormDateTime.tsx","../src/components/forms/FormInput.tsx","../src/components/forms/PasswordInput.tsx","../src/components/forms/FormPassword.tsx","../src/components/forms/FormPlaceAutocomplete.tsx","../src/components/forms/FormSelect.tsx","../src/components/forms/FormSlider.tsx","../src/components/forms/FormSwitch.tsx","../src/components/forms/FormTextarea.tsx","../src/components/forms/MultiFileUploader.tsx","../src/features/feature/components/forms/FormFeatures.tsx","../src/components/pages/PageContainerContentDetails.tsx","../src/components/pages/PageContentContainer.tsx","../src/components/tables/cells/cell.component.tsx","../src/components/tables/cells/cell.date.tsx","../src/components/tables/cells/cell.id.tsx","../src/components/tables/cells/cell.link.tsx","../src/components/tables/cells/cell.url.tsx","../src/client/context/JsonApiContext.ts","../src/client/context/JsonApiProvider.tsx","../src/client/hooks/useJsonApiGet.ts","../src/client/hooks/useJsonApiMutation.ts","../src/client/hooks/useRehydration.ts","../src/features/company/hooks/useCompanyTableStructure.tsx","../src/features/role/hooks/useRoleTableStructure.tsx","../src/features/user/hooks/useUserSearch.ts","../src/features/user/hooks/useUserTableStructure.tsx","../src/features/content/hooks/useContentTableStructure.tsx","../src/client/index.ts","../src/components/tables/ContentListTable.tsx","../src/components/tables/ContentTableSearch.tsx","../src/features/auth/components/containers/AuthContainer.tsx","../src/features/auth/contexts/AuthContext.tsx","../src/features/auth/components/forms/Register.tsx","../src/features/auth/components/details/LandingComponent.tsx","../src/features/auth/components/forms/AcceptInvitation.tsx","../src/features/auth/components/forms/ActivateAccount.tsx","../src/features/auth/components/forms/Cookies.tsx","../src/features/auth/components/forms/ForgotPassword.tsx","../src/features/auth/components/forms/Login.tsx","../src/features/auth/components/forms/Logout.tsx","../src/features/auth/components/forms/RefreshUser.tsx","../src/features/auth/components/forms/ResetPassword.tsx","../src/features/content/components/lists/ContentsList.tsx","../src/features/content/components/lists/ContentsListById.tsx","../src/features/content/components/lists/RelevantContentsList.tsx","../src/features/notification/components/common/NotificationErrorBoundary.tsx","../src/features/notification/components/containers/NotificationsListContainer.tsx","../src/features/notification/components/lists/NotificationsList.tsx","../src/features/notification/components/modals/NotificationModal.tsx","../src/features/notification/components/notifications/PushNotificationProvider.tsx","../src/features/role/components/details/RoleDetails.tsx","../src/features/role/components/containers/RoleContainer.tsx","../src/features/role/components/forms/FormRoles.tsx","../src/features/role/components/forms/RemoveUserFromRole.tsx","../src/features/role/components/forms/UserRoleAdd.tsx","../src/features/role/components/lists/RolesList.tsx","../src/features/role/components/lists/UserRolesList.tsx"],"names":["Label","RadioGroup","Link"],"mappings":"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A;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-4L7OWJ2P.js","sourcesContent":[null,"\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { Fragment, useState } from \"react\";\nimport { usePageUrlGenerator } from \"../../hooks\";\nimport { BreadcrumbItemData } from \"../../interfaces\";\nimport {\n BreadcrumbEllipsis,\n BreadcrumbItem,\n BreadcrumbList,\n BreadcrumbSeparator,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n Link,\n Breadcrumb as UIBreadcrumb,\n} from \"../../shadcnui\";\n\ntype BreadcrumbProps = { items: BreadcrumbItemData[] };\n\nconst ITEMS_TO_DISPLAY = 3;\n\nexport function BreadcrumbNavigation({ items }: BreadcrumbProps) {\n const generateUrl = usePageUrlGenerator();\n const t = useTranslations();\n\n const [open, setOpen] = useState<boolean>(false);\n\n return (\n <UIBreadcrumb>\n <BreadcrumbList>\n <BreadcrumbItem>\n <Link href={generateUrl({ page: `/` })}>{t(`generic.home`)}</Link>\n </BreadcrumbItem>\n {items.length > 0 && <BreadcrumbSeparator />}\n\n {items.length > ITEMS_TO_DISPLAY ? (\n <>\n <BreadcrumbItem>\n {items[0].href ? <Link href={items[0].href}>{items[0].name}</Link> : <>{items[0].name}</>}\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <DropdownMenu open={open} onOpenChange={setOpen}>\n <DropdownMenuTrigger className=\"flex items-center gap-1\" aria-label=\"Toggle menu\">\n <BreadcrumbEllipsis className=\"h-4 w-4\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n {items.slice(1, -ITEMS_TO_DISPLAY + 1).map((item, index) => (\n <DropdownMenuItem key={index}>\n <Link href={item.href ? item.href : \"#\"}>{item.name}</Link>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n {items.slice(-ITEMS_TO_DISPLAY + 1).map((item, index) => (\n <Fragment key={index}>\n <BreadcrumbItem>\n {item.href ? <Link href={item.href}>{item.name}</Link> : <>{item.name}</>}\n </BreadcrumbItem>\n {index < items.slice(-ITEMS_TO_DISPLAY + 1).length - 1 && <BreadcrumbSeparator />}\n </Fragment>\n ))}\n </>\n ) : (\n <>\n {items.map((item, index) => (\n <Fragment key={index}>\n <BreadcrumbItem>\n {item.href ? <Link href={item.href}>{item.name}</Link> : <>{item.name}</>}\n </BreadcrumbItem>\n {index < items.length - 1 && <BreadcrumbSeparator />}\n </Fragment>\n ))}\n </>\n )}\n </BreadcrumbList>\n </UIBreadcrumb>\n );\n}\n","\"use client\";\n\nimport { UseTableStructureHook, UseTableStructureHookParams, UseTableStructureHookReturn } from \"./types\";\n\ntype TableGeneratorHook = UseTableStructureHook<any, any>;\n\nexport class TableGeneratorRegistry {\n private static instance: TableGeneratorRegistry;\n private registry = new Map<string, TableGeneratorHook>();\n\n private constructor() {}\n\n public static getInstance(): TableGeneratorRegistry {\n if (!TableGeneratorRegistry.instance) {\n TableGeneratorRegistry.instance = new TableGeneratorRegistry();\n }\n return TableGeneratorRegistry.instance;\n }\n\n public register<T, U>(type: string, hook: UseTableStructureHook<T, U>): void {\n if (!this.registry.has(type)) this.registry.set(type, hook as TableGeneratorHook);\n }\n\n public get<T, U>(type: string, params: UseTableStructureHookParams<T, U>): UseTableStructureHookReturn<T> {\n const hook = this.registry.get(type);\n if (!hook) {\n throw new Error(\n `Table generator for type \"${type}\" is not registered. Available types: ${Array.from(this.registry.keys()).join(\n \", \",\n )}`,\n );\n }\n return hook(params);\n }\n\n public isRegistered(type: string): boolean {\n return this.registry.has(type);\n }\n\n public getRegisteredTypes(): string[] {\n return Array.from(this.registry.keys());\n }\n\n public unregister(type: string): boolean {\n return this.registry.delete(type);\n }\n\n public clear(): void {\n this.registry.clear();\n }\n}\n\nexport const tableGeneratorRegistry = TableGeneratorRegistry.getInstance();\n","\"use client\";\n\nimport { useLocale } from \"next-intl\";\nimport { useCallback } from \"react\";\nimport { ModuleWithPermissions } from \"../permissions\";\nimport { usePageUrlGenerator } from \"./usePageUrlGenerator\";\n\nexport function useUrlRewriter() {\n const locale = useLocale();\n const generateUrl = usePageUrlGenerator();\n\n return useCallback(\n (params: { page: ModuleWithPermissions | string; id?: string; childPage?: string }): void => {\n window.history.replaceState(\n null,\n \"\",\n generateUrl({ page: params.page, id: params.id, childPage: params.childPage, language: locale }),\n );\n },\n [locale, generateUrl],\n );\n}\n","import { PageUrl } from \"../permissions/types\";\n\nexport function usePageUrlGenerator(): (params: {\n page?: PageUrl | string;\n id?: string;\n childPage?: PageUrl | string;\n childId?: string;\n additionalParameters?: { [key: string]: string | string[] | undefined };\n language?: string;\n}) => string {\n const generateUrl = (params: {\n page?: PageUrl | string;\n id?: string;\n childPage?: PageUrl | string;\n childId?: string;\n additionalParameters?: { [key: string]: string | string[] | undefined };\n language?: string;\n }): string => {\n if (!params.page) return \"/\";\n\n const pathParams: string[] = [\n `${params.language ? `/${params.language}` : \"\"}${typeof params.page === \"string\" ? params.page : params.page.pageUrl}`,\n ];\n\n if (params.id) {\n pathParams.push(params.id);\n if (params.childPage) {\n pathParams.push(typeof params.childPage === \"string\" ? params.childPage : (params.childPage.pageUrl ?? \"\"));\n if (params.childId) {\n pathParams.push(params.childId);\n }\n }\n }\n const response = pathParams.join(`/`);\n\n if (params.additionalParameters) {\n const searchParams = new URLSearchParams();\n for (const key in params.additionalParameters) {\n if (params.additionalParameters[key]) {\n searchParams.append(key, params.additionalParameters[key] as string);\n }\n }\n return `${response}?${searchParams.toString()}`;\n }\n\n return response;\n };\n\n return generateUrl;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { ClientAbstractService } from \"../core/abstracts/ClientAbstractService\";\n\nexport type PageInfo = {\n startItem: number;\n endItem: number;\n pageSize: number;\n};\n\nexport type DataListRetriever<T> = {\n ready?: boolean;\n setReady: (state: boolean) => void;\n isLoaded: boolean;\n data: T[] | undefined;\n next?: (onlyNewRecords?: boolean) => Promise<void>;\n previous?: (onlyNewRecords?: boolean) => Promise<void>;\n search: (search: string) => Promise<void>;\n refresh: () => Promise<void>;\n addAdditionalParameter: (key: string, value: any | null) => void;\n removeAdditionalParameter: (key: string) => void;\n setRefreshedElement: (element: T) => void;\n removeElement: (element: T) => void;\n isSearch: boolean;\n pageInfo?: PageInfo;\n};\n\nexport function useDataListRetriever<T>(params: {\n ready?: boolean;\n retriever: (params: any) => Promise<T[]>;\n retrieverParams?: any;\n search?: string;\n addAdditionalParameter?: (key: string, value: any | null) => void;\n requiresSearch?: boolean;\n module: any;\n}): DataListRetriever<T> {\n const [data, setData] = useState<T[] | undefined>(undefined);\n const [nextPage, setNextPage] = useState<string | undefined>(undefined);\n const [previousPage, setPreviousPage] = useState<string | undefined>(undefined);\n const [isLoaded, setIsLoaded] = useState(false);\n const [ready, setReady] = useState<boolean>(params.ready ?? true);\n const searchTermRef = useRef<string>(\"\");\n const additionalParamsRef = useRef<any>({});\n const requestIdRef = useRef(0);\n const abortControllerRef = useRef<AbortController | null>(null);\n const isFetchingRef = useRef(false);\n\n const resolvedType = params.module;\n const resolvedService = ClientAbstractService; // We'll just use ClientAbstractService directly for pagination\n\n // Helper to parse page params from pagination URLs\n const parsePageParams = useCallback((url: string | undefined): { offset: number; size: number } | null => {\n if (!url) return null;\n try {\n const urlObj = new URL(url);\n const offset = parseInt(urlObj.searchParams.get(\"page[offset]\") || \"0\", 10);\n const size = parseInt(urlObj.searchParams.get(\"page[size]\") || \"25\", 10);\n return { offset, size };\n } catch {\n return null;\n }\n }, []);\n\n // Helper to adjust pagination URL offset (used when removing elements)\n const adjustPaginationUrl = useCallback((url: string | undefined, delta: number): string | undefined => {\n if (!url) return undefined;\n try {\n const urlObj = new URL(url);\n const currentOffset = parseInt(urlObj.searchParams.get(\"page[offset]\") || \"0\", 10);\n const newOffset = Math.max(0, currentOffset + delta);\n urlObj.searchParams.set(\"page[offset]\", String(newOffset));\n return urlObj.toString();\n } catch {\n return url;\n }\n }, []);\n\n // Calculate pageInfo from pagination URLs and current data\n const pageInfo = useMemo((): PageInfo | undefined => {\n if (!data || data.length === 0) return undefined;\n\n // Try to determine current offset and page size from pagination URLs\n const nextParams = parsePageParams(nextPage);\n const prevParams = parsePageParams(previousPage);\n\n let currentOffset = 0;\n let pageSize = 25; // default\n\n if (nextParams) {\n // If we have a next page, current offset = next offset - page size\n pageSize = nextParams.size;\n currentOffset = Math.max(0, nextParams.offset - pageSize);\n } else if (prevParams) {\n // If we only have a previous page (we're on the last page)\n pageSize = prevParams.size;\n currentOffset = prevParams.offset + pageSize;\n }\n\n const startItem = currentOffset + 1;\n const endItem = currentOffset + data.length;\n\n return { startItem, endItem, pageSize };\n }, [data, nextPage, previousPage, parsePageParams]);\n\n const stableParams = useMemo(\n () => ({\n service: resolvedService,\n type: resolvedType,\n retriever: params.retriever,\n retrieverParams: params.retrieverParams,\n requiresSearch: params.requiresSearch,\n }),\n [resolvedService, resolvedType, params.retriever, params.retrieverParams, params.requiresSearch],\n );\n\n const fetchData = useCallback(\n async (fetchParams?: { isRefine?: boolean; isRefresh?: boolean; callNext?: boolean; callPrevious?: boolean }) => {\n if (ready === false) {\n return;\n }\n\n // Prevent concurrent fetches (unless it's a pagination call)\n if (isFetchingRef.current && !fetchParams?.callNext && !fetchParams?.callPrevious) {\n return;\n }\n\n const thisRequestId = ++requestIdRef.current;\n isFetchingRef.current = true;\n\n if (stableParams.requiresSearch === true && fetchParams?.isRefine !== true && fetchParams?.isRefresh !== true)\n return;\n\n if (\n !nextPage &&\n !previousPage &&\n isLoaded &&\n fetchParams?.callNext !== true &&\n fetchParams?.callPrevious !== true &&\n params.search === searchTermRef.current\n )\n return;\n\n const currentSearchTerm = searchTermRef.current;\n\n setIsLoaded(false);\n\n try {\n let response: T[];\n const nextRef = { next: undefined };\n const previousRef = { previous: undefined };\n const selfRef = { self: undefined };\n\n if (nextPage && fetchParams?.callNext && fetchParams?.isRefine !== true) {\n const ServiceClass = stableParams.service as typeof ClientAbstractService;\n\n response = await ServiceClass.next<T[]>({\n type: stableParams.type,\n endpoint: nextPage,\n next: nextRef,\n previous: previousRef,\n self: selfRef,\n });\n } else if (previousPage && fetchParams?.callPrevious && fetchParams?.isRefine !== true) {\n const ServiceClass = stableParams.service as typeof ClientAbstractService;\n\n response = await ServiceClass.previous<T[]>({\n type: stableParams.type,\n endpoint: previousPage,\n next: nextRef,\n previous: previousRef,\n self: selfRef,\n });\n } else {\n let retrieverParams = stableParams.retrieverParams ? { ...stableParams.retrieverParams } : {};\n\n retrieverParams = {\n ...retrieverParams,\n ...additionalParamsRef.current,\n };\n\n retrieverParams.search = currentSearchTerm;\n retrieverParams.next = nextRef;\n retrieverParams.previous = previousRef;\n retrieverParams.self = selfRef;\n\n response = await stableParams.retriever(retrieverParams);\n }\n\n // Only update state if this is still the latest request and wasn't aborted\n if (thisRequestId === requestIdRef.current && !abortControllerRef.current?.signal.aborted) {\n if (fetchParams?.isRefresh === true) {\n setData(response);\n } else {\n setData((prevData) => [...(prevData ? (prevData as T[]) : []), ...response]);\n }\n setIsLoaded(true);\n setNextPage(nextRef.next ? nextRef.next : undefined);\n setPreviousPage(previousRef.previous ? previousRef.previous : undefined);\n }\n } catch (error) {\n // Don't update state if request was aborted (AbortController disabled)\n if (thisRequestId === requestIdRef.current) {\n setIsLoaded(true);\n console.error(\"Error fetching data:\", error);\n }\n } finally {\n // Always reset fetching flag when done\n if (thisRequestId === requestIdRef.current) {\n isFetchingRef.current = false;\n }\n }\n },\n [stableParams, ready, params.search],\n );\n\n const setRefreshedElement = useCallback(\n (element: T) => {\n setData((prevData) => {\n if (!prevData) return prevData;\n\n const index = prevData.findIndex((data) => (data as any).id === (element as any).id);\n if (index === -1) return prevData;\n\n // Use immutable update pattern instead of mutation\n return prevData.map((item, i) => (i === index ? element : item));\n });\n },\n [setData],\n );\n\n const removeElement = useCallback(\n (element: T) => {\n setData((prevData) => {\n if (!prevData) return prevData;\n\n const index = prevData.findIndex((data) => (data as any).id === (element as any).id);\n\n if (index === -1) return prevData;\n\n // Adjust nextPage offset since we're removing an item\n setNextPage((prev) => adjustPaginationUrl(prev, -1));\n\n const newData = [...prevData];\n newData.splice(index, 1);\n return newData;\n });\n },\n [adjustPaginationUrl],\n );\n\n // Consolidated effect: Only fetch once when ready and not loaded\n // This prevents the duplicate API calls that occurred when both the mount effect\n // and ready effect fired simultaneously on initial render\n useEffect(() => {\n // Only fetch if ready and haven't loaded yet\n if (ready && !isLoaded) {\n fetchData({ isRefresh: true });\n }\n }, [ready, fetchData]);\n\n const loadNext = useCallback(\n async (onlyNewRecords?: boolean) => {\n if (nextPage) fetchData({ isRefresh: onlyNewRecords, callNext: true });\n },\n [fetchData, nextPage],\n );\n\n const loadPrevious = useCallback(\n async (onlyNewRecords?: boolean) => {\n if (previousPage) fetchData({ isRefresh: onlyNewRecords, callPrevious: true });\n },\n [fetchData, previousPage],\n );\n\n const addAdditionalParameter = useCallback(\n (key: string, value: any | null) => {\n if (value === null) {\n delete additionalParamsRef.current[key];\n } else {\n additionalParamsRef.current[key] = value;\n }\n\n setReady(true);\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefine: true, isRefresh: true });\n },\n [fetchData],\n );\n\n const removeAdditionalParameter = useCallback(\n (key: string) => {\n if (additionalParamsRef.current[key] !== undefined) {\n delete additionalParamsRef.current[key];\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefine: true, isRefresh: true });\n }\n },\n [fetchData],\n );\n\n const search = useCallback(\n async (search: string) => {\n if (search === searchTermRef.current) return;\n\n setNextPage(undefined);\n setPreviousPage(undefined);\n searchTermRef.current = search;\n fetchData({ isRefine: true, isRefresh: true });\n },\n [fetchData],\n );\n\n const isSearch = !!searchTermRef.current;\n\n const refresh = useCallback(async () => {\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefresh: true });\n }, [fetchData]);\n\n // Cleanup abort controller on unmount\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n return {\n ready,\n setReady,\n isLoaded: isLoaded,\n data: data as T[],\n next: nextPage ? loadNext : undefined,\n previous: previousPage ? loadPrevious : undefined,\n search: search,\n addAdditionalParameter: addAdditionalParameter,\n removeAdditionalParameter: removeAdditionalParameter,\n refresh: refresh,\n setRefreshedElement: setRefreshedElement,\n isSearch: isSearch,\n removeElement: removeElement,\n pageInfo: pageInfo,\n };\n}\n","import { useCallback, useEffect, useRef } from \"react\";\n\nexport function useDebounce<T extends (...args: any[]) => any>(callback: T, delay: number): T & { cancel: () => void } {\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const callbackRef = useRef(callback);\n\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n const debouncedFunction = useCallback(\n (...args: Parameters<T>) => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = setTimeout(() => {\n callbackRef.current(...args);\n }, delay);\n },\n [delay],\n );\n\n // Attach a cancel method to clear pending timeout\n const cancel = () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n\n return Object.assign(debouncedFunction, { cancel }) as T & { cancel: () => void };\n}\n\nexport default useDebounce;\n","\"use client\";\n\nimport { UseTableStructureHook, UseTableStructureHookParams, UseTableStructureHookReturn } from \"./types\";\nimport { ModuleWithPermissions } from \"../permissions\";\nimport { tableGeneratorRegistry } from \"./TableGeneratorRegistry\";\n\nexport function registerTableGenerator<T, U>(\n type: string | ModuleWithPermissions,\n hook: UseTableStructureHook<T, U>,\n): void {\n const name = typeof type === \"string\" ? type : type.name;\n tableGeneratorRegistry.register(name, hook);\n}\n\nexport function useTableGenerator<T, U>(\n type: ModuleWithPermissions,\n params: UseTableStructureHookParams<T, U>,\n): UseTableStructureHookReturn<T> {\n return tableGeneratorRegistry.get(type.name, params);\n}\n","\"use client\";\n\nimport * as d3 from \"d3\";\nimport { Loader2 } from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\nimport { D3Link, D3Node } from \"../interfaces\";\n\n/**\n * Custom hook for D3 graph visualization with larger circles and more interactive features\n */\nexport function useCustomD3Graph(\n nodes: D3Node[],\n links: D3Link[],\n onNodeClick: (nodeId: string) => void,\n visibleNodeIds?: Set<string>,\n loadingNodeIds?: Set<string>,\n containerKey?: string | number,\n) {\n const svgRef = useRef<SVGSVGElement | null>(null);\n const zoomRef = useRef<d3.ZoomTransform | null>(null);\n const zoomBehaviorRef = useRef<d3.ZoomBehavior<SVGSVGElement, unknown> | null>(null);\n const nodePositionsRef = useRef<Map<string, { x: number; y: number }>>(new Map());\n const prevContainerKeyRef = useRef<string | number | undefined>(containerKey);\n\n const zoomToNode = useCallback(\n (nodeId: string, childIds: string[] = []) => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const targetNode = nodes.find((n) => n.id === nodeId);\n const childNodes = nodes.filter((n) => childIds.includes(n.id));\n\n if (!targetNode) return;\n\n const positions: { x: number; y: number }[] = [];\n\n if (\n targetNode.fx !== undefined &&\n targetNode.fy !== undefined &&\n targetNode.fx !== null &&\n targetNode.fy !== null\n ) {\n positions.push({ x: targetNode.fx, y: targetNode.fy });\n } else if (\n targetNode.x !== undefined &&\n targetNode.y !== undefined &&\n targetNode.x !== null &&\n targetNode.y !== null\n ) {\n positions.push({ x: targetNode.x, y: targetNode.y });\n }\n\n childNodes.forEach((child) => {\n if (child.fx !== undefined && child.fy !== undefined && child.fx !== null && child.fy !== null) {\n positions.push({ x: child.fx, y: child.fy });\n } else if (child.x !== undefined && child.y !== undefined && child.x !== null && child.y !== null) {\n positions.push({ x: child.x, y: child.y });\n }\n });\n\n if (positions.length === 0) return;\n\n const bounds = {\n xMin: Math.min(...positions.map((p) => p.x)),\n xMax: Math.max(...positions.map((p) => p.x)),\n yMin: Math.min(...positions.map((p) => p.y)),\n yMax: Math.max(...positions.map((p) => p.y)),\n };\n\n const padding = 150;\n bounds.xMin -= padding;\n bounds.xMax += padding;\n bounds.yMin -= padding;\n bounds.yMax += padding;\n\n const width = svgRef.current.clientWidth;\n const height = svgRef.current.clientHeight;\n\n const contentWidth = bounds.xMax - bounds.xMin;\n const contentHeight = bounds.yMax - bounds.yMin;\n\n const scaleX = width / contentWidth;\n const scaleY = height / contentHeight;\n\n let scale = Math.min(scaleX, scaleY);\n\n scale = Math.min(Math.max(scale, 0.2), 1.5);\n\n const centerX = (bounds.xMin + bounds.xMax) / 2;\n const centerY = (bounds.yMin + bounds.yMax) / 2;\n\n const translateX = width / 2 - centerX * scale;\n const translateY = height / 2 - centerY * scale;\n\n svg\n .transition()\n .duration(750)\n .call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(scale));\n },\n [nodes],\n );\n\n const colorScale = useMemo(() => {\n const accentColor = \"var(--accent)\";\n\n // Define unified color for all content types\n const contentColor = \"hsl(30, 80%, 55%)\"; // Orange for all content\n\n const groupTypes = new Set<string>();\n nodes.forEach((node) => {\n groupTypes.add(node.instanceType);\n });\n\n const typeColorMap = new Map<string, string>();\n\n Array.from(groupTypes).forEach((type, index) => {\n if (type === nodes[0]?.instanceType) {\n // Root node\n typeColorMap.set(type, accentColor);\n } else if (type === \"documents\" || type === \"articles\" || type === \"hyperlinks\") {\n // All content types get the same orange color\n typeColorMap.set(type, contentColor);\n } else {\n // Topics, Expertises, etc. - use golden angle\n const hueShift = (index * 137.508) % 360;\n typeColorMap.set(type, `hsl(${hueShift}, 32%, 52%)`);\n }\n });\n\n return typeColorMap;\n }, [nodes]);\n\n const washOutColor = useCallback((color: string): string => {\n // Parse HSL color and make it lighter and more desaturated\n const hslMatch = color.match(/hsl\\((\\d+\\.?\\d*),\\s*(\\d+\\.?\\d*)%,\\s*(\\d+\\.?\\d*)%\\)/);\n if (hslMatch) {\n const hue = parseFloat(hslMatch[1]);\n\n // Reduce saturation to 15% and increase lightness to 80%\n return `hsl(${hue}, 15%, 80%)`;\n }\n\n // For var(--accent), return a lighter version\n if (color.includes(\"var(--accent)\")) {\n return \"hsl(0, 0%, 80%)\"; // Light gray for washed out accent\n }\n\n // Fallback\n return \"hsl(0, 0%, 80%)\";\n }, []);\n\n const getNodeColor = useCallback(\n (node: D3Node) => {\n const baseColor = colorScale.get(node.instanceType) || \"gray\";\n if (node.washedOut) {\n return washOutColor(baseColor);\n }\n return baseColor;\n },\n [colorScale, washOutColor],\n );\n\n useEffect(() => {\n if (!nodes.length || !svgRef.current) return;\n\n const visibleNodes = visibleNodeIds\n ? nodes.filter((node) => visibleNodeIds.has(node.id))\n : nodes.filter((node) => node.visible !== false);\n\n const visibleNodeIdSet = new Set(visibleNodes.map((node) => node.id));\n const visibleLinks = links.filter((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n return visibleNodeIdSet.has(sourceId) && visibleNodeIdSet.has(targetId);\n });\n\n const svg = d3.select<SVGSVGElement, unknown>(svgRef.current);\n svg.selectAll(\"*\").remove();\n\n const container = svgRef.current?.parentElement;\n if (!container) return;\n\n const width = container.clientWidth;\n const height = container.clientHeight;\n\n svg.attr(\"width\", width).attr(\"height\", height).attr(\"viewBox\", `0 0 ${width} ${height}`);\n\n const graphGroup = svg.append(\"g\").attr(\"class\", \"graph-content\");\n\n const zoom = d3\n .zoom<SVGSVGElement, unknown>()\n .scaleExtent([0.1, 4])\n .on(\"zoom\", (event) => {\n const transform = event.transform;\n graphGroup.attr(\"transform\", transform.toString());\n zoomRef.current = transform;\n });\n\n zoomBehaviorRef.current = zoom;\n\n svg\n .call(zoom as any)\n .on(\"wheel.zoom\", null)\n .on(\"dblclick.zoom\", null);\n\n const nodeRadius = 40;\n\n const childDistanceFromRoot = Math.min(width, height) * 0.4;\n const grandchildDistanceFromChild = nodeRadius * 10;\n\n const centralNodeId = nodes[0].id;\n\n const nodeHierarchy = new Map<\n string,\n {\n depth: number;\n parent: string | null;\n children: string[];\n angle?: number;\n x?: number;\n y?: number;\n }\n >();\n\n nodeHierarchy.set(centralNodeId, {\n depth: 0,\n parent: null,\n children: [],\n });\n\n visibleLinks.forEach((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n\n if (sourceId === centralNodeId) {\n nodeHierarchy.set(targetId, { depth: 1, parent: centralNodeId, children: [] });\n const rootNode = nodeHierarchy.get(centralNodeId);\n if (rootNode) {\n rootNode.children.push(targetId);\n }\n }\n });\n\n visibleLinks.forEach((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n\n const sourceNode = nodeHierarchy.get(sourceId);\n if (sourceNode && sourceNode.depth === 1 && !nodeHierarchy.has(targetId)) {\n nodeHierarchy.set(targetId, { depth: 2, parent: sourceId, children: [] });\n sourceNode.children.push(targetId);\n }\n });\n\n const rootChildren = nodeHierarchy.get(centralNodeId)?.children || [];\n\n const childAngleStep = (2 * Math.PI) / Math.max(rootChildren.length, 1);\n\n rootChildren.forEach((childId, index) => {\n const childNode = nodeHierarchy.get(childId);\n if (childNode) {\n const angle = index * childAngleStep;\n childNode.angle = angle;\n childNode.x = width / 2 + childDistanceFromRoot * Math.cos(angle);\n childNode.y = height / 2 + childDistanceFromRoot * Math.sin(angle);\n }\n });\n\n for (const [nodeId, node] of nodeHierarchy.entries()) {\n if (node.depth === 1 && node.angle !== undefined && node.x !== undefined && node.y !== undefined) {\n const childAngle = node.angle;\n const childX = node.x;\n const childY = node.y;\n const grandchildren = node.children;\n\n if (grandchildren.length === 0) continue;\n\n const dirX = childX - width / 2;\n const dirY = childY - height / 2;\n const dirLength = Math.sqrt(dirX * dirX + dirY * dirY);\n\n const normDirX = dirX / dirLength;\n const normDirY = dirY / dirLength;\n\n if (grandchildren.length === 1) {\n const grandchildId = grandchildren[0];\n const grandchildNode = nodeHierarchy.get(grandchildId);\n if (grandchildNode) {\n grandchildNode.x = childX + normDirX * grandchildDistanceFromChild;\n grandchildNode.y = childY + normDirY * grandchildDistanceFromChild;\n grandchildNode.angle = childAngle;\n }\n } else {\n // Multiple grandchildren - arrange in semicircular arc\n const numChildren = grandchildren.length;\n\n // Dynamic arc span: scale from 60° (2 children) to 180° (7+ children)\n const minArc = Math.PI / 3; // 60 degrees\n const maxArc = Math.PI; // 180 degrees\n const arcProgress = Math.min(1, (numChildren - 2) / 5);\n const arcSpan = minArc + arcProgress * (maxArc - minArc);\n\n // Calculate starting angle (center the arc around the radial direction)\n const startAngle = childAngle - arcSpan / 2;\n\n grandchildren.forEach((grandchildId, index) => {\n const grandchildNode = nodeHierarchy.get(grandchildId);\n if (!grandchildNode) return;\n\n // Calculate angle for this child\n const angleOffset = numChildren > 1 ? (index / (numChildren - 1)) * arcSpan : 0;\n const angle = startAngle + angleOffset;\n\n // Position at constant radius from parent\n grandchildNode.x = childX + grandchildDistanceFromChild * Math.cos(angle);\n grandchildNode.y = childY + grandchildDistanceFromChild * Math.sin(angle);\n grandchildNode.angle = angle;\n });\n }\n }\n }\n\n visibleNodes.forEach((node) => {\n const savedPosition = nodePositionsRef.current.get(node.id);\n\n if (savedPosition) {\n node.fx = savedPosition.x;\n node.fy = savedPosition.y;\n } else {\n const hierarchyNode = nodeHierarchy.get(node.id);\n if (hierarchyNode && hierarchyNode.x !== undefined && hierarchyNode.y !== undefined) {\n node.fx = hierarchyNode.x;\n node.fy = hierarchyNode.y;\n // Save the calculated position so it persists across re-renders\n nodePositionsRef.current.set(node.id, { x: hierarchyNode.x, y: hierarchyNode.y });\n } else if (node.id === centralNodeId) {\n node.fx = width / 2;\n node.fy = height / 2;\n // Save the center position\n nodePositionsRef.current.set(node.id, { x: width / 2, y: height / 2 });\n }\n }\n });\n\n const simulation = d3\n .forceSimulation<D3Node>(visibleNodes)\n .force(\n \"link\",\n d3\n .forceLink<D3Node, D3Link>(visibleLinks)\n .id((d) => d.id)\n .distance(nodeRadius * 3)\n .strength(0.1),\n )\n .force(\"charge\", d3.forceManyBody().strength(-500).distanceMax(300))\n .force(\"collision\", d3.forceCollide().radius(nodeRadius * 1.2))\n .force(\"center\", d3.forceCenter(width / 2, height / 2).strength(0.1));\n\n simulation.stop();\n for (let i = 0; i < 100; i++) {\n simulation.tick();\n }\n\n visibleNodes.forEach((node) => {\n if (node.fx === undefined) {\n node.fx = node.x;\n node.fy = node.y;\n }\n });\n\n const link = graphGroup\n .append(\"g\")\n .attr(\"stroke\", \"#999\")\n .attr(\"stroke-opacity\", 0.6)\n .selectAll(\"line\")\n .data(visibleLinks)\n .join(\"line\")\n .attr(\"x1\", (d) => (d.source as D3Node).x || 0)\n .attr(\"y1\", (d) => (d.source as D3Node).y || 0)\n .attr(\"x2\", (d) => (d.target as D3Node).x || 0)\n .attr(\"y2\", (d) => (d.target as D3Node).y || 0)\n .attr(\"stroke-width\", 1.5);\n\n const node = graphGroup\n .append(\"g\")\n .selectAll(\"g\")\n .data(visibleNodes)\n .join(\"g\")\n .attr(\"class\", \"node-group\")\n .attr(\"cursor\", \"pointer\")\n .attr(\"transform\", (d) => `translate(${d.x || 0}, ${d.y || 0})`)\n .call(\n d3\n .drag<SVGGElement, D3Node>()\n .subject(function (d) {\n return d;\n })\n .on(\"start\", function (event, d) {\n d.fx = d.x;\n d.fy = d.y;\n })\n .on(\"drag\", function (event, d) {\n d.fx = event.x;\n d.fy = event.y;\n\n d3.select(this).attr(\"transform\", `translate(${event.x}, ${event.y})`);\n\n d3.select(this).attr(\"transform\", `translate(${event.x}, ${event.y})`);\n\n nodePositionsRef.current.set(d.id, { x: event.x, y: event.y });\n\n link\n .attr(\"x1\", (l) => {\n const source = l.source as D3Node;\n return source.fx || source.x || 0;\n })\n .attr(\"y1\", (l) => {\n const source = l.source as D3Node;\n return source.fy || source.y || 0;\n })\n .attr(\"x2\", (l) => {\n const target = l.target as D3Node;\n return target.fx || target.x || 0;\n })\n .attr(\"y2\", (l) => {\n const target = l.target as D3Node;\n return target.fy || target.y || 0;\n });\n })\n .on(\"end\", function (event, d) {\n d.fx = event.x;\n d.fy = event.y;\n }) as any,\n )\n .on(\"mouseenter\", function (_event, d) {\n // Skip hover effect for root node\n if (d.instanceType === \"root\") return;\n\n const currentNode = d3.select(this);\n\n // Bring node to front\n currentNode.raise();\n\n // Get current zoom scale for counter-scaling text\n const currentZoom = zoomRef.current?.k || 1;\n const targetScreenFontSize = 20; // Target font size in screen pixels\n const baseFontSize = 12; // Base font size in graph coordinates\n\n // Calculate smooth scale factor for transform\n const textScale = targetScreenFontSize / (baseFontSize * currentZoom);\n\n // Calculate text position offset - circle stays in graph coords, only gap is counter-scaled\n const hoverTextOffset = nodeRadius * 1.4 + 5 / currentZoom;\n\n // Scale up the circle with smooth transition (unchanged)\n currentNode\n .select(\"circle\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"r\", nodeRadius * 1.4)\n .attr(\"filter\", \"drop-shadow(0px 4px 12px rgba(0, 0, 0, 0.3))\");\n\n // Scale up the text with smooth transform scaling around its anchor point\n currentNode\n .select(\"text\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"dy\", -hoverTextOffset)\n .attr(\"transform\", `translate(0, ${-hoverTextOffset}) scale(${textScale}) translate(0, ${hoverTextOffset})`);\n })\n .on(\"mouseleave\", function (_event, d) {\n // Skip hover effect for root node\n if (d.instanceType === \"root\") return;\n\n const currentNode = d3.select(this);\n\n // Return circle to normal size\n currentNode\n .select(\"circle\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"r\", nodeRadius)\n .attr(\"filter\", null);\n\n // Return text to normal size with smooth transform\n const normalOffset = nodeRadius + 5;\n currentNode\n .select(\"text\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"dy\", -normalOffset)\n .attr(\"transform\", `translate(0, ${-normalOffset}) scale(1) translate(0, ${normalOffset})`);\n });\n\n node\n .append(\"circle\")\n .attr(\"r\", nodeRadius)\n .attr(\"fill\", (d) => getNodeColor(d))\n .attr(\"stroke\", \"#fff\")\n .attr(\"stroke-width\", 1.5)\n .on(\"click\", (event, d) => {\n event.preventDefault();\n event.stopPropagation();\n if (zoomBehaviorRef.current) {\n svg.on(\".zoom\", null);\n setTimeout(() => {\n if (zoomBehaviorRef.current) {\n svg\n .call(zoomBehaviorRef.current as any)\n .on(\"wheel.zoom\", null)\n .on(\"dblclick.zoom\", null);\n }\n }, 100);\n }\n onNodeClick(d.id);\n });\n\n node.each(function (d: D3Node) {\n if (d.icon) {\n const Icon = d.icon as React.FC<{ size: number; color: string }>;\n const iconSvg = renderToStaticMarkup(<Icon size={nodeRadius / 2} color=\"white\" />);\n\n const iconGroup = d3\n .select(this)\n .append(\"g\")\n .html(iconSvg)\n .attr(\"transform\", `translate(${-nodeRadius / 4}, ${-nodeRadius / 4})`)\n .style(\"pointer-events\", \"all\")\n .on(\"click\", (event) => {\n event.stopPropagation();\n onNodeClick(d.id);\n });\n }\n });\n\n // Add loading spinner for nodes that are fetching children\n node.each(function (d: D3Node) {\n if (loadingNodeIds && loadingNodeIds.has(d.id)) {\n // Remove existing icon\n d3.select(this).selectAll(\"g\").remove();\n\n // Add spinner\n const spinnerSvg = renderToStaticMarkup(<Loader2 size={nodeRadius / 2} color=\"white\" />);\n\n d3.select(this)\n .append(\"g\")\n .html(spinnerSvg)\n .attr(\"class\", \"animate-spin\")\n .attr(\"transform\", `translate(${-nodeRadius / 4}, ${-nodeRadius / 4})`)\n .style(\"pointer-events\", \"none\");\n }\n });\n\n node.each(function (d: D3Node) {\n const textElement = d3\n .select(this)\n .append(\"text\")\n .attr(\"text-anchor\", \"middle\")\n .attr(\"font-size\", 12)\n .attr(\"pointer-events\", \"none\");\n\n if (d.instanceType === \"root\") {\n // Split text by spaces for multi-line display\n const words = d.name.split(\" \");\n const lineHeight = 1.2; // em units\n const numLines = words.length;\n // Calculate starting position to center the text block vertically\n // Account for the fact that we want the middle of the entire text block at y=0\n const startY = -((numLines - 1) * lineHeight) / 2;\n\n textElement.attr(\"fill\", \"var(--accent-foreground)\").attr(\"dominant-baseline\", \"middle\");\n\n words.forEach((word, index) => {\n textElement\n .append(\"tspan\")\n .attr(\"x\", 0)\n .attr(\"dy\", index === 0 ? `${startY}em` : `${lineHeight}em`)\n .text(word);\n });\n } else {\n // Non-root nodes: single line text above the circle\n textElement\n .attr(\"dy\", -nodeRadius - 5)\n .attr(\"fill\", \"currentColor\")\n .text(d.name);\n }\n });\n\n return () => {\n simulation.stop();\n };\n }, [nodes, links, colorScale, visibleNodeIds, loadingNodeIds, onNodeClick]);\n\n const zoomIn = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const currentTransform = zoomRef.current || d3.zoomIdentity;\n const newScale = Math.min(currentTransform.k * 1.3, 4);\n\n svg\n .transition()\n .duration(300)\n .call(zoom.transform, d3.zoomIdentity.translate(currentTransform.x, currentTransform.y).scale(newScale));\n }, []);\n\n const zoomOut = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const currentTransform = zoomRef.current || d3.zoomIdentity;\n const newScale = Math.max(currentTransform.k * 0.7, 0.1);\n\n svg\n .transition()\n .duration(300)\n .call(zoom.transform, d3.zoomIdentity.translate(currentTransform.x, currentTransform.y).scale(newScale));\n }, []);\n\n const zoomToFitAll = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n // Get all visible nodes\n const visibleNodes = visibleNodeIds\n ? nodes.filter((node) => visibleNodeIds.has(node.id))\n : nodes.filter((node) => node.visible !== false);\n\n if (visibleNodes.length === 0) return;\n\n // Calculate bounds of all visible nodes\n const positions: { x: number; y: number }[] = [];\n visibleNodes.forEach((node) => {\n if (node.fx !== undefined && node.fy !== undefined && node.fx !== null && node.fy !== null) {\n positions.push({ x: node.fx, y: node.fy });\n } else if (node.x !== undefined && node.y !== undefined && node.x !== null && node.y !== null) {\n positions.push({ x: node.x, y: node.y });\n }\n });\n\n if (positions.length === 0) return;\n\n const bounds = {\n xMin: Math.min(...positions.map((p) => p.x)),\n xMax: Math.max(...positions.map((p) => p.x)),\n yMin: Math.min(...positions.map((p) => p.y)),\n yMax: Math.max(...positions.map((p) => p.y)),\n };\n\n // Add padding\n const padding = 150;\n bounds.xMin -= padding;\n bounds.xMax += padding;\n bounds.yMin -= padding;\n bounds.yMax += padding;\n\n const width = svgRef.current.clientWidth;\n const height = svgRef.current.clientHeight;\n\n const contentWidth = bounds.xMax - bounds.xMin;\n const contentHeight = bounds.yMax - bounds.yMin;\n\n const scaleX = width / contentWidth;\n const scaleY = height / contentHeight;\n\n let scale = Math.min(scaleX, scaleY);\n scale = Math.min(Math.max(scale, 0.1), 2); // Clamp between 0.1 and 2\n\n const centerX = (bounds.xMin + bounds.xMax) / 2;\n const centerY = (bounds.yMin + bounds.yMax) / 2;\n\n const translateX = width / 2 - centerX * scale;\n const translateY = height / 2 - centerY * scale;\n\n svg.transition().duration(750).call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(scale));\n }, [nodes, visibleNodeIds]);\n\n // When container size changes (full-screen toggle), zoom to fit all nodes\n // This scales the view instead of recalculating positions, maintaining relative layout\n useEffect(() => {\n if (containerKey !== undefined && containerKey !== prevContainerKeyRef.current) {\n // Small delay to allow the container to finish resizing\n const timeoutId = setTimeout(() => {\n zoomToFitAll();\n }, 100);\n\n prevContainerKeyRef.current = containerKey;\n\n return () => clearTimeout(timeoutId);\n }\n }, [containerKey, zoomToFitAll]);\n\n return { svgRef, zoomIn, zoomOut, zoomToNode, zoomToFitAll };\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useNotificationContext, useSocketContext } from \"../contexts\";\n\nexport function useNotificationSync() {\n const { socketNotifications, clearSocketNotifications } = useSocketContext();\n const { addSocketNotifications } = useNotificationContext();\n\n useEffect(() => {\n if (socketNotifications.length > 0) {\n try {\n addSocketNotifications(socketNotifications);\n clearSocketNotifications();\n } catch (error) {\n console.error(\"💥 [useNotificationSync] Error processing notifications:\", error);\n }\n }\n }, [socketNotifications, addSocketNotifications, clearSocketNotifications]);\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { createContext, ReactNode, useContext, useState } from \"react\";\nimport { SharedProvider } from \"../../../contexts\";\nimport { JsonApiHydratedDataInterface, Modules, rehydrate } from \"../../../core\";\nimport { usePageUrlGenerator } from \"../../../hooks\";\nimport { BreadcrumbItemData } from \"../../../interfaces\";\nimport { Action } from \"../../../permissions\";\nimport { getRoleId } from \"../../../roles\";\nimport { UserInterface } from \"../../user\";\nimport { useCurrentUserContext } from \"../../user/contexts\";\nimport { CompanyConfigurationEditor, CompanyDeleter, CompanyEditor } from \"../components\";\nimport { CompanyInterface } from \"../data\";\n\ninterface CompanyContextType {\n company: CompanyInterface | undefined;\n setCompany: (value: CompanyInterface | undefined) => void;\n}\n\nconst CompanyContext = createContext<CompanyContextType | undefined>(undefined);\n\ntype CompanyProviderProps = {\n children: ReactNode;\n dehydratedCompany?: JsonApiHydratedDataInterface;\n};\n\nconst defaultContextValue: CompanyContextType = {\n company: undefined,\n setCompany: () => {},\n};\n\nexport const CompanyProvider = ({ children, dehydratedCompany }: CompanyProviderProps) => {\n const generateUrl = usePageUrlGenerator();\n const t = useTranslations();\n const { hasPermissionToModule, hasRole } = useCurrentUserContext<UserInterface>();\n\n const [company, setCompany] = useState<CompanyInterface | undefined>(\n dehydratedCompany ? rehydrate<CompanyInterface>(Modules.Company, dehydratedCompany) : undefined,\n );\n\n const breadcrumb = () => {\n const response: BreadcrumbItemData[] = [];\n\n if (company)\n response.push({\n name: company.name,\n href: generateUrl({ page: Modules.Company }),\n });\n\n return response;\n };\n\n const title = () => {\n const response: any = {\n type: t(`types.companies`, { count: company ? 1 : 2 }),\n };\n\n if (company) response.element = company.name;\n\n const functions: ReactNode[] = [];\n\n if (\n company &&\n hasRole(getRoleId().Administrator) &&\n hasPermissionToModule({ module: Modules.Company, action: Action.Delete })\n )\n functions.push(<CompanyDeleter key=\"companyDeleter\" company={company} />);\n\n if (\n hasRole(getRoleId().Administrator) ||\n hasPermissionToModule({ module: Modules.Company, action: Action.Update })\n ) {\n if (company) functions.push(<CompanyConfigurationEditor key=\"companyConfigurationEditor\" company={company} />);\n functions.push(<CompanyEditor key=\"companyEditor\" company={company} propagateChanges={setCompany} />);\n }\n\n if (functions.length > 0) response.functions = functions;\n\n return response;\n };\n\n return (\n <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>\n <CompanyContext.Provider\n value={{\n company: company,\n setCompany: setCompany,\n }}\n >\n {children}\n </CompanyContext.Provider>\n </SharedProvider>\n );\n};\n\nexport const useCompanyContext = (): CompanyContextType => {\n return useContext(CompanyContext) ?? defaultContextValue;\n};\n","\"use client\";\n\nimport { getCookie } from \"cookies-next\";\nimport { useAtom } from \"jotai\";\nimport { atomWithStorage } from \"jotai/utils\";\nimport { usePathname } from \"next/navigation\";\nimport React, { createContext, useContext, useEffect } from \"react\";\nimport { Modules, rehydrate } from \"../../../core\";\nimport { Action, checkPermissions, ModuleWithPermissions } from \"../../../permissions\";\nimport { getRoleId } from \"../../../roles\";\nimport { CompanyInterface } from \"../../company\";\nimport { FeatureInterface } from \"../../feature\";\nimport { RoleInterface } from \"../../role\";\nimport { UserInterface } from \"../data\";\n\nexport interface CurrentUserContextType<T extends UserInterface = UserInterface> {\n currentUser: T | null;\n company: CompanyInterface | null;\n setUser: (user?: T) => void;\n hasPermissionToModule: <M extends ModuleWithPermissions>(params: {\n module: M;\n action: Action;\n data?: any;\n }) => boolean;\n hasPermissionToModules: <M extends ModuleWithPermissions>(params: {\n modules: M[];\n action: Action;\n data?: any;\n }) => boolean;\n hasPermissionToPath: (path: string) => boolean;\n hasAccesToFeature: (featureIdentifier: string) => boolean;\n matchUrlToModule: (prarms?: { path: string }) => ModuleWithPermissions | undefined;\n hasRole: (roleId: string) => boolean;\n}\n\nconst userAtom = atomWithStorage(\"user\", null);\n\nconst CurrentUserContext = createContext<CurrentUserContextType | undefined>(undefined);\n\nexport const CurrentUserProvider = ({ children }: { children: React.ReactNode }) => {\n const path = usePathname();\n\n const [dehydratedUser, setDehydratedUser] = useAtom(userAtom);\n\n useEffect(() => {\n const token = getCookie(\"token\");\n if (!token && dehydratedUser) setDehydratedUser(null);\n }, [dehydratedUser, setDehydratedUser]);\n\n const matchUrlToModule = (params?: { path: string }): ModuleWithPermissions | undefined => {\n const moduleKeys = Object.getOwnPropertyNames(Modules).filter(\n (key) => key !== \"prototype\" && key !== \"_factory\" && key !== \"length\" && key !== \"name\",\n );\n\n const matchedModuleKey = moduleKeys.find((key) => {\n const descriptor = Object.getOwnPropertyDescriptor(Modules, key);\n\n if (!descriptor?.get) return false;\n\n const selectedModule = descriptor.get.call(Modules);\n\n return path.toLowerCase().startsWith(selectedModule.pageUrl?.toLowerCase());\n });\n\n if (!matchedModuleKey) return undefined;\n\n const descriptor = Object.getOwnPropertyDescriptor(Modules, matchedModuleKey);\n return descriptor?.get?.call(Modules);\n };\n\n const currentUser = dehydratedUser ? rehydrate<UserInterface>(Modules.User, dehydratedUser) : null;\n\n const company = currentUser?.company ?? null;\n\n const setUser = (user?: UserInterface): void => {\n if (user) setDehydratedUser(user.dehydrate() as any);\n else setDehydratedUser(null);\n };\n\n const hasRole = (roleId: string): boolean => {\n if (!currentUser) return false;\n\n return !!currentUser.roles?.some((userRole: RoleInterface) => userRole.id === roleId);\n };\n\n const hasAccesToFeature = (featureIdentifier: string): boolean => {\n if (hasRole(getRoleId().Administrator)) return true;\n if (!company) return false;\n\n return company.features.some((feature: FeatureInterface) => feature.id === featureIdentifier);\n };\n\n function hasPermissionToModule<M extends ModuleWithPermissions>(params: {\n module: M;\n action: Action;\n data?: M extends ModuleWithPermissions ? any : never;\n }): boolean {\n if (!currentUser) return false;\n\n if (!!params.module.feature && !hasAccesToFeature(params.module.feature)) return false;\n\n return checkPermissions({ module: params.module, action: params.action, data: params.data, user: currentUser });\n }\n\n function hasPermissionToModules<M extends ModuleWithPermissions>(params: {\n modules: M[];\n action: Action;\n data?: M extends ModuleWithPermissions ? any : never;\n }): boolean {\n if (!currentUser) return false;\n\n if (!params.modules.every((module) => !module.feature || hasAccesToFeature(module.feature))) return false;\n\n return params.modules.every((module) =>\n checkPermissions({ module: module, action: params.action, data: params.data, user: currentUser }),\n );\n }\n\n function hasPermissionToPath(path: string): boolean {\n if (!currentUser) return false;\n if (path === \"#\" || path === \"/\") return true;\n\n const selectedModule = matchUrlToModule({ path: path });\n if (!selectedModule) return true;\n\n const response = hasPermissionToModule({ module: selectedModule, action: Action.Read });\n\n return response;\n }\n\n return (\n <CurrentUserContext.Provider\n value={{\n currentUser: currentUser,\n company: company,\n setUser: setUser,\n hasPermissionToModule: hasPermissionToModule,\n hasPermissionToModules: hasPermissionToModules,\n hasPermissionToPath: hasPermissionToPath,\n hasAccesToFeature: hasAccesToFeature,\n matchUrlToModule: matchUrlToModule,\n hasRole: hasRole,\n }}\n >\n {children}\n </CurrentUserContext.Provider>\n );\n};\n\nexport function useCurrentUserContext<T extends UserInterface = UserInterface>(): CurrentUserContextType<T> {\n const context = useContext(CurrentUserContext);\n if (context === undefined) {\n throw new Error(\"useCurrentUserContext must be used within a UserProvider\");\n }\n return context as unknown as CurrentUserContextType<T>;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { createContext, ReactNode, useContext, useState } from \"react\";\nimport { SharedProvider } from \"../../../contexts\";\nimport { JsonApiHydratedDataInterface, Modules, rehydrate } from \"../../../core\";\nimport { usePageUrlGenerator } from \"../../../hooks\";\nimport { BreadcrumbItemData } from \"../../../interfaces\";\nimport { Action } from \"../../../permissions\";\nimport { UserDeleter, UserEditor, UserReactivator, UserResentInvitationEmail } from \"../components/forms\";\nimport { UserInterface } from \"../data\";\nimport { useCurrentUserContext } from \"./CurrentUserContext\";\n\ninterface UserContextType {\n user: UserInterface | undefined;\n setUser: (value: UserInterface | undefined) => void;\n}\n\nconst UserContext = createContext<UserContextType | undefined>(undefined);\n\ntype UserProviderProps = {\n children: ReactNode;\n dehydratedUser?: JsonApiHydratedDataInterface;\n};\n\nexport const UserProvider = ({ children, dehydratedUser }: UserProviderProps) => {\n const generateUrl = usePageUrlGenerator();\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n const t = useTranslations();\n\n const [user, setUser] = useState<UserInterface | undefined>(\n dehydratedUser ? rehydrate<UserInterface>(Modules.User, dehydratedUser) : undefined,\n );\n\n const breadcrumb = () => {\n const response: BreadcrumbItemData[] = [];\n\n if (hasPermissionToModule({ module: Modules.User, action: Action.Update })) {\n response.push({\n name: t(`generic.settings`),\n href: generateUrl({ page: `/settings` }),\n });\n\n response.push({\n name: t(`types.users`, { count: 2 }),\n href: generateUrl({ page: `/settings`, id: Modules.User.pageUrl }),\n });\n }\n\n if (user)\n response.push({\n name: `${user.name}${user.isDeleted ? ` (${t(`foundations.user.deleted`)})` : \"\"}`,\n href: generateUrl({ page: Modules.User, id: user.id }),\n });\n\n return response;\n };\n\n const title = () => {\n const response: any = {\n type: t(`types.users`, { count: user ? 1 : 2 }),\n };\n\n const functions: ReactNode[] = [];\n\n if (user) {\n response.element = `${user.name}${user.isDeleted ? ` (${t(`foundations.user.deleted`)})` : \"\"}`;\n\n if (user.isDeleted) {\n functions.push(<UserReactivator key={`UserReactivator`} user={user} propagateChanges={setUser} />);\n } else {\n if (!user.isActivated)\n functions.push(<UserResentInvitationEmail key={`UserResentInvitationEmail`} user={user} />);\n\n functions.push(<UserDeleter key={`UserDeleter`} user={user} />);\n }\n\n functions.push(<UserEditor key={`UserEditor`} user={user} propagateChanges={setUser} />);\n }\n\n if (functions.length > 0) response.functions = functions;\n\n return response;\n };\n\n return (\n <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>\n <UserContext.Provider\n value={{\n user: user,\n setUser: setUser,\n }}\n >\n {children}\n </UserContext.Provider>\n </SharedProvider>\n );\n};\n\nexport const useUserContext = (): UserContextType => {\n const context = useContext(UserContext);\n if (context === undefined) {\n throw new Error(\"useUserContext must be used within a UserProvider\");\n }\n return context;\n};\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useState } from \"react\";\nimport {\n CommonAssociationCommandDialog,\n CommonAssociationTrigger,\n triggerAssociationToast,\n UserListInAdd,\n} from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { RoleInterface } from \"../../../role\";\nimport { RoleService } from \"../../../role/data/role.service\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype AddUserToRoleProps = {\n role: RoleInterface;\n refresh: () => Promise<void>;\n};\n\nfunction AddUserToRoleInternal({ role, refresh }: AddUserToRoleProps) {\n const { company } = useCurrentUserContext<UserInterface>();\n const [show, setShow] = useState<boolean>(false);\n const [users, setUsers] = useState<UserInterface[]>([]);\n const t = useTranslations();\n\n const [existingUsers, setExistingUsers] = useState<UserInterface[] | null>(null);\n useEffect(() => {\n const fetchExistingUsers = async () => {\n setExistingUsers(await UserService.findMany({ roleId: role.id, fetchAll: true }));\n };\n if (show) {\n setExistingUsers(null);\n fetchExistingUsers();\n }\n }, [show]);\n\n const addUserToRole = async (user: UserInterface) => {\n await RoleService.addUserToRole({\n roleId: role.id,\n userId: user.id,\n });\n setUsers(users.filter((u) => u.id !== user.id));\n\n triggerAssociationToast({\n t: t,\n source: t(`types.users`, { count: 1 }),\n destination: t(`types.roles`, { count: 1 }),\n source_name: user.name,\n destination_name: t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) }),\n });\n\n refresh();\n };\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n ready: !!company && show,\n retriever: (params) => UserService.findAllUsers(params),\n retrieverParams: { companyId: company?.id },\n module: Modules.User,\n }) as DataListRetriever<UserInterface>;\n\n useEffect(() => {\n if (!!company && show) {\n data.setReady(true);\n }\n }, [data, company, show]);\n\n return (\n <>\n <CommonAssociationTrigger\n sourceType={t(`types.users`, { count: 1 })}\n destinationType={t(`types.roles`, { count: 1 })}\n onTrigger={() => setShow(true)}\n />\n <CommonAssociationCommandDialog\n show={show}\n setShow={setShow}\n data={data}\n source={t(`types.users`, { count: 1 })}\n destination={t(`types.roles`, { count: 1 })}\n destinationName={t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) })}\n >\n <UserListInAdd data={data} existingUsers={existingUsers} setSelectedUser={addUserToRole} />\n </CommonAssociationCommandDialog>\n </>\n );\n}\n\nexport function AddUserToRole(props: AddUserToRoleProps) {\n return <AddUserToRoleInternal {...props} />;\n}\n","\"use client\";\n\nimport { UploadIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { DropzoneOptions } from \"react-dropzone\";\nimport { FileInput, FileUploader } from \"../../../../components\";\nimport { Button } from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../data\";\n\ntype UserAvatarEditorProps = {\n user?: UserInterface;\n file?: File | null;\n setFile: (file: File | null) => void;\n resetImage: boolean;\n setResetImage: (reset: boolean) => void;\n};\n\nexport function UserAvatarEditor({ user, file, setFile, resetImage, setResetImage }: UserAvatarEditorProps) {\n const [files, setFiles] = useState<File[] | null>(null);\n const t = useTranslations();\n\n useEffect(() => {\n if (files && files.length > 0) {\n setResetImage(false);\n setFile(files[0]);\n }\n }, [files]);\n\n const dropzone = {\n multiple: false,\n maxSize: 100 * 1024 * 1024,\n preventDropOnDocument: false,\n accept: {\n \"application/images\": [\".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".svg\"],\n },\n } satisfies DropzoneOptions;\n\n return (\n <div className=\"flex w-40 flex-col gap-y-4\">\n <FileUploader\n value={files}\n onValueChange={setFiles}\n dropzoneOptions={dropzone}\n className=\"h-40 w-40 rounded-full p-0\"\n >\n <FileInput className=\"bg-muted text-muted-foreground flex h-full w-full flex-col items-center justify-center\">\n {!resetImage && (file || user?.avatar) ? (\n <Image\n src={file ? URL.createObjectURL(file) : user?.avatar || \"\"}\n alt={t(`generic.avatar`)}\n width={200}\n height={200}\n />\n ) : (\n <UploadIcon className=\"my-4 h-8 w-8\" />\n )}\n </FileInput>\n </FileUploader>\n {!resetImage && (file || user?.avatar) && (\n <Button\n className=\"\"\n size={`sm`}\n variant={`outline`}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setFile(null);\n setResetImage(true);\n }}\n >\n {t(`generic.buttons.remove`)}\n </Button>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDownIcon } from \"@radix-ui/react-icons\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item ref={ref} className={cn(\"border-b\", className)} {...props} />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\" asChild>\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all\", className)}\n {...props}\n >\n <div className=\"flex items-center\">\n {children}\n <ChevronDownIcon className=\"h-4 w-4 shrink-0 bg-transparent text-muted-foreground transition-transform duration-200 [&[data-state=open]>svg]:rotate-180\" />\n </div>\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionContent, AccordionItem, AccordionTrigger };\n","import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive: \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div ref={ref} role=\"alert\" className={cn(alertVariants({ variant }), className)} {...props} />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(\n ({ className, ...props }, ref) => (\n <h5 ref={ref} className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)} {...props} />\n ),\n);\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"text-sm [&_p]:leading-relaxed\", className)} {...props} />\n ),\n);\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertDescription, AlertTitle };\n","\"use client\";\n\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\nimport * as React from \"react\";\n\nimport { buttonVariants } from \"./button\";\nimport { cn } from \"../../utils/cn\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n};\n","import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary: \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n ghostdestructive: \"hover:bg-destructive hover:text-primary-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot : \"button\";\n\n return <Comp data-slot=\"button\" className={cn(buttonVariants({ variant, size, className }))} {...props} />;\n}\n\nexport { Button, buttonVariants };\n","\"use client\";\n\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(\n \"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full\",\n className,\n )}\n {...props}\n />\n));\nAvatar.displayName = AvatarPrimitive.Root.displayName;\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn(\"aspect-square h-full w-full\", className)}\n {...props}\n />\n));\nAvatarImage.displayName = AvatarPrimitive.Image.displayName;\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n \"flex h-full w-full items-center justify-center rounded-full bg-muted\",\n className,\n )}\n {...props}\n />\n));\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;\n\nexport { Avatar, AvatarFallback, AvatarImage };\n","import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst badgeVariants = cva(\n \"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\",\n {\n variants: {\n variant: {\n default: \"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80\",\n secondary: \"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n destructive: \"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80\",\n outline: \"text-foreground\",\n\n blue: \"border-transparent bg-sky-500 text-primary-foreground rounded-full\",\n green: \"border-transparent bg-emerald-500 text-primary-foreground rounded-full\",\n red: \"border-transparent bg-red-500 text-primary-foreground rounded-full\",\n yellow: \"border-transparent bg-yellow-500 text-primary-foreground rounded-full\",\n purple: \"border-transparent bg-purple-500 text-primary-foreground rounded-full\",\n pink: \"border-transparent bg-pink-500 text-primary-foreground rounded-full\",\n gray: \"border-transparent bg-gray-500 text-primary-foreground rounded-full\",\n orange: \"border-transparent bg-orange-500 text-primary-foreground rounded-full\",\n teal: \"border-transparent bg-teal-500 text-primary-foreground rounded-full\",\n lime: \"border-transparent bg-lime-500 text-primary-foreground rounded-full\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return <div className={cn(badgeVariants({ variant }), className)} {...props} />;\n}\n\nexport { Badge, badgeVariants };\n","import { ChevronRightIcon, DotsHorizontalIcon } from \"@radix-ui/react-icons\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Breadcrumb = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<\"nav\"> & {\n separator?: React.ReactNode;\n }\n>(({ ...props }, ref) => <nav ref={ref} aria-label=\"breadcrumb\" {...props} />);\nBreadcrumb.displayName = \"Breadcrumb\";\n\nconst BreadcrumbList = React.forwardRef<\n HTMLOListElement,\n React.ComponentPropsWithoutRef<\"ol\">\n>(({ className, ...props }, ref) => (\n <ol\n ref={ref}\n className={cn(\n \"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5\",\n className,\n )}\n {...props}\n />\n));\nBreadcrumbList.displayName = \"BreadcrumbList\";\n\nconst BreadcrumbItem = React.forwardRef<\n HTMLLIElement,\n React.ComponentPropsWithoutRef<\"li\">\n>(({ className, ...props }, ref) => (\n <li\n ref={ref}\n className={cn(\"inline-flex items-center gap-1.5\", className)}\n {...props}\n />\n));\nBreadcrumbItem.displayName = \"BreadcrumbItem\";\n\nconst BreadcrumbLink = React.forwardRef<\n HTMLAnchorElement,\n React.ComponentPropsWithoutRef<\"a\"> & {\n asChild?: boolean;\n }\n>(({ asChild, className, ...props }, ref) => {\n const Comp = asChild ? Slot : \"a\";\n\n return (\n <Comp\n ref={ref}\n className={cn(\"transition-colors hover:text-foreground\", className)}\n {...props}\n />\n );\n});\nBreadcrumbLink.displayName = \"BreadcrumbLink\";\n\nconst BreadcrumbPage = React.forwardRef<\n HTMLSpanElement,\n React.ComponentPropsWithoutRef<\"span\">\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n role=\"link\"\n aria-disabled=\"true\"\n aria-current=\"page\"\n className={cn(\"font-normal text-foreground\", className)}\n {...props}\n />\n));\nBreadcrumbPage.displayName = \"BreadcrumbPage\";\n\nconst BreadcrumbSeparator = ({\n children,\n className,\n ...props\n}: React.ComponentProps<\"li\">) => (\n <li\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"[&>svg]:h-3.5 [&>svg]:w-3.5\", className)}\n {...props}\n >\n {children ?? <ChevronRightIcon />}\n </li>\n);\nBreadcrumbSeparator.displayName = \"BreadcrumbSeparator\";\n\nconst BreadcrumbEllipsis = ({\n className,\n ...props\n}: React.ComponentProps<\"span\">) => (\n <span\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"flex h-9 w-9 items-center justify-center\", className)}\n {...props}\n >\n <DotsHorizontalIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">More</span>\n </span>\n);\nBreadcrumbEllipsis.displayName = \"BreadcrumbElipssis\";\n\nexport {\n Breadcrumb,\n BreadcrumbEllipsis,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n};\n","\"use client\";\n\nimport * as React from \"react\";\nimport { DayPicker, getDefaultClassNames } from \"react-day-picker\";\n\nimport { cn } from \"../../utils/cn\";\nimport { buttonVariants } from \"./button\";\n// import \"react-day-picker/style.css\";\n\nfunction Calendar({ className, classNames, showOutsideDays = true, ...props }: React.ComponentProps<typeof DayPicker>) {\n const defaultClassNames = getDefaultClassNames();\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\"p-3\", className)}\n classNames={{\n months: `relative flex ${defaultClassNames.month}`,\n month_caption: `relative mx-10 flex h-7 items-center justify-center ${defaultClassNames.month_caption}`,\n weekdays: cn(\"flex flex-row\", classNames?.weekdays),\n weekday: cn(\"w-8 text-sm font-normal text-muted-foreground\", classNames?.weekday),\n month: cn(\"w-full\", classNames?.month),\n\n caption_label: cn(\"truncate text-sm font-medium\", classNames?.caption_label),\n button_next: cn(\n buttonVariants({ variant: \"outline\" }),\n \"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute right-1 [&_svg]:fill-foreground\",\n classNames?.button_next,\n ),\n button_previous: cn(\n buttonVariants({ variant: \"outline\" }),\n \"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute left-1 [&_svg]:fill-foreground\",\n classNames?.button_previous,\n ),\n nav: cn(\"flex items-start\", classNames?.nav),\n month_grid: cn(\"mx-auto mt-4\", classNames?.month_grid),\n week: cn(\"mt-2 flex w-max items-start\", classNames?.week),\n day: cn(\"flex size-8 flex-1 items-center justify-center p-0 text-sm\", classNames?.day),\n day_button: cn(\n \"size-8 rounded-md p-0 font-normal transition-none aria-selected:opacity-100\",\n classNames?.day_button,\n ),\n range_start: cn(\n \"bg-accent [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground day-range-start rounded-s-md\",\n classNames?.range_start,\n ),\n range_middle: cn(\n \"bg-accent !text-foreground [&>button]:bg-transparent [&>button]:!text-foreground [&>button]:hover:bg-transparent [&>button]:hover:!text-foreground\",\n classNames?.range_middle,\n ),\n range_end: cn(\n \"bg-accent [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground day-range-end rounded-e-md\",\n classNames?.range_end,\n ),\n selected: cn(\n \"[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground\",\n classNames?.selected,\n ),\n today: cn(\"[&>button]:bg-accent [&>button]:text-accent-foreground\", classNames?.today),\n outside: cn(\n \"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30\",\n classNames?.outside,\n ),\n disabled: cn(\"text-muted-foreground opacity-50\", classNames?.disabled),\n hidden: cn(\"invisible flex-1\", classNames?.hidden),\n ...classNames,\n }}\n {...props}\n />\n );\n}\nCalendar.displayName = \"Calendar\";\n\nexport { Calendar };\n","import * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"rounded-xl border bg-card text-card-foreground shadow\", className)} {...props} />\n));\nCard.displayName = \"Card\";\n\nconst CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"flex flex-col space-y-1.5 p-6\", className)} {...props} />\n ),\n);\nCardHeader.displayName = \"CardHeader\";\n\nconst CardTitle = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"font-semibold leading-none tracking-tight\", className)} {...props} />\n ),\n);\nCardTitle.displayName = \"CardTitle\";\n\nconst CardDescription = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"text-sm text-muted-foreground\", className)} {...props} />\n ),\n);\nCardDescription.displayName = \"CardDescription\";\n\nconst CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => <div ref={ref} className={cn(\"p-6 pt-0\", className)} {...props} />,\n);\nCardContent.displayName = \"CardContent\";\n\nconst CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"flex items-center p-6 pt-0\", className)} {...props} />\n ),\n);\nCardFooter.displayName = \"CardFooter\";\n\nexport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };\n","\"use client\";\n\nimport { Button } from \"./button\";\nimport { cn } from \"../../utils/cn\";\nimport { ArrowLeftIcon, ArrowRightIcon } from \"@radix-ui/react-icons\";\nimport useEmblaCarousel, { type UseEmblaCarouselType } from \"embla-carousel-react\";\nimport * as React from \"react\";\n\ntype CarouselApi = UseEmblaCarouselType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\ntype CarouselOptions = UseCarouselParameters[0];\ntype CarouselPlugin = UseCarouselParameters[1];\n\ntype CarouselProps = {\n opts?: CarouselOptions;\n plugins?: CarouselPlugin;\n orientation?: \"horizontal\" | \"vertical\";\n setApi?: (api: CarouselApi) => void;\n};\n\ntype CarouselContextProps = {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0];\n api: ReturnType<typeof useEmblaCarousel>[1];\n scrollPrev: () => void;\n scrollNext: () => void;\n canScrollPrev: boolean;\n canScrollNext: boolean;\n} & CarouselProps;\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null);\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext);\n\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\");\n }\n\n return context;\n}\n\nconst Carousel = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & CarouselProps>(\n ({ orientation = \"horizontal\", opts, setApi, plugins, className, children, ...props }, ref) => {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n },\n plugins,\n );\n const [canScrollPrev, setCanScrollPrev] = React.useState(false);\n const [canScrollNext, setCanScrollNext] = React.useState(false);\n\n const onSelect = React.useCallback((api: CarouselApi) => {\n if (!api) {\n return;\n }\n\n setCanScrollPrev(api.canScrollPrev());\n setCanScrollNext(api.canScrollNext());\n }, []);\n\n const scrollPrev = React.useCallback(() => {\n api?.scrollPrev();\n }, [api]);\n\n const scrollNext = React.useCallback(() => {\n api?.scrollNext();\n }, [api]);\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n scrollPrev();\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n scrollNext();\n }\n },\n [scrollPrev, scrollNext],\n );\n\n React.useEffect(() => {\n if (!api || !setApi) {\n return;\n }\n\n setApi(api);\n }, [api, setApi]);\n\n React.useEffect(() => {\n if (!api) {\n return;\n }\n\n onSelect(api);\n api.on(\"reInit\", onSelect);\n api.on(\"select\", onSelect);\n\n return () => {\n api?.off(\"select\", onSelect);\n };\n }, [api, onSelect]);\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api: api,\n opts,\n orientation: orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n ref={ref}\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n );\n },\n);\nCarousel.displayName = \"Carousel\";\n\nconst CarouselContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const { carouselRef, orientation } = useCarousel();\n\n return (\n <div ref={carouselRef} className=\"overflow-hidden\">\n <div\n ref={ref}\n className={cn(\"flex\", orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\", className)}\n {...props}\n />\n </div>\n );\n },\n);\nCarouselContent.displayName = \"CarouselContent\";\n\nconst CarouselItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const { orientation } = useCarousel();\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-roledescription=\"slide\"\n className={cn(\"min-w-0 shrink-0 grow-0 basis-full\", orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\", className)}\n {...props}\n />\n );\n },\n);\nCarouselItem.displayName = \"CarouselItem\";\n\nconst CarouselPrevious = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(\n ({ className, variant = \"outline\", size = \"icon\", ...props }, ref) => {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel();\n\n return (\n <Button\n ref={ref}\n variant={variant}\n size={size}\n className={cn(\n \"absolute h-8 w-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"-left-12 top-1/2 -translate-y-1/2\"\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n className,\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <ArrowLeftIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n );\n },\n);\nCarouselPrevious.displayName = \"CarouselPrevious\";\n\nconst CarouselNext = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(\n ({ className, variant = \"outline\", size = \"icon\", ...props }, ref) => {\n const { orientation, scrollNext, canScrollNext } = useCarousel();\n\n return (\n <Button\n ref={ref}\n variant={variant}\n size={size}\n className={cn(\n \"absolute h-8 w-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"-right-12 top-1/2 -translate-y-1/2\"\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n className,\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <ArrowRightIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n );\n },\n);\nCarouselNext.displayName = \"CarouselNext\";\n\nexport { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type CarouselApi };\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as RechartsPrimitive from \"recharts\";\nimport type { LegendPayload } from \"recharts/types/component/DefaultLegendContent\";\nimport { NameType, Payload, ValueType } from \"recharts/types/component/DefaultTooltipContent\";\nimport type { Props as LegendProps } from \"recharts/types/component/Legend\";\nimport { TooltipContentProps } from \"recharts/types/component/Tooltip\";\n\nimport { cn } from \"../../utils/cn\";\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const;\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode;\n icon?: React.ComponentType;\n } & ({ color?: string; theme?: never } | { color?: never; theme: Record<keyof typeof THEMES, string> });\n};\n\ntype ChartContextProps = {\n config: ChartConfig;\n};\n\nconst ChartContext = React.createContext<ChartContextProps | null>(null);\n\nfunction useChart() {\n const context = React.useContext(ChartContext);\n\n if (!context) {\n throw new Error(\"useChart must be used within a <ChartContainer />\");\n }\n\n return context;\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig;\n children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>[\"children\"];\n}) {\n const uniqueId = React.useId();\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`;\n\n return (\n <ChartContext.Provider value={{ config }}>\n <div\n data-slot=\"chart\"\n data-chart={chartId}\n className={cn(\n \"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden\",\n className,\n )}\n {...props}\n >\n <ChartStyle id={chartId} config={config} />\n <RechartsPrimitive.ResponsiveContainer>{children}</RechartsPrimitive.ResponsiveContainer>\n </div>\n </ChartContext.Provider>\n );\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(([, config]) => config.theme || config.color);\n\n if (!colorConfig.length) {\n return null;\n }\n\n return (\n <style\n dangerouslySetInnerHTML={{\n __html: Object.entries(THEMES)\n .map(\n ([theme, prefix]) => `\n ${prefix} [data-chart=${id}] {\n ${colorConfig\n .map(([key, itemConfig]) => {\n const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || itemConfig.color;\n return color ? ` --color-${key}: ${color};` : null;\n })\n .join(\"\\n\")}\n }\n `,\n )\n .join(\"\\n\"),\n }}\n />\n );\n};\n\nconst ChartTooltip = RechartsPrimitive.Tooltip;\n\ntype CustomTooltipProps = TooltipContentProps<ValueType, NameType> & {\n className?: string;\n hideLabel?: boolean;\n hideIndicator?: boolean;\n indicator?: \"line\" | \"dot\" | \"dashed\";\n nameKey?: string;\n labelKey?: string;\n labelFormatter?: (\n label: TooltipContentProps<number, string>[\"label\"],\n payload: TooltipContentProps<number, string>[\"payload\"],\n ) => React.ReactNode;\n formatter?: (\n value: number | string,\n name: string,\n item: Payload<number | string, string>,\n index: number,\n payload: ReadonlyArray<Payload<number | string, string>>,\n ) => React.ReactNode;\n labelClassName?: string;\n color?: string;\n};\n\nfunction ChartTooltipContent({\n active,\n payload,\n label,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n labelFormatter,\n formatter,\n labelClassName,\n color,\n nameKey,\n labelKey,\n}: CustomTooltipProps) {\n const { config } = useChart();\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null;\n }\n\n const [item] = payload;\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const value = (() => {\n const v =\n !labelKey && typeof label === \"string\"\n ? (config[label as keyof typeof config]?.label ?? label)\n : itemConfig?.label;\n\n return typeof v === \"string\" || typeof v === \"number\" ? v : undefined;\n })();\n\n if (labelFormatter) {\n return <div className={cn(\"font-medium\", labelClassName)}>{labelFormatter(value, payload)}</div>;\n }\n\n if (!value) {\n return null;\n }\n\n return <div className={cn(\"font-medium\", labelClassName)}>{value}</div>;\n }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);\n\n if (!active || !payload?.length) {\n return null;\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\";\n\n return (\n <div\n className={cn(\n \"border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl\",\n className,\n )}\n >\n {!nestLabel ? tooltipLabel : null}\n <div className=\"grid gap-1.5\">\n {payload.map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const indicatorColor = color || item.payload.fill || item.color;\n\n return (\n <div\n key={item.dataKey}\n className={cn(\n \"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5\",\n indicator === \"dot\" && \"items-center\",\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n <itemConfig.icon />\n ) : (\n !hideIndicator && (\n <div\n className={cn(\"shrink-0 rounded-[2px] border-[var(--color-border)] bg-[var(--color-bg)]\", {\n \"h-2.5 w-2.5\": indicator === \"dot\",\n \"w-1\": indicator === \"line\",\n \"w-0 border-[1.5px] border-dashed bg-transparent\": indicator === \"dashed\",\n \"my-0.5\": nestLabel && indicator === \"dashed\",\n })}\n style={\n {\n \"--color-bg\": indicatorColor,\n \"--color-border\": indicatorColor,\n } as React.CSSProperties\n }\n />\n )\n )}\n <div\n className={cn(\"flex flex-1 justify-between leading-none\", nestLabel ? \"items-end\" : \"items-center\")}\n >\n <div className=\"grid gap-1.5\">\n {nestLabel ? tooltipLabel : null}\n <span className=\"text-muted-foreground\">{itemConfig?.label || item.name}</span>\n </div>\n {item.value && (\n <span className=\"text-foreground font-mono font-medium tabular-nums\">\n {item.value.toLocaleString()}\n </span>\n )}\n </div>\n </>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nconst ChartLegend = RechartsPrimitive.Legend;\n\ntype ChartLegendContentProps = {\n className?: string;\n hideIcon?: boolean;\n verticalAlign?: LegendProps[\"verticalAlign\"];\n payload?: LegendPayload[];\n nameKey?: string;\n};\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: ChartLegendContentProps) {\n const { config } = useChart();\n\n if (!payload?.length) {\n return null;\n }\n\n return (\n <div className={cn(\"flex items-center justify-center gap-4\", verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\", className)}>\n {payload.map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n\n return (\n <div\n key={item.value}\n className={cn(\"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3\")}\n >\n {itemConfig?.icon && !hideIcon ? (\n <itemConfig.icon />\n ) : (\n <div\n className=\"h-2 w-2 shrink-0 rounded-[2px]\"\n style={{\n backgroundColor: item.color,\n }}\n />\n )}\n {itemConfig?.label}\n </div>\n );\n })}\n </div>\n );\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined;\n }\n\n const payloadPayload =\n \"payload\" in payload && typeof payload.payload === \"object\" && payload.payload !== null\n ? payload.payload\n : undefined;\n\n let configLabelKey: string = key;\n\n if (key in payload && typeof payload[key as keyof typeof payload] === \"string\") {\n configLabelKey = payload[key as keyof typeof payload] as string;\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string;\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config];\n}\n\nexport { ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent };\n","\"use client\";\n\nimport { cn } from \"../../utils/cn\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport * as React from \"react\";\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n \"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground\",\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className={cn(\"flex items-center justify-center text-current\")}\n >\n <CheckIcon className=\"h-4 w-4\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n));\nCheckbox.displayName = CheckboxPrimitive.Root.displayName;\n\nexport { Checkbox };\n","\"use client\";\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\";\n\nconst Collapsible = CollapsiblePrimitive.Root;\n\nconst CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;\n\nconst CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;\n\nexport { Collapsible, CollapsibleContent, CollapsibleTrigger };\n","\"use client\";\n\nimport { type DialogProps } from \"@radix-ui/react-dialog\";\nimport { MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport * as React from \"react\";\n\nimport { Dialog, DialogContent } from \"./dialog\";\nimport { cn } from \"../../utils/cn\";\n\nconst Command = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive\n ref={ref}\n className={cn(\n \"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground\",\n className,\n )}\n {...props}\n />\n));\nCommand.displayName = CommandPrimitive.displayName;\n\ninterface CommandDialogProps extends DialogProps {}\n\nconst CommandDialog = ({ children, ...props }: CommandDialogProps) => {\n return (\n <Dialog {...props}>\n <DialogContent className=\"overflow-hidden p-0\">\n <Command className=\"[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5\">\n {children}\n </Command>\n </DialogContent>\n </Dialog>\n );\n};\n\nconst CommandInput = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Input>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>\n>(({ className, ...props }, ref) => (\n <div className=\"flex items-center border-b px-3\" cmdk-input-wrapper=\"\">\n <MagnifyingGlassIcon className=\"mr-2 h-4 w-4 shrink-0 opacity-50\" />\n <CommandPrimitive.Input\n ref={ref}\n className={cn(\n \"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n </div>\n));\n\nCommandInput.displayName = CommandPrimitive.Input.displayName;\n\nconst CommandList = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.List\n ref={ref}\n className={cn(\"max-h-[300px] overflow-y-auto overflow-x-hidden\", className)}\n {...props}\n />\n));\n\nCommandList.displayName = CommandPrimitive.List.displayName;\n\nconst CommandEmpty = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Empty>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>\n>((props, ref) => (\n <CommandPrimitive.Empty\n ref={ref}\n className=\"py-6 text-center text-sm\"\n {...props}\n />\n));\n\nCommandEmpty.displayName = CommandPrimitive.Empty.displayName;\n\nconst CommandGroup = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Group\n ref={ref}\n className={cn(\n \"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground\",\n className,\n )}\n {...props}\n />\n));\n\nCommandGroup.displayName = CommandPrimitive.Group.displayName;\n\nconst CommandSeparator = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 h-px bg-border\", className)}\n {...props}\n />\n));\nCommandSeparator.displayName = CommandPrimitive.Separator.displayName;\n\nconst CommandItem = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n className,\n )}\n {...props}\n />\n));\n\nCommandItem.displayName = CommandPrimitive.Item.displayName;\n\nconst CommandShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className,\n )}\n {...props}\n />\n );\n};\nCommandShortcut.displayName = \"CommandShortcut\";\n\nexport {\n Command,\n CommandDialog,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n CommandShortcut,\n};\n","\"use client\";\n\nimport { cn } from \"../../utils/cn\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { Cross2Icon } from \"@radix-ui/react-icons\";\nimport * as React from \"react\";\n\nconst Dialog = DialogPrimitive.Root;\n\nconst DialogTrigger = DialogPrimitive.Trigger;\n\nconst DialogPortal = DialogPrimitive.Portal;\n\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <Cross2Icon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn(\"flex flex-col space-y-1.5 text-center sm:text-left\", className)} {...props} />\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nconst DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn(\"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\", className)} {...props} />\n);\nDialogFooter.displayName = \"DialogFooter\";\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold leading-none tracking-tight\", className)}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description ref={ref} className={cn(\"text-sm text-muted-foreground\", className)} {...props} />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","\"use client\";\n\nimport { cn } from \"../../utils/cn\";\nimport * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\";\nimport { CheckIcon, ChevronRightIcon, DotFilledIcon } from \"@radix-ui/react-icons\";\nimport * as React from \"react\";\n\nconst ContextMenu = ContextMenuPrimitive.Root;\n\nconst ContextMenuTrigger = ContextMenuPrimitive.Trigger;\n\nconst ContextMenuGroup = ContextMenuPrimitive.Group;\n\nconst ContextMenuPortal = ContextMenuPrimitive.Portal;\n\nconst ContextMenuSub = ContextMenuPrimitive.Sub;\n\nconst ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;\n\nconst ContextMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <ContextMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto h-4 w-4\" />\n </ContextMenuPrimitive.SubTrigger>\n));\nContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;\n\nconst ContextMenuSubContent = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n));\nContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;\n\nconst ContextMenuContent = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Content\n ref={ref}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n));\nContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;\n\nconst ContextMenuItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <ContextMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;\n\nconst ContextMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <ContextMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"h-4 w-4\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n));\nContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;\n\nconst ContextMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <ContextMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <DotFilledIcon className=\"h-4 w-4 fill-current\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n));\nContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;\n\nconst ContextMenuLabel = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <ContextMenuPrimitive.Label\n ref={ref}\n className={cn(\"px-2 py-1.5 text-sm font-semibold text-foreground\", inset && \"pl-8\", className)}\n {...props}\n />\n));\nContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;\n\nconst ContextMenuSeparator = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.Separator ref={ref} className={cn(\"-mx-1 my-1 h-px bg-border\", className)} {...props} />\n));\nContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;\n\nconst ContextMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {\n return <span className={cn(\"ml-auto text-xs tracking-widest text-muted-foreground\", className)} {...props} />;\n};\nContextMenuShortcut.displayName = \"ContextMenuShortcut\";\n\nexport {\n ContextMenu,\n ContextMenuCheckboxItem,\n ContextMenuContent,\n ContextMenuGroup,\n ContextMenuItem,\n ContextMenuLabel,\n ContextMenuPortal,\n ContextMenuRadioGroup,\n ContextMenuRadioItem,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuTrigger,\n};\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Drawer as DrawerPrimitive } from \"vaul\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Drawer = ({ shouldScaleBackground = true, ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>) => (\n <DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} />\n);\nDrawer.displayName = \"Drawer\";\n\nconst DrawerTrigger = DrawerPrimitive.Trigger;\n\nconst DrawerPortal = DrawerPrimitive.Portal;\n\nconst DrawerClose = DrawerPrimitive.Close;\n\nconst DrawerOverlay = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DrawerPrimitive.Overlay ref={ref} className={cn(\"fixed inset-0 z-50 bg-black/80\", className)} {...props} />\n));\nDrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;\n\nconst DrawerContent = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DrawerPortal>\n <DrawerOverlay />\n <DrawerPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background\",\n className,\n )}\n {...props}\n >\n <div className=\"mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n));\nDrawerContent.displayName = \"DrawerContent\";\n\nconst DrawerHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn(\"grid gap-1.5 p-4 text-center sm:text-left\", className)} {...props} />\n);\nDrawerHeader.displayName = \"DrawerHeader\";\n\nconst DrawerFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)} {...props} />\n);\nDrawerFooter.displayName = \"DrawerFooter\";\n\nconst DrawerTitle = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DrawerPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold leading-none tracking-tight\", className)}\n {...props}\n />\n));\nDrawerTitle.displayName = DrawerPrimitive.Title.displayName;\n\nconst DrawerDescription = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DrawerPrimitive.Description ref={ref} className={cn(\"text-sm text-muted-foreground\", className)} {...props} />\n));\nDrawerDescription.displayName = DrawerPrimitive.Description.displayName;\n\nexport {\n Drawer,\n DrawerClose,\n DrawerContent,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerOverlay,\n DrawerPortal,\n DrawerTitle,\n DrawerTrigger,\n};\n","\"use client\";\n\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport {\n CheckIcon,\n ChevronRightIcon,\n DotFilledIcon,\n} from \"@radix-ui/react-icons\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group;\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal;\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub;\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto h-4 w-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n));\nDropdownMenuSubTrigger.displayName =\n DropdownMenuPrimitive.SubTrigger.displayName;\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuSubContent.displayName =\n DropdownMenuPrimitive.SubContent.displayName;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md\",\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"h-4 w-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName =\n DropdownMenuPrimitive.CheckboxItem.displayName;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <DotFilledIcon className=\"h-4 w-4 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\n \"px-2 py-1.5 text-sm font-semibold\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nconst DropdownMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\"ml-auto text-xs tracking-widest opacity-60\", className)}\n {...props}\n />\n );\n};\nDropdownMenuShortcut.displayName = \"DropdownMenuShortcut\";\n\nexport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n};\n","\"use client\";\n\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { Controller, ControllerProps, FieldPath, FieldValues, FormProvider, useFormContext } from \"react-hook-form\";\n\nimport { Label } from \"./label\";\nimport { cn } from \"../../utils/cn\";\n\nconst Form = FormProvider;\n\ntype FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n name: TName;\n};\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n ...props\n}: ControllerProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\nconst useFormField = () => {\n const fieldContext = React.useContext(FormFieldContext);\n const itemContext = React.useContext(FormItemContext);\n const { getFieldState, formState } = useFormContext();\n\n const fieldState = getFieldState(fieldContext.name, formState);\n\n if (!fieldContext) {\n throw new Error(\"useFormField should be used within <FormField>\");\n }\n\n const { id } = itemContext;\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n };\n};\n\ntype FormItemContextValue = {\n id: string;\n};\n\nconst FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);\n\nconst FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const id = React.useId();\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <div ref={ref} className={cn(\"space-y-2\", className)} {...props} />\n </FormItemContext.Provider>\n );\n },\n);\nFormItem.displayName = \"FormItem\";\n\nconst FormLabel = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>\n>(({ className, ...props }, ref) => {\n const { error, formItemId } = useFormField();\n\n return <Label ref={ref} className={cn(error && \"text-destructive\", className)} htmlFor={formItemId} {...props} />;\n});\nFormLabel.displayName = \"FormLabel\";\n\nconst FormControl = React.forwardRef<React.ElementRef<typeof Slot>, React.ComponentPropsWithoutRef<typeof Slot>>(\n ({ ...props }, ref) => {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n return (\n <Slot\n ref={ref}\n id={formItemId}\n aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n aria-invalid={!!error}\n {...props}\n />\n );\n },\n);\nFormControl.displayName = \"FormControl\";\n\nconst FormDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(\n ({ className, ...props }, ref) => {\n const { formDescriptionId } = useFormField();\n\n return (\n <p ref={ref} id={formDescriptionId} className={cn(\"text-muted-foreground text-[0.8rem]\", className)} {...props} />\n );\n },\n);\nFormDescription.displayName = \"FormDescription\";\n\nconst FormMessage = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(\n ({ className, children, ...props }, ref) => {\n const { error, formMessageId } = useFormField();\n const body = error ? String(error?.message) : children;\n\n if (!body) {\n return null;\n }\n\n return (\n <p\n ref={ref}\n id={formMessageId}\n className={cn(\"text-destructive text-[0.8rem] font-medium\", className)}\n {...props}\n >\n {body}\n </p>\n );\n },\n);\nFormMessage.displayName = \"FormMessage\";\n\nexport { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };\n","\"use client\";\n\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst labelVariants = cva(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(labelVariants(), className)}\n {...props}\n />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","\"use client\";\n\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst HoverCard = HoverCardPrimitive.Root;\n\nconst HoverCardTrigger = HoverCardPrimitive.Trigger;\n\nconst HoverCardContent = React.forwardRef<\n React.ElementRef<typeof HoverCardPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n <HoverCardPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n));\nHoverCardContent.displayName = HoverCardPrimitive.Content.displayName;\n\nexport { HoverCard, HoverCardContent, HoverCardTrigger };\n","import * as React from \"react\"\n\nimport { cn } from \"../../utils/cn\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n","import * as React from \"react\"\nimport * as NavigationMenuPrimitive from \"@radix-ui/react-navigation-menu\"\nimport { cva } from \"class-variance-authority\"\nimport { ChevronDownIcon } from \"lucide-react\"\n\nimport { cn } from \"../../utils/cn\"\n\nfunction NavigationMenu({\n className,\n children,\n viewport = true,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {\n viewport?: boolean\n}) {\n return (\n <NavigationMenuPrimitive.Root\n data-slot=\"navigation-menu\"\n data-viewport={viewport}\n className={cn(\n \"group/navigation-menu relative flex max-w-max flex-1 items-center justify-center\",\n className\n )}\n {...props}\n >\n {children}\n {viewport && <NavigationMenuViewport />}\n </NavigationMenuPrimitive.Root>\n )\n}\n\nfunction NavigationMenuList({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {\n return (\n <NavigationMenuPrimitive.List\n data-slot=\"navigation-menu-list\"\n className={cn(\n \"group flex flex-1 list-none items-center justify-center gap-1\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction NavigationMenuItem({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {\n return (\n <NavigationMenuPrimitive.Item\n data-slot=\"navigation-menu-item\"\n className={cn(\"relative\", className)}\n {...props}\n />\n )\n}\n\nconst navigationMenuTriggerStyle = cva(\n \"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1\"\n)\n\nfunction NavigationMenuTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {\n return (\n <NavigationMenuPrimitive.Trigger\n data-slot=\"navigation-menu-trigger\"\n className={cn(navigationMenuTriggerStyle(), \"group\", className)}\n {...props}\n >\n {children}{\" \"}\n <ChevronDownIcon\n className=\"relative top-[1px] ml-1 size-3 transition duration-300 group-data-[state=open]:rotate-180\"\n aria-hidden=\"true\"\n />\n </NavigationMenuPrimitive.Trigger>\n )\n}\n\nfunction NavigationMenuContent({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {\n return (\n <NavigationMenuPrimitive.Content\n data-slot=\"navigation-menu-content\"\n className={cn(\n \"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 top-0 left-0 w-full p-2 pr-2.5 md:absolute md:w-auto\",\n \"group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:border group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:duration-200 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction NavigationMenuViewport({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {\n return (\n <div\n className={cn(\n \"absolute top-full left-0 isolate z-50 flex justify-center\"\n )}\n >\n <NavigationMenuPrimitive.Viewport\n data-slot=\"navigation-menu-viewport\"\n className={cn(\n \"origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border shadow md:w-[var(--radix-navigation-menu-viewport-width)]\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction NavigationMenuLink({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {\n return (\n <NavigationMenuPrimitive.Link\n data-slot=\"navigation-menu-link\"\n className={cn(\n \"data-[active=true]:focus:bg-accent data-[active=true]:hover:bg-accent data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:ring-ring/50 [&_svg:not([class*='text-'])]:text-muted-foreground flex flex-col gap-1 rounded-sm p-2 text-sm transition-all outline-none focus-visible:ring-[3px] focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction NavigationMenuIndicator({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {\n return (\n <NavigationMenuPrimitive.Indicator\n data-slot=\"navigation-menu-indicator\"\n className={cn(\n \"data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden\",\n className\n )}\n {...props}\n >\n <div className=\"bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md\" />\n </NavigationMenuPrimitive.Indicator>\n )\n}\n\nexport {\n NavigationMenu,\n NavigationMenuList,\n NavigationMenuItem,\n NavigationMenuContent,\n NavigationMenuTrigger,\n NavigationMenuLink,\n NavigationMenuIndicator,\n NavigationMenuViewport,\n navigationMenuTriggerStyle,\n}\n","\"use client\";\n\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };\n","\"use client\";\n\nimport * as ProgressPrimitive from \"@radix-ui/react-progress\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Progress = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n <ProgressPrimitive.Root\n ref={ref}\n className={cn(\"relative h-2 w-full overflow-hidden rounded-full bg-primary/20\", className)}\n {...props}\n >\n <ProgressPrimitive.Indicator\n className=\"h-full w-full flex-1 bg-primary transition-all\"\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n));\nProgress.displayName = ProgressPrimitive.Root.displayName;\n\nexport { Progress };\n","\"use client\";\n\nimport { cn } from \"../../utils/cn\";\nimport { DotFilledIcon } from \"@radix-ui/react-icons\";\nimport * as RadioGroupPrimitive from \"@radix-ui/react-radio-group\";\nimport * as React from \"react\";\n\nconst RadioGroup = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>\n>(({ className, ...props }, ref) => {\n return <RadioGroupPrimitive.Root className={cn(\"grid gap-2\", className)} {...props} ref={ref} />;\n});\nRadioGroup.displayName = RadioGroupPrimitive.Root.displayName;\n\nconst RadioGroupItem = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>\n>(({ className, ...props }, ref) => {\n return (\n <RadioGroupPrimitive.Item\n ref={ref}\n className={cn(\n \"aspect-square h-4 w-4 rounded-full border border-primary text-primary shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator className=\"flex items-center justify-center\">\n <DotFilledIcon className=\"h-3.5 w-3.5 fill-primary\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n );\n});\nRadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;\n\nexport { RadioGroup, RadioGroupItem };\n","\"use client\";\n\nimport { GripVerticalIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport * as ResizablePrimitive from \"react-resizable-panels\";\nimport { cn } from \"../../utils\";\n\nfunction ResizablePanelGroup({ className, ...props }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) {\n return (\n <ResizablePrimitive.PanelGroup\n data-slot=\"resizable-panel-group\"\n className={cn(\"flex h-full w-full data-[panel-group-direction=vertical]:flex-col\", className)}\n {...props}\n />\n );\n}\n\nfunction ResizablePanel({ ...props }: React.ComponentProps<typeof ResizablePrimitive.Panel>) {\n return <ResizablePrimitive.Panel data-slot=\"resizable-panel\" {...props} />;\n}\n\nfunction ResizableHandle({\n withHandle,\n className,\n ...props\n}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {\n withHandle?: boolean;\n}) {\n return (\n <ResizablePrimitive.PanelResizeHandle\n data-slot=\"resizable-handle\"\n className={cn(\n \"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90\",\n className,\n )}\n {...props}\n >\n {withHandle && (\n <div className=\"bg-border z-10 flex h-4 w-3 items-center justify-center rounded-xs border\">\n <GripVerticalIcon className=\"size-2.5\" />\n </div>\n )}\n </ResizablePrimitive.PanelResizeHandle>\n );\n}\n\nexport { ResizableHandle, ResizablePanel, ResizablePanelGroup };\n","\"use client\";\n\nimport * as ScrollAreaPrimitive from \"@radix-ui/react-scroll-area\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst ScrollArea = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>\n>(({ className, children, ...props }, ref) => (\n <ScrollAreaPrimitive.Root ref={ref} className={cn(\"relative overflow-hidden\", className)} {...props}>\n <ScrollAreaPrimitive.Viewport className=\"h-full w-full rounded-[inherit]\">{children}</ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n));\nScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;\n\nconst ScrollBar = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>\n>(({ className, orientation = \"vertical\", ...props }, ref) => (\n <ScrollAreaPrimitive.ScrollAreaScrollbar\n ref={ref}\n orientation={orientation}\n className={cn(\n \"flex touch-none select-none transition-colors\",\n orientation === \"vertical\" && \"h-full w-2.5 border-l border-l-transparent p-[1px]\",\n orientation === \"horizontal\" && \"h-2.5 flex-col border-t border-t-transparent p-[1px]\",\n className,\n )}\n {...props}\n >\n <ScrollAreaPrimitive.ScrollAreaThumb className=\"relative flex-1 rounded-full bg-border\" />\n </ScrollAreaPrimitive.ScrollAreaScrollbar>\n));\nScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;\n\nexport { ScrollArea, ScrollBar };\n","\"use client\";\n\nimport {\n CaretSortIcon,\n CheckIcon,\n ChevronDownIcon,\n ChevronUpIcon,\n} from \"@radix-ui/react-icons\";\nimport * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Select = SelectPrimitive.Root;\n\nconst SelectGroup = SelectPrimitive.Group;\n\nconst SelectValue = SelectPrimitive.Value;\n\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1\",\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <CaretSortIcon className=\"h-4 w-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n));\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName;\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className,\n )}\n {...props}\n >\n <ChevronUpIcon />\n </SelectPrimitive.ScrollUpButton>\n));\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className,\n )}\n {...props}\n >\n <ChevronDownIcon />\n </SelectPrimitive.ScrollDownButton>\n));\nSelectScrollDownButton.displayName =\n SelectPrimitive.ScrollDownButton.displayName;\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = \"popper\", ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n className={cn(\n \"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n position === \"popper\" &&\n \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n className,\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n \"p-1\",\n position === \"popper\" &&\n \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]\",\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\nSelectContent.displayName = SelectPrimitive.Content.displayName;\n\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\"px-2 py-1.5 text-sm font-semibold\", className)}\n {...props}\n />\n));\nSelectLabel.displayName = SelectPrimitive.Label.displayName;\n\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n));\nSelectItem.displayName = SelectPrimitive.Item.displayName;\n\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n {...props}\n />\n));\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName;\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as SeparatorPrimitive from \"@radix-ui/react-separator\"\n\nimport { cn } from \"../../utils/cn\"\n\nfunction Separator({\n className,\n orientation = \"horizontal\",\n decorative = true,\n ...props\n}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {\n return (\n <SeparatorPrimitive.Root\n data-slot=\"separator\"\n decorative={decorative}\n orientation={orientation}\n className={cn(\n \"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Separator }\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"../../utils/cn\"\n\nfunction Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />\n}\n\nfunction SheetTrigger({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Close>) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetPortal({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Portal>) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />\n}\n\nfunction SheetOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {\n return (\n <SheetPrimitive.Overlay\n data-slot=\"sheet-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Content> & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Content\n data-slot=\"sheet-content\"\n className={cn(\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500\",\n side === \"right\" &&\n \"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm\",\n side === \"left\" &&\n \"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm\",\n side === \"top\" &&\n \"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b\",\n side === \"bottom\" &&\n \"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t\",\n className\n )}\n {...props}\n >\n {children}\n <SheetPrimitive.Close className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none\">\n <XIcon className=\"size-4\" />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n </SheetPrimitive.Content>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"flex flex-col gap-1.5 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Title>) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Description>) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n","\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, VariantProps } from \"class-variance-authority\";\nimport { PanelLeftIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\nimport { Input } from \"./input\";\nimport { Separator } from \"./separator\";\nimport { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from \"./sheet\";\nimport { Skeleton } from \"./skeleton\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"./tooltip\";\nimport { useIsMobile } from \"../../utils/use-mobile\";\nimport { cn } from \"../../utils/cn\";\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\";\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;\nexport const SIDEBAR_WIDTH = \"16rem\";\nexport const SIDEBAR_WIDTH_MOBILE = \"18rem\";\nexport const SIDEBAR_WIDTH_ICON = \"3rem\";\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"\";\n\ntype SidebarContextProps = {\n state: \"expanded\" | \"collapsed\";\n open: boolean;\n setOpen: (open: boolean) => void;\n openMobile: boolean;\n setOpenMobile: (open: boolean) => void;\n isMobile: boolean;\n toggleSidebar: () => void;\n};\n\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null);\n\nfunction useSidebar() {\n const context = React.useContext(SidebarContext);\n if (!context) {\n throw new Error(\"useSidebar must be used within a SidebarProvider.\");\n }\n\n return context;\n}\n\nfunction SidebarProvider({\n defaultOpen = true,\n open: openProp,\n onOpenChange: setOpenProp,\n className,\n style,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n defaultOpen?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}) {\n const isMobile = useIsMobile();\n const [openMobile, setOpenMobile] = React.useState(false);\n\n // This is the internal state of the sidebar.\n // We use openProp and setOpenProp for control from outside the component.\n const [_open, _setOpen] = React.useState(defaultOpen);\n const open = openProp ?? _open;\n const setOpen = React.useCallback(\n (value: boolean | ((value: boolean) => boolean)) => {\n const openState = typeof value === \"function\" ? value(open) : value;\n if (setOpenProp) {\n setOpenProp(openState);\n } else {\n _setOpen(openState);\n }\n\n // This sets the cookie to keep the sidebar state.\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;\n },\n [setOpenProp, open],\n );\n\n // Helper to toggle the sidebar.\n const toggleSidebar = React.useCallback(() => {\n return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open);\n }, [isMobile, setOpen, setOpenMobile]);\n\n // Adds a keyboard shortcut to toggle the sidebar.\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {\n event.preventDefault();\n toggleSidebar();\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [toggleSidebar]);\n\n // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\n // This makes it easier to style the sidebar with Tailwind classes.\n const state = open ? \"expanded\" : \"collapsed\";\n\n const contextValue = React.useMemo<SidebarContextProps>(\n () => ({\n state,\n open,\n setOpen,\n isMobile,\n openMobile,\n setOpenMobile,\n toggleSidebar,\n }),\n [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar],\n );\n\n return (\n <SidebarContext.Provider value={contextValue}>\n <TooltipProvider delayDuration={0}>\n <div\n data-slot=\"sidebar-wrapper\"\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH,\n \"--sidebar-width-icon\": SIDEBAR_WIDTH_ICON,\n ...style,\n } as React.CSSProperties\n }\n className={cn(\"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full\", className)}\n {...props}\n >\n {children}\n </div>\n </TooltipProvider>\n </SidebarContext.Provider>\n );\n}\n\nfunction Sidebar({\n side = \"left\",\n variant = \"sidebar\",\n collapsible = \"offcanvas\",\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n side?: \"left\" | \"right\";\n variant?: \"sidebar\" | \"floating\" | \"inset\";\n collapsible?: \"offcanvas\" | \"icon\" | \"none\";\n}) {\n const { isMobile, state, openMobile, setOpenMobile } = useSidebar();\n\n if (collapsible === \"none\") {\n return (\n <div\n data-slot=\"sidebar\"\n className={cn(\"bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col\", className)}\n {...props}\n >\n {children}\n </div>\n );\n }\n\n if (isMobile) {\n return (\n <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>\n <SheetContent\n data-sidebar=\"sidebar\"\n data-slot=\"sidebar\"\n data-mobile=\"true\"\n className=\"bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden\"\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH_MOBILE,\n } as React.CSSProperties\n }\n side={side}\n >\n <SheetHeader className=\"sr-only\">\n <SheetTitle>Sidebar</SheetTitle>\n <SheetDescription>Displays the mobile sidebar.</SheetDescription>\n </SheetHeader>\n <div className=\"flex h-full w-full flex-col\">{children}</div>\n </SheetContent>\n </Sheet>\n );\n }\n\n return (\n <div\n className=\"group peer text-sidebar-foreground hidden md:block\"\n data-state={state}\n data-collapsible={state === \"collapsed\" ? collapsible : \"\"}\n data-variant={variant}\n data-side={side}\n data-slot=\"sidebar\"\n >\n {/* This is what handles the sidebar gap on desktop */}\n <div\n data-slot=\"sidebar-gap\"\n className={cn(\n \"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear\",\n \"group-data-[collapsible=offcanvas]:w-0\",\n \"group-data-[side=right]:rotate-180\",\n variant === \"floating\" || variant === \"inset\"\n ? \"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon)\",\n )}\n />\n <div\n data-slot=\"sidebar-container\"\n className={cn(\n \"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex\",\n side === \"left\"\n ? \"left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]\"\n : \"right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]\",\n // Adjust the padding for floating and inset variants.\n variant === \"floating\" || variant === \"inset\"\n ? \"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l\",\n className,\n )}\n {...props}\n >\n <div\n data-sidebar=\"sidebar\"\n data-slot=\"sidebar-inner\"\n className=\"bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm\"\n >\n {children}\n </div>\n </div>\n </div>\n );\n}\n\nfunction SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<typeof Button>) {\n const { toggleSidebar } = useSidebar();\n\n return (\n <Button\n data-sidebar=\"trigger\"\n data-slot=\"sidebar-trigger\"\n variant=\"ghost\"\n size=\"icon\"\n className={cn(\"size-7\", className)}\n onClick={(event) => {\n onClick?.(event);\n toggleSidebar();\n }}\n {...props}\n >\n <PanelLeftIcon />\n <span className=\"sr-only\">Toggle Sidebar</span>\n </Button>\n );\n}\n\nfunction SidebarRail({ className, ...props }: React.ComponentProps<\"button\">) {\n const { toggleSidebar } = useSidebar();\n\n return (\n <button\n data-sidebar=\"rail\"\n data-slot=\"sidebar-rail\"\n aria-label=\"Toggle Sidebar\"\n tabIndex={-1}\n onClick={toggleSidebar}\n title=\"Toggle Sidebar\"\n className={cn(\n \"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex\",\n \"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize\",\n \"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize\",\n \"hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full\",\n \"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2\",\n \"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarInset({ className, ...props }: React.ComponentProps<\"main\">) {\n return (\n <main\n data-slot=\"sidebar-inset\"\n className={cn(\n \"bg-background relative flex w-full flex-1 flex-col\",\n \"md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarInput({ className, ...props }: React.ComponentProps<typeof Input>) {\n return (\n <Input\n data-slot=\"sidebar-input\"\n data-sidebar=\"input\"\n className={cn(\"bg-background h-8 w-full shadow-none\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-header\"\n data-sidebar=\"header\"\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-footer\"\n data-sidebar=\"footer\"\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarSeparator({ className, ...props }: React.ComponentProps<typeof Separator>) {\n return (\n <Separator\n data-slot=\"sidebar-separator\"\n data-sidebar=\"separator\"\n className={cn(\"bg-sidebar-border mx-2 w-auto\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-content\"\n data-sidebar=\"content\"\n className={cn(\n \"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-group\"\n data-sidebar=\"group\"\n className={cn(\"relative flex w-full min-w-0 flex-col p-2\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarGroupLabel({\n className,\n asChild = false,\n ...props\n}: React.ComponentProps<\"div\"> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"div\";\n\n return (\n <Comp\n data-slot=\"sidebar-group-label\"\n data-sidebar=\"group-label\"\n className={cn(\n \"text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0\",\n \"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarGroupAction({\n className,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp\n data-slot=\"sidebar-group-action\"\n data-sidebar=\"group-action\"\n className={cn(\n \"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0\",\n // Increases the hit area of the button on mobile.\n \"after:absolute after:-inset-2 md:after:hidden\",\n \"group-data-[collapsible=icon]:hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarGroupContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-group-content\"\n data-sidebar=\"group-content\"\n className={cn(\"w-full text-sm\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarMenu({ className, ...props }: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"sidebar-menu\"\n data-sidebar=\"menu\"\n className={cn(\"flex w-full min-w-0 flex-col gap-1\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarMenuItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"sidebar-menu-item\"\n data-sidebar=\"menu-item\"\n className={cn(\"group/menu-item relative\", className)}\n {...props}\n />\n );\n}\n\nconst sidebarMenuButtonVariants = cva(\n \"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n outline:\n \"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]\",\n },\n size: {\n default: \"h-8 text-sm\",\n sm: \"h-7 text-xs\",\n lg: \"h-12 text-sm group-data-[collapsible=icon]:p-0!\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction SidebarMenuButton({\n asChild = false,\n isActive = false,\n variant = \"default\",\n size = \"default\",\n tooltip,\n className,\n ...props\n}: React.ComponentProps<\"button\"> & {\n asChild?: boolean;\n isActive?: boolean;\n tooltip?: string | React.ComponentProps<typeof TooltipContent>;\n} & VariantProps<typeof sidebarMenuButtonVariants>) {\n const Comp = asChild ? Slot : \"button\";\n const { isMobile, state } = useSidebar();\n\n const button = (\n <Comp\n data-slot=\"sidebar-menu-button\"\n data-sidebar=\"menu-button\"\n data-size={size}\n data-active={isActive}\n className={cn(sidebarMenuButtonVariants({ variant, size }), className)}\n {...props}\n />\n );\n\n if (!tooltip) {\n return button;\n }\n\n if (typeof tooltip === \"string\") {\n tooltip = {\n children: tooltip,\n };\n }\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent side=\"right\" align=\"center\" hidden={state !== \"collapsed\" || isMobile} {...tooltip} />\n </Tooltip>\n );\n}\n\nfunction SidebarMenuAction({\n className,\n asChild = false,\n showOnHover = false,\n ...props\n}: React.ComponentProps<\"button\"> & {\n asChild?: boolean;\n showOnHover?: boolean;\n}) {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp\n data-slot=\"sidebar-menu-action\"\n data-sidebar=\"menu-action\"\n className={cn(\n \"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0\",\n // Increases the hit area of the button on mobile.\n \"after:absolute after:-inset-2 md:after:hidden\",\n \"peer-data-[size=sm]/menu-button:top-1\",\n \"peer-data-[size=default]/menu-button:top-1.5\",\n \"peer-data-[size=lg]/menu-button:top-2.5\",\n \"group-data-[collapsible=icon]:hidden\",\n showOnHover &&\n \"peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarMenuBadge({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-menu-badge\"\n data-sidebar=\"menu-badge\"\n className={cn(\n \"text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none\",\n \"peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground\",\n \"peer-data-[size=sm]/menu-button:top-1\",\n \"peer-data-[size=default]/menu-button:top-1.5\",\n \"peer-data-[size=lg]/menu-button:top-2.5\",\n \"group-data-[collapsible=icon]:hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarMenuSkeleton({\n className,\n showIcon = false,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showIcon?: boolean;\n}) {\n // Random width between 50 to 90%.\n const width = React.useMemo(() => {\n return `${Math.floor(Math.random() * 40) + 50}%`;\n }, []);\n\n return (\n <div\n data-slot=\"sidebar-menu-skeleton\"\n data-sidebar=\"menu-skeleton\"\n className={cn(\"flex h-8 items-center gap-2 rounded-md px-2\", className)}\n {...props}\n >\n {showIcon && <Skeleton className=\"size-4 rounded-md\" data-sidebar=\"menu-skeleton-icon\" />}\n <Skeleton\n className=\"h-4 max-w-(--skeleton-width) flex-1\"\n data-sidebar=\"menu-skeleton-text\"\n style={\n {\n \"--skeleton-width\": width,\n } as React.CSSProperties\n }\n />\n </div>\n );\n}\n\nfunction SidebarMenuSub({ className, ...props }: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"sidebar-menu-sub\"\n data-sidebar=\"menu-sub\"\n className={cn(\n \"border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5\",\n \"group-data-[collapsible=icon]:hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarMenuSubItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"sidebar-menu-sub-item\"\n data-sidebar=\"menu-sub-item\"\n className={cn(\"group/menu-sub-item relative\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarMenuSubButton({\n asChild = false,\n size = \"md\",\n isActive = false,\n className,\n ...props\n}: React.ComponentProps<\"a\"> & {\n asChild?: boolean;\n size?: \"sm\" | \"md\";\n isActive?: boolean;\n}) {\n const Comp = asChild ? Slot : \"a\";\n\n return (\n <Comp\n data-slot=\"sidebar-menu-sub-button\"\n data-sidebar=\"menu-sub-button\"\n data-size={size}\n data-active={isActive}\n className={cn(\n \"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0\",\n \"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground\",\n size === \"sm\" && \"text-xs\",\n size === \"md\" && \"text-sm\",\n \"group-data-[collapsible=icon]:hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n Sidebar,\n SidebarContent,\n SidebarFooter,\n SidebarGroup,\n SidebarGroupAction,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarHeader,\n SidebarInput,\n SidebarInset,\n SidebarMenu,\n SidebarMenuAction,\n SidebarMenuBadge,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarMenuSkeleton,\n SidebarMenuSub,\n SidebarMenuSubButton,\n SidebarMenuSubItem,\n SidebarProvider,\n SidebarRail,\n SidebarSeparator,\n SidebarTrigger,\n useSidebar,\n};\n","import { cn } from \"../../utils/cn\"\n\nfunction Skeleton({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"skeleton\"\n className={cn(\"bg-accent animate-pulse rounded-md\", className)}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\"\n\nimport { cn } from \"../../utils/cn\"\n\nfunction TooltipProvider({\n delayDuration = 0,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delayDuration={delayDuration}\n {...props}\n />\n )\n}\n\nfunction Tooltip({\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Root>) {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n )\n}\n\nfunction TooltipTrigger({\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />\n}\n\nfunction TooltipContent({\n className,\n sideOffset = 0,\n children,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Content>) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n \"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance\",\n className\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]\" />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n )\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n","\"use client\";\n\nimport * as SliderPrimitive from \"@radix-ui/react-slider\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Slider = React.forwardRef<\n React.ElementRef<typeof SliderPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <SliderPrimitive.Root\n ref={ref}\n className={cn(\"relative flex w-full touch-none select-none items-center\", className)}\n {...props}\n >\n <SliderPrimitive.Track className=\"relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20\">\n <SliderPrimitive.Range className=\"absolute h-full bg-primary\" />\n </SliderPrimitive.Track>\n <SliderPrimitive.Thumb className=\"block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50\" />\n </SliderPrimitive.Root>\n));\nSlider.displayName = SliderPrimitive.Root.displayName;\n\nexport { Slider };\n","\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, ToasterProps } from \"sonner\"\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n style={\n {\n \"--normal-bg\": \"var(--popover)\",\n \"--normal-text\": \"var(--popover-foreground)\",\n \"--normal-border\": \"var(--border)\",\n } as React.CSSProperties\n }\n {...props}\n />\n )\n}\n\nexport { Toaster }\n","\"use client\";\n\nimport * as SwitchPrimitives from \"@radix-ui/react-switch\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitives.Root>,\n React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>\n>(({ className, children, ...props }, ref) => (\n <SwitchPrimitives.Root\n className={cn(\n \"bg-accent focus-visible:ring-ring focus-visible:ring-offset-background data-[state=checked]:bg-primary data-[state=unchecked]:bg-accent peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n ref={ref}\n >\n <SwitchPrimitives.Thumb\n className={cn(\n \"text-title pointer-events-none block flex h-5 w-5 items-center justify-center rounded-full bg-white shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0\",\n )}\n >\n {children}\n </SwitchPrimitives.Thumb>\n </SwitchPrimitives.Root>\n));\nSwitch.displayName = SwitchPrimitives.Root.displayName;\n\nexport { Switch };\n","import * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement>\n>(({ className, ...props }, ref) => (\n <div className=\"relative w-full overflow-auto\">\n <table\n ref={ref}\n className={cn(\"w-full caption-bottom text-sm\", className)}\n {...props}\n />\n </div>\n));\nTable.displayName = \"Table\";\n\nconst TableHeader = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <thead ref={ref} className={cn(\"[&_tr]:border-b\", className)} {...props} />\n));\nTableHeader.displayName = \"TableHeader\";\n\nconst TableBody = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tbody\n ref={ref}\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n));\nTableBody.displayName = \"TableBody\";\n\nconst TableFooter = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n className,\n )}\n {...props}\n />\n));\nTableFooter.displayName = \"TableFooter\";\n\nconst TableRow = React.forwardRef<\n HTMLTableRowElement,\n React.HTMLAttributes<HTMLTableRowElement>\n>(({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\n \"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted\",\n className,\n )}\n {...props}\n />\n));\nTableRow.displayName = \"TableRow\";\n\nconst TableHead = React.forwardRef<\n HTMLTableCellElement,\n React.ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n \"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]\",\n className,\n )}\n {...props}\n />\n));\nTableHead.displayName = \"TableHead\";\n\nconst TableCell = React.forwardRef<\n HTMLTableCellElement,\n React.TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <td\n ref={ref}\n className={cn(\n \"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]\",\n className,\n )}\n {...props}\n />\n));\nTableCell.displayName = \"TableCell\";\n\nconst TableCaption = React.forwardRef<\n HTMLTableCaptionElement,\n React.HTMLAttributes<HTMLTableCaptionElement>\n>(({ className, ...props }, ref) => (\n <caption\n ref={ref}\n className={cn(\"mt-4 text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nTableCaption.displayName = \"TableCaption\";\n\nexport {\n Table,\n TableBody,\n TableCaption,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n};\n","\"use client\";\n\nimport * as TabsPrimitive from \"@radix-ui/react-tabs\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Tabs = TabsPrimitive.Root;\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.List\n ref={ref}\n className={cn(\n \"inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground\",\n className,\n )}\n {...props}\n />\n));\nTabsList.displayName = TabsPrimitive.List.displayName;\n\nconst TabsTrigger = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\n \"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow\",\n className,\n )}\n {...props}\n />\n));\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName;\n\nconst TabsContent = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n \"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n className,\n )}\n {...props}\n />\n));\nTabsContent.displayName = TabsPrimitive.Content.displayName;\n\nexport { Tabs, TabsContent, TabsList, TabsTrigger };\n","import * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n \"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n },\n);\nTextarea.displayName = \"Textarea\";\n\nexport { Textarea };\n","\"use client\";\n\nimport * as TogglePrimitive from \"@radix-ui/react-toggle\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst toggleVariants = cva(\n \"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n outline: \"border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground\",\n },\n size: {\n default: \"h-9 px-2 min-w-9\",\n sm: \"h-8 px-1.5 min-w-8\",\n lg: \"h-10 px-2.5 min-w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nconst Toggle = React.forwardRef<\n React.ElementRef<typeof TogglePrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>\n>(({ className, variant, size, ...props }, ref) => (\n <TogglePrimitive.Root ref={ref} className={cn(toggleVariants({ variant, size, className }))} {...props} />\n));\n\nToggle.displayName = TogglePrimitive.Root.displayName;\n\nexport { Toggle, toggleVariants };\n","\"use client\";\n\nimport {\n type Announcements,\n type CollisionDetection,\n DndContext,\n type DndContextProps,\n type DragCancelEvent,\n type DragEndEvent,\n type DragOverEvent,\n DragOverlay,\n type DragStartEvent,\n type DraggableAttributes,\n type DraggableSyntheticListeners,\n type DropAnimation,\n type DroppableContainer,\n KeyboardCode,\n type KeyboardCoordinateGetter,\n KeyboardSensor,\n MeasuringStrategy,\n MouseSensor,\n TouchSensor,\n type UniqueIdentifier,\n closestCenter,\n closestCorners,\n defaultDropAnimationSideEffects,\n getFirstCollision,\n pointerWithin,\n rectIntersection,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport {\n type AnimateLayoutChanges,\n SortableContext,\n type SortableContextProps,\n arrayMove,\n defaultAnimateLayoutChanges,\n horizontalListSortingStrategy,\n useSortable,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport * as ReactDOM from \"react-dom\";\n\nimport { useComposedRefs } from \"../../utils/compose-refs\";\nimport { cn } from \"../../utils/cn\";\n\nconst directions: string[] = [KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left];\n\nconst coordinateGetter: KeyboardCoordinateGetter = (event, { context }) => {\n const { active, droppableRects, droppableContainers, collisionRect } = context;\n\n if (directions.includes(event.code)) {\n event.preventDefault();\n\n if (!active || !collisionRect) return;\n\n const filteredContainers: DroppableContainer[] = [];\n\n for (const entry of droppableContainers.getEnabled()) {\n if (!entry || entry?.disabled) return;\n\n const rect = droppableRects.get(entry.id);\n\n if (!rect) return;\n\n const data = entry.data.current;\n\n if (data) {\n const { type, children } = data;\n\n if (type === \"container\" && children?.length > 0) {\n if (active.data.current?.type !== \"container\") {\n return;\n }\n }\n }\n\n switch (event.code) {\n case KeyboardCode.Down:\n if (collisionRect.top < rect.top) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Up:\n if (collisionRect.top > rect.top) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Left:\n if (collisionRect.left >= rect.left + rect.width) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Right:\n if (collisionRect.left + collisionRect.width <= rect.left) {\n filteredContainers.push(entry);\n }\n break;\n }\n }\n\n const collisions = closestCorners({\n active,\n collisionRect: collisionRect,\n droppableRects,\n droppableContainers: filteredContainers,\n pointerCoordinates: null,\n });\n const closestId = getFirstCollision(collisions, \"id\");\n\n if (closestId != null) {\n const newDroppable = droppableContainers.get(closestId);\n const newNode = newDroppable?.node.current;\n const newRect = newDroppable?.rect.current;\n\n if (newNode && newRect) {\n if (newDroppable.id === \"placeholder\") {\n return {\n x: newRect.left + (newRect.width - collisionRect.width) / 2,\n y: newRect.top + (newRect.height - collisionRect.height) / 2,\n };\n }\n\n if (newDroppable.data.current?.type === \"container\") {\n return {\n x: newRect.left + 20,\n y: newRect.top + 74,\n };\n }\n\n return {\n x: newRect.left,\n y: newRect.top,\n };\n }\n }\n }\n\n return undefined;\n};\n\nconst ROOT_NAME = \"Kanban\";\nconst BOARD_NAME = \"KanbanBoard\";\nconst COLUMN_NAME = \"KanbanColumn\";\nconst COLUMN_HANDLE_NAME = \"KanbanColumnHandle\";\nconst ITEM_NAME = \"KanbanItem\";\nconst ITEM_HANDLE_NAME = \"KanbanItemHandle\";\nconst OVERLAY_NAME = \"KanbanOverlay\";\n\ninterface KanbanContextValue<T> {\n id: string;\n items: Record<UniqueIdentifier, T[]>;\n modifiers: DndContextProps[\"modifiers\"];\n strategy: SortableContextProps[\"strategy\"];\n orientation: \"horizontal\" | \"vertical\";\n activeId: UniqueIdentifier | null;\n setActiveId: (id: UniqueIdentifier | null) => void;\n getItemValue: (item: T) => UniqueIdentifier;\n flatCursor: boolean;\n}\n\nconst KanbanContext = React.createContext<KanbanContextValue<unknown> | null>(null);\nKanbanContext.displayName = ROOT_NAME;\n\nfunction useKanbanContext(consumerName: string) {\n const context = React.useContext(KanbanContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` must be used within \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\ninterface GetItemValue<T> {\n /**\n * Callback that returns a unique identifier for each kanban item. Required for array of objects.\n * @example getItemValue={(item) => item.id}\n */\n getItemValue: (item: T) => UniqueIdentifier;\n}\n\ntype KanbanRootProps<T> = Omit<DndContextProps, \"collisionDetection\"> &\n GetItemValue<T> & {\n value: Record<UniqueIdentifier, T[]>;\n onValueChange?: (columns: Record<UniqueIdentifier, T[]>) => void;\n onMove?: (event: DragEndEvent & { activeIndex: number; overIndex: number }) => void;\n strategy?: SortableContextProps[\"strategy\"];\n orientation?: \"horizontal\" | \"vertical\";\n flatCursor?: boolean;\n } & (T extends object ? GetItemValue<T> : Partial<GetItemValue<T>>);\n\nfunction KanbanRoot<T>(props: KanbanRootProps<T>) {\n const {\n value,\n onValueChange,\n modifiers,\n strategy = verticalListSortingStrategy,\n orientation = \"horizontal\",\n onMove,\n getItemValue: getItemValueProp,\n accessibility,\n flatCursor = false,\n ...kanbanProps\n } = props;\n\n const id = React.useId();\n const [activeId, setActiveId] = React.useState<UniqueIdentifier | null>(null);\n const lastOverIdRef = React.useRef<UniqueIdentifier | null>(null);\n const hasMovedRef = React.useRef(false);\n const sensors = useSensors(\n useSensor(MouseSensor),\n useSensor(TouchSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter,\n }),\n );\n\n const getItemValue = React.useCallback(\n (item: T): UniqueIdentifier => {\n if (typeof item === \"object\" && !getItemValueProp) {\n throw new Error(\"getItemValue is required when using array of objects\");\n }\n return getItemValueProp ? getItemValueProp(item) : (item as UniqueIdentifier);\n },\n [getItemValueProp],\n );\n\n const getColumn = React.useCallback(\n (id: UniqueIdentifier) => {\n if (id in value) return id;\n\n for (const [columnId, items] of Object.entries(value)) {\n if (items.some((item) => getItemValue(item) === id)) {\n return columnId;\n }\n }\n\n return null;\n },\n [value, getItemValue],\n );\n\n const collisionDetection: CollisionDetection = React.useCallback(\n (args) => {\n if (activeId && activeId in value) {\n return closestCenter({\n ...args,\n droppableContainers: args.droppableContainers.filter((container) => container.id in value),\n });\n }\n\n const pointerIntersections = pointerWithin(args);\n const intersections = pointerIntersections.length > 0 ? pointerIntersections : rectIntersection(args);\n let overId = getFirstCollision(intersections, \"id\");\n\n if (!overId) {\n if (hasMovedRef.current) {\n lastOverIdRef.current = activeId;\n }\n return lastOverIdRef.current ? [{ id: lastOverIdRef.current }] : [];\n }\n\n if (overId in value) {\n const containerItems = value[overId];\n if (containerItems && containerItems.length > 0) {\n const closestItem = closestCenter({\n ...args,\n droppableContainers: args.droppableContainers.filter(\n (container) =>\n container.id !== overId && containerItems.some((item) => getItemValue(item) === container.id),\n ),\n });\n\n if (closestItem.length > 0) {\n overId = closestItem[0]?.id ?? overId;\n }\n }\n }\n\n lastOverIdRef.current = overId;\n return [{ id: overId }];\n },\n [activeId, value, getItemValue],\n );\n\n const onDragStart = React.useCallback(\n (event: DragStartEvent) => {\n kanbanProps.onDragStart?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n setActiveId(event.active.id);\n },\n [kanbanProps.onDragStart],\n );\n\n const onDragOver = React.useCallback(\n (event: DragOverEvent) => {\n kanbanProps.onDragOver?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n\n const { active, over } = event;\n if (!over) return;\n\n const activeColumn = getColumn(active.id);\n const overColumn = getColumn(over.id);\n\n if (!activeColumn || !overColumn) return;\n\n if (activeColumn === overColumn) {\n const items = value[activeColumn];\n if (!items) return;\n\n const activeIndex = items.findIndex((item) => getItemValue(item) === active.id);\n const overIndex = items.findIndex((item) => getItemValue(item) === over.id);\n\n if (activeIndex !== overIndex) {\n const newColumns = { ...value };\n newColumns[activeColumn] = arrayMove(items, activeIndex, overIndex);\n onValueChange?.(newColumns);\n }\n } else {\n const activeItems = value[activeColumn];\n const overItems = value[overColumn];\n\n if (!activeItems || !overItems) return;\n\n const activeIndex = activeItems.findIndex((item) => getItemValue(item) === active.id);\n\n if (activeIndex === -1) return;\n\n const activeItem = activeItems[activeIndex];\n if (!activeItem) return;\n\n const updatedItems = {\n ...value,\n [activeColumn]: activeItems.filter((item) => getItemValue(item) !== active.id),\n [overColumn]: [...overItems, activeItem],\n };\n\n onValueChange?.(updatedItems);\n hasMovedRef.current = true;\n }\n },\n [value, getColumn, getItemValue, onValueChange, kanbanProps.onDragOver],\n );\n\n const onDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n kanbanProps.onDragEnd?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n\n const { active, over } = event;\n\n if (!over) {\n setActiveId(null);\n return;\n }\n\n if (active.id in value && over.id in value) {\n const activeIndex = Object.keys(value).indexOf(active.id as string);\n const overIndex = Object.keys(value).indexOf(over.id as string);\n\n if (activeIndex !== overIndex) {\n const orderedColumns = Object.keys(value);\n const newOrder = arrayMove(orderedColumns, activeIndex, overIndex);\n\n const newColumns: Record<UniqueIdentifier, T[]> = {};\n for (const key of newOrder) {\n const items = value[key];\n if (items) {\n newColumns[key] = items;\n }\n }\n\n if (onMove) {\n onMove({ ...event, activeIndex, overIndex });\n } else {\n onValueChange?.(newColumns);\n }\n }\n } else {\n const activeColumn = getColumn(active.id);\n const overColumn = getColumn(over.id);\n\n if (!activeColumn || !overColumn) {\n setActiveId(null);\n return;\n }\n\n if (activeColumn === overColumn) {\n const items = value[activeColumn];\n if (!items) {\n setActiveId(null);\n return;\n }\n\n const activeIndex = items.findIndex((item) => getItemValue(item) === active.id);\n const overIndex = items.findIndex((item) => getItemValue(item) === over.id);\n\n if (activeIndex !== overIndex) {\n const newColumns = { ...value };\n newColumns[activeColumn] = arrayMove(items, activeIndex, overIndex);\n if (onMove) {\n onMove({\n ...event,\n activeIndex,\n overIndex,\n });\n } else {\n onValueChange?.(newColumns);\n }\n }\n }\n }\n\n setActiveId(null);\n hasMovedRef.current = false;\n },\n [value, getColumn, getItemValue, onValueChange, onMove, kanbanProps.onDragEnd],\n );\n\n const onDragCancel = React.useCallback(\n (event: DragCancelEvent) => {\n kanbanProps.onDragCancel?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n\n setActiveId(null);\n hasMovedRef.current = false;\n },\n [kanbanProps.onDragCancel],\n );\n\n const announcements: Announcements = React.useMemo(\n () => ({\n onDragStart({ active }) {\n const isColumn = active.id in value;\n const itemType = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(active.id as string) + 1\n : (() => {\n const column = getColumn(active.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === active.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(active.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n return `Picked up ${itemType} at position ${position} of ${total}`;\n },\n onDragOver({ active, over }) {\n if (!over) return;\n\n const isColumn = active.id in value;\n const itemType = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(over.id as string) + 1\n : (() => {\n const column = getColumn(over.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === over.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(over.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n const overColumn = getColumn(over.id);\n const activeColumn = getColumn(active.id);\n\n if (isColumn) {\n return `${itemType} is now at position ${position} of ${total}`;\n }\n\n if (activeColumn !== overColumn) {\n return `${itemType} is now at position ${position} of ${total} in ${overColumn}`;\n }\n\n return `${itemType} is now at position ${position} of ${total}`;\n },\n onDragEnd({ active, over }) {\n if (!over) return;\n\n const isColumn = active.id in value;\n const itemType = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(over.id as string) + 1\n : (() => {\n const column = getColumn(over.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === over.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(over.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n const overColumn = getColumn(over.id);\n const activeColumn = getColumn(active.id);\n\n if (isColumn) {\n return `${itemType} was dropped at position ${position} of ${total}`;\n }\n\n if (activeColumn !== overColumn) {\n return `${itemType} was dropped at position ${position} of ${total} in ${overColumn}`;\n }\n\n return `${itemType} was dropped at position ${position} of ${total}`;\n },\n onDragCancel({ active }) {\n const isColumn = active.id in value;\n const itemType = isColumn ? \"column\" : \"item\";\n return `Dragging was cancelled. ${itemType} was dropped.`;\n },\n }),\n [value, getColumn, getItemValue],\n );\n\n const contextValue = React.useMemo<KanbanContextValue<T>>(\n () => ({\n id,\n items: value,\n modifiers,\n strategy,\n orientation,\n activeId,\n setActiveId,\n getItemValue,\n flatCursor,\n }),\n [id, value, activeId, modifiers, strategy, orientation, getItemValue, flatCursor],\n );\n\n return (\n <KanbanContext.Provider value={contextValue as KanbanContextValue<unknown>}>\n <DndContext\n collisionDetection={collisionDetection}\n modifiers={modifiers}\n sensors={sensors}\n {...kanbanProps}\n id={id}\n measuring={{\n droppable: {\n strategy: MeasuringStrategy.Always,\n },\n }}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDragEnd={onDragEnd}\n onDragCancel={onDragCancel}\n accessibility={{\n announcements,\n screenReaderInstructions: {\n draggable: `\n To pick up a kanban item or column, press space or enter.\n While dragging, use the arrow keys to move the item.\n Press space or enter again to drop the item in its new position, or press escape to cancel.\n `,\n },\n ...accessibility,\n }}\n />\n </KanbanContext.Provider>\n );\n}\n\nconst KanbanBoardContext = React.createContext<boolean>(false);\nKanbanBoardContext.displayName = BOARD_NAME;\n\ninterface KanbanBoardProps extends React.ComponentPropsWithoutRef<\"div\"> {\n children: React.ReactNode;\n asChild?: boolean;\n}\n\nconst KanbanBoard = React.forwardRef<HTMLDivElement, KanbanBoardProps>((props, forwardedRef) => {\n const { asChild, className, ...boardProps } = props;\n\n const context = useKanbanContext(BOARD_NAME);\n\n const columns = React.useMemo(() => {\n return Object.keys(context.items);\n }, [context.items]);\n\n const BoardPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanBoardContext.Provider value={true}>\n <SortableContext\n items={columns}\n strategy={context.orientation === \"horizontal\" ? horizontalListSortingStrategy : verticalListSortingStrategy}\n >\n <BoardPrimitive\n aria-orientation={context.orientation}\n data-orientation={context.orientation}\n data-slot=\"kanban-board\"\n {...boardProps}\n ref={forwardedRef}\n className={cn(\n \"flex size-full gap-4\",\n context.orientation === \"horizontal\" ? \"flex-row\" : \"flex-col\",\n className,\n )}\n />\n </SortableContext>\n </KanbanBoardContext.Provider>\n );\n});\nKanbanBoard.displayName = BOARD_NAME;\n\ninterface KanbanColumnContextValue {\n id: string;\n attributes: DraggableAttributes;\n listeners: DraggableSyntheticListeners | undefined;\n setActivatorNodeRef: (node: HTMLElement | null) => void;\n isDragging?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanColumnContext = React.createContext<KanbanColumnContextValue | null>(null);\nKanbanColumnContext.displayName = COLUMN_NAME;\n\nfunction useKanbanColumnContext(consumerName: string) {\n const context = React.useContext(KanbanColumnContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` must be used within \\`${COLUMN_NAME}\\``);\n }\n return context;\n}\n\nconst animateLayoutChanges: AnimateLayoutChanges = (args) =>\n defaultAnimateLayoutChanges({ ...args, wasDragging: true });\n\ninterface KanbanColumnProps extends React.ComponentPropsWithoutRef<\"div\"> {\n value: UniqueIdentifier;\n children: React.ReactNode;\n asChild?: boolean;\n asHandle?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanColumn = React.forwardRef<HTMLDivElement, KanbanColumnProps>((props, forwardedRef) => {\n const { value, asChild, asHandle, disabled, className, style, ...columnProps } = props;\n\n const id = React.useId();\n const context = useKanbanContext(COLUMN_NAME);\n const inBoard = React.useContext(KanbanBoardContext);\n const inOverlay = React.useContext(KanbanOverlayContext);\n\n if (!inBoard && !inOverlay) {\n throw new Error(`\\`${COLUMN_NAME}\\` must be used within \\`${BOARD_NAME}\\` or \\`${OVERLAY_NAME}\\``);\n }\n\n if (value === \"\") {\n throw new Error(`\\`${COLUMN_NAME}\\` value cannot be an empty string`);\n }\n\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n disabled,\n animateLayoutChanges,\n });\n\n const composedRef = useComposedRefs(forwardedRef, (node) => {\n if (disabled) return;\n setNodeRef(node);\n });\n\n const composedStyle = React.useMemo<React.CSSProperties>(() => {\n return {\n transform: CSS.Transform.toString(transform),\n transition,\n ...style,\n };\n }, [transform, transition, style]);\n\n const items = React.useMemo(() => {\n const items = context.items[value] ?? [];\n return items.map((item) => context.getItemValue(item));\n }, [context.items, value, context.getItemValue]);\n\n const columnContext = React.useMemo<KanbanColumnContextValue>(\n () => ({\n id,\n attributes,\n listeners,\n setActivatorNodeRef,\n isDragging,\n disabled,\n }),\n [id, attributes, listeners, setActivatorNodeRef, isDragging, disabled],\n );\n\n const ColumnPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanColumnContext.Provider value={columnContext}>\n <SortableContext\n items={items}\n strategy={context.orientation === \"horizontal\" ? horizontalListSortingStrategy : verticalListSortingStrategy}\n >\n <ColumnPrimitive\n id={id}\n data-disabled={disabled}\n data-dragging={isDragging ? \"\" : undefined}\n data-slot=\"kanban-column\"\n {...columnProps}\n {...(asHandle && !disabled ? attributes : {})}\n {...(asHandle && !disabled ? listeners : {})}\n ref={composedRef}\n style={composedStyle}\n className={cn(\n \"flex size-full w-full flex-col gap-2 rounded-lg border bg-zinc-100 p-2.5 aria-disabled:pointer-events-none aria-disabled:opacity-50 dark:bg-zinc-900\",\n {\n \"touch-none select-none\": asHandle,\n \"cursor-default\": context.flatCursor,\n \"data-dragging:cursor-grabbing\": !context.flatCursor,\n \"cursor-grab\": !isDragging && asHandle && !context.flatCursor,\n \"opacity-50\": isDragging,\n \"pointer-events-none opacity-50\": disabled,\n },\n className,\n )}\n />\n </SortableContext>\n </KanbanColumnContext.Provider>\n );\n});\nKanbanColumn.displayName = COLUMN_NAME;\n\ninterface KanbanColumnHandleProps extends React.ComponentPropsWithoutRef<\"button\"> {\n asChild?: boolean;\n}\n\nconst KanbanColumnHandle = React.forwardRef<HTMLButtonElement, KanbanColumnHandleProps>((props, forwardedRef) => {\n const { asChild, disabled, className, ...columnHandleProps } = props;\n\n const context = useKanbanContext(COLUMN_NAME);\n const columnContext = useKanbanColumnContext(COLUMN_HANDLE_NAME);\n\n const isDisabled = disabled ?? columnContext.disabled;\n\n const composedRef = useComposedRefs(forwardedRef, (node) => {\n if (isDisabled) return;\n columnContext.setActivatorNodeRef(node);\n });\n\n const HandlePrimitive = asChild ? Slot : \"button\";\n\n return (\n <HandlePrimitive\n type=\"button\"\n aria-controls={columnContext.id}\n data-disabled={isDisabled}\n data-dragging={columnContext.isDragging ? \"\" : undefined}\n data-slot=\"kanban-column-handle\"\n {...columnHandleProps}\n {...(isDisabled ? {} : columnContext.attributes)}\n {...(isDisabled ? {} : columnContext.listeners)}\n ref={composedRef}\n className={cn(\n \"select-none disabled:pointer-events-none disabled:opacity-50\",\n context.flatCursor ? \"cursor-default\" : \"cursor-grab data-dragging:cursor-grabbing\",\n className,\n )}\n disabled={isDisabled}\n />\n );\n});\nKanbanColumnHandle.displayName = COLUMN_HANDLE_NAME;\n\ninterface KanbanItemContextValue {\n id: string;\n attributes: DraggableAttributes;\n listeners: DraggableSyntheticListeners | undefined;\n setActivatorNodeRef: (node: HTMLElement | null) => void;\n isDragging?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanItemContext = React.createContext<KanbanItemContextValue | null>(null);\nKanbanItemContext.displayName = ITEM_NAME;\n\nfunction useKanbanItemContext(consumerName: string) {\n const context = React.useContext(KanbanItemContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` must be used within \\`${ITEM_NAME}\\``);\n }\n return context;\n}\n\ninterface KanbanItemProps extends React.ComponentPropsWithoutRef<\"div\"> {\n value: UniqueIdentifier;\n asHandle?: boolean;\n asChild?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanItem = React.forwardRef<HTMLDivElement, KanbanItemProps>((props, forwardedRef) => {\n const { value, style, asHandle, asChild, disabled, className, ...itemProps } = props;\n\n const id = React.useId();\n const context = useKanbanContext(ITEM_NAME);\n const inBoard = React.useContext(KanbanBoardContext);\n const inOverlay = React.useContext(KanbanOverlayContext);\n\n if (!inBoard && !inOverlay) {\n throw new Error(`\\`${ITEM_NAME}\\` must be used within \\`${BOARD_NAME}\\``);\n }\n\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n disabled,\n });\n\n if (value === \"\") {\n throw new Error(`\\`${ITEM_NAME}\\` value cannot be an empty string`);\n }\n\n const composedRef = useComposedRefs(forwardedRef, (node) => {\n if (disabled) return;\n setNodeRef(node);\n });\n\n const composedStyle = React.useMemo<React.CSSProperties>(() => {\n return {\n transform: CSS.Transform.toString(transform),\n transition,\n ...style,\n };\n }, [transform, transition, style]);\n\n const itemContext = React.useMemo<KanbanItemContextValue>(\n () => ({\n id,\n attributes,\n listeners,\n setActivatorNodeRef,\n isDragging,\n disabled,\n }),\n [id, attributes, listeners, setActivatorNodeRef, isDragging, disabled],\n );\n\n const ItemPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanItemContext.Provider value={itemContext}>\n <ItemPrimitive\n id={id}\n data-disabled={disabled}\n data-dragging={isDragging ? \"\" : undefined}\n data-slot=\"kanban-item\"\n {...itemProps}\n {...(asHandle && !disabled ? attributes : {})}\n {...(asHandle && !disabled ? listeners : {})}\n ref={composedRef}\n style={composedStyle}\n className={cn(\n \"focus-visible:ring-ring focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden\",\n {\n \"touch-none select-none\": asHandle,\n \"cursor-default\": context.flatCursor,\n \"data-dragging:cursor-grabbing\": !context.flatCursor,\n \"cursor-grab\": !isDragging && asHandle && !context.flatCursor,\n \"opacity-50\": isDragging,\n \"pointer-events-none opacity-50\": disabled,\n },\n className,\n )}\n />\n </KanbanItemContext.Provider>\n );\n});\nKanbanItem.displayName = ITEM_NAME;\n\ninterface KanbanItemHandleProps extends React.ComponentPropsWithoutRef<\"button\"> {\n asChild?: boolean;\n}\n\nconst KanbanItemHandle = React.forwardRef<HTMLButtonElement, KanbanItemHandleProps>((props, forwardedRef) => {\n const { asChild, disabled, className, ...itemHandleProps } = props;\n\n const context = useKanbanContext(ITEM_HANDLE_NAME);\n const itemContext = useKanbanItemContext(ITEM_HANDLE_NAME);\n\n const isDisabled = disabled ?? itemContext.disabled;\n\n const composedRef = useComposedRefs(forwardedRef, (node) => {\n if (isDisabled) return;\n itemContext.setActivatorNodeRef(node);\n });\n\n const HandlePrimitive = asChild ? Slot : \"button\";\n\n return (\n <HandlePrimitive\n type=\"button\"\n aria-controls={itemContext.id}\n data-disabled={isDisabled}\n data-dragging={itemContext.isDragging ? \"\" : undefined}\n data-slot=\"kanban-item-handle\"\n {...itemHandleProps}\n {...(isDisabled ? {} : itemContext.attributes)}\n {...(isDisabled ? {} : itemContext.listeners)}\n ref={composedRef}\n className={cn(\n \"select-none disabled:pointer-events-none disabled:opacity-50\",\n context.flatCursor ? \"cursor-default\" : \"cursor-grab data-dragging:cursor-grabbing\",\n className,\n )}\n disabled={isDisabled}\n />\n );\n});\nKanbanItemHandle.displayName = ITEM_HANDLE_NAME;\n\nconst KanbanOverlayContext = React.createContext(false);\nKanbanOverlayContext.displayName = OVERLAY_NAME;\n\nconst dropAnimation: DropAnimation = {\n sideEffects: defaultDropAnimationSideEffects({\n styles: {\n active: {\n opacity: \"0.4\",\n },\n },\n }),\n};\n\ninterface KanbanOverlayProps extends Omit<React.ComponentPropsWithoutRef<typeof DragOverlay>, \"children\"> {\n container?: Element | DocumentFragment | null;\n children?: ((params: { value: UniqueIdentifier; variant: \"column\" | \"item\" }) => React.ReactNode) | React.ReactNode;\n}\n\nfunction KanbanOverlay(props: KanbanOverlayProps) {\n const { container: containerProp, children, ...overlayProps } = props;\n\n const context = useKanbanContext(OVERLAY_NAME);\n\n const [mounted, setMounted] = React.useState(false);\n React.useLayoutEffect(() => setMounted(true), []);\n\n const container = containerProp ?? (mounted ? globalThis.document?.body : null);\n\n if (!container) return null;\n\n const variant = context.activeId && context.activeId in context.items ? \"column\" : \"item\";\n\n return ReactDOM.createPortal(\n <DragOverlay\n dropAnimation={dropAnimation}\n modifiers={context.modifiers}\n className={cn(!context.flatCursor && \"cursor-grabbing\")}\n {...overlayProps}\n >\n <KanbanOverlayContext.Provider value={true}>\n {context.activeId && children\n ? typeof children === \"function\"\n ? children({\n value: context.activeId,\n variant,\n })\n : children\n : null}\n </KanbanOverlayContext.Provider>\n </DragOverlay>,\n container,\n );\n}\n\nexport {\n KanbanBoard as Board,\n KanbanColumn as Column,\n KanbanColumnHandle as ColumnHandle,\n KanbanItem as Item,\n KanbanItemHandle as ItemHandle,\n KanbanRoot as Kanban,\n KanbanBoard,\n KanbanColumn,\n KanbanColumnHandle,\n KanbanItem,\n KanbanItemHandle,\n KanbanOverlay,\n KanbanOverlay as Overlay,\n //\n KanbanRoot as Root,\n};\n","\"use client\";\n\nimport NextLink from \"next/link\";\nimport { cn } from \"../../utils/cn\";\nimport * as React from \"react\";\n\n// Create our custom Link props interface that extends Next.js Link\nexport interface LinkProps extends React.ComponentPropsWithoutRef<typeof NextLink> {\n className?: string;\n}\n\nconst Link = React.forwardRef<HTMLAnchorElement, LinkProps>(({ className, ...props }, ref) => {\n return <NextLink ref={ref} className={cn(`font-medium`, className)} {...props} />;\n});\n\nLink.displayName = \"Link\";\n\nexport { Link };\n","\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { CheckIcon, ChevronDown, WandSparkles, XCircle, XIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Badge } from \"../ui/badge\";\nimport { Button } from \"../ui/button\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n} from \"../ui/command\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/popover\";\nimport { Separator } from \"../ui/separator\";\nimport { cn } from \"../../utils/cn\";\n\n/**\n * Variants for the multi-select component to handle different styles.\n * Uses class-variance-authority (cva) to define different styles based on \"variant\" prop.\n */\nconst multiSelectVariants = cva(\n \"m-1 transition ease-in-out delay-150 hover:-translate-y-1 hover:scale-110 duration-300\",\n {\n variants: {\n variant: {\n default: \"border-foreground/10 text-foreground bg-card hover:bg-card/80\",\n secondary: \"border-foreground/10 bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n destructive: \"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80\",\n inverted: \"inverted\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\n/**\n * Props for MultiSelect component\n */\ninterface MultiSelectProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof multiSelectVariants> {\n /**\n * An array of option objects to be displayed in the multi-select component.\n * Each option object has a label, value, and an optional icon.\n */\n options: {\n /** The text to display for the option. */\n label: string;\n /** The unique value associated with the option. */\n value: string;\n /** Optional icon component to display alongside the option. */\n icon?: React.ComponentType<{ className?: string }>;\n }[];\n\n /**\n * Callback function triggered when the selected values change.\n * Receives an array of the new selected values.\n */\n onValueChange: (value: string[]) => void;\n\n /** The default selected values when the component mounts. */\n defaultValue?: string[];\n\n /**\n * The controlled value for the component. When provided, the component\n * will be controlled rather than using internal state.\n */\n value?: string[];\n\n /**\n * Placeholder text to be displayed when no values are selected.\n * Optional, defaults to \"Select options\".\n */\n placeholder?: string;\n\n /**\n * Animation duration in seconds for the visual effects (e.g., bouncing badges).\n * Optional, defaults to 0 (no animation).\n */\n animation?: number;\n\n /**\n * Maximum number of items to display. Extra selected items will be summarized.\n * Optional, defaults to 3.\n */\n maxCount?: number;\n\n /**\n * The modality of the popover. When set to true, interaction with outside elements\n * will be disabled and only popover content will be visible to screen readers.\n * Optional, defaults to false.\n */\n modalPopover?: boolean;\n\n /**\n * If true, renders the multi-select component as a child of another component.\n * Optional, defaults to false.\n */\n asChild?: boolean;\n\n /**\n * Additional class names to apply custom styles to the multi-select component.\n * Optional, can be used to add custom styles.\n */\n className?: string;\n\n /**\n * Callback function triggered when the search input value changes.\n * Optional, receives the search string.\n */\n onSearchChange?: (search: string) => void;\n}\n\nexport const MultiSelect = React.forwardRef<HTMLButtonElement, MultiSelectProps>(\n (\n {\n options,\n onValueChange,\n variant,\n defaultValue = [],\n value,\n placeholder = \"Select options\",\n animation = 0,\n maxCount = 3,\n modalPopover = false,\n asChild = false,\n className,\n onSearchChange,\n ...props\n },\n ref,\n ) => {\n // Using internal state only if value prop is not provided (uncontrolled mode)\n const [internalSelectedValues, setInternalSelectedValues] = React.useState<string[]>(defaultValue);\n\n // If value prop is provided, use it (controlled mode), otherwise use internal state\n const selectedValues = value !== undefined ? value : internalSelectedValues;\n\n const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);\n const [isAnimating, setIsAnimating] = React.useState(false);\n\n const handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Enter\") {\n setIsPopoverOpen(true);\n } else if (event.key === \"Backspace\" && !event.currentTarget.value) {\n const newSelectedValues = [...selectedValues];\n newSelectedValues.pop();\n\n // If in uncontrolled mode, update internal state\n if (value === undefined) {\n setInternalSelectedValues(newSelectedValues);\n }\n\n // Always call the callback\n onValueChange(newSelectedValues);\n }\n };\n\n const toggleOption = (option: string) => {\n const newSelectedValues = selectedValues.includes(option)\n ? selectedValues.filter((value) => value !== option)\n : [...selectedValues, option];\n\n // If in uncontrolled mode, update internal state\n if (value === undefined) {\n setInternalSelectedValues(newSelectedValues);\n }\n\n // Always call the callback\n onValueChange(newSelectedValues);\n };\n\n const handleClear = () => {\n // If in uncontrolled mode, update internal state\n if (value === undefined) {\n setInternalSelectedValues([]);\n }\n\n // Always call the callback\n onValueChange([]);\n };\n\n const handleTogglePopover = () => {\n setIsPopoverOpen((prev) => !prev);\n };\n\n const clearExtraOptions = () => {\n const newSelectedValues = selectedValues.slice(0, maxCount);\n\n // If in uncontrolled mode, update internal state\n if (value === undefined) {\n setInternalSelectedValues(newSelectedValues);\n }\n\n // Always call the callback\n onValueChange(newSelectedValues);\n };\n\n const toggleAll = () => {\n let newSelectedValues: string[];\n\n if (selectedValues.length === options.length) {\n newSelectedValues = [];\n } else {\n newSelectedValues = options.map((option) => option.value);\n }\n\n // If in uncontrolled mode, update internal state\n if (value === undefined) {\n setInternalSelectedValues(newSelectedValues);\n }\n\n // Always call the callback\n onValueChange(newSelectedValues);\n };\n\n return (\n <Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen} modal={modalPopover}>\n <PopoverTrigger asChild>\n <Button\n ref={ref}\n {...props}\n onClick={handleTogglePopover}\n className={cn(\n \"flex h-auto min-h-10 w-full items-center justify-between rounded-md border bg-inherit p-1 hover:bg-inherit [&_svg]:pointer-events-auto\",\n className,\n )}\n >\n {selectedValues.length > 0 ? (\n <div className=\"flex w-full items-center justify-between\">\n <div className=\"flex flex-wrap items-center\">\n {selectedValues.slice(0, maxCount).map((value) => {\n const option = options.find((o) => o.value === value);\n const IconComponent = option?.icon;\n return (\n <Badge\n key={value}\n className={cn(isAnimating ? \"animate-bounce\" : \"\", multiSelectVariants({ variant }))}\n style={{ animationDuration: `${animation}s` }}\n >\n {IconComponent && <IconComponent className=\"mr-2 h-4 w-4\" />}\n {option?.label}\n <XCircle\n className=\"ml-2 h-4 w-4 cursor-pointer\"\n onClick={(event) => {\n event.stopPropagation();\n toggleOption(value);\n }}\n />\n </Badge>\n );\n })}\n {selectedValues.length > maxCount && (\n <Badge\n className={cn(\n \"text-foreground border-foreground/1 bg-transparent hover:bg-transparent\",\n isAnimating ? \"animate-bounce\" : \"\",\n multiSelectVariants({ variant }),\n )}\n style={{ animationDuration: `${animation}s` }}\n >\n {`+ ${selectedValues.length - maxCount} more`}\n <XCircle\n className=\"ml-2 h-4 w-4 cursor-pointer\"\n onClick={(event) => {\n event.stopPropagation();\n clearExtraOptions();\n }}\n />\n </Badge>\n )}\n </div>\n <div className=\"flex items-center justify-between\">\n <XIcon\n className=\"text-muted-foreground mx-2 h-4 cursor-pointer\"\n onClick={(event) => {\n event.stopPropagation();\n handleClear();\n }}\n />\n <Separator orientation=\"vertical\" className=\"flex h-full min-h-6\" />\n <ChevronDown className=\"text-muted-foreground mx-2 h-4 cursor-pointer\" />\n </div>\n </div>\n ) : (\n <div className=\"mx-auto flex w-full items-center justify-between\">\n <span className=\"text-muted-foreground mx-3 text-sm\">{placeholder}</span>\n <ChevronDown className=\"text-muted-foreground mx-2 h-4 cursor-pointer\" />\n </div>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\" onEscapeKeyDown={() => setIsPopoverOpen(false)}>\n <Command>\n <CommandInput\n autoFocus\n placeholder=\"Search...\"\n onKeyDown={handleInputKeyDown}\n onValueChange={onSearchChange}\n />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup>\n <CommandItem key=\"all\" onSelect={toggleAll} className=\"cursor-pointer\">\n <div\n className={cn(\n \"border-primary mr-2 flex h-4 w-4 items-center justify-center rounded-sm border\",\n selectedValues.length === options.length\n ? \"bg-primary text-primary-foreground\"\n : \"opacity-50 [&_svg]:invisible\",\n )}\n >\n <CheckIcon className=\"h-4 w-4\" />\n </div>\n <span>(Select All)</span>\n </CommandItem>\n {options.map((option) => {\n const isSelected = selectedValues.includes(option.value);\n return (\n <CommandItem\n key={option.value}\n onSelect={() => toggleOption(option.value)}\n className=\"cursor-pointer\"\n >\n <div\n className={cn(\n \"border-primary mr-2 flex h-4 w-4 items-center justify-center rounded-sm border\",\n isSelected ? \"bg-primary text-primary-foreground\" : \"opacity-50 [&_svg]:invisible\",\n )}\n >\n <CheckIcon className=\"h-4 w-4\" />\n </div>\n {option.icon && <option.icon className=\"text-muted-foreground mr-2 h-4 w-4\" />}\n <span>{option.label}</span>\n </CommandItem>\n );\n })}\n </CommandGroup>\n <CommandSeparator />\n <CommandGroup>\n <div className=\"flex items-center justify-between\">\n {selectedValues.length > 0 && (\n <>\n <CommandItem onSelect={handleClear} className=\"flex-1 cursor-pointer justify-center\">\n Clear\n </CommandItem>\n <Separator orientation=\"vertical\" className=\"flex h-full min-h-6\" />\n </>\n )}\n <CommandItem\n onSelect={() => setIsPopoverOpen(false)}\n className=\"max-w-full flex-1 cursor-pointer justify-center\"\n >\n Close\n </CommandItem>\n </div>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n {animation > 0 && selectedValues.length > 0 && (\n <WandSparkles\n className={cn(\n \"text-foreground bg-background my-2 h-3 w-3 cursor-pointer\",\n isAnimating ? \"\" : \"text-muted-foreground\",\n )}\n onClick={() => setIsAnimating(!isAnimating)}\n />\n )}\n </Popover>\n );\n },\n);\n\nMultiSelect.displayName = \"MultiSelect\";\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { CommonDeleter } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { useI18nRouter, usePageUrlGenerator } from \"../../../../hooks\";\nimport { Action } from \"../../../../permissions\";\nimport { getRoleId } from \"../../../../roles\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype UserDeleterProps = {\n user: UserInterface;\n companyId?: string;\n onDeleted?: () => void;\n};\n\nfunction UserDeleterInternal({ user, onDeleted, companyId }: UserDeleterProps) {\n const { currentUser, company } = useCurrentUserContext<UserInterface>();\n const generateUrl = usePageUrlGenerator();\n const router = useI18nRouter();\n const t = useTranslations();\n\n let cId;\n if (currentUser?.roles.find((role) => role.id === getRoleId().Administrator) && companyId) {\n cId = companyId;\n } else {\n if (!company) return;\n cId = company.id;\n }\n\n return (\n <CommonDeleter\n type={`users`}\n deleteFunction={() =>\n UserService.delete({ userId: user.id, companyId: cId }).then(() =>\n onDeleted ? onDeleted() : router.push(generateUrl({ page: Modules.User })),\n )\n }\n />\n );\n}\n\nexport function UserDeleter(props: UserDeleterProps) {\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n if (!hasPermissionToModule({ module: Modules.User, action: Action.Delete, data: props.user })) return null;\n\n return <UserDeleterInternal {...props} />;\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { v4 } from \"uuid\";\nimport { z } from \"zod\";\nimport {\n CommonEditorButtons,\n CommonEditorHeader,\n CommonEditorTrigger,\n errorToast,\n FormCheckbox,\n FormInput,\n FormPassword,\n FormRoles,\n FormTextarea,\n} from \"../../../../components\";\nimport { useCompanyContext } from \"../../../../contexts\";\nimport { Modules } from \"../../../../core\";\nimport { useI18nRouter, usePageUrlGenerator } from \"../../../../hooks\";\nimport { Action } from \"../../../../permissions\";\nimport { getRoleId } from \"../../../../roles\";\nimport { Dialog, DialogContent, DialogTrigger, Form } from \"../../../../shadcnui\";\nimport { CompanyInterface } from \"../../../company\";\nimport { RoleInterface } from \"../../../role\";\nimport { S3Interface } from \"../../../s3\";\nimport { RoleService } from \"../../../role/data/role.service\";\nimport { S3Service } from \"../../../s3/data/s3.service\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInput, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\nimport { UserAvatarEditor } from \"./UserAvatarEditor\";\nimport { UserDeleter } from \"./UserDeleter\";\n\ntype UserEditorProps = {\n user?: UserInterface;\n propagateChanges?: (user: UserInterface) => void;\n adminCreated?: boolean;\n trigger?: React.ReactNode;\n onRevalidate?: (path: string) => Promise<void>;\n};\n\nfunction UserEditorInternal({ user, propagateChanges, adminCreated, trigger, onRevalidate }: UserEditorProps) {\n const {\n company: userCompany,\n hasPermissionToModule,\n hasRole,\n currentUser,\n setUser,\n } = useCurrentUserContext<UserInterface>();\n const { company: companyFromContext } = useCompanyContext();\n const generateUrl = usePageUrlGenerator();\n const router = useI18nRouter();\n const [open, setOpen] = useState<boolean>(false);\n const [roles, setRoles] = useState<RoleInterface[]>([]);\n const [file, setFile] = useState<File | null>(null);\n const [contentType, setContentType] = useState<string | null>(null);\n const t = useTranslations();\n const [resetImage, setResetImage] = useState<boolean>(false);\n const [company, setCompany] = useState<CompanyInterface | null>(companyFromContext || userCompany);\n\n useEffect(() => {\n if (!companyFromContext && userCompany) setCompany(userCompany);\n }, [company]);\n\n const formSchema = z.object({\n id: z.uuidv4(),\n name: z.string().min(1, { message: t(`foundations.user.fields.name.error`) }),\n email: z.string().min(1, { message: t(`generic.fields.email.error`) }),\n password: z.string().optional(),\n title: z.string().optional(),\n bio: z.string().optional(),\n phone: z.string().optional(),\n roleIds: z.array(z.string()).optional(),\n sendInvitationEmail: z.boolean().optional(),\n avatar: z.string().optional(),\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n id: user?.id || v4(),\n name: user?.name || \"\",\n title: user?.title || \"\",\n bio: user?.bio || \"\",\n email: user?.email || \"\",\n phone: user?.phone || \"\",\n password: \"\",\n roleIds: user?.roles.map((role: RoleInterface) => role.id) || [],\n sendInvitationEmail: false,\n avatar: user?.avatarUrl || \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n if (!user) {\n try {\n const existingUser = await UserService.findByEmail({ email: values.email });\n if (existingUser) {\n form.setError(\"email\", {\n type: \"manual\",\n message: t(`foundations.user.errors.email_exists`),\n });\n errorToast({ title: t(`foundations.user.errors.email_exists`), error: \"\" });\n return;\n }\n } catch (error) {\n // User does not exist, proceed\n }\n }\n\n if (values.avatar && contentType) {\n const s3: S3Interface = await S3Service.getPreSignedUrl({\n key: values.avatar,\n contentType: contentType,\n isPublic: true,\n });\n\n await fetch(s3.url, {\n method: \"PUT\",\n headers: s3.headers,\n body: file,\n });\n }\n\n const payload: UserInput = {\n id: values.id,\n email: values.email,\n name: values.name,\n title: values.title,\n bio: values.bio,\n phone: values.phone,\n password: values.password,\n avatar: resetImage ? undefined : values.avatar,\n roleIds: values.roleIds,\n sendInvitationEmail: values.sendInvitationEmail,\n companyId: company!.id,\n adminCreated: adminCreated,\n };\n\n try {\n const updatedUser = user\n ? ((await UserService.update(payload)) as UserInterface)\n : ((await UserService.create(payload)) as UserInterface);\n\n if (currentUser?.id === updatedUser.id) setUser(updatedUser);\n\n if (onRevalidate) {\n await onRevalidate(generateUrl({ page: Modules.User, id: updatedUser.id, language: `[locale]` }));\n }\n if (propagateChanges) {\n propagateChanges(updatedUser);\n setOpen(false);\n } else {\n router.push(generateUrl({ page: Modules.User, id: updatedUser.id }));\n }\n } catch (error) {\n errorToast({ title: user ? t(`generic.errors.update`) : t(`generic.errors.create`), error });\n }\n };\n\n useEffect(() => {\n async function fetchRoles() {\n const roles = await RoleService.findAllRoles({});\n\n const availableRoles = roles.filter(\n (role: RoleInterface) =>\n role.id !== getRoleId().Administrator &&\n (role.requiredFeature === undefined ||\n company?.features.some((feature) => feature.id === role.requiredFeature?.id)),\n );\n\n setRoles(availableRoles);\n }\n\n if (\n open &&\n (company || currentUser?.roles.find((role: RoleInterface) => role.id === getRoleId().Administrator)) &&\n roles.length === 0\n )\n fetchRoles();\n }, [company, open]);\n\n useEffect(() => {\n if (file && company) {\n const id = form.getValues(\"id\");\n const fileType = file.type;\n let extension = \"\";\n\n switch (fileType) {\n default:\n extension = file.type.split(\"/\").pop() ?? \"\";\n break;\n }\n\n const timestamp = new Date().toISOString().replace(/[-:T]/g, \"\").split(\".\")[0];\n\n const fileUrl = `companies/${company.id}/users/${id}/${id}.${timestamp}.${extension}`;\n form.setValue(\"avatar\", fileUrl);\n\n setContentType(fileType);\n } else {\n setContentType(null);\n }\n }, [file]);\n\n const canChangeRoles =\n !(currentUser?.id === user?.id && hasRole(getRoleId().Administrator)) &&\n (hasPermissionToModule({ module: Modules.User, action: Action.Update }) || hasRole(getRoleId().Administrator));\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n {trigger ? <DialogTrigger asChild>{trigger}</DialogTrigger> : <CommonEditorTrigger isEdit={!!user} />}\n <DialogContent\n className={`flex max-h-[70vh] ${canChangeRoles ? `max-w-[90vw]` : `max-w-3xl`} min-h-3xl max-h-[90vh] flex-col overflow-y-auto`}\n >\n <CommonEditorHeader type={t(`types.users`, { count: 1 })} name={user?.name} />\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className={`flex w-full flex-col gap-y-4`}>\n <div className={`flex flex-row gap-x-4`}>\n <div className={`flex w-40 flex-col justify-start gap-y-2`}>\n <UserAvatarEditor\n user={user}\n file={file}\n setFile={setFile}\n resetImage={resetImage}\n setResetImage={setResetImage}\n />\n </div>\n <div className={`flex w-full flex-col justify-start`}>\n <FormInput\n form={form}\n id=\"name\"\n name={t(`foundations.user.fields.name.label`)}\n placeholder={t(`foundations.user.fields.name.placeholder`)}\n />\n <FormInput\n form={form}\n id=\"email\"\n name={t(`generic.fields.email.label`)}\n placeholder={t(`generic.fields.email.placeholder`)}\n />\n <FormInput\n form={form}\n id=\"phone\"\n name={t(`foundations.user.fields.phone.label`)}\n placeholder={t(`foundations.user.fields.phone.placeholder`)}\n />\n <FormPassword\n form={form}\n id=\"password\"\n name={t(`foundations.user.fields.password.label`)}\n placeholder={t(`foundations.user.fields.password.placeholder`)}\n />\n <FormInput\n form={form}\n id=\"title\"\n name={t(`foundations.user.fields.title.label`)}\n placeholder={t(`foundations.user.fields.title.placeholder`)}\n />\n <FormTextarea\n form={form}\n id=\"bio\"\n name={t(`foundations.user.fields.bio.label`)}\n placeholder={t(`foundations.user.fields.bio.placeholder`)}\n className=\"min-h-40\"\n />\n </div>\n {canChangeRoles && (\n <div className=\"flex w-1/3 flex-col\">\n {canChangeRoles && (\n <FormRoles form={form} id=\"roleIds\" name={t(`types.roles`, { count: 2 })} roles={roles} />\n )}\n {!user && (\n <div className=\"flex flex-col gap-y-4\">\n <div className=\"text-sm font-semibold\">{t(`foundations.user.send_activation_email`)}</div>\n <FormCheckbox\n form={form}\n id=\"sendInvitationEmail\"\n name={t(`foundations.user.send_activation_email`)}\n />\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"flex justify-end gap-x-4\">\n {user && currentUser?.roles.find((role: RoleInterface) => role.id === getRoleId().Administrator) && (\n <UserDeleter\n companyId={user.company?.id}\n user={user}\n onDeleted={() => {\n setOpen(false);\n if (propagateChanges) propagateChanges(user);\n }}\n />\n )}\n <CommonEditorButtons form={form} setOpen={setOpen} isEdit={!!user} />\n </div>\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport function UserEditor(props: UserEditorProps) {\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n if (\n !hasPermissionToModule({\n module: Modules.User,\n action: props.user ? Action.Update : Action.Create,\n data: props.user,\n })\n )\n return null;\n\n return <UserEditorInternal {...props} />;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useWatch } from \"react-hook-form\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever, useDebounce } from \"../../../../hooks\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n MultiSelect,\n} from \"../../../../shadcnui\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\n// Type for user objects in the form\ntype UserSelectType = {\n id: string;\n name: string;\n avatar?: string;\n};\n\ntype UserMultiSelectProps = {\n id: string;\n form: any;\n currentUser?: UserInterface;\n label?: string;\n placeholder?: string;\n onChange?: (users?: UserInterface[]) => void;\n maxCount?: number;\n isRequired?: boolean;\n};\n\nfunction UserAvatarIcon({ className, url, name }: { className?: string; url?: string; name?: string }) {\n return (\n <Avatar className={`${className || \"h-4 w-4\"}`}>\n <AvatarImage src={url} />\n <AvatarFallback>\n {name\n ? name\n .split(\" \")\n .map((n: string) => n.charAt(0).toUpperCase())\n .join(\"\")\n : \"U\"}\n </AvatarFallback>\n </Avatar>\n );\n}\n\nexport function UserMultiSelect({\n id,\n form,\n currentUser,\n label,\n placeholder,\n onChange,\n maxCount = 3,\n isRequired = false,\n}: UserMultiSelectProps) {\n const { company } = useCurrentUserContext<UserInterface>();\n\n const searchTermRef = useRef<string>(\"\");\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n const [isSearching, setIsSearching] = useState<boolean>(false);\n const [userOptions, setUserOptions] = useState<any[]>([]);\n\n // Get the current selected users from the form\n const selectedUsers: UserSelectType[] = useWatch({ control: form.control, name: id }) || [];\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n ready: !!company,\n retriever: (params) => {\n return UserService.findAllUsers(params);\n },\n retrieverParams: { companyId: company?.id },\n module: Modules.User,\n }) as DataListRetriever<UserInterface>;\n\n useEffect(() => {\n if (company) data.setReady(true);\n }, [company]);\n\n const search = useCallback(\n async (searchedTerm: string) => {\n try {\n if (searchedTerm === searchTermRef.current) return;\n setIsSearching(true);\n searchTermRef.current = searchedTerm;\n await data.search(searchedTerm);\n } finally {\n setIsSearching(false);\n }\n },\n [searchTermRef, data],\n );\n\n const updateSearchTerm = useDebounce(search, 500);\n\n useEffect(() => {\n setIsSearching(true);\n updateSearchTerm(searchTerm);\n }, [updateSearchTerm, searchTerm]);\n\n // Update userOptions when data changes or when initial selected users are available\n useEffect(() => {\n if (data.data && data.data.length > 0) {\n const users = data.data as UserInterface[];\n const filteredUsers = users.filter((user) => user.id !== currentUser?.id);\n\n const options = filteredUsers.map((user) => ({\n label: user.name,\n value: user.id,\n icon: ({ className }: { className?: string }) => (\n <UserAvatarIcon className={className} url={user.avatar} name={user.name} />\n ),\n userData: user,\n }));\n\n setUserOptions(options);\n }\n }, [data.data, currentUser]);\n\n // Add options for any already selected users that aren't in search results\n useEffect(() => {\n if (selectedUsers.length > 0) {\n // Create a map of existing option IDs for quick lookup\n const existingOptionIds = new Set(userOptions.map((option) => option.value));\n\n // Find selected users that don't have an option yet\n const missingOptions = selectedUsers\n .filter((user) => !existingOptionIds.has(user.id))\n .map((user) => ({\n label: user.name,\n value: user.id,\n icon: ({ className }: { className?: string }) => (\n <UserAvatarIcon className={className} url={user.avatar} name={user.name} />\n ),\n userData: user,\n }));\n\n // Add missing options if there are any\n if (missingOptions.length > 0) {\n setUserOptions((prev) => [...prev, ...missingOptions]);\n }\n }\n }, [selectedUsers, userOptions]);\n\n const handleValueChange = (selectedIds: string[]) => {\n // Map selected IDs to user objects for the form\n const updatedSelectedUsers = selectedIds.map((id) => {\n // First check if user is already in the selected users (preserve existing data)\n const existingUser = selectedUsers.find((user) => user.id === id);\n if (existingUser) {\n return existingUser;\n }\n\n // Otherwise, get user data from the options\n const option = userOptions.find((option) => option.value === id);\n if (option?.userData) {\n return {\n id: option.userData.id,\n name: option.userData.name,\n avatar: option.userData.avatar,\n };\n }\n\n // Fallback to just the ID if no data is available\n return { id, name: id };\n });\n\n form.setValue(id, updatedSelectedUsers);\n\n if (onChange) {\n const fullSelectedUsers = selectedIds\n .map((id) => userOptions.find((option) => option.value === id)?.userData)\n .filter(Boolean) as UserInterface[];\n onChange(fullSelectedUsers);\n }\n };\n\n // Extract just the IDs for the MultiSelect component\n const selectedUserIds = selectedUsers.map((user: UserSelectType) => user.id);\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${label ? \"mb-5\" : \"mb-1\"}`}>\n {label && (\n <FormLabel className=\"flex items-center\">\n {label}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <MultiSelect\n options={userOptions}\n onValueChange={handleValueChange}\n defaultValue={selectedUserIds}\n placeholder={placeholder}\n maxCount={maxCount}\n animation={0}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { UserCheckIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useState } from \"react\";\nimport { errorToast } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { Action } from \"../../../../permissions\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"../../../../shadcnui\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype UserReactivatorProps = {\n user: UserInterface;\n propagateChanges: (user: UserInterface) => void;\n};\n\nfunction UserReactivatorInterface({ user, propagateChanges }: UserReactivatorProps) {\n const [open, setOpen] = useState<boolean>(false);\n const t = useTranslations();\n\n const reactivateUser = async () => {\n try {\n const updatedUser = (await UserService.reactivate({ userId: user.id })) as UserInterface;\n\n setOpen(false);\n propagateChanges(updatedUser);\n } catch (error) {\n errorToast({ title: t(`generic.errors.error`), error: error });\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogTrigger asChild>\n <Button size=\"sm\">\n <UserCheckIcon className=\"mr-3 h-3.5 w-3.5\" />\n {t(`foundations.user.buttons.reactivate`)}\n </Button>\n </DialogTrigger>\n <DialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>\n <DialogHeader>\n <DialogTitle>{t(`foundations.user.reactivate.title`)}</DialogTitle>\n <DialogDescription>{t(`foundations.user.reactivate.subtitle`)}</DialogDescription>\n </DialogHeader>\n {t(`foundations.user.reactivate.description`, { name: user.name })}\n <div className=\"flex justify-end\">\n <Button className=\"mr-2\" variant={\"outline\"} type={`button`} onClick={() => setOpen(false)}>\n {t(`generic.buttons.cancel`)}\n </Button>\n <Button\n type=\"submit\"\n onClick={(e) => {\n e.preventDefault();\n reactivateUser();\n }}\n >\n {t(`foundations.user.buttons.reactivate`)}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport function UserReactivator(props: UserReactivatorProps) {\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n if (!hasPermissionToModule({ module: Modules.User, action: Action.Update, data: props.user })) return null;\n\n return <UserReactivatorInterface {...props} />;\n}\n","\"use client\";\n\nimport { MailIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { errorToast } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { Action } from \"../../../../permissions\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../../../shadcnui\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype UserResentInvitationEmailProps = {\n user: UserInterface;\n};\n\nfunction UserResentInvitationEmailInternal({ user }: UserResentInvitationEmailProps) {\n const [open, setOpen] = useState<boolean>(false);\n const t = useTranslations();\n\n const sendInvitationEmail = async () => {\n try {\n await UserService.sendInvitation({ userId: user.id, companyId: user.company!.id });\n\n setOpen(false);\n toast.message(t(`foundations.user.resend_activation.email_sent`), {\n description: t(`foundations.user.resend_activation.email_sent_description`, { email: user.email }),\n });\n } catch (error) {\n errorToast({ title: t(`generic.errors.error`), error: error });\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <Tooltip>\n <TooltipTrigger asChild>\n <DialogTrigger asChild>\n <Button size=\"sm\" variant={`ghost`} className=\"text-muted-foreground\">\n <MailIcon />\n </Button>\n </DialogTrigger>\n </TooltipTrigger>\n <TooltipContent>{t(`foundations.user.buttons.resend_activation`)}</TooltipContent>\n </Tooltip>\n <DialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>\n <DialogHeader>\n <DialogTitle>{t(`foundations.user.resend_activation.title`)}</DialogTitle>\n <DialogDescription>{t(`foundations.user.resend_activation.subtitle`)}</DialogDescription>\n </DialogHeader>\n {t(`foundations.user.resend_activation.description`, { email: user.email })}\n <div className=\"flex justify-end\">\n <Button className=\"mr-2\" variant={\"outline\"} type={`button`} onClick={() => setOpen(false)}>\n {t(`generic.buttons.cancel`)}\n </Button>\n <Button\n type=\"submit\"\n onClick={(e) => {\n e.preventDefault();\n sendInvitationEmail();\n }}\n >\n {t(`foundations.user.buttons.resend_activation`)}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport function UserResentInvitationEmail(props: UserResentInvitationEmailProps) {\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n if (!hasPermissionToModule({ module: Modules.User, action: Action.Update, data: props.user })) return null;\n\n return <UserResentInvitationEmailInternal {...props} />;\n}\n","\"use client\";\n\nimport { CircleX, RefreshCwIcon, SearchIcon, XIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever, useDebounce } from \"../../../../hooks\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n Command,\n CommandItem,\n CommandList,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\nimport { UserAvatar } from \"../widgets\";\n\ntype UserSelectorProps = {\n id: string;\n form: any;\n label?: string;\n placeholder?: string;\n onChange?: (user?: UserInterface) => void;\n isRequired?: boolean;\n};\n\nexport function UserSelector({ id, form, label, placeholder, onChange, isRequired = false }: UserSelectorProps) {\n const t = useTranslations();\n\n const [open, setOpen] = useState<boolean>(false);\n\n const searchTermRef = useRef<string>(\"\");\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n\n const [isSearching, setIsSearching] = useState<boolean>(false);\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n retriever: (params) => {\n return UserService.findMany(params);\n },\n retrieverParams: {},\n module: Modules.User,\n });\n\n const search = useCallback(\n async (searchedTerm: string) => {\n try {\n if (searchedTerm === searchTermRef.current) return;\n setIsSearching(true);\n searchTermRef.current = searchedTerm;\n await data.search(searchedTerm);\n } finally {\n setIsSearching(false);\n }\n },\n [searchTermRef, data],\n );\n\n const updateSearchTerm = useDebounce(search, 500);\n\n useEffect(() => {\n setIsSearching(true);\n updateSearchTerm(searchTerm);\n }, [updateSearchTerm, searchTerm]);\n\n const setUser = (user?: UserInterface) => {\n if (onChange) onChange(user);\n if (!user) {\n form.setValue(id, undefined);\n setOpen(false);\n return;\n }\n\n form.setValue(id, { id: user.id, name: user.name, avatar: user.avatar });\n setOpen(false);\n\n setTimeout(() => {\n setOpen(false);\n }, 0);\n };\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${label ? \"mb-5\" : \"mb-1\"}`}>\n {label && (\n <FormLabel className=\"flex items-center\">\n {label}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <Popover open={open} onOpenChange={setOpen} modal={true}>\n <div className=\"flex w-full flex-row items-center justify-between\">\n <PopoverTrigger className=\"w-full\">\n <div className=\"flex w-full flex-row items-center justify-start rounded-md\">\n {field.value ? (\n <>\n <div className=\"flex w-full flex-row items-center justify-start rounded-md border p-2\">\n <div className=\"*:ring-border *:ring-1\">\n <Avatar className={`mr-2 h-6 w-6`}>\n <AvatarImage src={field.value?.avatar} />\n <AvatarFallback>\n {field.value?.name\n ? field.value?.name.split(\" \").map((name: string) => name.charAt(0).toUpperCase())\n : \"X\"}\n </AvatarFallback>\n </Avatar>\n </div>\n <span className=\"\">{field.value?.name ?? \"\"}</span>\n </div>\n </>\n ) : (\n <div className=\"text-muted-foreground mr-7 flex h-10 w-full flex-row items-center justify-start rounded-md border p-2 text-sm\">\n {placeholder ?? t(`generic.search.placeholder`, { type: t(`types.users`, { count: 1 }) })}\n </div>\n )}\n </div>\n </PopoverTrigger>\n {field.value && (\n <CircleX\n className=\"text-muted hover:text-destructive ml-2 h-6 w-6 cursor-pointer\"\n onClick={() => setUser()}\n />\n )}\n </div>\n <PopoverContent>\n <Command shouldFilter={false}>\n <div className=\"relative mb-2 w-full\">\n <SearchIcon className=\"text-muted-foreground absolute top-2.5 left-2.5 h-4 w-4\" />\n <Input\n placeholder={t(`generic.search.placeholder`, { type: t(`types.users`, { count: 1 }) })}\n type=\"text\"\n className=\"w-full pr-8 pl-8\"\n onChange={(e) => setSearchTerm(e.target.value)}\n value={searchTerm}\n />\n {isSearching ? (\n <RefreshCwIcon className=\"text-muted-foreground absolute top-2.5 right-2.5 h-4 w-4 animate-spin\" />\n ) : searchTermRef.current ? (\n <XIcon\n className={`absolute top-2.5 right-2.5 h-4 w-4 ${searchTermRef.current ? \"cursor-pointer\" : \"text-muted-foreground\"}`}\n onClick={() => {\n setSearchTerm(\"\");\n search(\"\");\n }}\n />\n ) : (\n <></>\n )}\n </div>\n <CommandList>\n {data.data &&\n data.data.length > 0 &&\n (data.data as UserInterface[]).map((user: UserInterface) => (\n <CommandItem className=\"cursor-pointer\" key={user.id} onSelect={() => setUser(user)}>\n <UserAvatar user={user} className={`mr-2 h-4 w-4`} />\n <span className=\"\">{user.name}</span>\n </CommandItem>\n ))}\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n Link,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../../../shadcnui\";\nimport { cn } from \"../../../../utils\";\nimport { UserInterface } from \"../../data\";\n\ntype UserAvatarProps = {\n user: UserInterface;\n className?: string;\n showFull?: boolean;\n showLink?: boolean;\n};\n\nexport function UserAvatar({ user, className, showFull, showLink }: UserAvatarProps) {\n const generateUrl = usePageUrlGenerator();\n\n const getInitial = (param?: string) => {\n if (!param) return \"\";\n return param[0].toUpperCase();\n };\n\n const getInitials = (name: string) => {\n const words = name.split(\" \");\n const initials =\n words.length > 1 ? getInitial(words[0][0]) + getInitial(words[words.length - 1][0]) : getInitial(words[0][0]);\n\n return initials ?? \"\";\n };\n\n const getAvatar = () => {\n return (\n <div className=\"*:ring-border *:ring-1\">\n <Avatar className={`h-6 w-6 ${className}`}>\n <AvatarImage className=\"object-cover\" src={user?.avatar} />\n <AvatarFallback>{getInitials(user.name)}</AvatarFallback>\n </Avatar>\n </div>\n );\n };\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n {showLink === false ? (\n // If showLink is explicitly false, never show a link\n showFull ? (\n <div className={cn(`mb-2 flex w-full flex-row items-center justify-start gap-x-2 text-sm`, className)}>\n {getAvatar()}\n {user.name}\n </div>\n ) : (\n getAvatar()\n )\n ) : showFull ? (\n <Link\n href={generateUrl({ page: Modules.User, id: user.id })}\n className={cn(`mb-2 flex w-full flex-row items-center justify-start gap-x-2 text-sm`, className)}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex w-full flex-row items-center gap-x-2\">\n {getAvatar()}\n {user.name}\n </div>\n </Link>\n ) : showLink ? (\n <Link href={generateUrl({ page: Modules.User, id: user.id })} className={className}>\n {getAvatar()}\n </Link>\n ) : (\n getAvatar()\n )}\n </TooltipTrigger>\n <TooltipContent>{user.name}</TooltipContent>\n </Tooltip>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { useUserContext } from \"../../contexts\";\nimport { UserDetails } from \"../details\";\n\nexport function UserContainer() {\n const { user } = useUserContext();\n if (!user) return null;\n\n const t = useTranslations();\n\n return (\n <div className=\"flex w-full gap-x-4\">\n <div className=\"w-2xl flex h-[calc(100vh-theme(spacing.20))] flex-col justify-between border-r pr-4\">\n <div className=\"flex h-full overflow-y-auto\">\n <UserDetails user={user} />\n </div>\n </div>\n <div className=\"flex w-full flex-col gap-y-4\"></div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { ReactElement } from \"react\";\nimport { AttributeElement, ContentTitle } from \"../../../../components\";\nimport { useSharedContext } from \"../../../../contexts\";\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { Badge, Link } from \"../../../../shadcnui\";\nimport { RoleInterface } from \"../../../role\";\nimport { UserInterface } from \"../../data\";\n\ntype UserDetailsProps = {\n user: UserInterface;\n};\n\nexport function UserDetails({ user }: UserDetailsProps) {\n const generateUrl = usePageUrlGenerator();\n const t = useTranslations();\n const { title } = useSharedContext();\n\n let roles: ReactElement<any> = <></>;\n\n if (user.roles && user.roles.length > 0) {\n roles = (\n <div className=\"mb-4 w-full\">\n <div className=\"flex flex-wrap gap-2\">\n {user.roles.map((role: RoleInterface, index: number) => (\n <Link key={role.id} href={generateUrl({ page: Modules.Role, id: role.id })}>\n <Badge className=\"mr-2\" variant={`default`}>\n {t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) })}\n </Badge>\n </Link>\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex w-full flex-col gap-y-2\">\n {user.avatar && (\n <div className=\"relative aspect-auto w-full max-w-md overflow-hidden rounded-lg\">\n <Image\n src={user.avatar}\n alt={user.name}\n width={800}\n height={600}\n className=\"h-auto w-full rounded-lg object-contain\"\n />\n </div>\n )}\n <ContentTitle type={title.type} element={title.element} functions={title.functions} />\n {user.isDeleted ? (\n <div>\n <Badge variant=\"destructive\">{t(`foundations.user.errors.deleted`)}</Badge>\n </div>\n ) : (\n <>\n {!user.isActivated && (\n <div>\n <Badge variant=\"destructive\">{t(`foundations.user.errors.inactive`)}</Badge>\n </div>\n )}\n </>\n )}\n {roles}\n <AttributeElement inline={true} title={t(`foundations.user.fields.title.label`)} value={user.title} />\n <AttributeElement inline={true} title={t(`generic.fields.email.label`)} value={user.email} />\n <AttributeElement inline={false} title={t(`foundations.user.fields.bio.label`)} value={user.bio} />\n </div>\n );\n}\n","\"use client\";\n\nimport { Card, CardContent } from \"../../../../shadcnui\";\nimport { useCurrentUserContext, useUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserAvatar } from \"../widgets\";\n\nexport function UserIndexDetails() {\n const { user } = useUserContext();\n const { currentUser } = useCurrentUserContext<UserInterface>();\n if (!user || !currentUser) return null;\n\n return (\n <div className=\"flex w-full flex-row gap-x-4\">\n <Card className=\"min-h-96 w-96 flex-shrink-0 self-start p-2\">\n <CardContent className=\"flex h-full flex-col gap-y-4 p-2\">\n <div className=\"flex w-full justify-start gap-x-4\">\n {user.avatar && <UserAvatar user={user} className=\"h-40 w-40\" />}\n <div className=\"flex flex-col justify-start gap-y-2\">\n <div className=\"text-primary text-2xl font-semibold\">{user.name}</div>\n <div className=\"text-muted-foreground text-xs\">{user.bio ?? \"\"}</div>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n","\"use client\";\n\nimport { PageContentContainer } from \"../../../../components\";\nimport { useUserContext } from \"../../contexts\";\nimport { UserIndexDetails } from \"../details\";\n\nexport function UserIndexContainer() {\n const { user } = useUserContext();\n if (!user) return null;\n\n return <PageContentContainer details={<UserIndexDetails />} />;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { CompanyUsersList, Tab, TabsContainer } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { Action } from \"../../../../permissions\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\n\nfunction UsersListContainerInternal() {\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n const t = useTranslations();\n\n if (!hasPermissionToModule({ module: Modules.User, action: Action.Delete })) return <CompanyUsersList />;\n\n const tabs: Tab[] = [\n {\n label: t(`types.users`, { count: 2 }),\n content: <CompanyUsersList />,\n modules: [Modules.Company],\n action: Action.Read,\n },\n {\n label: t(`foundations.user.deleted`),\n content: <CompanyUsersList isDeleted={true} />,\n modules: [Modules.Company],\n action: Action.Update,\n },\n ];\n\n return <TabsContainer tabs={tabs} />;\n}\n\nexport function UsersListContainer() {\n return <UsersListContainerInternal />;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { useCompanyContext } from \"../../../../contexts\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { CompanyInterface } from \"../../../company\";\nimport { UserFields, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\nimport { UserEditor } from \"../forms\";\n\ntype AdminUsersListProps = {\n company: CompanyInterface;\n};\n\nfunction AdminUsersListInternal({ company }: AdminUsersListProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n retriever: (params) => UserService.findManyForAmin(params),\n retrieverParams: { companyId: company.id },\n module: Modules.User,\n });\n\n return (\n <ContentListTable\n title={t(`types.users`, { count: 2 })}\n data={data}\n fields={[UserFields.name, UserFields.email, UserFields.createdAt]}\n tableGeneratorType={Modules.User}\n functions={<UserEditor propagateChanges={data.refresh} adminCreated />}\n />\n );\n}\n\nexport function AdminUsersList() {\n const { company } = useCompanyContext();\n if (!company) return null;\n\n return <AdminUsersListInternal company={company} />;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ReactNode, useEffect } from \"react\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserFields, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\nimport { UserEditor } from \"../forms\";\n\ntype CompanyUsersListProps = {\n isDeleted?: boolean;\n};\n\nexport function CompanyUsersList({ isDeleted }: CompanyUsersListProps) {\n const { company } = useCurrentUserContext<UserInterface>();\n const t = useTranslations();\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n ready: !!company,\n retriever: (params) => UserService.findAllUsers(params),\n retrieverParams: { companyId: company?.id, isDeleted: isDeleted },\n module: Modules.User,\n }) as DataListRetriever<UserInterface>;\n\n useEffect(() => {\n if (company) data.setReady(true);\n }, [company]);\n\n const functions: ReactNode[] = [\n isDeleted ? undefined : <UserEditor key=\"create-user\" propagateChanges={data.refresh} />,\n ];\n\n return (\n <ContentListTable\n data={data}\n fields={[UserFields.name, UserFields.email]}\n tableGeneratorType={Modules.User}\n functions={functions}\n title={t(`types.users`, { count: 2 })}\n />\n );\n}\n","\"use client\";\n\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { Link } from \"../../../../shadcnui\";\nimport { ContentInterface } from \"../../../content\";\nimport { UserInterface } from \"../../data\";\nimport { UserAvatar } from \"../widgets\";\n\ntype ContributorsListProps = {\n content: ContentInterface;\n};\n\nexport function ContributorsList({ content }: ContributorsListProps) {\n const generateUrl = usePageUrlGenerator();\n\n return (\n <div className=\"flex flex-row items-center\">\n <Link\n key={content.author.id}\n href={generateUrl({ page: Modules.User, id: content.author.id })}\n onClick={(e) => e.stopPropagation()}\n >\n <UserAvatar user={content.author} className=\"mr-1 h-6 w-6\" />\n </Link>\n <div className=\"flex flex-row-reverse justify-end -space-x-1 space-x-reverse\">\n {content.editors\n .filter((editor: UserInterface) => editor.id !== content.author.id)\n .map((editor: UserInterface) => (\n <Link\n key={editor.id}\n href={generateUrl({ page: Modules.User, id: editor.id })}\n onClick={(e) => e.stopPropagation()}\n >\n <UserAvatar user={editor} className=\"h-5 w-5\" />\n </Link>\n ))}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { UserFields, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype RelevantUsersListProps = {\n id: string;\n};\n\nexport function RelevantUsersList({ id }: RelevantUsersListProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n module: Modules.User,\n retriever: (params) => UserService.findRelevant(params),\n retrieverParams: { id: id },\n }) as DataListRetriever<UserInterface>;\n\n return (\n <ContentListTable\n data={data}\n fields={[UserFields.name, UserFields.email, UserFields.relevance]}\n tableGeneratorType={Modules.User}\n title={t(`generic.relevant_users`)}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { RoleInterface } from \"../../../role\";\nimport { UserFields, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype RoleUsersListProps = {\n role: RoleInterface;\n};\n\nexport function RoleUsersList({ role }: RoleUsersListProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n retriever: (params) => UserService.findAllUsersByRole(params),\n retrieverParams: { roleId: role.id },\n module: Modules.User,\n }) as DataListRetriever<UserInterface>;\n\n return (\n <ContentListTable\n data={data}\n fields={[UserFields.name, UserFields.email]}\n tableGeneratorType={Modules.User}\n title={t(`types.users`, { count: 2 })}\n />\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { DataListRetriever } from \"../../../../hooks\";\nimport { CommandItem } from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../data\";\nimport { UserAvatar } from \"../widgets\";\n\ntype UserListInAddProps = {\n data: DataListRetriever<UserInterface>;\n existingUsers: UserInterface[] | null;\n setSelectedUser: (user: UserInterface) => void;\n setLevelOpen?: (open: boolean) => void;\n};\n\nexport function UserListInAdd({ data, existingUsers, setSelectedUser, setLevelOpen }: UserListInAddProps) {\n return (\n <>\n {data.data !== undefined &&\n (data.data as UserInterface[])\n .filter(\n (user: UserInterface) =>\n existingUsers && !existingUsers.find((existingUser: UserInterface) => existingUser.id === user.id),\n )\n .map((user: UserInterface) => {\n return (\n <React.Fragment key={user.id}>\n <CommandItem\n className=\"cursor-pointer\"\n key={user.id}\n onClick={(e) => {\n setSelectedUser(user);\n setLevelOpen?.(true);\n }}\n onSelect={(e) => {\n setSelectedUser(user);\n setLevelOpen?.(true);\n }}\n >\n <div className=\"flex w-full flex-row items-center justify-between px-4 py-1\">\n <UserAvatar user={user} />\n <div className=\"ml-5 flex w-full flex-col\">\n <div className=\"text-sm font-medium\">{user.name}</div>\n <div className=\"text-xs font-normal\">{user.email}</div>\n </div>\n </div>\n </CommandItem>\n </React.Fragment>\n );\n })}\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ReactElement } from \"react\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever } from \"../../../../hooks\";\nimport { UserFields, UserInterface } from \"../../data\";\n\ntype UsersListProps = {\n data: DataListRetriever<UserInterface>;\n optionComponents?: ReactElement<any>[];\n removeFunction?: (user: UserInterface) => Promise<void>;\n hideOptions?: boolean;\n showRelevance?: boolean;\n restrictToJoinRequests?: boolean;\n};\n\nexport function UsersList({ data, optionComponents, removeFunction, hideOptions, showRelevance }: UsersListProps) {\n const t = useTranslations();\n\n return (\n <ContentListTable\n data={data}\n fields={[UserFields.name, UserFields.email]}\n tableGeneratorType={Modules.User}\n title={t(`types.users`, { count: 2 })}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { UserFields, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype UsersListByContentIdsProps = {\n contentIds: string[];\n};\n\nexport function UsersListByContentIds({ contentIds }: UsersListByContentIdsProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n module: Modules.User,\n retriever: (params) => UserService.findManyByContentIds(params),\n retrieverParams: { contentIds: contentIds },\n });\n\n return (\n <ContentListTable\n data={data}\n fields={[UserFields.name, UserFields.email]}\n tableGeneratorType={Modules.User}\n title={t(`generic.relevant_users`)}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { ContentTitle } from \"../../../../components\";\nimport { useSharedContext } from \"../../../../contexts\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { useCompanyContext } from \"../../contexts/CompanyContext\";\n\nexport function CompanyDetails() {\n const t = useTranslations();\n const { title } = useSharedContext();\n const generateUrl = usePageUrlGenerator();\n\n const { company } = useCompanyContext();\n if (!company) return null;\n\n return (\n <div className=\"flex w-full flex-col gap-y-2\">\n <ContentTitle type={title.type} element={title.element} functions={title.functions} />\n {company.logo && (\n <Image src={company.logo} alt={company.name} width={150} height={150} className=\"mb-4 rounded-md\" />\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { getRoleId } from \"../../../../roles\";\nimport { UserInterface } from \"../../../user\";\nimport { AdminUsersList } from \"../../../user/components\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { useCompanyContext } from \"../../contexts/CompanyContext\";\nimport { CompanyDetails } from \"../details/CompanyDetails\";\n\nfunction AdminCompanyContainerInternal() {\n const { company } = useCompanyContext();\n const { hasRole } = useCurrentUserContext<UserInterface>();\n\n if (!company || !hasRole(getRoleId().Administrator)) return null;\n\n return (\n <>\n <CompanyDetails />\n <AdminUsersList />\n </>\n );\n}\n\nexport function AdminCompanyContainer() {\n return <AdminCompanyContainerInternal />;\n}\n","\"use client\";\n\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { CompanyProvider } from \"../../contexts/CompanyContext\";\nimport { CompanyDetails } from \"../details/CompanyDetails\";\n\nexport function CompanyContainer() {\n const { currentUser } = useCurrentUserContext<UserInterface>();\n if (!currentUser) return null;\n\n return (\n <CompanyProvider dehydratedCompany={currentUser.company}>\n <CompanyDetails />\n </CompanyProvider>\n );\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Settings2Icon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport z from \"zod\";\nimport { CommonEditorButtons, errorToast } from \"../../../../components\";\nimport { getRoleId } from \"../../../../roles\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n Form,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { UserService } from \"../../../user/data/user.service\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { CompanyInput, CompanyInterface } from \"../../data\";\nimport { CompanyService } from \"../../data/company.service\";\nimport { CompanyConfigurationSecurityForm } from \"./CompanyConfigurationSecurityForm\";\n\ntype CompanyConfigurationEditorProps = {\n company: CompanyInterface;\n};\n\nfunction CompanyConfigurationEditorInternal({ company }: CompanyConfigurationEditorProps) {\n const [open, setOpen] = useState<boolean>(false);\n const t = useTranslations();\n const { setUser } = useCurrentUserContext<UserInterface>();\n\n const defaultValues = useMemo(() => {\n return {\n isManagedKnowledge: company.configurations?.isManagedKnowledge ?? false,\n allowPublicBot: company.configurations?.allowPublicBot ?? false,\n };\n }, [company.configurations]);\n\n const close = () => {\n setOpen(false);\n form.reset();\n };\n\n const formSchema = z.object({\n isManagedKnowledge: z.boolean().optional(),\n allowPublicBot: z.boolean().optional(),\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: defaultValues,\n shouldUnregister: false,\n });\n\n useEffect(() => {\n if (open) {\n form.reset({\n isManagedKnowledge: company.configurations?.isManagedKnowledge ?? false,\n allowPublicBot: company.configurations?.allowPublicBot ?? false,\n });\n }\n }, [company, open]);\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values) => {\n const payload: CompanyInput = {\n id: company.id,\n configurations: {\n isManagedKnowledge: values.isManagedKnowledge ?? false,\n allowPublicBot: values.allowPublicBot ?? false,\n },\n };\n\n try {\n await CompanyService.updateConfigurations(payload);\n\n // Refresh user data to update localStorage with new company configurations\n const fullUser = await UserService.findFullUser();\n if (fullUser) {\n setUser(fullUser);\n }\n\n toast.message(\"Configurations Updated\", {\n description: `The system configurations have been updated successfully.`,\n });\n close();\n } catch (error) {\n errorToast({\n title: t(`generic.errors.update`),\n error,\n });\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogTrigger asChild>\n <Button size=\"sm\" variant={`ghost`} className=\"cursor-pointer\">\n <Settings2Icon className=\"h-3.5 w-3.5\" />\n </Button>\n </DialogTrigger>\n <DialogContent className={`flex max-h-[70vh] max-w-4xl flex-col overflow-y-auto`}>\n <DialogHeader>\n <DialogTitle>{t(`types.configurations`, { count: 2 })}</DialogTitle>\n <DialogDescription className=\"text-destructive\">\n {t(`features.configuration.warning_description`)}\n </DialogDescription>\n </DialogHeader>\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className={`flex w-full flex-col gap-y-4`}>\n <div className={`flex flex-row gap-x-4`}>\n <div className={`flex w-full flex-col justify-start gap-y-4`}>\n <Tabs defaultValue={process.env.NEXT_PUBLIC_PRIVATE_INSTALLATION ? \"security\" : \"ai\"}>\n <TabsList>\n <TabsTrigger value=\"security\">Privacy & Security</TabsTrigger>\n </TabsList>\n <TabsContent value=\"features\">\n <div className=\"space-y-4\">\n <p className=\"text-muted-foreground text-sm\">\n Feature configuration will be implemented in future updates.\n </p>\n </div>\n </TabsContent>\n <TabsContent value=\"security\">\n <CompanyConfigurationSecurityForm form={form} />\n </TabsContent>\n </Tabs>\n </div>\n </div>\n <CommonEditorButtons form={form} setOpen={setOpen} isEdit={true} />\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport function CompanyConfigurationEditor(props: CompanyConfigurationEditorProps) {\n const { hasRole } = useCurrentUserContext<UserInterface>();\n\n if (hasRole(getRoleId().Administrator)) return <CompanyConfigurationEditorInternal {...props} />;\n\n return <CompanyConfigurationEditorInternal {...props} />;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { UseFormReturn } from \"react-hook-form\";\nimport { Checkbox, FormControl, FormField, FormItem, FormLabel, FormMessage, Input } from \"../../../../shadcnui\";\n\ntype SecurityConfigurationFormProps = {\n form: UseFormReturn<any>;\n};\n\ntype Fields = {\n fields: string[];\n defaults: Record<string, any>;\n};\n\nconst providerConfig: Fields = {\n fields: [\"isManagedKnowledge\", \"allowPublicBot\"],\n defaults: {},\n};\n\nexport function CompanyConfigurationSecurityForm({ form }: SecurityConfigurationFormProps) {\n const t = useTranslations();\n\n const renderProviderFields = () => {\n const config = providerConfig;\n if (!config) return null;\n\n return config.fields.map((currentField) => {\n const isRequired = currentField === \"\";\n\n let label = \"\";\n let placeholder = \"\";\n let type = \"text\";\n\n switch (currentField) {\n case \"isManagedKnowledge\":\n label = \"Limit Require structured knowledge management\";\n placeholder =\n \"Enforce single-nesting expertises, require expertise associations to content, and enable knowledge manager roles for better long-term organization.\";\n type = \"checkbox\";\n break;\n case \"allowPublicBot\":\n label = \"Allow Public Bot\";\n placeholder = \"Enable this to allow the public to access public information.\";\n type = \"checkbox\";\n break;\n }\n\n return (\n <FormField\n key={currentField}\n control={form.control}\n name={currentField}\n render={({ field: formField }) =>\n type === \"checkbox\" ? (\n <FormItem className=\"flex items-start space-x-4\">\n <FormControl>\n <Checkbox\n id={currentField}\n checked={formField.value}\n onCheckedChange={(checked) => {\n return checked ? formField.onChange(true) : formField.onChange(false);\n }}\n />\n </FormControl>\n <div className=\"grid gap-2\">\n <FormLabel htmlFor={currentField}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </FormLabel>\n <p className=\"text-muted-foreground text-sm\">{placeholder}</p>\n </div>\n <FormLabel></FormLabel>\n <FormMessage />\n </FormItem>\n ) : (\n <FormItem>\n <FormLabel>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </FormLabel>\n <FormControl>\n <Input type={type} placeholder={placeholder} {...formField} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )\n }\n />\n );\n });\n };\n\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-4 border-t pt-4\">{renderProviderFields()}</div>\n </div>\n );\n}\n","\"use client\";\n\nimport { LoaderCircleIcon, Trash2Icon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useState } from \"react\";\nimport { errorToast } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { useI18nRouter } from \"../../../../i18n\";\nimport { Action } from \"../../../../permissions\";\nimport { getRoleId } from \"../../../../roles\";\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n Button,\n Input,\n Label,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { CompanyInterface } from \"../../data\";\nimport { CompanyService } from \"../../data/company.service\";\n\ntype CompanyDeleterProps = {\n company: CompanyInterface;\n};\n\nfunction CompanyDeleterInternal({ company }: CompanyDeleterProps) {\n const t = useTranslations();\n const router = useI18nRouter();\n const [open, setOpen] = useState<boolean>(false);\n const [isDeleting, setIsDeleting] = useState<boolean>(false);\n const [companyName, setCompanyName] = useState<string>(\"\");\n\n const handleDelete = async () => {\n setIsDeleting(true);\n try {\n await CompanyService.delete({ companyId: company.id });\n router.push(\"/\");\n } catch (error) {\n errorToast({ title: t(`generic.errors.delete`), error: error });\n }\n setIsDeleting(false);\n };\n\n return (\n <AlertDialog open={open} onOpenChange={setOpen}>\n <AlertDialogTrigger asChild>\n <Button size=\"sm\" variant={\"destructive\"}>\n <Trash2Icon className=\"mr-3 h-3.5 w-3.5\" />\n {t(`generic.buttons.delete`)}\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>\n <AlertDialogHeader>\n <AlertDialogTitle>{t(`generic.delete.title`, { type: t(`types.companies`, { count: 1 }) })}</AlertDialogTitle>\n <AlertDialogDescription>\n {t(`generic.delete.subtitle`, { type: t(`types.companies`, { count: 1 }) })}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <div className=\"text-destructive p-4 text-sm\">\n {t(`generic.delete.description`, { type: t(`types.companies`, { count: 1 }) })}\n </div>\n <div className=\"flex w-full flex-col gap-y-2\">\n <div>{t(`generic.delete.confirmation`, { type: t(`types.companies`, { count: 1 }) })}</div>\n <div className=\"flex w-full flex-col\">\n <Label className=\"flex items-center\">\n {t(`foundations.company.fields.name.label`)}\n <span className=\"text-destructive ml-2 font-semibold\">*</span>\n </Label>\n <Input\n className={`w-full`}\n placeholder={t(`foundations.company.fields.name.placeholder`)}\n onChange={(e) => setCompanyName(e.target.value)}\n />\n </div>\n </div>\n <div className=\"flex justify-end\">\n <Button\n className=\"mr-2\"\n variant={\"outline\"}\n type={`button`}\n onClick={() => setOpen(false)}\n disabled={isDeleting}\n >\n {t(`generic.buttons.cancel`)}\n </Button>\n <Button\n type=\"submit\"\n onClick={(e) => {\n e.preventDefault();\n handleDelete();\n }}\n variant={\"destructive\"}\n disabled={company.name !== companyName || isDeleting}\n >\n {isDeleting ? (\n <>\n {t(`generic.buttons.is_deleting`)}\n <LoaderCircleIcon className=\"animate-spin-slow h-5 w-5\" />\n </>\n ) : (\n t(`generic.buttons.delete`)\n )}\n </Button>\n </div>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n\nexport function CompanyDeleter({ company }: CompanyDeleterProps) {\n const { hasPermissionToModule, hasRole } = useCurrentUserContext<UserInterface>();\n\n if (!hasRole(getRoleId().Administrator) && !hasPermissionToModule({ module: Modules.Company, action: Action.Delete }))\n return null;\n\n return <CompanyDeleterInternal company={company} />;\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { setCookie } from \"cookies-next\";\nimport { UploadIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { DropzoneOptions } from \"react-dropzone\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { v4 } from \"uuid\";\nimport { z } from \"zod\";\nimport {\n CommonEditorButtons,\n CommonEditorHeader,\n CommonEditorTrigger,\n errorToast,\n FileInput,\n FileUploader,\n FormFeatures,\n FormInput,\n} from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { useI18nRouter } from \"../../../../i18n\";\nimport { getRoleId } from \"../../../../roles\";\nimport { Dialog, DialogContent, Form, ScrollArea } from \"../../../../shadcnui\";\nimport { FeatureInterface } from \"../../../feature\";\nimport { S3Interface } from \"../../../s3\";\nimport { FeatureService } from \"../../../feature/data/feature.service\";\nimport { S3Service } from \"../../../s3/data/s3.service\";\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { CompanyInput, CompanyInterface } from \"../../data\";\nimport { CompanyService } from \"../../data/company.service\";\n\ntype CompanyEditorProps = {\n company?: CompanyInterface;\n propagateChanges?: (company: CompanyInterface) => void;\n onRevalidate?: (path: string) => Promise<void>;\n};\n\nfunction CompanyEditorInternal({ company, propagateChanges, onRevalidate }: CompanyEditorProps) {\n const { hasRole } = useCurrentUserContext<UserInterface>();\n const router = useI18nRouter();\n const [open, setOpen] = useState<boolean>(false);\n const [features, setFeatures] = useState<FeatureInterface[]>([]);\n const [file, setFile] = useState<File | null>(null);\n const [files, setFiles] = useState<File[] | null>(null);\n const [contentType, setContentType] = useState<string | null>(null);\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n\n const formSchema = z.object({\n id: z.uuidv4(),\n name: z.string().min(1, {\n message: t(`foundations.company.fields.name.error`),\n }),\n featureIds: z.array(z.string()).optional(),\n moduleIds: z.array(z.string()).optional(),\n logo: z.string().optional(),\n });\n\n const form = useForm({\n resolver: zodResolver(formSchema),\n defaultValues: {\n id: company?.id || v4(),\n name: company?.name || \"\",\n featureIds: company?.features.map((feature) => feature.id) || [],\n moduleIds: company?.modules.map((module) => module.id) || [],\n logo: company?.logo || \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n if (values.logo && contentType) {\n const s3: S3Interface = await S3Service.getPreSignedUrl({\n key: values.logo,\n contentType: contentType,\n isPublic: true,\n });\n\n await fetch(s3.url, {\n method: \"PUT\",\n headers: s3.headers,\n body: file,\n });\n }\n\n const payload: CompanyInput = {\n id: company?.id ?? v4(),\n name: values.name,\n logo: files && contentType ? values.logo : undefined,\n featureIds: values.featureIds,\n moduleIds: values.moduleIds,\n };\n\n try {\n const updatedCompany = company ? await CompanyService.update(payload) : await CompanyService.create(payload);\n\n if (onRevalidate) {\n await onRevalidate(generateUrl({ page: Modules.Company, id: updatedCompany.id, language: `[locale]` }));\n }\n if (company && propagateChanges) {\n setCookie(\"reloadData\", \"true\", { path: \"/\" });\n propagateChanges(updatedCompany);\n setOpen(false);\n } else {\n router.push(`/administration/companies/${updatedCompany.id}`);\n }\n } catch (error) {\n errorToast({\n title: company ? t(`generic.errors.update`) : t(`generic.errors.create`),\n error,\n });\n }\n };\n\n useEffect(() => {\n async function fetchFeatures() {\n const allfeatures = await FeatureService.findMany({});\n if (hasRole(getRoleId().Administrator)) {\n setFeatures(allfeatures);\n } else {\n setFeatures(allfeatures.filter((feature) => feature.isProduction));\n }\n }\n if (\n open &&\n features.length === 0 &&\n (hasRole(getRoleId().Administrator) ||\n (hasRole(getRoleId().CompanyAdministrator) &&\n process.env.NEXT_PUBLIC_PRIVATE_INSTALLATION?.toLowerCase() === \"true\"))\n )\n fetchFeatures();\n }, [open, features]);\n\n useEffect(() => {\n if (file && company) {\n const id = form.getValues(\"id\");\n const fileType = file.type;\n let extension = \"\";\n\n switch (fileType) {\n default:\n extension = file.type.split(\"/\").pop() ?? \"\";\n break;\n }\n\n const timestamp = new Date().toISOString().replace(/[-:T]/g, \"\").split(\".\")[0];\n\n const fileUrl = `companies/${form.getValues(\"id\")}/companies/${id}/${id}.${timestamp}.${extension}`;\n form.setValue(\"logo\", fileUrl);\n\n setContentType(fileType);\n } else {\n setContentType(null);\n }\n }, [file]);\n\n useEffect(() => {\n if (files && files.length > 0) {\n setFile(files[0]);\n }\n }, [files]);\n\n const dropzone = {\n multiple: false,\n maxSize: 100 * 1024 * 1024,\n preventDropOnDocument: false,\n accept: {\n \"application/images\": [\".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".svg\"],\n },\n } satisfies DropzoneOptions;\n\n const canAccessFeatures =\n hasRole(getRoleId().Administrator) ||\n (hasRole(getRoleId().CompanyAdministrator) &&\n process.env.NEXT_PUBLIC_PRIVATE_INSTALLATION?.toLowerCase() === \"true\");\n\n const isAdministrator = hasRole(getRoleId().Administrator);\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <CommonEditorTrigger isEdit={!!company} />\n <DialogContent\n className={`flex max-h-[70vh] w-full ${isAdministrator || canAccessFeatures ? `max-w-5xl` : `max-w-4xl`} flex-col overflow-y-auto`}\n >\n <CommonEditorHeader type={t(`types.companies`, { count: 1 })} name={company?.name} />\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className={`flex w-full flex-col gap-y-4`}>\n <div className=\"flex w-full items-start justify-between gap-x-4\">\n <div className={`flex w-96 flex-col justify-start gap-y-4`}>\n <FileUploader value={files} onValueChange={setFiles} dropzoneOptions={dropzone} className=\"w-full p-4\">\n <FileInput className=\"text-neutral-300 outline-dashed\">\n <div className=\"flex w-full flex-col items-center justify-center pt-3 pb-4\">\n <div className=\"flex w-full flex-col items-center justify-center pt-3 pb-4\">\n {file || company?.logo ? (\n <Image\n src={file ? URL.createObjectURL(file) : company?.logo || \"\"}\n alt=\"Company Logo\"\n width={200}\n height={200}\n />\n ) : (\n <>\n <UploadIcon className=\"my-4 h-8 w-8\" />\n <p className=\"mb-1 flex w-full text-center text-sm\">\n {t(`foundations.company.click_drag_logo`)}\n </p>\n </>\n )}\n </div>\n </div>\n </FileInput>\n </FileUploader>\n </div>\n <div className={`flex w-full flex-col justify-start gap-y-4`}>\n <FormInput\n form={form}\n id=\"name\"\n name={t(`foundations.company.fields.name.label`)}\n placeholder={t(`foundations.company.fields.name.placeholder`)}\n />\n </div>\n {canAccessFeatures && (\n <div className={`flex w-96 flex-col justify-start gap-y-4`}>\n <ScrollArea className=\"h-max\">\n <FormFeatures\n form={form}\n name={t(`foundations.company.features_and_modules`)}\n features={features}\n />\n </ScrollArea>\n </div>\n )}\n </div>\n <CommonEditorButtons form={form} setOpen={setOpen} isEdit={!!company} />\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport function CompanyEditor(props: CompanyEditorProps) {\n return <CompanyEditorInternal {...props} />;\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { deleteCookie } from \"cookies-next\";\nimport { ClipboardIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport z from \"zod\";\nimport { errorToast, FormInput, FormTextarea } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { useI18nRouter, usePageUrlGenerator } from \"../../../../hooks\";\nimport { getRoleId } from \"../../../../roles\";\nimport {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n Form,\n Input,\n Label,\n Link,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { UserService } from \"../../../user/data/user.service\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { CompanyInput } from \"../../data\";\nimport { CompanyService } from \"../../data/company.service\";\n\ntype TokenPayload = {\n userId: string;\n companyId?: string;\n licenseExpirationDate?: Date;\n roles: string[];\n features: string[];\n modules: {\n id: string;\n permissions: {\n create: boolean | string;\n read: boolean | string;\n update: boolean | string;\n delete: boolean | string;\n };\n }[];\n};\n\ntype CompanyLicenseProps = {\n onRevalidate?: (path: string) => Promise<void>;\n onUpdateToken?: (token: TokenPayload) => Promise<void>;\n};\n\nexport default function CompanyLicense({ onRevalidate, onUpdateToken }: CompanyLicenseProps = {}) {\n const { currentUser, setUser, hasRole } = useCurrentUserContext<UserInterface>();\n\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n const router = useI18nRouter();\n\n const copyToClipboard = (text: string) => {\n navigator.clipboard.writeText(text);\n toast(\"Copied to clipboard\");\n };\n\n const formSchema = z.object({\n license: z.string().min(1, {\n message: `License is required`,\n }),\n privateKey: z.string().min(1, {\n message: `Private key is required`,\n }),\n });\n\n const defaultValues = {\n license:\n \"09001678dca2f4a6d2d32bb984811278:3e93a432f6130579e543a511346c0d2c6ca7a97d49c7ff2d3e789ca7c7c8d79b864fd3406c8315e72aa5febf6232776dfaea51d72168ddcdd34a59ea1a05b3b3dd60ac3af6c3934203d19ea68642293aa5b79f012633b4ba2e4a474e9ceed6b6cda13d8dedc8e60ece61886843ee6edc1af6d2da5e07945033295507df6f87994f8347b5759b446aa20b1185d7b5c54c67509ae280e729913d0e68e95b5f090b0577a8a735f24fb7c1df8f6586886d840af4a43f9dc74d5d1f291058a45ace759176fa19fe5e164f5d8307981e8bcd166f346e97b676dd0242d1c30ec4fe744f22621fae603b1caaac25f198d2b29be0e0f2afc81a40edeb20242345e2feac8666027d0c30aa8dadbca742dd68ade46602545979f473b344021d27921553d5b284fd96a717b74573ca7e693723876357013e3c0d07a35d270a0e32654d2c244220e2492380279aa34a4744d145b89d06a8abef49cc2ef0dd0171e0eefcf16724decf53e545d10d9bfd8e0c4b03ca720b0fc63d8a20ca2c71d74cb0cf7e547637dbcc8d27257414b5b0b40eabe9eb53a4b5f61ca2250d5933a13565f785a89fc5e3e3c468acbeddf14627aa4109f32af641fc96513e52edc21849e81331cafc900ea85f58927d583aafe5a959af69ce5c967d0cd5d9050cf6601a615e8e3ccf32e6a04227f1f228d94f9bd24073c7b0ec2550f4efc69bddde745144dcb279864fb3e7e7d57d1e96d0701b55f0d6f3bd688880e4a78adb0974cba278cd34bc02753e8a736a4b3a4e48afdf206b9330fee4e29a3c28dec8457e0f44adc10735c1d1992b798e0dd710053ce98ff38b6ff59004079a5face769950401b49fdc13e4cd3324d7df2cf0f40593f51c117debbafd\",\n privateKey:\n \"-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCKDXrjEXBcYx6p\\nChtixITGiFqZeaurD3n2SeJl8QuniKlbl7ytC71gS9BzIG5Q/ENhAE41qa7FaHdN\\nHLQ2anfAjS/wd/41wx9ilvQeN/IcDb5Dx3Qd07OMLdrgDvkhlUPSvt7Y5/yft1IX\\nS8NaDrKoO4zjpVB9SeLYGyFXmfP0ciJ97AkWDfXp3l2WjwwxEQByo5uXOMzpEZla\\nkqBFy7kkO3c/SJWqnuXbXrUVr7AjZ9zMCPP/NbvvOkGzovrOYHN5WO9Rg7m+wIFK\\n+gTL2e3RnyjUUSoX5/NMZO9oyDNEaaWgIv6LOG72A2Xq55gpNQihjltZWd/o+xFb\\nIRZzbmllAgMBAAECggEABrrvgcBo5OgkJ4OJoEAKZQ9is1a+KsG/ZWVmtyeQNOOx\\ntfhox1rqKZaom+Q53JLfygvUxEL4dUFJh6Xdl0WLfwSjEKsY5pATqJ/JWOvLTtjQ\\nrMc9fvLCLxRRNlkkhiGbw9twS8zLgRHT27Ti2jIbPZ5hmPuHOARxHa386yNjREh1\\n14Vlhk+dvhmqtYt11AKWuU8nHuf92wCCetATUg/pfNQ1itf6XDlygUZTl4GkoJg/\\nVrt1MnsrTKcGzP+gvpNH0aOuUbgtUWtBIKaSuGgY6lMMny6AApeJ+kXZR8cyPVSi\\nYm/185AcxQDlPunoyl3QzvV41zJUccoMI576wFTUQQKBgQC8QQtNXjfcQvYDeVv8\\ntWKAxgk+OE6/3ntLkbYxPw2H5IOikhb5OjNirzUzRs4CKjnGhx0zDzCi4TV2xwZf\\nwDHpd9VEhEXmKBJe43RCQs0vb1jwz4ttRk9eoz1Oa4cNij3yH5F4oNu5ZnOSZWi/\\n1c4mIsGjjTWzeOkJ6J+fCc6ztQKBgQC7u53nuvMubVhNW3FyuHaXuE+nUlNaw2gc\\n9mhm17DY+MBf2YqdJOCY1B44WMIZe3k/75qXrZEYG4ikdlAGzrh7q3/8GMKCxk8P\\n5y+YeKODdURM1SsUoOqAzga7s2vFxnChtWxk3KfXCzjKUoX/9zWX/zfIAl9VsVVC\\nhrARyffM8QKBgC6pIJgIpmfd4QRzbC1y9/tbGqdlZX+BMaZFc5c5Pa1VIpuFAlS7\\n7EiljNYs0psOxEtE6iPhu/hjQdEy+414IebwYNgewQSPIh6K2iIiVKFRRAZMKw7m\\nwn1+kI+Db3IXtcrxsCjqFgwaLMM4h4IlCHfDXaOgOJNHgNuH4SiWUbmRAoGAUGD4\\nLuugi1RN5nEslc3dGQDVOfLJtabMwPnPoZjgI0X+OAvQiY/sigLoHYADOx3ewD06\\nl468/PFtA92UThXcbzbyyWFghtWZrFlzy3h7qiFfaPYsR9zOCvAredpMXpWkS9h9\\n3IGNa0lmu1mx/fI+hCHGJGC/qNUQiDda04MCEkECgYAxDhQW7sRox+7Pn0TsRotN\\nTv6AJggyTjBaF45fVy+28sn53f/9HE++Rxn8W5xQl+hEOywT95OcWB9b4CiZsp1P\\nZyjkByeUuraVM1DoFh66UdXUvC2FECdyz4N3JyKHvV82GdrTPsQLVPCsGfzkj7V8\\nX+iuQoeEbUvwnnrg3pbClQ==\\n-----END PRIVATE KEY-----\\n\",\n };\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: defaultValues,\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n if (!currentUser || !currentUser.company) {\n errorToast({\n title: t(\"generic.errors.error\"),\n error: new Error(\"User or company not found\"),\n });\n return;\n }\n\n const payload: CompanyInput = {\n id: currentUser.company.id,\n license: values.license,\n privateKey: values.privateKey,\n };\n\n try {\n const updatedLicense = await CompanyService.activateLicense(payload);\n\n const fullUser = await UserService.findFullUser();\n\n if (fullUser) {\n setUser(fullUser);\n const token = {\n userId: fullUser.id,\n companyId: fullUser.company?.id,\n licenseExpirationDate: fullUser.company?.licenseExpirationDate,\n roles: fullUser.roles.map((role) => role.id),\n features: fullUser.company?.features?.map((feature) => feature.id) ?? [],\n modules: fullUser.modules.map((module) => {\n return { id: module.id, permissions: module.permissions };\n }),\n };\n\n if (onUpdateToken) {\n await onUpdateToken(token);\n }\n deleteCookie(\"reloadData\");\n }\n\n if (onRevalidate) {\n await onRevalidate(generateUrl({ page: Modules.Company, id: updatedLicense.id, language: `[locale]` }));\n }\n router.push(generateUrl({ page: \"/\" }));\n } catch (error) {\n errorToast({\n title: t(`generic.errors.update`),\n error,\n });\n }\n };\n\n if (!currentUser || !currentUser.company) return null;\n\n return (\n <Form {...form}>\n <form\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"relative flex min-h-screen w-full flex-col items-center justify-center\"\n >\n <div className=\"absolute top-4 left-4 z-0\">\n <Image src={`/logo.webp`} className=\"object-contain p-4\" height={300} width={300} alt={\"Logo\"} priority />\n </div>\n <Card className=\"z-10 w-3xl\">\n {hasRole(getRoleId().CompanyAdministrator) ? (\n <>\n <CardHeader>\n <CardTitle>Company License Required</CardTitle>\n <CardDescription className={`flex w-full flex-col`}>\n <div>You need to activate your license to use Phlow.</div>\n <div>\n <span>To obtain your license, please visit</span>\n <Link href=\"https://phlow.com\" target=\"_blank\" className={`text-primary`}>\n our website (https://phlow.com)\n </Link>\n <span>, register for an account and follow the instructions provided.</span>\n </div>\n <div>You will be required to provide the installation identifier provided below.</div>\n <div>\n Once you have activated your license, please paste your license and private key in the fields below.\n </div>\n </CardDescription>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-y-4\">\n <div>\n <Label>Installation Identifier</Label>\n <div className=\"flex items-center\">\n <Input disabled value={currentUser.company.id} />\n <ClipboardIcon\n className=\"text-muted-foreground ml-2 cursor-pointer\"\n onClick={() => copyToClipboard(currentUser!.company!.id)}\n />\n </div>\n </div>\n <div>\n <FormInput form={form} id=\"license\" name={\"license\"} placeholder=\"Enter your license\" />\n </div>\n <div>\n <FormTextarea name=\"Private Key\" form={form} id=\"privateKey\" placeholder=\"Enter your private key\" />\n </div>\n </CardContent>\n <CardFooter className=\"flex justify-end\">\n <Button type=\"submit\">Activate License</Button>\n </CardFooter>\n </>\n ) : (\n <>\n <CardHeader>\n <CardTitle>Company License Required</CardTitle>\n <CardDescription className={`flex w-full flex-col`}>\n The company license is either missing or expired.\n </CardDescription>\n </CardHeader>\n <CardContent>Please contact your system administrator to resolve this issue.</CardContent>\n </>\n )}\n </Card>\n </form>\n </Form>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ReactNode } from \"react\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { CompanyFields, CompanyInterface } from \"../../data\";\nimport { CompanyService } from \"../../data/company.service\";\nimport { CompanyEditor } from \"../forms/CompanyEditor\";\n\nexport function CompaniesList() {\n const t = useTranslations();\n\n const data: DataListRetriever<CompanyInterface> = useDataListRetriever({\n retriever: (params) => CompanyService.findMany(params),\n retrieverParams: {},\n module: Modules.Company,\n });\n\n const functions: ReactNode[] = [<CompanyEditor key=\"create-account\" />];\n\n return (\n <ContentListTable\n data={data}\n fields={[CompanyFields.name, CompanyFields.createdAt]}\n tableGeneratorType={Modules.Company}\n functions={functions}\n title={t(`types.companies`, { count: 2 })}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport React, { createContext, ReactElement, useCallback, useContext, useState } from \"react\";\nimport { SharedProvider } from \"../../../contexts\";\nimport { Modules } from \"../../../core\";\nimport { useI18nRouter } from \"../../../i18n\";\nimport { BreadcrumbItemData } from \"../../../interfaces\";\nimport { NotificationMenuItem, NotificationToast } from \"../components/notifications/Notification\";\nimport { NotificationInterface } from \"../data\";\nimport { NotificationService } from \"../data/notification.service\";\n\ninterface NotificationContextType {\n notifications: NotificationInterface[];\n setNotifications: (notifications: NotificationInterface[]) => void;\n addNotification: (notification: NotificationInterface) => void;\n addSocketNotifications: (socketNotifications: NotificationInterface[]) => void;\n loadNotifications: () => Promise<void>;\n generateNotification: (notification: NotificationInterface, closePopover: () => void) => ReactElement<any>;\n generateToastNotification: (\n notification: NotificationInterface,\n t: any,\n generateUrl: any,\n ) => {\n title: string;\n description: string | ReactElement<any>;\n action?: {\n label: string;\n onClick: () => void;\n };\n };\n markNotificationsAsRead: (ids: string[]) => Promise<void>;\n isLoading: boolean;\n error: string | null;\n lastLoaded: number;\n shouldRefresh: boolean;\n}\n\nconst NotificationContext = createContext<NotificationContextType | undefined>(undefined);\n\ntype NotificationContextProviderProps = {\n children: React.ReactNode;\n};\n\nexport const NotificationContextProvider = ({ children }: NotificationContextProviderProps) => {\n const t = useTranslations();\n const router = useI18nRouter();\n\n const [notifications, setNotifications] = useState<NotificationInterface[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [lastLoaded, setLastLoaded] = useState(0);\n\n // Calculate shouldRefresh (5 minute cache)\n const shouldRefresh = Date.now() - lastLoaded > 5 * 60 * 1000;\n\n const addNotification = useCallback((notification: NotificationInterface) => {\n setNotifications((prev) => {\n // Check if notification already exists to prevent duplicates\n const exists = prev.some((n) => n.id === notification.id);\n if (exists) return prev;\n return [notification, ...prev];\n });\n }, []);\n\n const addSocketNotifications = useCallback((socketNotifications: NotificationInterface[]) => {\n setNotifications((prev) => {\n const newNotifications = socketNotifications.filter(\n (newNotif) => !prev.some((existingNotif) => existingNotif.id === newNotif.id),\n );\n return [...prev, ...newNotifications];\n });\n }, []);\n\n const loadNotifications = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n const fetchedNotifications = await NotificationService.findMany({});\n setNotifications(fetchedNotifications);\n setLastLoaded(Date.now());\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Failed to load notifications\";\n setError(errorMessage);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const markNotificationsAsRead = useCallback(async (ids: string[]) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const data: any = {\n data: ids.map((id: string) => ({\n type: Modules.Notification.name,\n id: id,\n attributes: {\n isRead: true,\n },\n meta: {},\n relationships: {},\n })),\n };\n\n await NotificationService.markAsRead({ data: data });\n const allNotifications = await NotificationService.findMany({});\n setNotifications(allNotifications);\n setLastLoaded(Date.now());\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Failed to mark notifications as read\";\n setError(errorMessage);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const generateToastNotification = (\n notification: NotificationInterface,\n t: any,\n generateUrl: any,\n ): {\n title: string;\n description: string | ReactElement<any>;\n action?: {\n label: string;\n onClick: () => void;\n };\n } => {\n return NotificationToast(notification, t, generateUrl, router);\n };\n\n const generateNotification = (notification: NotificationInterface, closePopover: () => void) => {\n return <NotificationMenuItem notification={notification} closePopover={closePopover} />;\n };\n\n const breadcrumb = () => {\n const response: BreadcrumbItemData[] = [];\n\n response.push({\n name: t(`types.notifications`, { count: 2 }),\n });\n\n return response;\n };\n\n const title = () => {\n const response: any = {\n type: t(`types.notifications`, { count: 2 }),\n };\n\n return response;\n };\n\n return (\n <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>\n <NotificationContext.Provider\n value={{\n notifications,\n setNotifications,\n addNotification,\n addSocketNotifications,\n loadNotifications,\n generateNotification,\n generateToastNotification,\n markNotificationsAsRead,\n isLoading,\n error,\n lastLoaded,\n shouldRefresh,\n }}\n >\n {children}\n </NotificationContext.Provider>\n </SharedProvider>\n );\n};\n\nexport const useNotificationContext = (): NotificationContextType => {\n const context = useContext(NotificationContext);\n if (context === undefined) {\n throw new Error(`Notification.messages.errors.use_context`);\n }\n return context;\n};\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ReactElement, useEffect, useState } from \"react\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { Link } from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { UserAvatar } from \"../../../user/components\";\nimport { NotificationInterface } from \"../../data\";\n\ntype TaskCommentedOnProps = {\n notification: NotificationInterface;\n closePopover: () => void;\n};\n\nexport const generateNotificationData = (params: {\n notification: NotificationInterface;\n generateUrl: any;\n}): { title: string; actor?: UserInterface; url?: string; taskId?: string } => {\n const response: any = {};\n\n response.actor = params.notification.actor;\n\n return response;\n};\n\nexport function NotificationToast(\n notification: NotificationInterface,\n t: any,\n generateUrl: any,\n reouter: any,\n): {\n title: string;\n description: string | ReactElement<any>;\n action?: {\n label: string;\n onClick: () => void;\n };\n} {\n const data = generateNotificationData({ notification: notification, generateUrl: generateUrl });\n\n return {\n title: t(`foundations.notification.${notification.notificationType}.title`),\n description: (\n <div className={`flex w-full flex-row items-center p-2`}>\n {data.actor ? (\n <div className=\"flex w-12 max-w-12 px-2\">\n <UserAvatar user={data.actor} className=\"h-8 w-8\" />\n </div>\n ) : (\n <div className=\"flex w-14 max-w-14 px-2\"></div>\n )}\n <div className=\"flex w-full flex-col\">\n <p className=\"text-sm\">\n {t.rich(`foundations.notification.${notification.notificationType}.description`, {\n strong: (chunks: any) => <strong>{chunks}</strong>,\n actor: data.actor?.name ?? \"\",\n title: data.title,\n })}\n </p>\n <div className=\"text-muted-foreground mt-1 w-full text-xs\">\n {new Date(notification.createdAt).toLocaleString()}\n </div>\n </div>\n </div>\n ),\n action: data.url\n ? {\n label: t(`foundations.notification.${notification.notificationType}.buttons.action`),\n onClick: () => {\n reouter.push(data.url!);\n },\n }\n : undefined,\n };\n}\n\nexport function NotificationMenuItem({ notification, closePopover }: TaskCommentedOnProps) {\n const generateUrl = usePageUrlGenerator();\n const [isRead, setIsRead] = useState<boolean>(false);\n const t = useTranslations();\n\n useEffect(() => {\n setIsRead(notification.isRead);\n }, []);\n\n const data = generateNotificationData({ notification: notification, generateUrl: generateUrl });\n\n const response = (\n <div className={`flex w-full flex-row p-2 ${isRead ? \"\" : \"bg-muted\"} items-center`}>\n {data.actor ? (\n <div className=\"flex w-12 max-w-12 px-2\">\n <UserAvatar user={data.actor} className=\"h-8 w-8\" />\n </div>\n ) : (\n <div className=\"flex w-14 max-w-14 px-2\"></div>\n )}\n <div className=\"flex w-full flex-col\">\n <p className=\"text-sm\">\n {t.rich(`foundations.notification.${notification.notificationType}.description` as any, {\n strong: (chunks: any) => <strong>{chunks}</strong>,\n actor: data.actor?.name ?? \"\",\n title: data.title,\n })}\n </p>\n <div className=\"text-muted-foreground mt-1 w-full text-xs\">\n {new Date(notification.createdAt).toLocaleString()}\n </div>\n </div>\n </div>\n );\n\n if (!data.url) return response;\n\n return (\n <Link href={data.url} onClick={closePopover}>\n {response}\n </Link>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { createContext, ReactNode, useContext, useState } from \"react\";\nimport { SharedProvider } from \"../../../contexts\";\nimport { JsonApiHydratedDataInterface, Modules, rehydrate } from \"../../../core\";\nimport { usePageUrlGenerator } from \"../../../hooks\";\nimport { BreadcrumbItemData } from \"../../../interfaces\";\nimport { RoleInterface } from \"../data\";\n\ninterface RoleContextType {\n role: RoleInterface | undefined;\n setRole: (value: RoleInterface | undefined) => void;\n}\n\nconst RoleContext = createContext<RoleContextType | undefined>(undefined);\n\ntype RoleProviderProps = {\n children: ReactNode;\n dehydratedRole?: JsonApiHydratedDataInterface;\n};\n\nexport const RoleProvider = ({ children, dehydratedRole }: RoleProviderProps) => {\n const generateUrl = usePageUrlGenerator();\n const t = useTranslations();\n\n const [role, setRole] = useState<RoleInterface | undefined>(\n dehydratedRole ? rehydrate<RoleInterface>(Modules.Role, dehydratedRole) : undefined,\n );\n\n const breadcrumb = () => {\n const response: BreadcrumbItemData[] = [];\n\n response.push({\n name: t(`types.roles`, { count: 2 }),\n href: generateUrl({ page: Modules.Role }),\n });\n\n if (role)\n response.push({\n name: role.name,\n href: generateUrl({ page: Modules.Role, id: role.id }),\n });\n\n return response;\n };\n\n const title = () => {\n const response: any = {\n type: t(`types.roles`, { count: role ? 1 : 2 }),\n };\n\n const functions: ReactNode[] = [];\n\n if (role) {\n response.element = role.name;\n }\n\n if (functions.length > 0) response.functions = functions;\n\n return response;\n };\n\n return (\n <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>\n <RoleContext.Provider\n value={{\n role: role,\n setRole: setRole,\n }}\n >\n {children}\n </RoleContext.Provider>\n </SharedProvider>\n );\n};\n\nexport const useRoleContext = (): RoleContextType => {\n const context = useContext(RoleContext);\n if (context === undefined) {\n throw new Error(\"useRoleContext must be used within a RoleProvider\");\n }\n return context;\n};\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\n\nimport { createContext, ReactNode, useContext } from \"react\";\nimport { UserInterface } from \"../features/user/data\";\nimport { useCurrentUserContext } from \"../features/user/contexts\";\nimport { BreadcrumbItemData } from \"../interfaces\";\nimport { SharedProvider } from \"./SharedContext\";\n\ninterface CommonContextType {}\n\nconst CommonContext = createContext<CommonContextType | undefined>(undefined);\n\ntype CommonProviderProps = {\n children: ReactNode;\n};\n\nexport const CommonProvider = ({ children }: CommonProviderProps) => {\n const { company } = useCurrentUserContext<UserInterface>();\n const t = useTranslations();\n\n const breadcrumb = () => {\n const response: BreadcrumbItemData[] = [];\n\n return response;\n };\n\n const title = () => {\n const response: any = {\n type: t(`generic.title`),\n };\n\n if (company) response.element = company.name;\n\n return response;\n };\n\n return (\n <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>\n <CommonContext.Provider value={{}}>{children}</CommonContext.Provider>\n </SharedProvider>\n );\n};\n\nexport const useCommonContext = (): CommonContextType => {\n const context = useContext(CommonContext);\n if (context === undefined) {\n throw new Error(\"useCommonContext must be used within a CommonProvider\");\n }\n return context;\n};\n","\"use client\";\n\nimport { createContext, ReactNode, useContext } from \"react\";\nimport { BreadcrumbItemData } from \"../interfaces\";\n\nconst SharedContext = createContext<{\n breadcrumbs: BreadcrumbItemData[];\n title: {\n type: string | string[];\n element?: string;\n functions?: ReactNode;\n };\n} | null>(null);\n\ninterface SharedProviderProps {\n children: ReactNode;\n value: {\n breadcrumbs: BreadcrumbItemData[];\n title: {\n type: string;\n element?: string;\n functions?: ReactNode;\n };\n };\n}\n\nexport const SharedProvider = ({ children, value }: SharedProviderProps) => {\n return <SharedContext.Provider value={value}>{children}</SharedContext.Provider>;\n};\n\nexport const useSharedContext = () => {\n const context = useContext(SharedContext);\n if (!context) {\n throw new Error(\"useSharedContext must be used within a SharedProvider\");\n }\n return context;\n};\n","\"use client\";\n\nimport React, { createContext, useContext } from \"react\";\nimport { NotificationInterface } from \"../features/notification/data\";\nimport { useSocket } from \"../hooks\";\n\ninterface SocketContextProps {\n socket: ReturnType<typeof useSocket>[\"socket\"];\n isConnected: boolean;\n messages: any[];\n socketNotifications: NotificationInterface[];\n sendMessage: (event: string, data: any) => void;\n removeMessage: (index: number) => void;\n removeSocketNotification: (index: number) => void;\n clearMessages: () => void;\n clearSocketNotifications: () => void;\n}\n\nconst defaultContextValue: SocketContextProps = {\n socket: null,\n isConnected: false,\n messages: [],\n socketNotifications: [],\n sendMessage: () => {},\n removeMessage: () => {},\n removeSocketNotification: () => {},\n clearMessages: () => {},\n clearSocketNotifications: () => {},\n};\n\nexport const SocketContext = createContext<SocketContextProps>(defaultContextValue);\n\ninterface SocketProviderProps {\n token?: string;\n children: React.ReactNode;\n}\n\nexport const SocketProvider: React.FC<SocketProviderProps> = ({ token, children }) => {\n const socketHookData = token ? useSocket({ token }) : null;\n\n const sendMessage = (event: string, data: any) => {\n const currentSocket = socketHookData ? socketHookData.socket : defaultContextValue.socket;\n const currentIsConnected = socketHookData ? socketHookData.isConnected : defaultContextValue.isConnected;\n\n if (currentSocket && currentIsConnected) {\n currentSocket.emit(event, data);\n }\n };\n\n const value: SocketContextProps = {\n ...defaultContextValue,\n ...(socketHookData || {}),\n sendMessage: sendMessage,\n };\n\n return <SocketContext.Provider value={value}>{children}</SocketContext.Provider>;\n};\n\nexport const useSocketContext = () => {\n const context = useContext(SocketContext);\n if (!context) {\n throw new Error(\"useSocketContext must be used within a SocketProvider\");\n }\n return context;\n};\n","import { atomWithStorage } from \"jotai/utils\";\n\nexport interface RecentPage {\n url: string;\n title: string;\n moduleType: string;\n timestamp: number;\n}\n\nexport const recentPagesAtom = atomWithStorage<RecentPage[]>(\"recentPages\", []);\n","\"use client\";\n\nimport { useAtom } from \"jotai\";\nimport { usePathname } from \"next/navigation\";\nimport { useEffect } from \"react\";\nimport { RecentPage, recentPagesAtom } from \"../atoms\";\nimport { getTrackablePages } from \"../client/config\";\n\n// Routes to exclude from tracking\nconst EXCLUDED_ROUTES = [\"/\", \"/login\", \"/register\", \"/forgot-password\", \"/reset-password\", \"/activate\"];\n\nexport function usePageTracker() {\n const pathname = usePathname();\n const [_recentPages, setRecentPages] = useAtom(recentPagesAtom);\n\n useEffect(() => {\n if (!pathname) return;\n\n // Exclude certain routes\n if (EXCLUDED_ROUTES.some((route) => pathname === route || pathname.endsWith(route))) {\n return;\n }\n\n // Extract page information from pathname (already locale-free from next-intl)\n const pathParts = pathname.split(\"/\").filter(Boolean);\n\n if (pathParts.length === 0) return;\n\n // Try to find the module based on the route\n const moduleName = pathParts[0];\n const entityId = pathParts.length > 1 ? pathParts[1] : null;\n\n // Only track pages with entity IDs (detail pages)\n if (!entityId) return;\n\n // Find the module from configured trackable pages\n const trackablePages = getTrackablePages();\n const foundModule = trackablePages.find((mod) => mod.pageUrl === `/${moduleName}`);\n\n if (!foundModule) return;\n\n // Only use base path (module/id), ignoring any sub-paths\n const baseUrl = `/${moduleName}/${entityId}`;\n\n let pageTitle = foundModule.name;\n if (typeof document !== \"undefined\") {\n const titleParts = document.title.split(\"]\");\n if (titleParts[1]) {\n const cleanTitle = titleParts[1].split(\"|\")[0]?.trim();\n pageTitle = cleanTitle || foundModule.name;\n }\n }\n\n const newPage: RecentPage = {\n url: baseUrl,\n title: pageTitle,\n moduleType: foundModule.name,\n timestamp: Date.now(),\n };\n\n setRecentPages((prev) => {\n // Remove if already exists (to move to top)\n const filtered = prev.filter((page) => page.url !== newPage.url);\n\n // Add to beginning and limit to 10\n return [newPage, ...filtered].slice(0, 10);\n });\n }, [pathname, setRecentPages]);\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useCurrentUserContext } from \"../contexts\";\nimport { UserInterface } from \"../features/user/data\";\nimport { PushService } from \"../features/push/data/push.service\";\nimport { getRoleId } from \"../roles\";\nimport { getAppUrl } from \"../client/config\";\n\nfunction urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = window.atob(base64);\n const outputArray = new Uint8Array(rawData.length);\n for (let i = 0; i < rawData.length; i++) {\n outputArray[i] = rawData.charCodeAt(i);\n }\n return outputArray;\n}\n\nexport default function usePushNotifications(): void {\n const { currentUser, hasRole } = useCurrentUserContext<UserInterface>();\n\n useEffect(() => {\n const register = async () => {\n if (\"serviceWorker\" in navigator && \"PushManager\" in window) {\n try {\n // Check if we've already processed push notifications for this user in this session\n const sessionKey = `push_registered_${currentUser?.id}`;\n const lastRegisteredSubscription = sessionStorage.getItem(sessionKey);\n\n const registration = await navigator.serviceWorker.register(`${getAppUrl()}/sw.js`);\n\n // Check current permission status first\n let permission = Notification.permission;\n\n // Only request permission if it's not already determined\n if (permission === \"default\") {\n permission = await Notification.requestPermission();\n }\n\n if (permission !== \"granted\") {\n return; // User denied permission, this is not an error\n }\n\n const vapidPublicKey = (process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY || \"\").trim();\n const convertedKey = urlBase64ToUint8Array(vapidPublicKey);\n\n await navigator.serviceWorker.ready;\n\n let subscription = await registration.pushManager.getSubscription();\n if (!subscription) {\n const appServerKey = new Uint8Array(Array.from(convertedKey));\n\n subscription = await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: appServerKey,\n });\n }\n\n const plainSubscription = {\n endpoint: subscription.endpoint,\n keys: subscription.toJSON().keys,\n };\n\n // Create a simple hash to detect subscription changes\n const subscriptionHash = btoa(JSON.stringify(plainSubscription));\n\n // Only call the API if subscription has changed or this is the first registration\n if (lastRegisteredSubscription !== subscriptionHash) {\n await PushService.register({ data: plainSubscription });\n // Store the current subscription hash to avoid duplicate registrations\n sessionStorage.setItem(sessionKey, subscriptionHash);\n }\n } catch (error) {\n console.error(\"Error during service worker registration or push subscription:\", error);\n }\n }\n };\n\n if (currentUser && !hasRole(getRoleId().Administrator)) register();\n }, [currentUser]);\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport io from \"socket.io-client\";\nimport { Modules, rehydrate } from \"../core\";\nimport { NotificationInterface } from \"../features/notification/data\";\n\ntype Socket = ReturnType<typeof io>;\n\ninterface UseSocketOptions {\n token: string;\n}\n\ninterface SocketLike {\n emit: (event: string, ...args: any[]) => void;\n on: (event: string, callback: (...args: any[]) => void) => void;\n off: (event: string, callback?: (...args: any[]) => void) => void;\n connected: boolean;\n}\n\ninterface UseSocketReturn {\n socket: SocketLike | null;\n isConnected: boolean;\n messages: any[];\n socketNotifications: NotificationInterface[];\n sendMessage: (event: string, data: any) => void;\n removeMessage: (index: number) => void;\n removeSocketNotification: (index: number) => void;\n clearMessages: () => void;\n clearSocketNotifications: () => void;\n}\n\nexport function useSocket({ token }: UseSocketOptions): UseSocketReturn {\n const _errorCount = useRef(0);\n const shouldConnect = useRef(true);\n const _hookInstanceId = useRef(Math.random().toString(36).substring(2, 11));\n\n const [socket, setSocket] = useState<Socket | null>(null);\n const [isConnected, setIsConnected] = useState<boolean>(false);\n const [messages, setMessages] = useState<any[]>([]);\n const [socketNotifications, setSocketNotifications] = useState<NotificationInterface[]>([]);\n\n const socketRef = useRef<Socket | null>(null);\n\n useEffect(() => {\n if (!token) return;\n\n const globalSocketKey = `__socket_${process.env.NEXT_PUBLIC_API_URL?.replace(/[^a-zA-Z0-9]/g, \"_\")}`;\n\n if (typeof window !== \"undefined\") {\n const _allSocketKeys = Object.keys(window).filter((key) => key.startsWith(\"__socket_\"));\n\n const existingSocket = (window as any)[globalSocketKey];\n if (existingSocket) {\n if (existingSocket.connected) {\n // CRITICAL: Clear existing listeners to prevent accumulation\n existingSocket.removeAllListeners();\n\n socketRef.current = existingSocket;\n setSocket(existingSocket);\n setIsConnected(existingSocket.connected);\n } else {\n existingSocket.disconnect();\n delete (window as any)[globalSocketKey];\n }\n }\n }\n\n let currentSocket: any;\n const isReusing = socketRef.current && socketRef.current.connected;\n\n if (isReusing) {\n currentSocket = socketRef.current;\n } else {\n // React StrictMode protection: Prevent double-mounting issues\n if (!shouldConnect.current) {\n return;\n }\n shouldConnect.current = false;\n\n try {\n currentSocket = io(process.env.NEXT_PUBLIC_API_URL as string, {\n auth: { token },\n transports: [\"websocket\"],\n timeout: 20000,\n });\n\n if (typeof window !== \"undefined\") {\n if (currentSocket.id && currentSocket.id !== \"undefined\") {\n (window as any)[globalSocketKey] = currentSocket;\n }\n }\n\n socketRef.current = currentSocket;\n setSocket(currentSocket);\n } catch {\n return () => {}; // Return empty cleanup function on error\n }\n }\n\n const handleConnect = () => {\n setIsConnected(true);\n };\n\n const handleDisconnect = () => {\n setIsConnected(false);\n };\n\n const handleMessage = (data: any) => {\n setMessages((prevMessages) => {\n const newMessages = [...prevMessages, data];\n return newMessages;\n });\n };\n\n const handleNotification = (data: any) => {\n const notification = rehydrate(Modules.Notification, data) as NotificationInterface;\n if (notification) {\n setSocketNotifications((prev) => {\n const newNotifications = [...prev, notification];\n return newNotifications;\n });\n }\n };\n\n // Attach event listeners\n if (currentSocket) {\n currentSocket.on(\"connect\", handleConnect);\n currentSocket.on(\"disconnect\", handleDisconnect);\n currentSocket.on(\"message\", handleMessage);\n currentSocket.on(\"notification\", handleNotification);\n }\n\n return () => {\n shouldConnect.current = true;\n\n // In development, preserve socket in window for HMR but remove listeners\n if (currentSocket) {\n if (process.env.NODE_ENV === \"development\") {\n currentSocket.off(\"connect\", handleConnect);\n currentSocket.off(\"disconnect\", handleDisconnect);\n currentSocket.off(\"message\", handleMessage);\n currentSocket.off(\"notification\", handleNotification);\n } else {\n currentSocket.off(\"connect\", handleConnect);\n currentSocket.off(\"disconnect\", handleDisconnect);\n currentSocket.off(\"message\", handleMessage);\n currentSocket.off(\"notification\", handleNotification);\n\n currentSocket.disconnect();\n\n if (typeof window !== \"undefined\") {\n delete (window as any)[globalSocketKey];\n }\n }\n }\n };\n }, [token]);\n\n const sendMessage = (event: string, data: any) => {\n if (socketRef.current && isConnected) {\n socketRef.current.emit(event, data);\n }\n };\n\n const removeMessage = (index: number) => {\n setMessages((prevMessages) => {\n const newMessages = [...prevMessages];\n newMessages.splice(index, 1);\n return newMessages;\n });\n };\n\n const removeSocketNotification = (index: number) => {\n setSocketNotifications((prevNotifications) => {\n const newNotifications = [...prevNotifications];\n newNotifications.splice(index, 1);\n return newNotifications;\n });\n };\n\n const clearMessages = () => {\n setMessages([]);\n };\n\n const clearSocketNotifications = () => {\n setSocketNotifications([]);\n };\n\n return {\n socket,\n isConnected,\n messages,\n socketNotifications,\n sendMessage,\n removeMessage,\n removeSocketNotification,\n clearMessages,\n clearSocketNotifications,\n };\n}\n","\"use client\";\n\nimport { ReactNode, useEffect, useState } from \"react\";\nimport { cn } from \"../../utils\";\n\ntype TitleProps = {\n type?: string | string[];\n element?: string;\n functions?: ReactNode;\n className?: string;\n};\n\nexport function ContentTitle({ type, element, functions, className }: TitleProps) {\n const [clientFunctions, setClientFunctions] = useState<ReactNode>(null);\n const [isClient, setIsClient] = useState(false);\n\n // Defer function rendering to client-side only to prevent hydration mismatches\n // caused by Radix UI's dynamic ID generation in Dialog/AlertDialog components\n useEffect(() => {\n setIsClient(true);\n setClientFunctions(functions);\n }, [functions]);\n\n if (!element) return null;\n\n return (\n <div className={cn(`mb-4 flex w-full flex-col`, className)}>\n {(type || isClient) && (\n <div className=\"flex flex-row items-center justify-between gap-x-4\">\n {type && <div className={`text-muted-foreground text-xl font-light`}>{type}</div>}\n {isClient && clientFunctions && (\n <div className=\"flex flex-row items-center justify-start\">{clientFunctions}</div>\n )}\n </div>\n )}\n <div className={`text-primary w-full text-3xl font-semibold`}>{element}</div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useSharedContext } from \"../../contexts/SharedContext\";\nimport { SidebarTrigger } from \"../../shadcnui\";\nimport { BreadcrumbNavigation } from \"./Breadcrumb\";\n\ntype HeaderProps = {\n children?: React.ReactNode;\n};\n\nexport function Header({ children }: HeaderProps) {\n const { breadcrumbs } = useSharedContext();\n\n return (\n <header className={`sticky top-0 z-10 flex h-12 flex-col items-center justify-start gap-x-4 border-b`}>\n <div className=\"bg-sidebar flex h-12 w-full flex-row items-center justify-between pl-2 pr-4\">\n <SidebarTrigger aria-label=\"Toggle sidebar\" />\n <div className=\"flex w-full flex-row items-center justify-start\">\n <BreadcrumbNavigation items={breadcrumbs} />\n </div>\n <div className=\"flex w-64 flex-row items-center justify-end gap-x-4 whitespace-nowrap\">\n {children ? children : null}\n </div>\n </div>\n </header>\n );\n}\n","\"use client\";\n\nimport { MoonIcon, SunIcon } from \"lucide-react\";\nimport { useTheme } from \"next-themes\";\nimport { Switch } from \"../../shadcnui\";\n\nexport function ModeToggleSwitch() {\n const { theme, setTheme } = useTheme();\n\n const handleToggle = () => {\n setTheme(theme === \"light\" ? \"dark\" : \"light\");\n };\n\n return (\n <div className=\"flex items-center\">\n <Switch checked={theme === \"dark\"} onCheckedChange={handleToggle} className=\"relative\">\n {theme === \"dark\" ? (\n <MoonIcon className=\"text-primary-foreground h-4 w-4\" />\n ) : (\n <SunIcon className=\"text-primary h-4 w-4\" />\n )}\n </Switch>\n </div>\n );\n}\n","\"use client\";\n\nimport { ChevronDownIcon, ChevronRightIcon } from \"lucide-react\";\nimport { ReactNode, useEffect, useState } from \"react\";\nimport { v4 } from \"uuid\";\n\ntype PageSectionProps = {\n children: ReactNode;\n title?: string;\n options?: ReactNode[];\n open?: boolean;\n small?: boolean;\n onToggle?: (isOpen: boolean) => void;\n};\n\nexport function PageSection({ children, title, options, open, small, onToggle }: PageSectionProps) {\n const [isOpen, setIsOpen] = useState<boolean>(open ?? true);\n const [shouldRender, setShouldRender] = useState<boolean>(open ?? true);\n\n useEffect(() => {\n if (onToggle) {\n onToggle(isOpen);\n }\n }, [isOpen]);\n\n const toggleOpen = () => setIsOpen(!isOpen);\n\n useEffect(() => {\n if (isOpen) {\n setShouldRender(true);\n } else {\n const timer = setTimeout(() => setShouldRender(false), 300);\n return () => clearTimeout(timer);\n }\n }, [isOpen]);\n\n return (\n <section\n id={title ? title.toLowerCase().replaceAll(\" \", \"\") : v4()}\n className={`${isOpen ? \"mb-4\" : \"my-0\"} flex w-full scroll-mt-40 flex-col`}\n >\n {title && (\n <div\n className={`${isOpen ? \"mb-4\" : \"mb-0\"} flex w-full justify-between border-b ${small ? `border-muted` : `border-primary`} pb-1`}\n >\n <div className=\"flex w-full cursor-pointer items-center justify-start gap-x-2\" onClick={toggleOpen}>\n {isOpen ? (\n <ChevronDownIcon className={`text-primary h-4 w-4`} />\n ) : (\n <ChevronRightIcon className=\"text-primary h-4 w-4\" />\n )}\n <h2 className={`flex w-full ${small === true ? `text-sm` : `text-lg`} text-primary font-semibold`}>\n {title}\n </h2>\n </div>\n {options && <div className=\"flex gap-2\">{options}</div>}\n </div>\n )}\n <div className={`overflow-hidden transition-all duration-300 ${isOpen ? \"\" : \"max-h-0\"}`}>\n {shouldRender && children}\n </div>\n </section>\n );\n}\n","\"use client\";\n\nimport { useAtomValue } from \"jotai\";\nimport { HistoryIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { recentPagesAtom } from \"../../atoms\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Link,\n useSidebar,\n} from \"../../shadcnui\";\n\nexport function RecentPagesNavigator() {\n const recentPages = useAtomValue(recentPagesAtom);\n const t = useTranslations();\n const { state } = useSidebar();\n\n if (recentPages.length === 0) {\n return null;\n }\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <div className=\"flex w-full cursor-pointer items-center gap-2\">\n {state === \"collapsed\" ? <HistoryIcon className=\"h-4 w-4\" /> : <span>{t(`generic.recent_pages`)}</span>}\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-96\">\n <DropdownMenuLabel>{t(`generic.recent_pages`)}</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {recentPages.map((page, index) => (\n <DropdownMenuItem key={`${page.url}-${index}`} asChild>\n <Link href={page.url} className=\"flex items-center gap-2\">\n <div className=\"flex flex-col\">\n <div className=\"truncate text-sm\">{page.title}</div>\n <div className=\"text-muted-foreground text-xs font-normal\">\n {t(`types.${page.moduleType}`, { count: 1 })}\n </div>\n </div>\n </Link>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","\"use client\";\n\nimport { cn } from \"../../utils\";\nimport { Header } from \"../navigations\";\n\ntype PageContainerProps = { children: React.ReactNode; testId?: string; className?: string };\n\nexport function PageContainer({ children, testId, className }: PageContainerProps) {\n return (\n <div className={`flex h-full w-full flex-col`} data-testid={testId}>\n <Header />\n <main className={cn(`flex w-full flex-1 flex-col gap-y-4 pt-4 pl-4 pr-4`, className)}>{children}</main>\n </div>\n );\n}\n","\"use client\";\n\nimport { ChevronDown, ChevronUp } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useRef, useState } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\n\ntype ReactMarkdownContainerProps = {\n content: string;\n collapsible?: boolean;\n initialLines?: number;\n size?: \"small\" | \"normal\";\n};\n\nexport function ReactMarkdownContainer({\n content,\n collapsible = false,\n initialLines = 4,\n size = \"normal\",\n}: ReactMarkdownContainerProps) {\n const t = useTranslations(\"generic.buttons\");\n const [isExpanded, setIsExpanded] = useState(false);\n const [showExpandButton, setShowExpandButton] = useState(false);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (collapsible && contentRef.current && !isExpanded) {\n // Check if content exceeds the clamped height\n const isOverflowing = contentRef.current.scrollHeight > contentRef.current.clientHeight;\n setShowExpandButton(isOverflowing);\n }\n }, [collapsible, content, isExpanded]);\n\n const handleToggle = () => {\n setIsExpanded(!isExpanded);\n };\n\n const clampStyle =\n collapsible && !isExpanded\n ? {\n display: \"-webkit-box\",\n WebkitLineClamp: initialLines,\n WebkitBoxOrient: \"vertical\" as const,\n overflow: \"hidden\",\n }\n : {};\n\n return (\n <div className=\"flex flex-col\">\n <div className=\"relative\">\n <div ref={contentRef} style={clampStyle} className=\"transition-all duration-300 ease-in-out\">\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n p: ({ children }) => <p className={size === \"small\" ? \"text-xs\" : \"\"}>{children}</p>,\n li: ({ children }) => <li className={size === \"small\" ? \"text-xs\" : \"\"}>{children}</li>,\n table: ({ children }) => <table className=\"w-full table-auto border-collapse border\">{children}</table>,\n th: ({ children }) => (\n <th className={`border px-4 py-2 text-left ${size === \"small\" ? \"px-2 py-1 text-xs\" : \"\"}`}>\n {children}\n </th>\n ),\n td: ({ children }) => (\n <td className={`border px-4 py-2 ${size === \"small\" ? \"px-2 py-1 text-xs\" : \"\"}`}>{children}</td>\n ),\n tr: ({ children }) => <tr className=\"even:bg-gray-50\">{children}</tr>,\n ul: ({ children }) => <ul className={`list-disc ${size === \"small\" ? \"pl-3\" : \"pl-4\"}`}>{children}</ul>,\n ol: ({ children }) => (\n <ol className={`list-decimal ${size === \"small\" ? \"pl-3\" : \"pl-4\"}`}>{children}</ol>\n ),\n h1: ({ children }) => (\n <h1 className={size === \"small\" ? \"my-1 mt-2 text-sm font-bold\" : \"my-2 mt-4 text-3xl font-medium\"}>\n {children}\n </h1>\n ),\n h2: ({ children }) => (\n <h2\n className={size === \"small\" ? \"my-1 mt-2 text-sm font-semibold\" : \"my-2 mt-4 text-2xl font-semibold\"}\n >\n {children}\n </h2>\n ),\n h3: ({ children }) => (\n <h3 className={size === \"small\" ? \"my-1 mt-2 text-sm font-medium\" : \"my-2 mt-4 text-xl font-semibold\"}>\n {children}\n </h3>\n ),\n h4: ({ children }) => (\n <h4 className={size === \"small\" ? \"my-1 mt-2 text-sm font-medium\" : \"my-2 mt-4 text-lg font-semibold\"}>\n {children}\n </h4>\n ),\n }}\n >\n {content}\n </ReactMarkdown>\n </div>\n\n {collapsible && !isExpanded && showExpandButton && (\n <div className=\"pointer-events-none absolute right-0 bottom-0 left-0 h-12 bg-gradient-to-t from-white to-transparent\" />\n )}\n </div>\n\n {collapsible && showExpandButton && (\n <div className=\"mt-2 flex justify-end\">\n <button\n onClick={handleToggle}\n className=\"flex items-center gap-1 rounded-md px-3 py-1.5 text-sm text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900\"\n aria-label={isExpanded ? t(\"show_less\") : t(\"show_more\")}\n >\n <span>{isExpanded ? t(\"show_less\") : t(\"show_more\")}</span>\n {isExpanded ? <ChevronUp className=\"h-4 w-4\" /> : <ChevronDown className=\"h-4 w-4\" />}\n </button>\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../features/user/data\";\nimport { Action, ModuleWithPermissions } from \"../../permissions\";\nimport { ScrollArea, Tabs, TabsContent, TabsList, TabsTrigger } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\nexport type Tab = {\n label: string;\n contentLabel?: React.ReactNode;\n content: React.ReactNode;\n modules?: ModuleWithPermissions[];\n action?: Action;\n};\n\ntype TabsContainerProps = {\n tabs: Tab[];\n defaultTab?: string;\n tabsListClassName?: string;\n tabsTriggerClassName?: string;\n scrollAreaClassName?: string;\n style?: \"navigation\";\n additionalComponent?: React.ReactNode;\n};\n\nexport function TabsContainer({\n tabs,\n defaultTab,\n tabsListClassName,\n tabsTriggerClassName,\n scrollAreaClassName,\n style,\n additionalComponent,\n}: TabsContainerProps) {\n const { hasPermissionToModules } = useCurrentUserContext<UserInterface>();\n\n const validTabs = tabs.filter((tab) =>\n tab.modules && tab.action ? hasPermissionToModules({ modules: tab.modules, action: tab.action }) : true,\n );\n\n if (validTabs.length === 0) return null;\n\n const defaultValue = defaultTab ?? tabs[0].label;\n\n if (validTabs.length === 1) {\n return validTabs[0].content;\n }\n\n return (\n <Tabs defaultValue={defaultValue} className=\"w-full\">\n <div className=\"flex w-full items-center justify-between\">\n <TabsList\n className={cn(\n `${style ? `my-4 flex w-full justify-start rounded-none border-b bg-transparent pb-0` : ``}`,\n tabsListClassName,\n )}\n >\n {validTabs.map((tab) => (\n <TabsTrigger\n key={tab.label}\n value={tab.label}\n className={cn(\n `${style ? `text-muted-foreground border-accent data-[state=active]:text-foreground hover:text-foreground cursor-pointer rounded-none bg-transparent pb-2 text-sm font-light hover:border-0 data-[state=active]:border-b data-[state=active]:font-medium data-[state=active]:shadow-none` : `text-primary text-xs`}`,\n tabsTriggerClassName,\n )}\n >\n {tab.contentLabel ?? tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n {additionalComponent && additionalComponent}\n </div>\n {scrollAreaClassName ? (\n <ScrollArea className={scrollAreaClassName}>\n {validTabs.map((tab) => (\n <TabsContent key={tab.label} value={tab.label}>\n {tab.content}\n </TabsContent>\n ))}\n </ScrollArea>\n ) : (\n <>\n {validTabs.map((tab) => (\n <TabsContent key={tab.label} value={tab.label}>\n {tab.content}\n </TabsContent>\n ))}\n </>\n )}\n </Tabs>\n );\n}\n","\"use client\";\n\nimport { ReactElement } from \"react\";\nimport { cn } from \"../../utils\";\n\ntype AttributeElementProps = {\n inline?: boolean;\n title?: string | ReactElement<any>;\n value?: string | ReactElement<any>;\n className?: string;\n};\n\nexport function AttributeElement({ inline, title, value, className }: AttributeElementProps) {\n return (\n <div className={cn(`flex ${inline === true ? \"flex-row\" : \"flex-col\"} my-1 justify-start`, className)}>\n {title && <div className={`${inline === true ? \"min-w-48 pr-4\" : \"w-full\"} text-sm font-semibold`}>{title}</div>}\n {value && <div className=\"flex w-full flex-col text-sm\">{value}</div>}\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentInterface } from \"../../features/content/data\";\nimport { ContributorsList } from \"../../features/user/components\";\n\ntype AllowedUsersDetailsProps = {\n showTitle?: boolean;\n content: ContentInterface;\n};\n\nexport function AllowedUsersDetails({ showTitle, content }: AllowedUsersDetailsProps) {\n const t = useTranslations();\n\n return (\n <div className=\"mb-2 flex w-full flex-col gap-y-2\">\n {showTitle && <h3 className=\"text-xs font-semibold\">{t(\"generic.permissions\")}</h3>}\n <div className=\"flex w-full items-center justify-start gap-x-4\">\n <ContributorsList content={content} />\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport dynamic from \"next/dynamic\";\nimport React from \"react\";\nimport { BlockNoteEditorProps } from \"./BlockNoteEditor\";\n\nconst BlockNoteEditor = dynamic(() => import(\"./BlockNoteEditor\"), {\n ssr: false,\n});\n\nexport const BlockNoteEditorContainer = React.memo(function EditorContainer(props: BlockNoteEditorProps) {\n return <BlockNoteEditor {...props} />;\n});\n","\"use client\";\n\nimport Image from \"next/image\";\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from \"../../shadcnui\";\n\nexport function ErrorDetails({ title, message, code }: { title?: string; message: string; code: number }) {\n if (code === 403)\n return (\n <div className=\"w-xl max-w-xl\">\n <Card className=\"w-full\">\n <CardHeader>\n <CardTitle className=\"text-foreground flex flex-col items-center gap-y-4 pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {/* <div>{code}</div> */}\n <div>Unauthorised</div>\n </CardTitle>\n <CardDescription className=\"text-center text-lg\">\n We are sorry, but you are not allowed to access this content.\n </CardDescription>\n </CardHeader>\n <CardContent></CardContent>\n </Card>\n </div>\n );\n\n return (\n <div className=\"w-xl max-w-xl\">\n <Card className=\"w-full\">\n <CardHeader>\n <CardTitle className=\"text-foreground flex flex-col items-center gap-y-4 pb-10 text-center text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n <div>{code}</div>\n <div>{title}</div>\n </CardTitle>\n <CardDescription className=\"text-center text-lg\">{message}</CardDescription>\n </CardHeader>\n <CardContent></CardContent>\n </Card>\n </div>\n );\n}\n","// import { toast } from \"@/hooks/use-toast\";\n\nimport { toast } from \"sonner\";\n\nexport function errorToast(params: { title?: string; error: any }) {\n toast.error(params?.title ?? \"Error\", {\n description: params.error instanceof Error ? params.error.message : String(params.error),\n });\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ReactNode, useCallback, useEffect, useRef, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { DataListRetriever, useDebounce } from \"../../hooks\";\nimport {\n Button,\n Command,\n CommandDialog,\n CommandEmpty,\n CommandInput,\n CommandList,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from \"../../shadcnui\";\n\ntype CommonAssociationTriggerProps = {\n sourceType: string;\n destinationType: string;\n hasDestination?: boolean;\n onTrigger: () => void;\n};\n\nexport function CommonAssociationTrigger({\n sourceType,\n destinationType,\n hasDestination,\n onTrigger,\n}: CommonAssociationTriggerProps) {\n const t = useTranslations();\n\n if (hasDestination)\n return (\n <div className=\"hover:text-accent cursor-pointer\" onClick={onTrigger}>\n Join\n </div>\n );\n\n return (\n <Button variant={`outline`} size={`sm`} onClick={onTrigger}>\n {t(`generic.association.label`, {\n source: sourceType,\n destination: destinationType,\n })}\n </Button>\n );\n}\n\ntype CommonAssociationCommandDialogProps = {\n show: boolean;\n setShow: (show: boolean) => void;\n data: DataListRetriever<any>;\n source: string;\n destination: string;\n destinationName: string;\n children: ReactNode;\n};\n\nexport function CommonAssociationCommandDialog({\n show,\n setShow,\n data,\n source,\n destination,\n destinationName,\n children,\n}: CommonAssociationCommandDialogProps) {\n const t = useTranslations();\n\n const searchTermRef = useRef<string>(\"\");\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n\n const refreshList = useCallback(\n async (searchedTerm: string) => {\n if (searchedTerm === searchTermRef.current) return;\n searchTermRef.current = searchedTerm;\n await data.search(searchedTerm);\n },\n [searchTerm, data],\n );\n\n const updateSearchTerm = useDebounce(refreshList, 500);\n\n useEffect(() => {\n if (show) updateSearchTerm(searchTerm);\n }, [show, searchTerm]);\n\n return (\n <CommandDialog open={show} onOpenChange={setShow}>\n <DialogHeader className=\"flex flex-col items-start p-4 pb-0\">\n <DialogTitle>\n {t(`generic.association.label`, {\n source: source,\n destination: destination,\n })}\n </DialogTitle>\n <DialogDescription>\n {t(`generic.association.description`, {\n source: source,\n destination: destination,\n destination_name: destinationName,\n })}\n </DialogDescription>\n </DialogHeader>\n <Command shouldFilter={false} className=\"p-4\">\n <CommandInput\n placeholder={t(`generic.search.placeholder`, { type: source })}\n value={searchTerm}\n onValueChange={setSearchTerm}\n />\n <CommandList className=\"mt-3 h-auto max-h-96 min-h-96 max-w-full overflow-y-auto overflow-x-hidden\">\n <CommandEmpty>{t(`generic.search.no_results`, { type: source })}</CommandEmpty>\n {children}\n </CommandList>\n </Command>\n </CommandDialog>\n );\n}\n\nexport const triggerAssociationToast = (params: {\n t: any;\n source: string;\n destination: string;\n source_name: string;\n destination_name: string;\n level?: string;\n}) => {\n if (params.level) {\n toast.message(\n params.t(`generic.association.label`, {\n source: params.source,\n destination: params.destination,\n }),\n {\n description: params.t(`generic.association.success_level`, {\n source: params.source,\n destination: params.destination,\n source_name: params.source_name,\n destination_name: params.destination_name,\n level: params.level,\n }),\n },\n );\n } else {\n toast.message(\n params.t(`generic.association.label`, {\n source: params.source,\n destination: params.destination,\n }),\n {\n description: params.t(`generic.association.success`, {\n source: params.source,\n destination: params.destination,\n source_name: params.source_name,\n destination_name: params.destination_name,\n }),\n },\n );\n }\n};\n","\"use client\";\n\nimport { LoaderCircleIcon, Trash2Icon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useI18nRouter, useI18nTranslations } from \"../../i18n\";\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n Button,\n} from \"../../shadcnui\";\nimport { errorToast } from \"../errors\";\n\ntype CommonDeleterProps = {\n type: string;\n deleteFunction: () => Promise<void>;\n redirectTo?: string;\n forceShow?: boolean;\n};\n\nexport function CommonDeleter({ deleteFunction, redirectTo, type, forceShow }: CommonDeleterProps) {\n const t = useI18nTranslations();\n const router = useI18nRouter();\n const [open, setOpen] = useState<boolean>(forceShow || false);\n const [isDeleting, setIsDeleting] = useState<boolean>(false);\n\n const handleDelete = async () => {\n setIsDeleting(true);\n try {\n await deleteFunction();\n\n setOpen(false);\n if (redirectTo) router.push(redirectTo);\n } catch (error) {\n errorToast({ title: t(`generic.errors.delete`), error: error });\n }\n setIsDeleting(false);\n };\n\n return (\n <AlertDialog open={open} onOpenChange={setOpen}>\n {forceShow ? null : (\n <AlertDialogTrigger asChild>\n <Button size=\"sm\" variant={\"ghost\"} className=\"text-muted-foreground hover:text-destructive\">\n <Trash2Icon />\n </Button>\n </AlertDialogTrigger>\n )}\n <AlertDialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>\n <AlertDialogHeader>\n <AlertDialogTitle>{t(`generic.delete.title`, { type: t(`types.${type}`, { count: 1 }) })}</AlertDialogTitle>\n <AlertDialogDescription>\n {t(`generic.delete.subtitle`, { type: t(`types.${type}`, { count: 1 }) })}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <div className=\"text-destructive p-4 text-sm\">\n {t(`generic.delete.description`, { type: t(`types.${type}`, { count: 1 }) })}\n </div>\n <div className=\"flex justify-end\">\n <Button\n className=\"mr-2\"\n variant={\"outline\"}\n type={`button`}\n onClick={() => setOpen(false)}\n disabled={isDeleting}\n >\n {t(`generic.buttons.cancel`)}\n </Button>\n <Button\n type=\"submit\"\n onClick={(e) => {\n e.preventDefault();\n handleDelete();\n }}\n variant={\"destructive\"}\n disabled={isDeleting}\n >\n {isDeleting ? (\n <>\n {t(`generic.buttons.is_deleting`)}\n <LoaderCircleIcon className=\"animate-spin-slow h-5 w-5\" />\n </>\n ) : (\n t(`generic.buttons.delete`)\n )}\n </Button>\n </div>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n","import { useTranslations } from \"next-intl\";\nimport { Button } from \"../../shadcnui\";\n\ntype CommonEditorButtonsProps = {\n isEdit: boolean;\n form: any;\n disabled?: boolean;\n setOpen: (open: boolean) => void;\n};\nexport function CommonEditorButtons({ isEdit, form, disabled, setOpen }: CommonEditorButtonsProps) {\n const t = useTranslations();\n\n return (\n <div className=\"flex justify-end\">\n <Button\n className=\"mr-2\"\n variant={\"outline\"}\n type={`button`}\n onClick={() => setOpen(false)}\n data-testid={`modal-button-cancel`}\n >\n {t(`generic.buttons.cancel`)}\n </Button>\n\n <Button type=\"submit\" disabled={form.formState.isSubmitting || disabled} data-testid={`modal-button-create`}>\n {isEdit ? t(`generic.buttons.confirm_update`) : t(`generic.buttons.confirm_create`)}\n </Button>\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { DialogDescription, DialogHeader, DialogTitle } from \"../../shadcnui\";\n\ntype CommonEditorHeaderProps = {\n type: string;\n name?: string;\n};\n\nexport function CommonEditorHeader({ type, name }: CommonEditorHeaderProps) {\n const t = useTranslations();\n\n return (\n <DialogHeader>\n <DialogTitle>\n {name\n ? t(`generic.edit.update.title`, {\n type: type,\n })\n : t(`generic.edit.create.title`, { type: type })}\n </DialogTitle>\n <DialogDescription>\n {name\n ? t(`generic.edit.update.description`, {\n type: type,\n name: name,\n })\n : t(`generic.edit.create.description`, {\n type: type,\n })}\n </DialogDescription>\n </DialogHeader>\n );\n}\n","\"use client\";\n\nimport { PencilIcon } from \"lucide-react\";\n\nimport { useTranslations } from \"next-intl\";\nimport { Button, DialogTrigger } from \"../../shadcnui\";\n\ntype CommonEditorTriggerProps = { isEdit: boolean; edit?: string; create?: string };\n\nexport function CommonEditorTrigger({ isEdit, edit, create }: CommonEditorTriggerProps) {\n const t = useTranslations();\n\n return (\n <DialogTrigger asChild>\n {isEdit ? (\n <Button size=\"sm\" variant={`ghost`} className=\"text-muted-foreground\">\n <PencilIcon />\n </Button>\n ) : (\n <Button size=\"sm\" variant={`outline`}>\n {create ? create : t(`generic.buttons.create`)}\n </Button>\n )}\n </DialogTrigger>\n );\n}\n","\"use client\";\n\nimport { isValid, parse } from \"date-fns\";\nimport { Calendar as CalendarIcon, CircleXIcon } from \"lucide-react\";\nimport { ReactNode, useMemo, useState } from \"react\";\nimport { useI18nDateFnsLocale, useI18nLocale } from \"../../i18n\";\nimport {\n Calendar,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\ntype DatePickerPopoverProps = {\n children: ReactNode;\n value?: Date;\n onSelect: (date?: Date) => void;\n minDate?: Date;\n align?: \"start\" | \"center\" | \"end\";\n className?: string;\n};\n\nexport const DatePickerPopover = ({\n children,\n value,\n onSelect,\n minDate,\n align = \"start\",\n className,\n}: DatePickerPopoverProps) => {\n const locale = useI18nLocale();\n const dateFnsLocale = useI18nDateFnsLocale();\n const [isOpen, setIsOpen] = useState(false);\n const [displayMonth, setDisplayMonth] = useState<Date>(() => value || new Date());\n\n // Locale-aware date formatter\n const dateFormatter = useMemo(\n () => new Intl.DateTimeFormat(locale, { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" }),\n [locale],\n );\n\n // Format date for display\n const formatDate = (date: Date): string => dateFormatter.format(date);\n\n // Get placeholder based on locale format\n const datePlaceholder = useMemo(() => {\n const parts = dateFormatter.formatToParts(new Date(2000, 0, 1));\n return parts\n .map((part) => {\n if (part.type === \"day\") return \"dd\";\n if (part.type === \"month\") return \"mm\";\n if (part.type === \"year\") return \"yyyy\";\n return part.value;\n })\n .join(\"\");\n }, [dateFormatter]);\n\n // Get date-fns format string from locale\n const dateFormatPattern = useMemo(() => {\n const parts = dateFormatter.formatToParts(new Date(2000, 0, 1));\n return parts\n .map((part) => {\n if (part.type === \"day\") return \"dd\";\n if (part.type === \"month\") return \"MM\";\n if (part.type === \"year\") return \"yyyy\";\n return part.value;\n })\n .join(\"\");\n }, [dateFormatter]);\n\n const [inputValue, setInputValue] = useState<string>(() => (value ? formatDate(value) : \"\"));\n\n // Generate year options (1900 to current year + 10)\n const currentYear = new Date().getFullYear();\n const yearOptions = Array.from({ length: currentYear - 1900 + 11 }, (_, i) => 1900 + i);\n\n // Generate month names dynamically based on current locale\n const monthNames = useMemo(() => {\n const formatter = new Intl.DateTimeFormat(locale, { month: \"long\" });\n return Array.from({ length: 12 }, (_, i) => {\n const monthName = formatter.format(new Date(2000, i, 1));\n return monthName.charAt(0).toUpperCase() + monthName.slice(1);\n });\n }, [locale]);\n\n // Handle text input change\n const handleInputChange = (inputValue: string) => {\n setInputValue(inputValue);\n\n // Try to parse the date using locale format\n const parsedDate = parse(inputValue, dateFormatPattern, new Date());\n\n if (isValid(parsedDate)) {\n onSelect(parsedDate);\n setDisplayMonth(parsedDate);\n } else if (inputValue === \"\") {\n onSelect(undefined);\n }\n };\n\n // Handle calendar selection\n const handleCalendarSelect = (selectedDate: Date | undefined) => {\n onSelect(selectedDate);\n if (selectedDate) {\n setInputValue(formatDate(selectedDate));\n setDisplayMonth(selectedDate);\n } else {\n setInputValue(\"\");\n }\n setIsOpen(false);\n };\n\n // Handle clear button\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation();\n onSelect(undefined);\n setInputValue(\"\");\n };\n\n return (\n <Popover open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent className={cn(\"w-auto p-0\", className)} align={align} onClick={(e) => e.stopPropagation()}>\n <div className=\"p-3\">\n {/* Manual Input */}\n <div className=\"relative mb-3\">\n <Input\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value)}\n placeholder={datePlaceholder}\n className=\"pr-16\"\n onClick={(e) => e.stopPropagation()}\n />\n <div className=\"absolute right-1 top-1/2 flex -translate-y-1/2 items-center space-x-1\">\n <button\n type=\"button\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md hover:bg-muted\"\n onClick={(e) => e.stopPropagation()}\n >\n <CalendarIcon className=\"h-4 w-4 opacity-50\" />\n </button>\n {value && (\n <button\n type=\"button\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md hover:bg-muted\"\n onClick={handleClear}\n >\n <CircleXIcon className=\"h-4 w-4 opacity-50 hover:opacity-100\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Year and Month Selectors */}\n <div className=\"mb-3 flex gap-2\">\n <Select\n value={displayMonth.getMonth().toString()}\n onValueChange={(value) => {\n const newMonth = parseInt(value);\n const newDate = new Date(displayMonth.getFullYear(), newMonth, 1);\n setDisplayMonth(newDate);\n }}\n >\n <SelectTrigger className=\"w-[130px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {monthNames.map((month, index) => (\n <SelectItem key={index} value={index.toString()}>\n {month}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <Select\n value={displayMonth.getFullYear().toString()}\n onValueChange={(value) => {\n const newYear = parseInt(value);\n const newDate = new Date(newYear, displayMonth.getMonth(), 1);\n setDisplayMonth(newDate);\n }}\n >\n <SelectTrigger className=\"w-[80px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {yearOptions.reverse().map((year) => (\n <SelectItem key={year} value={year.toString()}>\n {year}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Calendar */}\n <Calendar\n mode=\"single\"\n selected={value}\n onSelect={handleCalendarSelect}\n disabled={(date) => (minDate && date < minDate ? true : false)}\n locale={dateFnsLocale}\n weekStartsOn={1}\n month={displayMonth}\n onMonthChange={setDisplayMonth}\n />\n </div>\n </PopoverContent>\n </Popover>\n );\n};\n","\"use client\";\n\nimport { format } from \"date-fns\";\nimport { CalendarIcon } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { DateRange } from \"react-day-picker\";\nimport { Button, Calendar, Popover, PopoverContent, PopoverTrigger } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\ntype DateRangeSelectorProps = {\n onDateChange: (date?: DateRange) => void;\n avoidSettingDates?: boolean;\n showPreviousMonth?: boolean;\n};\n\nexport function DateRangeSelector({ onDateChange, avoidSettingDates, showPreviousMonth }: DateRangeSelectorProps) {\n const [date, setDate] = useState<DateRange | undefined>(\n avoidSettingDates\n ? undefined\n : {\n from: new Date(new Date().getFullYear(), new Date().getMonth(), 1),\n to: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0),\n },\n );\n\n const [open, setOpen] = useState(false);\n\n const [prevRange, setPrevRange] = useState<DateRange | undefined>(date);\n useEffect(() => {\n if (\n date?.from &&\n date?.to &&\n date.to > date.from &&\n (prevRange?.from?.getTime() !== date.from.getTime() || prevRange?.to?.getTime() !== date.to.getTime())\n ) {\n onDateChange(date);\n setPrevRange(date);\n setOpen(false);\n }\n }, [date, prevRange, onDateChange]);\n\n // Custom handler to reset end date if a new start date is picked\n const handleSelect = (range: DateRange | undefined) => {\n if (!range) {\n setDate(undefined);\n return;\n }\n // If a new start date is picked, reset end date\n if (range.from && (!date?.from || range.from.getTime() !== date.from.getTime())) {\n setDate({ from: range.from, to: undefined });\n } else {\n setDate(range);\n }\n };\n\n return (\n <div className={cn(\"grid gap-2\")}>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n id=\"date\"\n variant={\"outline\"}\n className={cn(\"w-[300px] justify-start text-left font-normal\", !date && \"text-muted-foreground\")}\n >\n <CalendarIcon />\n {date?.from ? (\n date.to ? (\n <>\n {format(date.from, \"LLL dd, y\")} - {format(date.to, \"LLL dd, y\")}\n </>\n ) : (\n format(date.from, \"LLL dd, y\")\n )\n ) : (\n <span>Pick a date</span>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\n <div className=\"flex flex-col gap-2 p-2\">\n <Calendar\n mode=\"range\"\n defaultMonth={\n date?.from ??\n (showPreviousMonth ? new Date(new Date().getFullYear(), new Date().getMonth() - 1, 1) : undefined)\n }\n selected={date}\n onSelect={handleSelect}\n numberOfMonths={2}\n />\n <Button\n variant=\"secondary\"\n type=\"button\"\n onClick={() => {\n setDate(undefined);\n setPrevRange(undefined);\n onDateChange(undefined);\n setOpen(false);\n }}\n className=\"cursor-pointer\"\n disabled={!date}\n >\n Clear\n </Button>\n </div>\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n","\"use client\";\n\nimport { Trash2 as RemoveIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport {\n createContext,\n Dispatch,\n forwardRef,\n SetStateAction,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { DropzoneOptions, DropzoneState, FileRejection, useDropzone } from \"react-dropzone\";\nimport { toast } from \"sonner\";\nimport { buttonVariants, Input } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\ntype DirectionOptions = \"rtl\" | \"ltr\" | undefined;\n\ntype FileUploaderContextType = {\n dropzoneState: DropzoneState;\n isLOF: boolean;\n isFileTooBig: boolean;\n removeFileFromSet: (index: number) => void;\n activeIndex: number;\n setActiveIndex: Dispatch<SetStateAction<number>>;\n orientation: \"horizontal\" | \"vertical\";\n direction: DirectionOptions;\n};\n\nconst FileUploaderContext = createContext<FileUploaderContextType | null>(null);\n\nexport const useFileUpload = () => {\n const context = useContext(FileUploaderContext);\n if (!context) {\n throw new Error(\"useFileUpload must be used within a FileUploaderProvider\");\n }\n return context;\n};\n\ntype FileUploaderProps = {\n value: File[] | null;\n reSelect?: boolean;\n onValueChange: (value: File[] | null) => void;\n dropzoneOptions: DropzoneOptions;\n orientation?: \"horizontal\" | \"vertical\";\n};\n\nexport const FileUploader = forwardRef<HTMLDivElement, FileUploaderProps & React.HTMLAttributes<HTMLDivElement>>(\n (\n { className, dropzoneOptions, value, onValueChange, reSelect, orientation = \"vertical\", children, dir, ...props },\n ref,\n ) => {\n const [isFileTooBig, setIsFileTooBig] = useState(false);\n const [isLOF, setIsLOF] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const { maxFiles = 1, maxSize = 4 * 1024 * 1024, multiple = true } = dropzoneOptions;\n const t = useTranslations();\n\n const reSelectAll = maxFiles === 1 ? true : reSelect;\n const direction: DirectionOptions = dir === \"rtl\" ? \"rtl\" : \"ltr\";\n\n const removeFileFromSet = useCallback(\n (i: number) => {\n if (!value) return;\n const newFiles = value.filter((_, index) => index !== i);\n onValueChange(newFiles);\n },\n [value, onValueChange],\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (!value) return;\n\n const moveNext = () => {\n const nextIndex = activeIndex + 1;\n setActiveIndex(nextIndex > value.length - 1 ? 0 : nextIndex);\n };\n\n const movePrev = () => {\n const nextIndex = activeIndex - 1;\n setActiveIndex(nextIndex < 0 ? value.length - 1 : nextIndex);\n };\n\n const prevKey = orientation === \"horizontal\" ? (direction === \"ltr\" ? \"ArrowLeft\" : \"ArrowRight\") : \"ArrowUp\";\n\n const nextKey = orientation === \"horizontal\" ? (direction === \"ltr\" ? \"ArrowRight\" : \"ArrowLeft\") : \"ArrowDown\";\n\n if (e.key === nextKey) {\n moveNext();\n } else if (e.key === prevKey) {\n movePrev();\n } else if (e.key === \"Enter\" || e.key === \"Space\") {\n if (activeIndex === -1) {\n dropzoneState.inputRef.current?.click();\n }\n } else if (e.key === \"Delete\" || e.key === \"Backspace\") {\n if (activeIndex !== -1) {\n removeFileFromSet(activeIndex);\n if (value.length - 1 === 0) {\n setActiveIndex(-1);\n return;\n }\n movePrev();\n }\n } else if (e.key === \"Escape\") {\n setActiveIndex(-1);\n }\n },\n [value, activeIndex, removeFileFromSet],\n );\n\n const onDrop = useCallback(\n (acceptedFiles: File[], rejectedFiles: FileRejection[]) => {\n const files = acceptedFiles;\n\n if (!files) {\n toast.error(t(\"generic.errors.file\"), {\n description: t(\"generic.errors.file_large\"),\n });\n return;\n }\n\n const newValues: File[] = value ? [...value] : [];\n\n if (reSelectAll) {\n newValues.splice(0, newValues.length);\n }\n\n files.forEach((file) => {\n if (newValues.length < maxFiles) {\n newValues.push(file);\n }\n });\n\n onValueChange(newValues);\n\n if (rejectedFiles.length > 0) {\n for (let i = 0; i < rejectedFiles.length; i++) {\n if (rejectedFiles[i].errors[0]?.code === \"file-too-large\") {\n toast.error(t(\"generic.errors.file\"), {\n description: t(`generic.errors.file_max`, { size: maxSize / 1024 / 1024 }),\n });\n break;\n }\n if (rejectedFiles[i].errors[0]?.message) {\n toast.error(t(`generic.errors.file`), {\n description: rejectedFiles[i].errors[0].message,\n });\n break;\n }\n }\n }\n },\n [reSelectAll, value],\n );\n\n useEffect(() => {\n if (!value) return;\n if (value.length === maxFiles) {\n // setIsLOF(true);\n return;\n }\n setIsLOF(false);\n }, [value, maxFiles]);\n\n const opts = dropzoneOptions ? dropzoneOptions : { maxFiles, maxSize, multiple };\n\n const dropzoneState = useDropzone({\n ...opts,\n onDrop,\n onDropRejected: () => setIsFileTooBig(true),\n onDropAccepted: () => setIsFileTooBig(false),\n });\n\n const { isDragActive } = dropzoneState; // Correctly get isDragActive\n\n return (\n <FileUploaderContext.Provider\n value={{\n dropzoneState,\n isLOF,\n isFileTooBig,\n removeFileFromSet,\n activeIndex,\n setActiveIndex,\n orientation,\n direction,\n }}\n >\n <div\n ref={ref}\n tabIndex={0}\n onKeyDownCapture={handleKeyDown}\n className={cn(\n \"grid w-full overflow-hidden focus:outline-none\",\n className, // Original className from props\n {\n \"gap-2\": value && value.length > 0,\n \"bg-muted border-primary border-dashed\": isDragActive, // Apply drag-active styles to the main FileUploader div\n },\n )}\n dir={dir}\n {...props}\n >\n {children}\n </div>\n </FileUploaderContext.Provider>\n );\n },\n);\n\nFileUploader.displayName = \"FileUploader\";\n\nexport const FileUploaderContent = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ children, className, ...props }, ref) => {\n const { orientation } = useFileUpload();\n const containerRef = useRef<HTMLDivElement>(null);\n\n return (\n <div className={cn(\"w-full px-1\")} ref={containerRef} aria-description=\"content file holder\">\n <div\n {...props}\n ref={ref}\n className={cn(\n \"flex gap-1 rounded-xl\",\n orientation === \"horizontal\" ? \"flex-raw flex-wrap\" : \"flex-col\",\n className,\n )}\n >\n {children}\n </div>\n </div>\n );\n },\n);\n\nFileUploaderContent.displayName = \"FileUploaderContent\";\n\nexport const FileUploaderItem = forwardRef<HTMLDivElement, { index: number } & React.HTMLAttributes<HTMLDivElement>>(\n ({ className, index, children, ...props }, ref) => {\n const { removeFileFromSet, activeIndex, direction } = useFileUpload();\n const isSelected = index === activeIndex;\n const t = useTranslations();\n\n return (\n <div\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"ghost\" }),\n \"relative h-6 cursor-pointer justify-between p-1\",\n className,\n isSelected ? \"bg-muted\" : \"\",\n )}\n {...props}\n >\n <div className=\"flex h-full w-full items-center gap-1.5 leading-none font-medium tracking-tight\">\n {children}\n </div>\n <button\n type=\"button\"\n className={cn(\"absolute\", direction === \"rtl\" ? \"top-1 left-1\" : \"top-1 right-1\")}\n onClick={() => removeFileFromSet(index)}\n >\n <span className=\"sr-only\">{t(`generic.remove_item`, { index: index })}</span>\n <RemoveIcon className=\"hover:stroke-destructive h-4 w-4 duration-200 ease-in-out\" />\n </button>\n </div>\n );\n },\n);\n\nFileUploaderItem.displayName = \"FileUploaderItem\";\n\nexport const FileInput = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, children, ...props }, ref) => {\n const { dropzoneState, isFileTooBig, isLOF } = useFileUpload();\n const rootProps = isLOF ? {} : dropzoneState.getRootProps();\n // Get isDragActive from the context for FileInput as well, to ensure it can react if needed, or to simplify its own styling.\n const { isDragActive: parentIsDragActive } = dropzoneState;\n\n return (\n <div\n ref={ref}\n {...props}\n className={cn(`relative w-full ${isLOF ? \"cursor-not-allowed opacity-50\" : \"cursor-pointer\"}`, className)}\n >\n <div\n className={cn(\n \"w-full rounded-lg duration-300 ease-in-out\",\n // Simpler border logic: if parent is drag-active, it controls the border.\n // Otherwise, FileInput can show its own accept/reject/default border.\n {\n \"border-green-500\": dropzoneState.isDragAccept && !parentIsDragActive,\n \"border-red-500\": (dropzoneState.isDragReject || isFileTooBig) && !parentIsDragActive,\n \"border-gray-300\":\n !dropzoneState.isDragAccept && !dropzoneState.isDragReject && !isFileTooBig && !parentIsDragActive,\n },\n // className from props should be last to allow overrides if necessary\n className,\n )}\n {...rootProps}\n >\n {children}\n </div>\n <Input\n ref={dropzoneState.inputRef}\n disabled={isLOF}\n {...dropzoneState.getInputProps()}\n className={`${isLOF ? \"cursor-not-allowed\" : \"\"}`}\n />\n </div>\n );\n },\n);\n\nFileInput.displayName = \"FileInput\";\n","\"use client\";\n\nimport {\n Checkbox,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../shadcnui\";\n\ntype FormCheckboxProps = {\n form: any;\n id: string;\n name: string;\n labelBefore?: boolean;\n description?: string;\n isRequired?: boolean;\n};\n\nexport function FormCheckbox({ form, id, name, labelBefore, description, isRequired }: FormCheckboxProps) {\n const simpleLabel = () => {\n return (\n <FormLabel htmlFor={id} className={`font-normal ${labelBefore ? \"\" : \"ml-3\"}`}>\n {name}\n </FormLabel>\n );\n };\n\n const label = () => {\n if (description) return simpleLabel();\n else\n return (\n <Tooltip>\n <TooltipTrigger asChild>{simpleLabel()}</TooltipTrigger>\n <TooltipContent>{description}</TooltipContent>\n </Tooltip>\n );\n };\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n <FormControl>\n <div className=\"flex gap-x-4\">\n {labelBefore && label()}\n {labelBefore && isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n <Checkbox id={id} defaultChecked={field.value} onCheckedChange={field.onChange} />\n {!labelBefore && label()}\n {!labelBefore && isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { ReactElement } from \"react\";\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage } from \"../../shadcnui\";\n\nexport function FormContainerGeneric({\n form,\n id,\n name,\n children,\n isRequired = false,\n}: {\n form: any;\n id: string;\n name?: string;\n children: ReactElement<any>;\n isRequired?: boolean;\n}) {\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && (\n <FormLabel className=\"flex items-center\">\n <span>{name}</span>\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>{children}</FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { isValid, parse } from \"date-fns\";\nimport { Calendar as CalendarIcon, CircleXIcon } from \"lucide-react\";\nimport { useMemo, useState } from \"react\";\nimport { useI18nDateFnsLocale, useI18nLocale } from \"../../i18n\";\nimport {\n Calendar,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\n\nexport function FormDate({\n form,\n id,\n name,\n minDate,\n onChange,\n isRequired = false,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n minDate?: Date;\n onChange?: (date?: Date) => Promise<void>;\n isRequired?: boolean;\n}) {\n const locale = useI18nLocale();\n const dateFnsLocale = useI18nDateFnsLocale();\n const [open, setOpen] = useState<boolean>(false);\n const [displayMonth, setDisplayMonth] = useState<Date>(() => {\n const currentValue = form.getValues(id);\n return currentValue || new Date();\n });\n\n // Locale-aware date formatter\n const dateFormatter = useMemo(\n () => new Intl.DateTimeFormat(locale, { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" }),\n [locale],\n );\n\n // Format date for display\n const formatDate = (date: Date): string => dateFormatter.format(date);\n\n // Get placeholder based on locale format\n const datePlaceholder = useMemo(() => {\n const parts = dateFormatter.formatToParts(new Date(2000, 0, 1));\n return parts\n .map((part) => {\n if (part.type === \"day\") return \"dd\";\n if (part.type === \"month\") return \"mm\";\n if (part.type === \"year\") return \"yyyy\";\n return part.value;\n })\n .join(\"\");\n }, [dateFormatter]);\n\n // Get date-fns format string from locale\n const dateFormatPattern = useMemo(() => {\n const parts = dateFormatter.formatToParts(new Date(2000, 0, 1));\n return parts\n .map((part) => {\n if (part.type === \"day\") return \"dd\";\n if (part.type === \"month\") return \"MM\";\n if (part.type === \"year\") return \"yyyy\";\n return part.value;\n })\n .join(\"\");\n }, [dateFormatter]);\n\n const [inputValue, setInputValue] = useState<string>(() => {\n const currentValue = form.getValues(id);\n return currentValue ? formatDate(currentValue) : \"\";\n });\n\n // Generate year options (1900 to current year)\n const currentYear = new Date().getFullYear();\n const yearOptions = Array.from({ length: currentYear - 1900 + 1 }, (_, i) => 1900 + i);\n\n // Generate month names dynamically based on current locale\n const monthNames = useMemo(() => {\n const formatter = new Intl.DateTimeFormat(locale, { month: \"long\" });\n return Array.from({ length: 12 }, (_, i) => {\n const monthName = formatter.format(new Date(2000, i, 1));\n return monthName.charAt(0).toUpperCase() + monthName.slice(1);\n });\n }, [locale]);\n\n // Handle text input change\n const handleInputChange = (value: string, field: any) => {\n setInputValue(value);\n\n // Try to parse the date using locale format\n const parsedDate = parse(value, dateFormatPattern, new Date());\n\n if (isValid(parsedDate)) {\n field.onChange(parsedDate);\n setDisplayMonth(parsedDate);\n if (onChange) onChange(parsedDate);\n } else if (value === \"\") {\n field.onChange(undefined);\n if (onChange) onChange(undefined);\n }\n };\n\n // Handle calendar selection\n const handleCalendarSelect = (selectedDate: Date | undefined, field: any) => {\n field.onChange(selectedDate);\n if (selectedDate) {\n setInputValue(formatDate(selectedDate));\n setDisplayMonth(selectedDate);\n } else {\n setInputValue(\"\");\n }\n if (onChange) onChange(selectedDate);\n };\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"} w-full`}>\n {name && (\n <FormLabel className=\"dlex items-center\">\n {name} {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <div className=\"relative\">\n <Popover open={open} onOpenChange={setOpen} modal={true}>\n <div className=\"relative\">\n <Input\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value, field)}\n placeholder={datePlaceholder}\n className=\"pr-16\"\n />\n <div className=\"absolute right-1 top-1/2 flex -translate-y-1/2 items-center space-x-1\">\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"hover:bg-muted flex h-8 w-8 items-center justify-center rounded-md\"\n >\n <CalendarIcon className=\"h-4 w-4 opacity-50\" />\n </button>\n </PopoverTrigger>\n {field.value && (\n <button\n type=\"button\"\n className=\"hover:bg-muted flex h-8 w-8 items-center justify-center rounded-md\"\n onClick={() => {\n field.onChange(undefined);\n setInputValue(\"\");\n if (onChange) onChange(undefined);\n }}\n >\n <CircleXIcon className=\"h-4 w-4 opacity-50 hover:opacity-100\" />\n </button>\n )}\n </div>\n </div>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\n <div className=\"p-3\">\n {/* Year and Month Selectors */}\n <div className=\"mb-3 flex gap-2\">\n <Select\n value={displayMonth.getMonth().toString()}\n onValueChange={(value) => {\n const newMonth = parseInt(value);\n const newDate = new Date(displayMonth.getFullYear(), newMonth, 1);\n setDisplayMonth(newDate);\n }}\n >\n <SelectTrigger className=\"w-[130px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {monthNames.map((month, index) => (\n <SelectItem key={index} value={index.toString()}>\n {month}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <Select\n value={displayMonth.getFullYear().toString()}\n onValueChange={(value) => {\n const newYear = parseInt(value);\n const newDate = new Date(newYear, displayMonth.getMonth(), 1);\n setDisplayMonth(newDate);\n }}\n >\n <SelectTrigger className=\"w-[80px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {yearOptions.reverse().map((year) => (\n <SelectItem key={year} value={year.toString()}>\n {year}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Calendar */}\n <Calendar\n mode=\"single\"\n selected={field.value}\n onSelect={(e) => {\n handleCalendarSelect(e, field);\n setOpen(false);\n }}\n disabled={(date) => (minDate && date < minDate ? true : false)}\n locale={dateFnsLocale}\n weekStartsOn={1}\n month={displayMonth}\n onMonthChange={setDisplayMonth}\n />\n </div>\n </PopoverContent>\n </Popover>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { Calendar as CalendarIcon, CircleXIcon } from \"lucide-react\";\nimport { useMemo, useState } from \"react\";\nimport { useI18nDateFnsLocale, useI18nLocale, useI18nTranslations } from \"../../i18n\";\nimport {\n Button,\n Calendar,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Label,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\nexport function FormDateTime({\n form,\n id,\n name,\n minDate,\n onChange,\n allowEmpty,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n minDate?: Date;\n onChange?: (date?: Date) => Promise<void>;\n allowEmpty?: boolean;\n}) {\n const [open, setOpen] = useState<boolean>(false);\n const t = useI18nTranslations();\n const locale = useI18nLocale();\n const dateFnsLocale = useI18nDateFnsLocale();\n\n // Locale-aware date-time formatter\n const dateTimeFormatter = useMemo(\n () =>\n new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n }),\n [locale],\n );\n\n // Format date-time for display\n const formatDateTime = (date: Date): string => dateTimeFormatter.format(date);\n\n const [selectedHours, setSelectedHours] = useState<number>(new Date().getHours());\n const [selectedMinutes, setSelectedMinutes] = useState<number>(roundToNearestFiveMinutes(new Date().getMinutes()));\n\n const hoursOptions = Array.from({ length: 24 }, (_, i) => {\n const hour = i;\n return {\n value: hour,\n label: hour.toString().padStart(2, \"0\"),\n };\n });\n\n const minutesOptions = Array.from({ length: 12 }, (_, i) => {\n const minute = i * 5;\n return {\n value: minute,\n label: minute.toString().padStart(2, \"0\"),\n };\n });\n\n function roundToNearestFiveMinutes(minutes: number): number {\n return (Math.round(minutes / 5) * 5) % 60;\n }\n\n const handleTimeChange = (hours: number, minutes: number) => {\n const currentDate = form.getValues(id);\n if (currentDate) {\n const updatedDate = new Date(currentDate);\n updatedDate.setHours(hours);\n updatedDate.setMinutes(minutes);\n form.setValue(id, updatedDate);\n if (onChange) onChange(updatedDate);\n }\n };\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"} w-full`}>\n {name && <FormLabel>{name}</FormLabel>}\n <FormControl>\n <div className=\"relative flex flex-row\">\n <Popover open={open} onOpenChange={setOpen} modal={true}>\n <div className=\"flex w-full flex-row items-center justify-between\">\n <PopoverTrigger asChild>\n <FormControl>\n <Button\n variant={\"outline\"}\n className={cn(\"w-full pl-3 text-left font-normal\", !field.value && \"text-muted-foreground\")}\n >\n {field.value ? formatDateTime(field.value) : <span>{t(`generic.pick_date_time`)}</span>}\n <CalendarIcon className=\"ml-auto h-4 w-4 opacity-50\" />\n </Button>\n </FormControl>\n </PopoverTrigger>\n {field.value && allowEmpty !== false && (\n <CircleXIcon\n className=\"text-muted hover:text-destructive ml-2 h-6 w-6 cursor-pointer\"\n onClick={() => {\n if (onChange) onChange(undefined);\n form.setValue(id, \"\");\n }}\n />\n )}\n </div>\n <PopoverContent className=\"w-auto p-4\" align=\"start\">\n <div className=\"flex flex-col space-y-4\">\n <Calendar\n mode=\"single\"\n selected={field.value}\n onSelect={(date) => {\n if (date) {\n // Preserve the current time when selecting a new date\n const newDate = new Date(date);\n if (field.value) {\n const currentDate = new Date(field.value);\n newDate.setHours(currentDate.getHours(), currentDate.getMinutes());\n } else {\n newDate.setHours(selectedHours, selectedMinutes);\n }\n form.setValue(id, newDate);\n if (onChange) onChange(newDate);\n\n // Update time state values\n setSelectedHours(newDate.getHours());\n setSelectedMinutes(roundToNearestFiveMinutes(newDate.getMinutes()));\n }\n }}\n disabled={(date) => (minDate && date < minDate ? true : false)}\n locale={dateFnsLocale}\n />\n <div className=\"flex flex-row items-end justify-center space-x-4\">\n <div className=\"flex flex-col space-y-2\">\n <Label htmlFor=\"hours-select\">{t(`generic.hours`)}</Label>\n <Select\n value={String(field.value ? new Date(field.value).getHours() : selectedHours)}\n onValueChange={(value) => {\n const hours = parseInt(value);\n setSelectedHours(hours);\n handleTimeChange(\n hours,\n field.value\n ? roundToNearestFiveMinutes(new Date(field.value).getMinutes())\n : selectedMinutes,\n );\n }}\n >\n <SelectTrigger id=\"hours-select\" className=\"w-[70px]\">\n <SelectValue placeholder=\"Hour\" />\n </SelectTrigger>\n <SelectContent>\n {hoursOptions.map((option) => (\n <SelectItem key={option.value} value={String(option.value)}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"mb-[9px] text-xl\">:</div>\n <div className=\"flex flex-col space-y-2\">\n <Label htmlFor=\"minutes-select\">{t(`generic.minutes`)}</Label>\n <Select\n value={String(\n field.value\n ? roundToNearestFiveMinutes(new Date(field.value).getMinutes())\n : selectedMinutes,\n )}\n onValueChange={(value) => {\n const minutes = parseInt(value);\n setSelectedMinutes(minutes);\n handleTimeChange(field.value ? new Date(field.value).getHours() : selectedHours, minutes);\n }}\n >\n <SelectTrigger id=\"minutes-select\" className=\"w-[70px]\">\n <SelectValue placeholder=\"Min\" />\n </SelectTrigger>\n <SelectContent>\n {minutesOptions.map((option) => (\n <SelectItem key={option.value} value={String(option.value)}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <Button\n className=\"mt-2\"\n onClick={() => {\n setOpen(false);\n }}\n >\n {t(`generic.buttons.select_date`)}\n </Button>\n </div>\n </PopoverContent>\n </Popover>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport React from \"react\";\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, Input } from \"../../shadcnui\";\n\nexport function FormInput({\n form,\n id,\n name,\n placeholder,\n type,\n onBlur,\n disabled,\n onKeyDown,\n autoFocus,\n onChange,\n testId,\n isRequired = false,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n type?: \"text\" | \"number\" | \"currency\" | \"password\" | \"link\";\n onBlur?: () => Promise<void>;\n disabled?: boolean;\n onKeyDown?: (event: React.KeyboardEvent) => void;\n autoFocus?: boolean;\n onChange?: (value: string | number) => Promise<void>;\n testId?: string;\n isRequired?: boolean;\n}) {\n const t = useTranslations();\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => {\n const handleBlur = async (e: React.FocusEvent<HTMLInputElement>) => {\n let value = e.target.value;\n\n if (type === \"link\" && value) {\n if (!/^https?:\\/\\//i.test(value)) {\n value = \"https://\" + value;\n field.onChange(value);\n }\n try {\n new URL(value);\n form.clearErrors(id);\n } catch (error) {\n form.setError(id, {\n type: \"validate\",\n message: t(`generic.errors.valid_url`),\n });\n }\n }\n\n if (onBlur) await onBlur();\n field.onBlur();\n };\n\n return (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && (\n <FormLabel className=\"flex items-center\">\n {name}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <div className=\"relative\">\n {type === \"currency\" && (\n <span className=\"text-muted-foreground absolute top-0 left-0 pt-2 pl-3\">€</span>\n )}\n <Input\n data-testid={testId}\n {...field}\n autoFocus={autoFocus === true}\n type={\n type === \"number\" || type === \"currency\" ? \"number\" : type === \"password\" ? \"password\" : \"text\"\n }\n className={`w-full ${type === \"number\" || type === \"currency\" ? \"text-end\" : \"\"}`}\n disabled={disabled === true || form.formState.isSubmitting}\n placeholder={placeholder || \"\"}\n onBlur={handleBlur}\n onKeyDown={onKeyDown}\n onChange={(e) => {\n if (type === \"number\" || type === \"currency\") {\n const value = e.target.value.replace(/[^0-9]/g, \"\");\n field.onChange(+value);\n if (onChange) onChange(+value);\n } else {\n field.onChange(e.target.value);\n if (onChange) onChange(e.target.value);\n }\n }}\n />\n </div>\n </FormControl>\n <FormMessage data-testid={testId ? `${testId}-error` : undefined} />\n </FormItem>\n );\n }}\n />\n </div>\n );\n}\n","import * as React from \"react\";\n\nimport { EyeIcon, EyeOffIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { Button, Input } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\nexport interface PasswordInputProps extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>(({ className, type, ...props }, ref) => {\n const [showPassword, setShowPassword] = React.useState(false);\n const disabled = props.value === \"\" || props.value === undefined || props.disabled;\n const t = useTranslations();\n\n return (\n <div className=\"relative\">\n <Input type={showPassword ? \"text\" : \"password\"} className={cn(\"\", className)} ref={ref} {...props} />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent\"\n onClick={() => setShowPassword((prev) => !prev)}\n disabled={disabled}\n >\n {showPassword && !disabled ? (\n <EyeIcon className=\"h-4 w-4\" aria-hidden=\"true\" />\n ) : (\n <EyeOffIcon className=\"h-4 w-4\" aria-hidden=\"true\" />\n )}\n <span className=\"sr-only\">{showPassword ? t(`generic.hide_password`) : t(`generic.show_password`)}</span>\n </Button>\n\n <style>{`\n\t\t\t\t\t.hide-password-toggle::-ms-reveal,\n\t\t\t\t\t.hide-password-toggle::-ms-clear {\n\t\t\t\t\t\tvisibility: hidden;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\tdisplay: none;\n\t\t\t\t\t}\n\t\t\t\t`}</style>\n </div>\n );\n});\nPasswordInput.displayName = \"PasswordInput\";\n\nexport { PasswordInput };\n","\"use client\";\n\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage } from \"../../shadcnui\";\nimport { PasswordInput } from \"./PasswordInput\";\n\nexport function FormPassword({\n form,\n id,\n name,\n placeholder,\n onBlur,\n disabled,\n testId,\n isRequired,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n onBlur?: () => Promise<void>;\n disabled?: boolean;\n testId?: string;\n isRequired?: boolean;\n}) {\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && (\n <FormLabel>\n {name}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <PasswordInput\n {...field}\n className={`w-full`}\n disabled={disabled === true || form.formState.isSubmitting}\n placeholder={placeholder ? placeholder : \"\"}\n onBlur={onBlur}\n data-testid={testId}\n />\n </FormControl>\n <FormMessage data-testid={testId ? `${testId}-error` : undefined} />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, Input } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\n/**\n * FormPlaceAutocomplete component integrates Google Places API (New)\n * to provide address suggestions as the user types.\n *\n * Prerequisites:\n * 1. Set NEXT_PUBLIC_GOOGLE_MAPS_API_KEY environment variable\n * 2. Enable Places API (New) in Google Cloud Console\n * 3. Configure API key restrictions as needed\n *\n * Note: This uses the new Places API via REST calls, not the legacy JavaScript API\n */\n\ninterface PlaceSuggestion {\n place_id: string;\n description: string;\n structured_formatting: {\n main_text: string;\n secondary_text: string;\n };\n}\n\ninterface PlaceAutocompleteProps {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n disabled?: boolean;\n testId?: string;\n isRequired?: boolean;\n onPlaceSelect?: (place: PlaceSuggestion) => void;\n className?: string;\n /**\n * Optional array of place types to include in search results.\n * When not specified, defaults to address types: [\"street_address\", \"premise\", \"subpremise\"]\n * For cities, use: [\"locality\", \"administrative_area_level_3\"]\n * For regions, use: [\"administrative_area_level_1\", \"administrative_area_level_2\"]\n */\n includeTypes?: string[];\n}\n\nexport function FormPlaceAutocomplete({\n form,\n id,\n name,\n placeholder,\n disabled,\n testId,\n isRequired = false,\n onPlaceSelect,\n className,\n includeTypes,\n}: PlaceAutocompleteProps) {\n const [inputValue, setInputValue] = useState(\"\");\n const [suggestions, setSuggestions] = useState<PlaceSuggestion[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [loadError, setLoadError] = useState(false);\n const [apiKey, setApiKey] = useState<string | null>(null);\n const debounceRef = useRef<NodeJS.Timeout | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Initialize API key\n useEffect(() => {\n const key = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY;\n\n if (!key) {\n console.error(\"Google Maps API key not found. Please set NEXT_PUBLIC_GOOGLE_MAPS_API_KEY environment variable.\");\n setLoadError(true);\n return;\n }\n\n setApiKey(key);\n }, []);\n\n // Update input value when form value changes\n useEffect(() => {\n const formValue = form.getValues(id);\n if (formValue !== inputValue) {\n setInputValue(formValue || \"\");\n }\n }, [form.watch(id), id, inputValue]);\n\n // Fetch place suggestions from Google Places API (New)\n const fetchSuggestions = async (input: string) => {\n if (!apiKey) return;\n\n try {\n setIsLoading(true);\n\n // Using the new Places API autocomplete endpoint\n const response = await fetch(`https://places.googleapis.com/v1/places:autocomplete`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Goog-Api-Key\": apiKey,\n },\n body: JSON.stringify({\n input: input,\n includedPrimaryTypes: includeTypes || [\"street_address\", \"premise\", \"subpremise\"],\n languageCode: \"en\",\n }),\n });\n\n if (!response.ok) {\n throw new Error(`Places API error: ${response.status}`);\n }\n\n const data = await response.json();\n\n if (data.suggestions) {\n const formattedSuggestions: PlaceSuggestion[] = data.suggestions.map((suggestion: any) => ({\n place_id: suggestion.placePrediction?.placeId || \"\",\n description: suggestion.placePrediction?.text?.text || \"\",\n structured_formatting: {\n main_text: suggestion.placePrediction?.structuredFormat?.mainText?.text || \"\",\n secondary_text: suggestion.placePrediction?.structuredFormat?.secondaryText?.text || \"\",\n },\n }));\n\n setSuggestions(formattedSuggestions);\n setShowSuggestions(true);\n } else {\n setSuggestions([]);\n }\n } catch (error) {\n console.error(\"Error fetching place suggestions:\", error);\n setSuggestions([]);\n } finally {\n setIsLoading(false);\n }\n };\n\n // Handle input changes with debouncing\n const handleInputChange = (value: string) => {\n setInputValue(value);\n form.setValue(id, value);\n\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n\n if (value.length > 2 && apiKey) {\n debounceRef.current = setTimeout(() => {\n fetchSuggestions(value);\n }, 300);\n } else {\n setSuggestions([]);\n setShowSuggestions(false);\n setIsLoading(false);\n }\n };\n\n // Handle suggestion selection\n const handleSuggestionSelect = (suggestion: PlaceSuggestion) => {\n setInputValue(suggestion.description);\n form.setValue(id, suggestion.description);\n setShowSuggestions(false);\n setSuggestions([]);\n\n if (onPlaceSelect) {\n onPlaceSelect(suggestion);\n }\n };\n\n // Close suggestions when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setShowSuggestions(false);\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, []);\n\n // Cleanup debounce on unmount\n useEffect(() => {\n return () => {\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n };\n }, []);\n\n // Fallback to regular input if API key is not available\n if (loadError) {\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && (\n <FormLabel className=\"flex items-center\">\n {name}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <Input\n {...field}\n placeholder={placeholder}\n disabled={disabled}\n data-testid={testId}\n className={cn(\"w-full\", className)}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n }\n\n return (\n <div className=\"flex w-full flex-col\" ref={containerRef}>\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && (\n <FormLabel className=\"flex items-center\">\n {name}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <div className=\"relative\">\n <Input\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value)}\n onBlur={field.onBlur}\n onFocus={() => {\n if (suggestions.length > 0) {\n setShowSuggestions(true);\n }\n }}\n placeholder={placeholder}\n disabled={disabled || !apiKey}\n data-testid={testId}\n className={cn(\"w-full\", className)}\n />\n\n {/* Loading indicator */}\n {isLoading && (\n <div className=\"absolute right-3 top-1/2 -translate-y-1/2\">\n <div className=\"border-primary h-4 w-4 animate-spin rounded-full border-2 border-t-transparent\"></div>\n </div>\n )}\n\n {/* Suggestions dropdown */}\n {showSuggestions && suggestions.length > 0 && (\n <div className=\"bg-background absolute left-0 right-0 top-full z-50 mt-1 max-h-60 overflow-auto rounded-md border shadow-lg\">\n {suggestions.map((suggestion, index) => (\n <div\n key={suggestion.place_id || index}\n className=\"hover:bg-muted cursor-pointer px-3 py-2 text-sm\"\n onClick={() => handleSuggestionSelect(suggestion)}\n >\n <div className=\"font-medium\">{suggestion.structured_formatting?.main_text}</div>\n <div className=\"text-muted-foreground\">{suggestion.structured_formatting?.secondary_text}</div>\n </div>\n ))}\n </div>\n )}\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport {\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\n\nexport function FormSelect({\n form,\n id,\n name,\n placeholder,\n disabled,\n values,\n onChange,\n useRows,\n testId,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n disabled?: boolean;\n values: { id: string; text: string }[];\n onChange?: (value: string) => void;\n useRows?: boolean;\n testId?: string;\n}) {\n return (\n <div className={`flex w-full flex-col`}>\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`flex w-full ${useRows ? `flex-row items-center justify-between gap-x-4` : `flex-col`}`}>\n {name && <FormLabel className={`${useRows ? `min-w-28` : ``}`}>{name}</FormLabel>}\n <Select\n onValueChange={(e) => {\n field.onChange(e);\n if (onChange) onChange(e);\n }}\n defaultValue={field.value}\n data-testid={testId}\n >\n <FormControl className=\"w-full\">\n <SelectTrigger>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n </FormControl>\n <SelectContent>\n {values.map((type: { id: string; text: string }) => (\n <SelectItem key={type.id} value={type.id}>\n {type.text}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { useWatch } from \"react-hook-form\";\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, Slider } from \"../../shadcnui\";\n\nexport function FormSlider({\n form,\n id,\n name,\n disabled,\n showPercentage,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n disabled?: boolean;\n showPercentage?: boolean;\n}) {\n const value = useWatch({ control: form.control, name: id });\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && <FormLabel>{name}</FormLabel>}\n <FormControl>\n <div>\n {showPercentage && (\n <div className=\"text-muted-foreground mb-2 flex w-full justify-center text-xs\">{`${value}%`}</div>\n )}\n <Slider\n onValueChange={(value: number[]) => form.setValue(id, value[0])}\n value={[value]}\n max={100}\n step={5}\n disabled={disabled === true || form.formState.isSubmitting}\n />\n {/* </div> */}\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, Switch } from \"../../shadcnui\";\n\nexport function FormSwitch({ form, id, name, disabled }: { form: any; id: string; name?: string; disabled?: boolean }) {\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n <FormControl>\n <div className=\"flex flex-row gap-x-4\">\n <Switch checked={field.value} onCheckedChange={field.onChange} />\n {name && <FormLabel>{name}</FormLabel>}\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, Textarea } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\nexport function FormTextarea({\n form,\n id,\n name,\n className,\n placeholder,\n testId,\n}: {\n form: any;\n id: string;\n name: string;\n placeholder?: string;\n className?: string;\n testId?: string;\n}) {\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className=\"mb-5\">\n <FormLabel>{name}</FormLabel>\n <FormControl>\n <Textarea\n {...field}\n className={cn(\"min-h-96 w-full\", className)}\n disabled={form.formState.isSubmitting}\n placeholder={placeholder}\n data-testid={testId}\n />\n </FormControl>\n <FormMessage data-testid={testId ? `${testId}-error` : undefined} />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { FileIcon, FileImageIcon, FileSpreadsheetIcon, FileTextIcon, UploadIcon, XIcon } from \"lucide-react\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { DropzoneOptions } from \"react-dropzone\";\nimport { cn } from \"../../utils\";\nimport { FileInput, FileUploader } from \"./FileUploader\";\n\ntype MultiFileUploaderProps = {\n files: File[];\n setFiles: (files: File[]) => void;\n};\n\nconst dropzone = {\n multiple: false,\n maxSize: 100 * 1024 * 1024,\n preventDropOnDocument: false,\n accept: {\n \"application/images\": [\".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".svg\", \".docx\", \".xslx\", \".pdf\", \".txt\", \".md\"],\n },\n} satisfies DropzoneOptions;\n\nexport default function MultiFileUploader({ files, setFiles }: MultiFileUploaderProps) {\n const uploadFiles = (newFiles: File[] | null) => {\n if (!newFiles) return;\n\n setFiles([...files, ...newFiles]);\n };\n\n const handleRemoveFile = (indexToRemove: number) => {\n setFiles(files.filter((_, index) => index !== indexToRemove));\n };\n\n return (\n <div className=\"grid w-full grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6\">\n <FileUploader\n value={files}\n onValueChange={uploadFiles}\n dropzoneOptions={dropzone}\n className=\"text-muted-foreground hover:text-primary relative aspect-square h-full cursor-pointer overflow-hidden rounded-lg border\"\n >\n <FileInput className={cn(\"text-muted-foreground flex h-full w-full flex-col items-center justify-center\")}>\n <UploadIcon className=\"my-4 h-8 w-8\" />\n </FileInput>\n </FileUploader>\n {files.map((file, index) => (\n <FilePreviewItem key={file.name + \"-\" + index} file={file} onRemoveClick={() => handleRemoveFile(index)} />\n ))}\n </div>\n );\n}\n\nconst FilePreviewItem = ({ file, onRemoveClick }: { file: File; onRemoveClick: () => void }) => {\n const [objectUrl, setObjectUrl] = useState<string | null>(null);\n\n useEffect(() => {\n if (file.type.startsWith(\"image/\")) {\n const url = URL.createObjectURL(file);\n setObjectUrl(url);\n return () => URL.revokeObjectURL(url);\n }\n setObjectUrl(null);\n }, [file]);\n\n const getFileIcon = () => {\n const extension = file.name.split(\".\").pop()?.toLowerCase();\n if (file.type.startsWith(\"image/\")) {\n return <FileImageIcon className=\"text-muted h-10 w-10 sm:h-12 sm:w-12\" />;\n }\n if (file.type === \"application/pdf\") {\n return <FileTextIcon className=\"text-destructive h-10 w-10 sm:h-12 sm:w-12\" />;\n }\n if (file.type.includes(\"wordprocessingml\") || extension === \"docx\" || extension === \"doc\") {\n return <FileTextIcon className=\"text-primary h-10 w-10 sm:h-12 sm:w-12\" />;\n }\n if (file.type.includes(\"spreadsheetml\") || extension === \"xlsx\" || extension === \"xls\") {\n return <FileSpreadsheetIcon className=\"text-secondary h-10 w-10 sm:h-12 sm:w-12\" />;\n }\n if (file.type.startsWith(\"text/\")) {\n return <FileTextIcon className=\"h-10 w-10 sm:h-12 sm:w-12\" />;\n }\n return <FileIcon className=\"text-muted h-10 w-10 sm:h-12 sm:w-12\" />;\n };\n\n return (\n <div className=\"text-muted-foreground group relative aspect-square h-full overflow-hidden rounded-lg border\">\n <button\n onClick={onRemoveClick}\n className=\"absolute top-1.5 right-1.5 z-20 rounded-full bg-black/60 p-1 text-white opacity-0 transition-all duration-200 ease-in-out group-hover:opacity-100 hover:bg-red-600 focus:outline-none\"\n aria-label=\"Remove file\"\n >\n <XIcon className=\"h-3.5 w-3.5\" />\n </button>\n {objectUrl ? (\n <Image src={objectUrl} alt={file.name} className=\"h-full w-full object-cover\" width={200} height={200} />\n ) : (\n <div className=\"bg-muted/30 flex h-full w-full flex-col items-center justify-center p-2\">\n {getFileIcon()}\n <span className=\"text-foreground/80 mt-2 w-full truncate px-1 text-center text-[10px] sm:text-xs\">\n {file.name}\n </span>\n </div>\n )}\n </div>\n );\n};\n","\"use client\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n Checkbox,\n FormLabel,\n FormMessage,\n} from \"../../../../shadcnui\";\nimport { ModuleInterface } from \"../../../module\";\nimport { FeatureInterface } from \"../../data\";\n\ntype FormFeaturesProps = {\n form: any;\n name?: string;\n features: FeatureInterface[];\n featureField?: string;\n moduleField?: string;\n};\n\nexport function FormFeatures({\n form,\n name,\n features,\n featureField = \"featureIds\",\n moduleField = \"moduleIds\",\n}: FormFeaturesProps) {\n const selectedFeatures: string[] = form.watch(featureField);\n const selectedModules: string[] = form.watch(moduleField);\n\n const toggleFeature = (feature: FeatureInterface, checked: boolean) => {\n let newFeatureIds = [...selectedFeatures];\n let newModuleIds = [...selectedModules];\n\n if (checked) {\n if (!newFeatureIds.includes(feature.id)) {\n newFeatureIds.push(feature.id);\n }\n feature.modules.forEach((module) => {\n if (!newModuleIds.includes(module.id)) {\n newModuleIds.push(module.id);\n }\n });\n } else {\n newFeatureIds = newFeatureIds.filter((id) => id !== feature.id);\n feature.modules.forEach((module) => {\n newModuleIds = newModuleIds.filter((id) => id !== module.id);\n });\n }\n form.setValue(featureField, newFeatureIds);\n form.setValue(moduleField, newModuleIds);\n };\n\n const toggleModule = (feature: FeatureInterface, module: ModuleInterface, checked: boolean) => {\n const modulesForFeature = feature.modules.map((m) => m.id);\n let newModuleIds = [...selectedModules];\n\n if (checked) {\n if (!selectedFeatures.includes(feature.id)) {\n newModuleIds = newModuleIds.filter((id) => !modulesForFeature.includes(id));\n newModuleIds.push(module.id);\n form.setValue(featureField, [...selectedFeatures, feature.id]);\n } else {\n if (!newModuleIds.includes(module.id)) {\n newModuleIds.push(module.id);\n }\n }\n } else {\n newModuleIds = newModuleIds.filter((id) => id !== module.id);\n const remaining = feature.modules.filter((m) => newModuleIds.includes(m.id));\n if (remaining.length === 0) {\n form.setValue(\n featureField,\n selectedFeatures.filter((id) => id !== feature.id),\n );\n }\n }\n form.setValue(moduleField, newModuleIds);\n };\n\n const isFeatureChecked = (feature: FeatureInterface) =>\n selectedFeatures.includes(feature.id) || feature.modules.every((module) => selectedModules.includes(module.id));\n\n return (\n <div className=\"flex w-full flex-col\">\n {name && <h2 className=\"mb-5 font-semibold\">{name}</h2>}\n {features.map((feature) => (\n <Accordion\n key={feature.id}\n type=\"single\"\n collapsible\n // className={`w-full p-0 ${feature.modules.filter((module) => !module.isCore).length === 0 ? \"border-t\" : \"\"}`}\n className={`w-full p-0`}\n >\n <AccordionItem value={feature.id} className=\"p-0\">\n <div\n className={`flex items-center justify-between p-0 ${feature.modules.filter((module) => !module.isCore).length === 0 ? \"py-4\" : \"\"}`}\n >\n <div className=\"flex items-center\" onClick={(e) => e.stopPropagation()}>\n <Checkbox\n id={feature.id}\n checked={isFeatureChecked(feature)}\n onCheckedChange={(val) => {\n toggleFeature(feature, val === true);\n }}\n />\n <FormLabel htmlFor={feature.id} className=\"ml-3 cursor-pointer font-normal\">\n {feature.name}\n </FormLabel>\n </div>\n {feature.modules.filter((module) => !module.isCore).length > 0 && (\n <AccordionTrigger asChild>\n <div className=\"w-full\"></div>\n </AccordionTrigger>\n )}\n </div>\n {feature.modules.filter((module) => !module.isCore).length > 0 && (\n <AccordionContent className=\"pl-6\">\n {feature.modules\n .filter((module) => !module.isCore)\n .sort((a: ModuleInterface, b: ModuleInterface) => a.name.localeCompare(b.name))\n .map((module: ModuleInterface) => (\n <div\n key={module.id}\n className=\"flex items-center border-t py-2\"\n onClick={(e) => e.stopPropagation()}\n >\n <Checkbox\n id={module.id}\n checked={selectedModules.includes(module.id)}\n onCheckedChange={(val) => {\n toggleModule(feature, module, val === true);\n }}\n />\n <FormLabel htmlFor={module.id} className=\"ml-3 cursor-pointer font-normal\">\n {module.name}\n </FormLabel>\n </div>\n ))}\n </AccordionContent>\n )}\n </AccordionItem>\n </Accordion>\n ))}\n <FormMessage />\n </div>\n );\n}\n","\"use client\";\n\nimport { ReactNode, useEffect, useRef, useState } from \"react\";\nimport { useUrlRewriter } from \"../../hooks/url.rewriter\";\nimport { ModuleWithPermissions } from \"../../permissions\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"../../shadcnui\";\n\nexport type PageContainerItems = {\n title: string;\n content: ReactNode;\n};\n\ntype PageContainerContentDetailsProps = {\n items: PageContainerItems[];\n section?: string;\n module: ModuleWithPermissions;\n id: string;\n};\n\nexport function PageContainerContentDetails({ items, section, module, id }: PageContainerContentDetailsProps) {\n const rewriteUrl = useUrlRewriter();\n const [isScrolled, setIsScrolled] = useState<boolean>(false);\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n // Use IntersectionObserver to detect when content scrolls past the TabsList\n useEffect(() => {\n const sentinel = sentinelRef.current;\n if (!sentinel) return;\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n // When sentinel is not visible (scrolled past), show border\n setIsScrolled(!entry.isIntersecting);\n },\n {\n threshold: 0,\n rootMargin: \"0px\",\n },\n );\n\n observer.observe(sentinel);\n\n return () => {\n observer.disconnect();\n };\n }, []);\n\n return (\n <Tabs\n defaultValue={section || items[0].title}\n onValueChange={(a) => rewriteUrl({ page: module, id: id, childPage: a })}\n >\n {/* Sentinel element - invisible, used to detect scroll position */}\n <div ref={sentinelRef} className=\"h-0\" />\n\n {/* Sticky TabsList with conditional border */}\n <div className={`bg-background sticky top-0 z-10 mb-2 pb-2 transition-shadow ${isScrolled ? \"border-b\" : \"\"}`}>\n <TabsList>\n {items.map((item) => (\n <TabsTrigger key={item.title} value={item.title}>\n {item.title}\n </TabsTrigger>\n ))}\n </TabsList>\n </div>\n\n <div className=\"pr-4\">\n {items.map((item) => (\n <TabsContent key={item.title} value={item.title}>\n {item.content}\n </TabsContent>\n ))}\n </div>\n </Tabs>\n );\n}\n","\"use client\";\n\nimport { ReactNode } from \"react\";\nimport { ResizableHandle, ResizablePanel, ResizablePanelGroup } from \"../../shadcnui\";\n\ntype PageContentContainerProps = {\n details: ReactNode;\n footer?: ReactNode;\n content?: ReactNode;\n};\n\nexport function PageContentContainer({ details, footer, content }: PageContentContainerProps) {\n return (\n <div className=\"flex h-[calc(100vh-(--spacing(16)))] w-full\">\n <ResizablePanelGroup direction=\"horizontal\" className=\"items-stretch\" autoSaveId=\"page-content-layout\">\n <ResizablePanel id=\"left-panel\" defaultSize={32} minSize={20} maxSize={40}>\n <div className=\"@container flex h-full flex-col pr-4\">\n <div className=\"flex-1 overflow-y-auto\">{details}</div>\n\n {/* Sticky footer - always visible at bottom */}\n {footer && <div className=\"flex flex-col gap-y-2 pt-2 pb-2\">{footer}</div>}\n </div>\n </ResizablePanel>\n <ResizableHandle withHandle />\n <ResizablePanel id=\"right-panel\" className=\"pl-4\">\n <div className=\"h-full overflow-y-auto\">{content}</div>\n </ResizablePanel>\n </ResizablePanelGroup>\n </div>\n );\n}\n","import { ColumnDef } from \"@tanstack/react-table\";\nimport React from \"react\";\n\nexport const cellComponent = (params: {\n id: string;\n name: string;\n title: string;\n component: React.ReactNode;\n}): ColumnDef<any> => {\n return {\n id: params.name,\n accessorKey: params.name,\n header: params.title,\n cell: ({ row }) => params.component,\n enableSorting: false,\n enableHiding: false,\n };\n};\n","import { ColumnDef } from \"@tanstack/react-table\";\n\nexport const cellDate = (params: { name: string; title: string }): ColumnDef<any> => {\n return {\n id: params.name,\n accessorKey: params.name,\n header: params.title,\n cell: ({ row }) => (\n <span className=\"text-muted-foreground text-xs\">\n {row.getValue<Date>(params.name).toLocaleDateString(\"en\", { dateStyle: \"medium\" })}\n </span>\n ),\n enableSorting: false,\n enableHiding: false,\n };\n};\n","import { ColumnDef } from \"@tanstack/react-table\";\nimport { Checkbox } from \"../../../shadcnui\";\n\nexport const cellId = (params: {\n name: string;\n checkedIds?: string[];\n toggleId?: (id: string) => void;\n}): ColumnDef<any> => {\n return {\n id: params.name,\n accessorKey: params.name,\n header: \"\",\n cell: ({ row }) =>\n params.toggleId ? (\n <Checkbox\n checked={params.checkedIds?.includes(row.getValue(params.name)) || false}\n onCheckedChange={(value) => {\n row.toggleSelected(!!value);\n params.toggleId?.(row.getValue(params.name));\n }}\n aria-label=\"Select row\"\n />\n ) : null,\n enableSorting: false,\n enableHiding: true,\n };\n};\n","import { ColumnDef } from \"@tanstack/react-table\";\nimport { Link } from \"../../../shadcnui\";\n\nexport const cellLink = <T,>(params: {\n id: string;\n name: string;\n title: string;\n generateUrl: (id: string) => string;\n}): ColumnDef<T> => {\n return {\n id: params.name,\n accessorKey: params.name,\n header: params.title,\n cell: ({ row }) => <Link href={params.generateUrl(row.getValue(params.id))}>{row.getValue(params.name)}</Link>,\n enableSorting: false,\n enableHiding: false,\n };\n};\n","import { ColumnDef } from \"@tanstack/react-table\";\nimport { Link } from \"../../../shadcnui\";\n\nexport const cellUrl = (params: { name: string; title: string }): ColumnDef<any> => {\n return {\n id: params.name,\n accessorKey: params.name,\n header: params.title,\n cell: ({ row }) => <Link href={row.getValue(params.name)}>{row.getValue(params.name)}</Link>,\n enableSorting: false,\n enableHiding: false,\n };\n};\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\n\nexport type CacheProfile = \"seconds\" | \"minutes\" | \"hours\" | \"days\" | \"weeks\" | \"max\" | \"default\";\n\nexport interface JsonApiConfig {\n /**\n * The base URL for API requests (e.g., https://api.example.com)\n */\n apiUrl: string;\n\n /**\n * Custom token getter function. If not provided, will use default cookie-based token retrieval.\n */\n tokenGetter?: () => Promise<string | undefined>;\n\n /**\n * Custom language getter function. If not provided, will use browser locale or next-intl.\n */\n languageGetter?: () => Promise<string>;\n\n /**\n * Default headers to include in all requests\n */\n defaultHeaders?: Record<string, string>;\n\n /**\n * Global error handler for failed requests (client-side only)\n */\n onError?: (status: number, message: string) => void;\n\n /**\n * Cache configuration\n */\n cacheConfig?: {\n defaultProfile: CacheProfile;\n };\n\n /**\n * Function to bootstrap the data class registry.\n * Will be called automatically when needed.\n */\n bootstrapper?: () => void;\n}\n\nconst JsonApiContext = createContext<JsonApiConfig | null>(null);\n\nexport function useJsonApiConfig(): JsonApiConfig {\n const config = useContext(JsonApiContext);\n if (!config) {\n throw new Error(\"useJsonApiConfig must be used within a JsonApiProvider\");\n }\n return config;\n}\n\nexport function useJsonApiConfigOptional(): JsonApiConfig | null {\n return useContext(JsonApiContext);\n}\n\nexport { JsonApiContext };\n","\"use client\";\n\nimport React, { useEffect, useMemo } from \"react\";\nimport { JsonApiConfig, JsonApiContext } from \"./JsonApiContext\";\n\nexport interface JsonApiProviderProps {\n config: JsonApiConfig;\n children: React.ReactNode;\n}\n\nexport function JsonApiProvider({ config, children }: JsonApiProviderProps) {\n // Run bootstrapper on mount if provided\n useEffect(() => {\n if (config.bootstrapper) {\n config.bootstrapper();\n }\n }, [config.bootstrapper]);\n\n // Memoize config to prevent unnecessary re-renders\n const memoizedConfig = useMemo(() => config, [config]);\n\n return (\n <JsonApiContext.Provider value={memoizedConfig}>\n {children}\n </JsonApiContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport { ApiDataInterface } from \"../../core/interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../../core/interfaces/ApiRequestDataTypeInterface\";\nimport { ApiResponseInterface } from \"../../core/interfaces/ApiResponseInterface\";\n\nexport interface UseJsonApiGetOptions {\n /**\n * Whether to enable the query. If false, the query won't run.\n */\n enabled?: boolean;\n /**\n * Dependencies that trigger a refetch when changed.\n */\n deps?: any[];\n}\n\nexport interface UseJsonApiGetResult<T> {\n /**\n * The fetched data, or null if not yet fetched.\n */\n data: T | null;\n /**\n * Whether the query is currently loading.\n */\n loading: boolean;\n /**\n * Error message if the query failed.\n */\n error: string | null;\n /**\n * The full API response (includes raw data, pagination, etc.)\n */\n response: ApiResponseInterface | null;\n /**\n * Function to manually refetch the data.\n */\n refetch: () => Promise<void>;\n /**\n * Whether there is a next page available.\n */\n hasNextPage: boolean;\n /**\n * Whether there is a previous page available.\n */\n hasPreviousPage: boolean;\n /**\n * Function to fetch the next page.\n */\n fetchNextPage: () => Promise<void>;\n /**\n * Function to fetch the previous page.\n */\n fetchPreviousPage: () => Promise<void>;\n}\n\n/**\n * Hook for fetching data from a JSON:API endpoint.\n *\n * @example\n * ```tsx\n * const { data, loading, error, refetch } = useJsonApiGet<Article>({\n * classKey: Modules.Article,\n * endpoint: `/articles/${id}`,\n * });\n *\n * if (loading) return <Loading />;\n * if (error) return <Error message={error} />;\n * return <ArticleView article={data} />;\n * ```\n */\nexport function useJsonApiGet<T extends ApiDataInterface>(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n options?: UseJsonApiGetOptions;\n}): UseJsonApiGetResult<T> {\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [response, setResponse] = useState<ApiResponseInterface | null>(null);\n const isMounted = useRef(true);\n\n const fetchData = useCallback(async () => {\n if (params.options?.enabled === false) return;\n\n setLoading(true);\n setError(null);\n\n try {\n const { JsonApiGet } = await import(\"../../unified/JsonApiRequest\");\n const language = navigator.language.split(\"-\")[0] || \"en\";\n\n const apiResponse = await JsonApiGet({\n classKey: params.classKey,\n endpoint: params.endpoint,\n companyId: params.companyId,\n language,\n });\n\n if (!isMounted.current) return;\n\n setResponse(apiResponse);\n\n if (apiResponse.ok) {\n setData(apiResponse.data as T);\n } else {\n setError(apiResponse.error);\n }\n } catch (err) {\n if (!isMounted.current) return;\n setError(err instanceof Error ? err.message : \"Unknown error\");\n } finally {\n if (isMounted.current) {\n setLoading(false);\n }\n }\n }, [params.classKey, params.endpoint, params.companyId, params.options?.enabled]);\n\n const fetchNextPage = useCallback(async () => {\n if (!response?.nextPage) return;\n\n setLoading(true);\n try {\n const nextResponse = await response.nextPage();\n if (!isMounted.current) return;\n\n setResponse(nextResponse);\n if (nextResponse.ok) {\n setData(nextResponse.data as T);\n } else {\n setError(nextResponse.error);\n }\n } catch (err) {\n if (!isMounted.current) return;\n setError(err instanceof Error ? err.message : \"Unknown error\");\n } finally {\n if (isMounted.current) {\n setLoading(false);\n }\n }\n }, [response]);\n\n const fetchPreviousPage = useCallback(async () => {\n if (!response?.prevPage) return;\n\n setLoading(true);\n try {\n const prevResponse = await response.prevPage();\n if (!isMounted.current) return;\n\n setResponse(prevResponse);\n if (prevResponse.ok) {\n setData(prevResponse.data as T);\n } else {\n setError(prevResponse.error);\n }\n } catch (err) {\n if (!isMounted.current) return;\n setError(err instanceof Error ? err.message : \"Unknown error\");\n } finally {\n if (isMounted.current) {\n setLoading(false);\n }\n }\n }, [response]);\n\n useEffect(() => {\n isMounted.current = true;\n fetchData();\n return () => {\n isMounted.current = false;\n };\n }, [fetchData, ...(params.options?.deps || [])]);\n\n return {\n data,\n loading,\n error,\n response,\n refetch: fetchData,\n hasNextPage: !!response?.next,\n hasPreviousPage: !!response?.prev,\n fetchNextPage,\n fetchPreviousPage,\n };\n}\n","\"use client\";\n\nimport { useState, useCallback } from \"react\";\nimport { ApiDataInterface } from \"../../core/interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../../core/interfaces/ApiRequestDataTypeInterface\";\nimport { ApiResponseInterface } from \"../../core/interfaces/ApiResponseInterface\";\n\nexport type MutationMethod = \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\nexport interface UseJsonApiMutationResult<T> {\n /**\n * The result data from the mutation, or null if not yet executed.\n */\n data: T | null;\n /**\n * Whether the mutation is currently in progress.\n */\n loading: boolean;\n /**\n * Error message if the mutation failed.\n */\n error: string | null;\n /**\n * The full API response.\n */\n response: ApiResponseInterface | null;\n /**\n * Execute the mutation.\n */\n mutate: (params: MutationParams) => Promise<T | null>;\n /**\n * Reset the mutation state.\n */\n reset: () => void;\n}\n\nexport interface MutationParams {\n /**\n * The endpoint to call.\n */\n endpoint: string;\n /**\n * The request body.\n */\n body?: any;\n /**\n * Files to upload.\n */\n files?: { [key: string]: File | Blob } | File | Blob;\n /**\n * Company ID for multi-tenant requests.\n */\n companyId?: string;\n /**\n * Override the default JSON:API body creation.\n */\n overridesJsonApiCreation?: boolean;\n /**\n * Response type if different from the request type.\n */\n responseType?: ApiRequestDataTypeInterface;\n}\n\n/**\n * Hook for making mutations (POST, PUT, PATCH, DELETE) to a JSON:API endpoint.\n *\n * @example\n * ```tsx\n * const { mutate, loading, error } = useJsonApiMutation<Article>({\n * method: \"POST\",\n * classKey: Modules.Article,\n * });\n *\n * const handleSubmit = async (data: ArticleInput) => {\n * const result = await mutate({\n * endpoint: \"/articles\",\n * body: data,\n * });\n * if (result) {\n * // Success!\n * }\n * };\n * ```\n */\nexport function useJsonApiMutation<T extends ApiDataInterface>(config: {\n method: MutationMethod;\n classKey: ApiRequestDataTypeInterface;\n onSuccess?: (data: T) => void;\n onError?: (error: string) => void;\n}): UseJsonApiMutationResult<T> {\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [response, setResponse] = useState<ApiResponseInterface | null>(null);\n\n const reset = useCallback(() => {\n setData(null);\n setLoading(false);\n setError(null);\n setResponse(null);\n }, []);\n\n const mutate = useCallback(\n async (params: MutationParams): Promise<T | null> => {\n setLoading(true);\n setError(null);\n\n try {\n const { JsonApiPost, JsonApiPut, JsonApiPatch, JsonApiDelete } = await import(\"../../unified/JsonApiRequest\");\n const language = navigator.language.split(\"-\")[0] || \"en\";\n\n let apiResponse: ApiResponseInterface;\n\n switch (config.method) {\n case \"POST\":\n apiResponse = await JsonApiPost({\n classKey: config.classKey,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.body,\n overridesJsonApiCreation: params.overridesJsonApiCreation,\n files: params.files,\n language,\n responseType: params.responseType,\n });\n break;\n case \"PUT\":\n apiResponse = await JsonApiPut({\n classKey: config.classKey,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.body,\n files: params.files,\n language,\n responseType: params.responseType,\n });\n break;\n case \"PATCH\":\n apiResponse = await JsonApiPatch({\n classKey: config.classKey,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.body,\n overridesJsonApiCreation: params.overridesJsonApiCreation,\n files: params.files,\n language,\n responseType: params.responseType,\n });\n break;\n case \"DELETE\":\n apiResponse = await JsonApiDelete({\n classKey: config.classKey,\n endpoint: params.endpoint,\n companyId: params.companyId,\n language,\n responseType: params.responseType,\n });\n break;\n }\n\n setResponse(apiResponse);\n\n if (apiResponse.ok) {\n const resultData = apiResponse.data as T;\n setData(resultData);\n config.onSuccess?.(resultData);\n return resultData;\n } else {\n setError(apiResponse.error);\n config.onError?.(apiResponse.error);\n return null;\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n config.onError?.(errorMessage);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [config],\n );\n\n return {\n data,\n loading,\n error,\n response,\n mutate,\n reset,\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { ApiDataInterface } from \"../../core/interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../../core/interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../../core/interfaces/JsonApiHydratedDataInterface\";\nimport { RehydrationFactory } from \"../../core/factories/RehydrationFactory\";\n\n/**\n * Hook to rehydrate server-passed data into typed objects.\n * Use this when passing data from server components to client components.\n *\n * @example\n * ```tsx\n * // In server component\n * const article = await ArticleService.findOne(id);\n * return <ArticleDetails data={article.dehydrate()} />;\n *\n * // In client component\n * function ArticleDetails({ data }: { data: JsonApiHydratedDataInterface }) {\n * const article = useRehydration<Article>(Modules.Article, data);\n * return <div>{article.title}</div>;\n * }\n * ```\n */\nexport function useRehydration<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface | null | undefined,\n): T | null {\n return useMemo(() => {\n if (!data) return null;\n return RehydrationFactory.rehydrate<T>(classKey, data);\n }, [classKey, data]);\n}\n\n/**\n * Hook to rehydrate a list of server-passed data into typed objects.\n */\nexport function useRehydrationList<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface[] | null | undefined,\n): T[] {\n return useMemo(() => {\n if (!data || data.length === 0) return [];\n return RehydrationFactory.rehydrateList<T>(classKey, data);\n }, [classKey, data]);\n}\n","\"use client\";\n\nimport { ColumnDef, Row } from \"@tanstack/react-table\";\nimport { useTranslations } from \"next-intl\";\nimport { useMemo } from \"react\";\nimport { cellDate, cellId } from \"../../../components\";\nimport { Modules } from \"../../../core\";\nimport { TableContent, usePageUrlGenerator, UseTableStructureHook } from \"../../../hooks\";\nimport { getRoleId } from \"../../../roles\";\nimport { Link } from \"../../../shadcnui\";\nimport { UserInterface } from \"../../user\";\nimport { useCurrentUserContext } from \"../../user/contexts\";\nimport { CompanyFields, CompanyInterface } from \"../data\";\n\nexport const useCompanyTableStructure: UseTableStructureHook<CompanyInterface, CompanyFields> = (params) => {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n const { hasRole } = useCurrentUserContext<UserInterface>();\n\n // Memoize tableData to prevent infinite re-renders\n const tableData = useMemo(() => {\n return params.data.map((company: CompanyInterface) => {\n const entry: TableContent<CompanyInterface> = {\n jsonApiData: company,\n };\n entry[CompanyFields.companyId] = company.id;\n params.fields.forEach((field) => {\n entry[field] = company[field as keyof CompanyInterface];\n });\n return entry;\n });\n }, [params.data, params.fields]);\n\n const fieldColumnMap: Partial<Record<CompanyFields, () => any>> = {\n [CompanyFields.companyId]: () =>\n cellId({\n name: \"companyId\",\n checkedIds: params.checkedIds,\n toggleId: params.toggleId,\n }),\n [CompanyFields.name]: () => ({\n id: \"name\",\n accessorKey: \"name\",\n header: t(`foundations.user.fields.name.label`),\n cell: ({ row }: { row: Row<TableContent<CompanyInterface>> }) => {\n const company = row.original.jsonApiData as CompanyInterface;\n return (\n <Link\n href={\n hasRole(getRoleId().Administrator)\n ? generateUrl({\n page: \"/administration\",\n id: Modules.Company.pageUrl?.substring(1),\n childPage: company.id,\n })\n : generateUrl({ page: Modules.Company, id: company.id })\n }\n >\n {row.getValue(\"name\")}\n </Link>\n );\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [CompanyFields.createdAt]: () =>\n cellDate({\n name: \"createdAt\",\n title: t(`generic.date.create`),\n }),\n };\n\n // Memoize columns to prevent infinite re-renders\n const columns = useMemo(() => {\n return params.fields.map((field) => fieldColumnMap[field]?.()).filter((col) => col !== undefined) as ColumnDef<\n TableContent<CompanyInterface>\n >[];\n }, [params.fields, fieldColumnMap, t, generateUrl, hasRole]);\n\n // Memoize the return object to prevent infinite re-renders\n return useMemo(() => ({ data: tableData, columns: columns }), [tableData, columns]);\n};\n","\"use client\";\n\nimport { ColumnDef, Row } from \"@tanstack/react-table\";\nimport { useTranslations } from \"next-intl\";\nimport { useMemo } from \"react\";\nimport { cellDate, cellId } from \"../../../components\";\nimport { Modules } from \"../../../core\";\nimport { TableContent, usePageUrlGenerator, UseTableStructureHook } from \"../../../hooks\";\nimport { Link } from \"../../../shadcnui\";\nimport { RoleFields, RoleInterface } from \"../data\";\n\nexport const useRoleTableStructure: UseTableStructureHook<RoleInterface, RoleFields> = (params) => {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n\n // Memoize tableData to prevent infinite re-renders\n const tableData = useMemo(() => {\n return params.data.map((role: RoleInterface) => {\n const entry: TableContent<RoleInterface> = {\n jsonApiData: role,\n };\n entry[RoleFields.roleId] = role.id;\n params.fields.forEach((field) => {\n entry[field] = role[field as keyof RoleInterface];\n });\n return entry;\n });\n }, [params.data, params.fields]);\n\n const fieldColumnMap: Partial<Record<RoleFields, () => any>> = {\n [RoleFields.roleId]: () =>\n cellId({\n name: \"roleId\",\n checkedIds: params.checkedIds,\n toggleId: params.toggleId,\n }),\n [RoleFields.name]: () => ({\n id: \"name\",\n accessorKey: \"name\",\n header: t(`foundations.role.fields.name.label`),\n cell: ({ row }: { row: Row<TableContent<RoleInterface>> }) => {\n const role = row.original.jsonApiData as RoleInterface;\n return <Link href={generateUrl({ page: Modules.Role, id: role.id })}>{row.getValue(\"name\")}</Link>;\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [RoleFields.description]: () => ({\n id: \"description\",\n accessorKey: \"description\",\n header: t(`foundations.role.fields.description.label`),\n cell: ({ row }: { row: Row<TableContent<RoleInterface>> }) => <>{row.getValue(\"description\")}</>,\n enableSorting: false,\n enableHiding: false,\n }),\n [RoleFields.createdAt]: () =>\n cellDate({\n name: \"createdAt\",\n title: t(`generic.date.create`),\n }),\n };\n\n // Memoize columns to prevent infinite re-renders\n const columns = useMemo(() => {\n return params.fields.map((field) => fieldColumnMap[field]?.()).filter((col) => col !== undefined) as ColumnDef<\n TableContent<RoleInterface>\n >[];\n }, [params.fields, fieldColumnMap, t, generateUrl]);\n\n // Memoize the return object to prevent infinite re-renders\n return useMemo(() => ({ data: tableData, columns: columns }), [tableData, columns]);\n};\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useDebounce } from \"../../../hooks/useDebounce\";\nimport { UserInterface } from \"../data\";\nimport { UserService } from \"../data/user.service\";\n\nexport const useUserSearch = () => {\n const [users, setUsers] = useState<UserInterface[]>([]);\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [isLoading, setIsLoading] = useState(false);\n const searchQueryRef = useRef(\"\");\n\n const loadUsers = useCallback(\n async (search: string) => {\n try {\n if (search === searchQueryRef.current && users.length > 0) return;\n setIsLoading(true);\n searchQueryRef.current = search;\n const fetchedUsers = await UserService.findMany({ search, fetchAll: true });\n setUsers(fetchedUsers);\n } catch (error) {\n console.error(\"Failed to load users:\", error);\n } finally {\n setIsLoading(false);\n }\n },\n [users.length],\n );\n\n const debouncedLoadUsers = useDebounce(loadUsers, 500);\n\n useEffect(() => {\n if (searchQuery !== searchQueryRef.current) {\n setIsLoading(true);\n debouncedLoadUsers(searchQuery);\n }\n }, [searchQuery, debouncedLoadUsers]);\n\n const clearSearch = () => {\n setSearchQuery(\"\");\n searchQueryRef.current = \"\";\n };\n\n return {\n users,\n searchQuery,\n setSearchQuery,\n isLoading,\n loadUsers,\n clearSearch,\n searchQueryRef,\n };\n};\n","\"use client\";\n\nimport { ColumnDef, Row } from \"@tanstack/react-table\";\nimport { useTranslations } from \"next-intl\";\nimport { useMemo } from \"react\";\nimport { cellDate, cellId, UserAvatar } from \"../../../components\";\nimport { Modules } from \"../../../core\";\nimport { TableContent, UseTableStructureHook } from \"../../../hooks/types\";\nimport { usePageUrlGenerator } from \"../../../hooks/usePageUrlGenerator\";\nimport { Link } from \"../../../shadcnui\";\nimport { cn } from \"../../../utils\";\nimport { UserFields, UserInterface } from \"../data\";\n\nexport const useUserTableStructure: UseTableStructureHook<UserInterface, UserFields> = (params) => {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n\n // Memoize tableData to prevent infinite re-renders\n const tableData = useMemo(() => {\n return params.data.map((user: UserInterface) => {\n const entry: TableContent<UserInterface> = {\n jsonApiData: user,\n };\n entry[UserFields.userId] = user.id;\n params.fields.forEach((field) => {\n entry[field] = user[field as keyof UserInterface];\n });\n return entry;\n });\n }, [params.data, params.fields]);\n\n const fieldColumnMap: Partial<Record<UserFields, () => any>> = {\n [UserFields.userId]: () =>\n cellId({\n name: \"userId\",\n checkedIds: params.checkedIds,\n toggleId: params.toggleId,\n }),\n [UserFields.name]: () => ({\n id: \"name\",\n accessorKey: \"name\",\n header: t(`foundations.user.fields.name.label`),\n cell: ({ row }: { row: Row<TableContent<UserInterface>> }) => {\n const user = row.original.jsonApiData as UserInterface;\n return (\n <Link\n href={generateUrl({ page: Modules.User, id: user.id })}\n className={cn(\n `flex items-center justify-start gap-2`,\n user.isDeleted || !user.isActivated ? \"text-muted-foreground italic\" : \"\",\n )}\n >\n <UserAvatar user={user} />\n {user.name}\n {user.isDeleted ? ` - ${t(\"foundations.user.errors.deleted\")}` : \"\"}\n {!user.isActivated ? ` - ${t(\"foundations.user.errors.inactive\")}` : \"\"}\n </Link>\n );\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [UserFields.email]: () => ({\n id: \"email\",\n accessorKey: \"email\",\n header: t(`generic.fields.email.label`),\n cell: ({ row }: { row: Row<TableContent<UserInterface>> }) => <>{row.getValue(\"email\")}</>,\n enableSorting: false,\n enableHiding: false,\n }),\n [UserFields.relevance]: () => ({\n id: \"relevance\",\n accessorKey: \"relevance\",\n header: t(`generic.relevance`),\n cell: ({ row }: { row: TableContent<UserInterface> }) => {\n const user: UserInterface = row.original.jsonApiData;\n\n if (!user.relevance) return <></>;\n\n const response = `${user.relevance.toFixed(0)}%`;\n\n return (\n <div className=\"relative flex h-5 w-20 items-center justify-center overflow-hidden rounded border text-center\">\n <div\n className={`bg-accent absolute top-0 left-0 h-full opacity-${Math.round(user.relevance)}`}\n style={{ width: `${user.relevance}%` }}\n ></div>\n <span\n className={`relative text-xs ${user.relevance < 40 ? \"text-muted-foreground\" : \"text-accent-foreground font-semibold\"}`}\n >\n {response}\n </span>\n </div>\n );\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [UserFields.createdAt]: () =>\n cellDate({\n name: \"createdAt\",\n title: t(`generic.date.create`),\n }),\n };\n\n // Memoize columns to prevent infinite re-renders\n const columns = useMemo(() => {\n return params.fields.map((field) => fieldColumnMap[field]?.()).filter((col) => col !== undefined) as ColumnDef<\n TableContent<UserInterface>\n >[];\n }, [params.fields, fieldColumnMap, t, generateUrl]);\n\n // Memoize the return object to prevent infinite re-renders\n return useMemo(() => ({ data: tableData, columns: columns }), [tableData, columns]);\n};\n","\"use client\";\n\nimport { ColumnDef } from \"@tanstack/react-table\";\nimport { useTranslations } from \"next-intl\";\nimport { useMemo } from \"react\";\nimport { cellDate, cellId, ContributorsList } from \"../../../components\";\nimport { Modules } from \"../../../core\";\nimport { TableContent, usePageUrlGenerator, UseTableStructureHook } from \"../../../hooks\";\nimport { Link, Tooltip, TooltipContent, TooltipTrigger } from \"../../../shadcnui\";\nimport { getIconByModule } from \"../../../utils\";\nimport { ContentFields, ContentInterface } from \"../data\";\n\nexport const useContentTableStructure = <U extends string = ContentFields>(\n params: Parameters<UseTableStructureHook<ContentInterface, U>>[0],\n): ReturnType<UseTableStructureHook<ContentInterface, U>> => {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n\n const tableData = useMemo(() => {\n return params.data.map((content: ContentInterface) => {\n const entry: TableContent<ContentInterface> = {\n jsonApiData: content,\n };\n entry[ContentFields.contentId] = content.id;\n params.fields.forEach((field) => {\n entry[field as string] = content[field as keyof ContentInterface];\n });\n return entry;\n });\n }, [params.data, params.fields]);\n\n const fieldColumnMap: Partial<Record<string, () => any>> = {\n [ContentFields.contentId]: () =>\n cellId({\n name: \"contentId\",\n checkedIds: params.checkedIds,\n toggleId: params.toggleId,\n }),\n [ContentFields.name]: () => ({\n id: \"name\",\n accessorKey: \"name\",\n header: t(`foundations.content.fields.name.label`),\n cell: ({ row }: { row: TableContent<ContentInterface> }) => {\n const content: ContentInterface = row.original.jsonApiData;\n\n const contentModule = content.contentType ? Modules.findByModelName(content.contentType) : undefined;\n const link = contentModule ? generateUrl({ page: contentModule, id: content.id }) : \"#\";\n\n return (\n <Tooltip>\n <TooltipTrigger className=\"flex items-center justify-start space-x-2\">\n <>\n {contentModule && getIconByModule({ module: contentModule, className: \"h-4 w-4\" })}\n <Link href={link}>{content.name}</Link>\n </>\n </TooltipTrigger>\n <TooltipContent>{content.tldr}</TooltipContent>\n </Tooltip>\n );\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [ContentFields.relevance]: () => ({\n id: \"relevance\",\n accessorKey: \"relevance\",\n header: t(`generic.relevance`),\n cell: ({ row }: { row: TableContent<ContentInterface> }) => {\n const content: ContentInterface = row.original.jsonApiData;\n\n if (!content.relevance) return <></>;\n\n const response = `${content.relevance.toFixed(0)}%`;\n\n return (\n <div className=\"relative flex h-5 w-20 items-center justify-center overflow-hidden rounded border text-center\">\n <div\n className={`bg-accent absolute top-0 left-0 h-full opacity-${Math.round(content.relevance)}`}\n style={{ width: `${content.relevance}%` }}\n ></div>\n <span\n className={`relative text-xs ${content.relevance < 40 ? \"text-muted-foreground\" : \"text-accent-foreground font-semibold\"}`}\n >\n {response}\n </span>\n </div>\n );\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [ContentFields.authors]: () => ({\n id: \"authors\",\n accessorKey: \"authors\",\n header: t(`generic.relationships.author.label`),\n cell: ({ row }: { row: TableContent<ContentInterface> }) => {\n const content: ContentInterface = row.original.jsonApiData;\n return <ContributorsList content={content} />;\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [ContentFields.createdAt]: () =>\n cellDate({\n name: \"createdAt\",\n title: t(`generic.date.create`),\n }),\n [ContentFields.updatedAt]: () =>\n cellDate({\n name: \"updatedAt\",\n title: t(`generic.date.update`),\n }),\n };\n\n const columns = useMemo(() => {\n return params.fields\n .map((field) => {\n // First check local fieldColumnMap\n const localHandler = fieldColumnMap[field];\n if (localHandler) return localHandler();\n\n // Fallback to customCells from context\n const customHandler = params.context?.customCells?.[field];\n if (customHandler) return customHandler({ t });\n\n return undefined;\n })\n .filter((col) => col !== undefined) as ColumnDef<TableContent<ContentInterface>>[];\n }, [params.fields, fieldColumnMap, t, generateUrl, params.context?.customCells]);\n\n return useMemo(() => ({ data: tableData, columns: columns }), [tableData, columns]);\n};\n","\"use client\";\n\n// Context and Provider\nexport * from \"./context\";\n\n// Client-side hooks\nexport * from \"./hooks\";\n\n// Client-side request utilities\nexport * from \"./request\";\nexport * from \"./token\";\nexport * from \"./JsonApiClient\";\nexport * from \"./config\";\n\n// All hooks (merged from /hooks entry point)\nexport * from \"../hooks\";\n\n// Table generator registration (must be in client-only context)\nimport { useCompanyTableStructure } from \"../features/company/hooks\";\nimport { useRoleTableStructure } from \"../features/role/hooks\";\nimport { useUserTableStructure } from \"../features/user/hooks\";\nimport { registerTableGenerator } from \"../hooks\";\n\nexport * from \"../features/content/hooks\";\nexport * from \"../features/role/hooks\";\nexport * from \"../features/user/hooks\";\n\nregisterTableGenerator(\"roles\", useRoleTableStructure);\nregisterTableGenerator(\"users\", useUserTableStructure);\nregisterTableGenerator(\"companies\", useCompanyTableStructure);\n// Note: Content registration moved to app-level to support app-specific cellTopic\n","\"use client\";\nimport \"../../client\";\n\nimport { flexRender, getCoreRowModel, useReactTable } from \"@tanstack/react-table\";\n\nimport { CaretLeftIcon, CaretRightIcon } from \"@radix-ui/react-icons\";\nimport { ReactNode, memo, useMemo } from \"react\";\nimport { DataListRetriever, useTableGenerator } from \"../../hooks\";\nimport { ModuleWithPermissions } from \"../../permissions\";\nimport { Button, Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from \"../../shadcnui\";\nimport { ContentTableSearch } from \"./ContentTableSearch\";\n\nconst EMPTY_ARRAY: any[] = [];\n\nexport type GenerateTableStructureParams = {\n data: any[];\n toggleValueToFormIdsId: (id: string, name: string) => void;\n isSelected: (id: string) => boolean;\n};\n\ntype ContentListTableProps = {\n title?: string;\n data: DataListRetriever<any>;\n tableGenerator?: never;\n tableGeneratorType: ModuleWithPermissions;\n fields: any[];\n checkedIds?: string[];\n toggleId?: (id: string) => void;\n functions?: ReactNode;\n filters?: ReactNode;\n allowSearch?: boolean;\n context?: Record<string, any>;\n};\n\nexport const ContentListTable = memo(function ContentListTable(props: ContentListTableProps) {\n const { data, fields, checkedIds, toggleId, allowSearch, filters } = props;\n\n const { data: tableData, columns: tableColumns } = useTableGenerator(props.tableGeneratorType, {\n data: data?.data ?? EMPTY_ARRAY,\n fields: fields,\n checkedIds: checkedIds,\n toggleId: toggleId,\n dataRetriever: data,\n context: props.context,\n });\n\n const columnVisibility = useMemo(\n () =>\n fields.reduce(\n (acc, columnId) => {\n acc[columnId] = true;\n return acc;\n },\n {} as Record<string, boolean>,\n ),\n [fields],\n );\n\n const table = useReactTable({\n data: tableData,\n columns: tableColumns,\n getCoreRowModel: getCoreRowModel(),\n initialState: {\n columnVisibility,\n },\n });\n\n // if (!data.isLoaded || !data.data) {\n // return <ContentListTableLoader />;\n // }\n\n const rowModel = tableData ? table.getRowModel() : null;\n const showFooter = !!(props.functions || data.next || data.previous);\n\n return (\n <div className=\"flex w-full flex-col\">\n <div className=\"overflow-hidden rounded-md border\">\n <Table>\n <TableHeader className=\"bg-muted font-semibold\">\n {props.title && (\n <TableRow>\n <TableHead className=\"bg-card text-primary p-4 text-left font-bold\" colSpan={tableColumns.length}>\n <div className=\"flex w-full items-center justify-between gap-x-2\">\n <div className=\"w-full\">{props.title}</div>\n {(props.functions || props.filters || allowSearch) && (\n <>\n {props.functions}\n {props.filters}\n <ContentTableSearch data={data} />\n </>\n )}\n </div>\n </TableHead>\n </TableRow>\n )}\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map((header) => {\n return (\n <TableHead key={header.id}>\n {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}\n </TableHead>\n );\n })}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n {rowModel && rowModel.rows?.length ? (\n rowModel.rows.map((row) => (\n <TableRow key={row.id}>\n {row.getVisibleCells().map((cell) => (\n <TableCell key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCell>\n ))}\n </TableRow>\n ))\n ) : (\n <TableRow>\n <TableCell colSpan={tableColumns.length} className=\"h-24 text-center\">\n No results.\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n {showFooter && (\n <TableFooter>\n <TableRow>\n <TableCell colSpan={tableColumns.length} className=\"bg-card py-4 text-right\">\n <div className=\"flex items-center justify-end space-x-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.preventDefault();\n data.previous?.(true);\n }}\n disabled={!data.previous}\n >\n <CaretLeftIcon className=\"h-4 w-4\" />\n </Button>\n {data.pageInfo && (\n <span className=\"text-muted-foreground text-xs\">\n {data.pageInfo.startItem}-{data.pageInfo.endItem}\n </span>\n )}\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.preventDefault();\n data.next?.(true);\n }}\n disabled={!data.next}\n >\n <CaretRightIcon className=\"h-4 w-4\" />\n </Button>\n </div>\n </TableCell>\n </TableRow>\n </TableFooter>\n )}\n </Table>\n </div>\n </div>\n );\n});\n","\"use client\";\n\nimport { RefreshCw, Search, X } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { DataListRetriever, useDebounce } from \"../../hooks\";\nimport { Input } from \"../../shadcnui\";\n\ntype ContentTableSearchProps = {\n data: DataListRetriever<any>;\n};\n\nexport function ContentTableSearch({ data }: ContentTableSearchProps) {\n const t = useTranslations();\n const searchTermRef = useRef<string>(\"\");\n const inputRef = useRef<HTMLInputElement>(null);\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n const [isFocused, setIsFocused] = useState<boolean>(false);\n const [isSearching, setIsSearching] = useState<boolean>(false);\n\n const isExpanded = isFocused || searchTerm.length > 0;\n\n const search = useCallback(\n async (searchedTerm: string) => {\n try {\n if (searchedTerm === searchTermRef.current) return;\n searchTermRef.current = searchedTerm;\n\n await data.search(searchedTerm);\n } finally {\n setIsSearching(false);\n }\n },\n [searchTermRef, data],\n );\n\n const updateSearchTerm = useDebounce(search, 500);\n\n useEffect(() => {\n setIsSearching(true);\n updateSearchTerm(searchTerm);\n }, [updateSearchTerm, searchTerm]);\n\n const handleSearchIconClick = () => {\n if (!isExpanded) {\n setIsFocused(true);\n // Small delay to ensure the input is rendered before focusing\n setTimeout(() => inputRef.current?.focus(), 50);\n }\n };\n\n const handleBlur = () => {\n // Auto-collapse only if search is empty\n if (searchTerm.length === 0) {\n setIsFocused(false);\n }\n };\n\n const handleClear = () => {\n setSearchTerm(\"\");\n search(\"\");\n setIsFocused(false);\n };\n\n return (\n <div\n className={`relative flex h-6 items-center text-xs font-normal transition-all duration-300 ease-in-out ${\n isExpanded ? \"w-64\" : \"w-6\"\n }`}\n >\n <Search\n className={`absolute top-1 left-1 h-4 w-4 transition-colors ${\n isExpanded ? \"text-muted-foreground\" : \"text-muted-foreground hover:text-foreground cursor-pointer\"\n }`}\n onClick={handleSearchIconClick}\n />\n {isExpanded && (\n <Input\n ref={inputRef}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n handleClear();\n }\n }}\n onFocus={() => setIsFocused(true)}\n onBlur={handleBlur}\n placeholder={t(`generic.search.placeholder_global`)}\n type=\"text\"\n className=\"border-border/50 focus-visible:border-border h-10 w-full pr-8 pl-8 text-xs shadow-none focus-visible:ring-0\"\n onChange={(e) => setSearchTerm(e.target.value)}\n value={searchTerm}\n />\n )}\n {isExpanded && isSearching && (\n <RefreshCw className=\"text-muted-foreground absolute top-1 right-1 h-4 w-4 animate-spin\" />\n )}\n {isExpanded && !isSearching && searchTermRef.current && (\n <X\n className=\"text-muted-foreground hover:text-foreground absolute top-1 right-1 h-4 w-4 cursor-pointer\"\n onClick={handleClear}\n />\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport Image from \"next/image\";\nimport { Card } from \"../../../../shadcnui\";\nimport { AuthContextProvider, useAuthContext } from \"../../contexts\";\nimport { AuthComponent } from \"../../enums\";\n\ntype AuthContainerProps = {\n componentType: AuthComponent;\n params?: { code?: string };\n};\n\nexport function AuthContainer({ componentType, params }: AuthContainerProps) {\n return (\n <AuthContextProvider initialComponentType={componentType} initialParams={params}>\n <InnerAuthContainer />\n </AuthContextProvider>\n );\n}\n\nfunction InnerAuthContainer() {\n const { activeComponent } = useAuthContext();\n\n if (activeComponent === null)\n return (\n <div className=\"max-w-sm\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} className=\"animate-spin-slow\" priority />\n </div>\n );\n\n return <Card className=\"w-full max-w-md\">{activeComponent}</Card>;\n}\n","\"use client\";\n\nimport { createContext, ReactElement, useContext, useMemo, useState } from \"react\";\nimport {\n AcceptInvitation,\n ActivateAccount,\n ForgotPassword,\n LandingComponent,\n Login,\n ResetPassword,\n} from \"../components\";\nimport Register from \"../components/forms/Register\";\nimport { AuthComponent } from \"../enums\";\n\ninterface AuthContextType {\n activeComponent: ReactElement<any> | null;\n setComponentType: (componentType: AuthComponent) => void;\n setParams: (params?: { code?: string }) => void;\n params?: { code?: string };\n}\n\nconst AuthContext = createContext<AuthContextType | undefined>(undefined);\n\nexport const AuthContextProvider = ({\n children,\n initialComponentType,\n initialParams,\n}: {\n children: React.ReactNode;\n initialComponentType?: AuthComponent;\n initialParams?: { code?: string };\n}) => {\n const [componentType, setComponentType] = useState<AuthComponent | undefined>(initialComponentType);\n const [params, setParams] = useState<{ code?: string } | undefined>(initialParams);\n\n const activeComponent = useMemo(() => {\n if (componentType === undefined) return null;\n\n switch (componentType) {\n case AuthComponent.Login:\n return <Login />;\n case AuthComponent.Register:\n return <Register />;\n case AuthComponent.ForgotPassword:\n return <ForgotPassword />;\n case AuthComponent.ActivateAccount:\n return <ActivateAccount />;\n case AuthComponent.ResetPassword:\n return <ResetPassword />;\n case AuthComponent.AcceptInvitation:\n return <AcceptInvitation />;\n default:\n return <LandingComponent />;\n }\n }, [componentType]);\n\n return (\n <AuthContext.Provider\n value={{\n activeComponent,\n setComponentType,\n setParams,\n params,\n }}\n >\n {children}\n </AuthContext.Provider>\n );\n};\n\nexport const useAuthContext = (): AuthContextType => {\n const context = useContext(AuthContext);\n if (context === undefined) {\n throw new Error(\"useAuthContext must be used within a AuthComponentProvider\");\n }\n return context;\n};\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { v4 } from \"uuid\";\nimport { z } from \"zod\";\nimport { errorToast, FormInput, FormPassword } from \"../../../../components\";\nimport {\n Button,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n Form,\n Link,\n} from \"../../../../shadcnui\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport default function Register() {\n const t = useTranslations();\n const { setComponentType } = useAuthContext();\n\n const [showConfirmation, setShowConfirmation] = useState<boolean>(false);\n\n const formSchema = z.object({\n company: z.string().min(1, {\n message: t(`generic.errors.missing_company_name`),\n }),\n name: z.string().min(1, {\n message: t(\"generic.errors.missing_name\"),\n }),\n email: z.string().email({\n message: t(`generic.errors.invalid_email`),\n }),\n password: z\n .string()\n .min(8, t(`foundations.auth.errors.password_too_short`))\n .regex(/^(?=.*[0-9])(?=.*[^a-zA-Z0-9]).*$/, {\n message: t(`foundations.auth.errors.password_invalid_format`),\n }),\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n company: \"\",\n name: \"\",\n email: \"\",\n password: \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n try {\n const payload = {\n id: v4(),\n companyName: values.company,\n name: values.name,\n email: values.email,\n password: values.password,\n };\n\n await AuthService.register(payload);\n setShowConfirmation(true);\n } catch (e) {\n errorToast({ error: e });\n }\n };\n\n return (\n <>\n <CardHeader>\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(`foundations.auth.register`)}\n </CardTitle>\n <CardDescription className=\"text-sm\">\n {showConfirmation ? <> </> : <>{t(`foundations.auth.register_description`)}</>}\n </CardDescription>\n </CardHeader>\n {showConfirmation ? (\n <CardContent>\n <CardDescription className=\"text-center text-xl\">\n {t(\"foundations.auth.register_confirmation\")}\n </CardDescription>\n </CardContent>\n ) : (\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <CardContent>\n <FormInput\n isRequired\n form={form}\n id=\"company\"\n name={t(`foundations.company.fields.name.label`)}\n placeholder={t(`foundations.company.fields.name.placeholder`)}\n />\n <FormInput\n isRequired\n form={form}\n id=\"name\"\n name={t(`foundations.user.fields.name.label`)}\n placeholder={t(`foundations.user.fields.name.placeholder`)}\n />\n <FormInput\n isRequired\n form={form}\n id=\"email\"\n name={t(`generic.fields.email.label`)}\n placeholder={t(`generic.fields.email.placeholder`)}\n />\n <FormPassword\n isRequired\n form={form}\n id=\"password\"\n name={t(`foundations.user.fields.password.label`)}\n placeholder={t(`foundations.user.fields.password.placeholder`)}\n />\n <Button className=\"mt-4 w-full\" type={\"submit\"}>\n {t(`foundations.auth.buttons.register`)}\n </Button>\n </CardContent>\n <CardFooter className=\"flex w-full flex-row justify-between\">\n <Link\n href=\"#\"\n className=\"flex w-full justify-start\"\n onClick={() => setComponentType(AuthComponent.Login)}\n >\n {t(`foundations.auth.buttons.login`)}\n </Link>\n <Link\n href=\"#\"\n className=\"flex w-full justify-end\"\n onClick={() => setComponentType(AuthComponent.ForgotPassword)}\n >\n {t(`foundations.auth.buttons.forgot_password`)}\n </Link>\n </CardFooter>\n </form>\n </Form>\n )}\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { isDiscordConfigured, isInternalAuthConfigured } from \"../../../../discord\";\nimport { Button, CardDescription, CardFooter, CardHeader, CardTitle, Link } from \"../../../../shadcnui\";\nimport { getApiUrl } from \"../../../../client/config\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function LandingComponent() {\n const t = useTranslations();\n\n const { setComponentType } = useAuthContext();\n\n return (\n <>\n <CardHeader className=\"mb-4\" data-testid=\"page-pre-login-container\">\n <CardTitle className=\"text-primary flex flex-col items-center gap-y-8 pb-8 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(`generic.title`)}\n </CardTitle>\n <CardDescription className=\"flex w-full justify-center text-center text-sm\">\n {t(`generic.description`)}\n </CardDescription>\n </CardHeader>\n <CardFooter className=\"mt-4 flex w-full flex-col justify-between gap-y-4\">\n {isInternalAuthConfigured() && (\n <>\n <Link\n href=\"#\"\n className=\"flex w-full justify-start\"\n onClick={() => setComponentType(AuthComponent.Register)}\n >\n <Button className=\"w-full\" variant={`default`}>\n {t(`foundations.auth.buttons.register`)}\n </Button>\n </Link>\n <Link href=\"#\" className=\"flex w-full justify-end\" onClick={() => setComponentType(AuthComponent.Login)}>\n <Button className=\"w-full\" variant={`outline`} data-testid=\"page-login-button-initial-login\">\n {t(`foundations.auth.buttons.login`)}\n </Button>\n </Link>\n </>\n )}\n {isDiscordConfigured() && (\n <Link href={`${getApiUrl()}auth/discord`} className=\"flex w-full justify-end\">\n <Button className=\"w-full\" variant={`outline`} data-testid=\"page-login-button-initial-login\">\n Login with Discord\n </Button>\n </Link>\n )}\n </CardFooter>\n </>\n );\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\nimport { errorToast, FormPassword } from \"../../../../components\";\nimport { Button, CardContent, CardDescription, CardHeader, CardTitle, Form } from \"../../../../shadcnui\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function AcceptInvitation() {\n const { setComponentType, params, setParams } = useAuthContext();\n const [showConfirmation, setShowConfirmation] = useState<boolean>(false);\n const [error, setError] = useState<string | undefined>(undefined);\n const t = useTranslations();\n\n useEffect(() => {\n async function validateCode(code: string) {\n try {\n const payload: any = {\n code: code,\n };\n\n await AuthService.validateCode(payload);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n errorToast({ title: t(`generic.errors.error`), error: e });\n }\n }\n\n if (params && params.code) {\n validateCode(params.code);\n } else {\n setError(t(`foundations.auth.errors.invalid_invitation_code`));\n }\n }, []);\n\n const formSchema = z\n .object({\n password: z.string().min(1, {\n message: t(`foundations.user.fields.password.error`),\n }),\n passwordRetype: z.string().min(1, {\n message: t(\"foundations.auth.errors.password_retype_required\"),\n }),\n })\n .refine((data) => data.password === data.passwordRetype, {\n message: t(\"foundations.auth.fields.retype_password.error_not_match\"),\n path: [\"passwordRetype\"],\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n password: \"\",\n passwordRetype: \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n try {\n if (!params?.code) return;\n\n const payload = {\n code: params?.code,\n password: values.password,\n };\n\n await AuthService.acceptInvitation(payload);\n setShowConfirmation(true);\n\n toast.success(t(\"foundations.auth.account_activated\"), {\n description: t(\"foundations.auth.account_activated_description\"),\n });\n\n setTimeout(() => {\n setComponentType(AuthComponent.Login);\n setParams(undefined);\n }, 2000);\n } catch (e) {\n errorToast({ title: t(`generic.errors.error`), error });\n }\n };\n\n return (\n <>\n <CardHeader>\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(\"foundations.auth.accept_invitation\")}\n </CardTitle>\n <CardDescription className=\"text-center text-sm\">\n {error ? (\n <>{t(\"foundations.auth.errors.activating_account\")}</>\n ) : (\n <>{t(\"foundations.auth.select_password\")}</>\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {showConfirmation ? (\n <CardDescription className=\"text-center text-xl\">\n {t(\"foundations.auth.activation_description\")}\n </CardDescription>\n ) : error ? (\n <CardDescription className=\"text-center text-xl\">{error}</CardDescription>\n ) : (\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <FormPassword\n form={form}\n id=\"password\"\n name={t(`foundations.user.fields.password.label`)}\n placeholder={t(`foundations.user.fields.password.placeholder`)}\n />\n <FormPassword\n form={form}\n id=\"passwordRetype\"\n name={t(\"foundations.auth.fields.retype_password.label\")}\n placeholder={t(`foundations.auth.fields.retype_password.placeholder`)}\n />\n <Button className=\"mt-4 w-full\" type={\"submit\"}>\n {t(\"foundations.auth.accept_invitation\")}\n </Button>\n </form>\n </Form>\n )}\n </CardContent>\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { errorToast } from \"../../../../components\";\nimport { CardContent, CardDescription, CardHeader, CardTitle } from \"../../../../shadcnui\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function ActivateAccount() {\n const { setComponentType, params, setParams } = useAuthContext();\n const [showConfirmation, setShowConfirmation] = useState<boolean>(false);\n const [error, setError] = useState<string | undefined>(undefined);\n const t = useTranslations();\n\n useEffect(() => {\n async function ActivateAccount(code: string) {\n try {\n const payload = {\n activationCode: code,\n };\n\n await AuthService.activate(payload);\n setShowConfirmation(true);\n\n setParams(undefined);\n\n toast.success(t(\"foundations.auth.account_activated\"), {\n description: t(\"foundations.auth.account_activated_description\"),\n });\n\n setTimeout(() => {\n setComponentType(AuthComponent.Login);\n }, 2000);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n errorToast({ title: t(`generic.errors.error`), error: e });\n }\n }\n\n if (params && params.code) {\n ActivateAccount(params.code);\n } else {\n setError(t(`foundations.auth.errors.invalid_invitation_code`));\n }\n }, []);\n\n return (\n <>\n <CardHeader>\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(\"foundations.auth.accept_invitation\")}\n </CardTitle>\n <CardDescription className=\"text-center text-sm\">\n {error ? <>{t(\"foundations.auth.errors.activating_account\")}</> : <> </>}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <CardDescription className=\"text-center text-xl\">\n {showConfirmation ? (\n <>{t(\"foundations.auth.activation_description\")}</>\n ) : error ? (\n <>{error}</>\n ) : (\n <>{t(\"foundations.auth.activation_wait\")}</>\n )}\n </CardDescription>\n </CardContent>\n </>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { JsonApiHydratedDataInterface, Modules, rehydrate } from \"../../../../core\";\nimport { useI18nRouter } from \"../../../../i18n\";\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { AuthInterface } from \"../../data\";\nimport { AuthService } from \"../../data/auth.service\";\n\nexport function Cookies({ dehydratedAuth, page }: { dehydratedAuth: JsonApiHydratedDataInterface; page?: string }) {\n const { setUser } = useCurrentUserContext<UserInterface>();\n const router = useI18nRouter();\n const [hasSaved, setHasSaved] = useState(false);\n\n useEffect(() => {\n if (hasSaved) return;\n async function saveTokenOnServer() {\n await AuthService.saveToken({ dehydratedAuth });\n const auth: AuthInterface = rehydrate(Modules.Auth, dehydratedAuth) as AuthInterface;\n setUser(auth.user as UserInterface);\n setHasSaved(true);\n\n if (page) {\n if (page.startsWith(\"/\")) router.push(page ?? \"/\");\n window.location.href = page;\n }\n }\n saveTokenOnServer();\n }, [dehydratedAuth, setUser, hasSaved, router]);\n\n return null;\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { errorToast, FormInput } from \"../../../../components\";\nimport {\n Button,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n Form,\n Link,\n} from \"../../../../shadcnui\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function ForgotPassword() {\n const t = useTranslations();\n const { setComponentType } = useAuthContext();\n\n const [showConfirmation, setShowConfirmation] = useState<boolean>(false);\n\n const formSchema = z.object({\n email: z.string().email({\n message: t(`generic.errors.invalid_email`),\n }),\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n email: \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n try {\n const payload = {\n email: values.email,\n };\n\n await AuthService.initialiseForgotPassword(payload);\n setShowConfirmation(true);\n } catch (e) {\n errorToast({ error: e });\n }\n };\n\n return (\n <>\n <CardHeader data-testid=\"page-forgot-password-container\">\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(\"foundations.auth.forgot_password\")}\n </CardTitle>\n <CardDescription className=\"text-sm\">\n {showConfirmation ? <> </> : <>{t(`foundations.auth.add_email_to_reset`)}</>}\n </CardDescription>\n </CardHeader>\n {showConfirmation ? (\n <CardContent>\n <CardDescription className=\"text-center text-xl\">{t(`foundations.auth.reset_confirmation`)}</CardDescription>\n </CardContent>\n ) : (\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <CardContent>\n <FormInput\n form={form}\n id=\"email\"\n name={t(`generic.fields.email.label`)}\n placeholder={t(`generic.fields.email.placeholder`)}\n testId=\"form-forgot-password-input-email\"\n />\n <Button className=\"mt-4 w-full\" type={\"submit\"} data-testid=\"form-forgot-password-button-reset\">\n {t(`foundations.auth.buttons.reset_password`)}\n </Button>\n </CardContent>\n <CardFooter className=\"flex w-full flex-row justify-between\">\n {/* <Link\n href=\"#\"\n className=\"flex w-full justify-start\"\n onClick={() => setComponentType(AuthComponent.Register)}\n >\n {t(\"foundations.auth.buttons.register\")}\n </Link> */}\n <Link\n href=\"#\"\n className=\"flex w-full justify-end\"\n onClick={() => setComponentType(AuthComponent.Login)}\n data-testid=\"form-forgot-password-link-login\"\n >\n {t(`foundations.auth.buttons.login`)}\n </Link>\n </CardFooter>\n </form>\n </Form>\n )}\n </>\n );\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { errorToast, FormInput, FormPassword } from \"../../../../components\";\nimport { useI18nRouter, usePageUrlGenerator } from \"../../../../hooks\";\nimport {\n Button,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n Form,\n Link,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function Login() {\n const t = useTranslations();\n const { setUser } = useCurrentUserContext<UserInterface>();\n const { setComponentType } = useAuthContext();\n const generateUrl = usePageUrlGenerator();\n const router = useI18nRouter();\n\n const formSchema = z.object({\n email: z.string().email({\n message: t(`generic.errors.invalid_email`),\n }),\n password: z.string().min(3, { message: t(`foundations.auth.errors.password_too_short`) }),\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n email: \"\",\n password: \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n try {\n const user: UserInterface = (await AuthService.login({\n email: values.email,\n password: values.password,\n })) as UserInterface;\n\n setUser(user);\n router.replace(generateUrl({ page: `/` }));\n } catch (e) {\n errorToast({\n title: t(`generic.errors.error`),\n error: e,\n });\n }\n };\n\n return (\n <>\n <CardHeader data-testid=\"page-login-container\">\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(\"foundations.auth.login\")}\n </CardTitle>\n\n <CardDescription className=\"text-sm\">{t(`foundations.auth.login_description`)}</CardDescription>\n </CardHeader>\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <CardContent>\n <FormInput\n autoFocus\n form={form}\n id=\"email\"\n name={t(`generic.fields.email.label`)}\n placeholder={t(`generic.fields.email.placeholder`)}\n testId=\"form-login-input-email\"\n />\n <FormPassword\n form={form}\n id=\"password\"\n name={t(`foundations.user.fields.password.label`)}\n placeholder={t(`foundations.user.fields.password.placeholder`)}\n testId=\"form-login-input-password\"\n />\n <Button className=\"mt-4 w-full\" type={\"submit\"} data-testid=\"form-login-button-submit\">\n {t(`foundations.auth.login`)}\n </Button>\n </CardContent>\n <CardFooter className=\"flex w-full flex-row justify-between\">\n <Link\n href=\"#\"\n className=\"flex w-full justify-start\"\n onClick={() => setComponentType(AuthComponent.Register)}\n >\n {t(`foundations.auth.register`)}\n </Link>\n <Link\n href=\"#\"\n className=\"flex w-full justify-end\"\n onClick={() => setComponentType(AuthComponent.ForgotPassword)}\n data-testid=\"form-login-link-forgot-password\"\n >\n {t(`foundations.auth.forgot_password`)}\n </Link>\n </CardFooter>\n </form>\n </Form>\n </>\n );\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { AuthService } from \"../../data/auth.service\";\n\nexport function Logout() {\n const generateUrl = usePageUrlGenerator();\n\n useEffect(() => {\n const logOut = async () => {\n await AuthService.logout();\n window.location.href = generateUrl({ page: `/` });\n };\n logOut();\n }, []);\n\n return <></>;\n}\n","\"use client\";\n\nimport { deleteCookie, getCookie } from \"cookies-next\";\nimport { useEffect } from \"react\";\nimport { UserInterface } from \"../../../user\";\nimport { UserService } from \"../../../user/data/user.service\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { getTokenHandler } from \"../../config\";\n\nexport function RefreshUser() {\n const { setUser } = useCurrentUserContext<UserInterface>();\n\n const loadFullUser = async () => {\n const fullUser = await UserService.findFullUser();\n\n if (fullUser) {\n setUser(fullUser);\n const token = {\n userId: fullUser.id,\n companyId: fullUser.company?.id,\n licenseExpirationDate: fullUser.company?.licenseExpirationDate,\n roles: fullUser.roles.map((role) => role.id),\n features: fullUser.company?.features?.map((feature) => feature.id) ?? [],\n modules: fullUser.modules.map((module) => {\n return { id: module.id, permissions: module.permissions };\n }),\n };\n\n await getTokenHandler()?.updateToken(token);\n deleteCookie(\"reloadData\");\n }\n };\n\n useEffect(() => {\n const reloadData = getCookie(\"reloadData\");\n if (reloadData !== undefined) loadFullUser();\n }, []);\n\n return null;\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\nimport { errorToast, FormPassword } from \"../../../../components\";\nimport { Button, CardContent, CardDescription, CardHeader, CardTitle, Form } from \"../../../../shadcnui\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function ResetPassword() {\n const { setComponentType, params, setParams } = useAuthContext();\n const [showConfirmation, setShowConfirmation] = useState<boolean>(false);\n const [error, setError] = useState<string | undefined>(undefined);\n const t = useTranslations();\n\n useEffect(() => {\n async function validateResetPasswordCode(code: string) {\n try {\n const payload: any = {\n code: code,\n };\n\n await AuthService.validateCode(payload);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n errorToast({ title: t(`generic.errors.error`), error: e });\n }\n }\n\n if (params && params.code) {\n validateResetPasswordCode(params.code);\n } else {\n setError(t(`foundations.auth.errors.invalid_password_reset_code`));\n }\n }, []);\n\n const formSchema = z\n .object({\n password: z.string().min(1, {\n message: t(`foundations.user.fields.password.error`),\n }),\n passwordRetype: z.string().min(1, {\n message: t(`foundations.auth.fields.retype_password.error`),\n }),\n })\n .refine((data) => data.password === data.passwordRetype, {\n message: t(`foundations.auth.fields.retype_password.error_not_match`),\n path: [\"passwordRetype\"],\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n password: \"\",\n passwordRetype: \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n try {\n if (!params?.code) return;\n\n const payload = {\n code: params?.code,\n password: values.password,\n };\n\n await AuthService.resetPassword(payload);\n setShowConfirmation(true);\n\n toast.success(t(`foundations.auth.reset_success`), {\n description: t(`foundations.auth.reset_success_description`),\n });\n\n setTimeout(() => {\n setComponentType(AuthComponent.Login);\n setParams(undefined);\n }, 2000);\n } catch (e) {\n errorToast({ title: t(`generic.errors.error`), error });\n }\n };\n\n return (\n <>\n <CardHeader>\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(`foundations.auth.password_reset`)}\n </CardTitle>\n <CardDescription className=\"text-center text-sm\">\n {error ? (\n <>{t(`foundations.auth.errors.password_reset_error`)}</>\n ) : (\n <>{t(`foundations.auth.reset_password`)}</>\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {showConfirmation ? (\n <CardDescription className=\"text-center text-xl\">\n {t(`foundations.auth.reset_success_description`)}\n </CardDescription>\n ) : error ? (\n <CardDescription className=\"text-center text-xl\">{error}</CardDescription>\n ) : (\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <FormPassword form={form} id=\"password\" name={\"Password\"} />\n <FormPassword form={form} id=\"passwordRetype\" name={\"Retype Password\"} />\n <Button className=\"mt-4 w-full\" type={\"submit\"}>\n {t(`foundations.auth.buttons.reset_password`)}\n </Button>\n </form>\n </Form>\n )}\n </CardContent>\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { HoverCard, HoverCardContent, HoverCardTrigger, Link } from \"../../../../shadcnui\";\nimport { getIconByModule } from \"../../../../utils\";\nimport { ContributorsList } from \"../../../user/components\";\nimport { ContentInterface } from \"../../data\";\n\ntype ContentsListProps = {\n contentList: ContentInterface[];\n};\n\nexport function ContentsList({ contentList }: ContentsListProps) {\n const t = useTranslations();\n\n return (\n <div className=\"flex min-h-0 w-full flex-col overflow-y-auto\">\n <h2 className=\"text-xl font-semibold\">{t(`foundations.content.news`)}</h2>\n <div className=\"flex flex-col\">\n {contentList.map((content) => (\n <ContentsListElement content={content} key={content.id} />\n ))}\n </div>\n </div>\n );\n}\n\ntype ContentsListElementProps = {\n content: ContentInterface;\n};\n\nfunction ContentsListElement({ content }: ContentsListElementProps) {\n const generateUrl = usePageUrlGenerator();\n\n const contentModule = content.contentType ? Modules.findByModelName(content.contentType) : undefined;\n const link = contentModule ? generateUrl({ page: contentModule, id: content.id }) : \"#\";\n\n return (\n <div className=\"hover:bg-muted flex w-full flex-col gap-y-2 border-b p-2 py-4\">\n <div className=\"flex w-full justify-between gap-x-2\">\n <HoverCard>\n <HoverCardTrigger asChild>\n <Link href={link} className=\"flex w-full items-center justify-start gap-2 font-semibold\">\n {contentModule && getIconByModule({ module: contentModule, className: \"h-4 w-4\" })}\n {content.name}\n </Link>\n </HoverCardTrigger>\n <HoverCardContent className=\"flex max-h-96 w-96 flex-col gap-y-4 overflow-y-auto\">\n <Link href={link} className=\"font-semibold\">\n {content.name}\n </Link>\n <div className=\"text-xs\">{content.abstract}</div>\n </HoverCardContent>\n </HoverCard>\n <ContributorsList content={content} />\n </div>\n {/* <div className=\"text-muted-foreground text-xs\">{content.tldr}</div>\n {content.topics.length > 0 && (\n <div className=\"flex w-full items-center justify-between\">\n <TopicBadgesList topics={content.topics} limit={1} />\n </div>\n )} */}\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { ContentFields, ContentInterface } from \"../../data\";\nimport { ContentService } from \"../../data/content.service\";\n\ntype ContentsListByIdProps = {\n contentIds: string[];\n};\n\nexport function ContentsListById({ contentIds }: ContentsListByIdProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<ContentInterface> = useDataListRetriever({\n module: Modules.Content,\n retriever: (params) => ContentService.findMany(params),\n retrieverParams: { contentIds: contentIds },\n });\n\n return (\n <ContentListTable\n data={data}\n fields={[ContentFields.name, ContentFields.authors, ContentFields.updatedAt]}\n tableGeneratorType={Modules.Content}\n title={t(`generic.relevant`)}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { ContentFields, ContentInterface } from \"../../data\";\nimport { ContentService } from \"../../data/content.service\";\n\ntype RelevantContentsListProps = {\n id: string;\n};\n\nexport function RelevantContentsList({ id }: RelevantContentsListProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<ContentInterface> = useDataListRetriever({\n module: Modules.Content,\n retriever: (params) => ContentService.findRelevant(params),\n retrieverParams: { id: id },\n });\n\n return (\n <ContentListTable\n data={data}\n fields={[ContentFields.name, ContentFields.authors, ContentFields.relevance, ContentFields.updatedAt]}\n tableGeneratorType={Modules.Content}\n title={t(`generic.relevant`)}\n />\n );\n}\n","\"use client\";\n\nimport React, { Component, ReactNode } from \"react\";\n\ninterface Props {\n children: ReactNode;\n fallback?: ReactNode;\n}\n\ninterface State {\n hasError: boolean;\n error?: Error;\n}\n\nexport class NotificationErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false };\n }\n\n static getDerivedStateFromError(error: Error): State {\n // Update state so the next render will show the fallback UI\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n console.error(\"🚨 [NotificationErrorBoundary] Caught error:\", error, errorInfo);\n }\n\n render() {\n if (this.state.hasError) {\n return (\n this.props.fallback || (\n <div className=\"flex items-center justify-center p-4 text-center\">\n <div className=\"text-muted-foreground text-sm\">\n <p>Something went wrong with notifications.</p>\n <button\n onClick={() => this.setState({ hasError: false })}\n className=\"text-primary mt-2 underline hover:no-underline\"\n >\n Try again\n </button>\n </div>\n </div>\n )\n );\n }\n\n return this.props.children;\n }\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { Tab, TabsContainer } from \"../../../../components\";\nimport { useNotificationContext } from \"../../contexts/NotificationContext\";\nimport { NotificationErrorBoundary } from \"../common\";\nimport { NotificationsList } from \"../lists/NotificationsList\";\n\nfunction NotificationsListContainerContent() {\n const t = useTranslations();\n const { notifications, isLoading, error } = useNotificationContext();\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center p-8 text-center\">\n <div className=\"text-destructive text-sm\">\n <p>Error loading notifications: {error}</p>\n <p className=\"text-muted-foreground mt-2\">Please try refreshing the page.</p>\n </div>\n </div>\n );\n }\n\n const tabs: Tab[] = [\n {\n label: t(`foundations.notification.inbox`),\n content: <NotificationsList archived={false} />,\n },\n {\n label: t(`foundations.notification.archived`),\n content: <NotificationsList archived={true} />,\n },\n ];\n\n return <TabsContainer tabs={tabs} />;\n}\n\nexport function NotificationsListContainer() {\n return (\n <NotificationErrorBoundary>\n <NotificationsListContainerContent />\n </NotificationErrorBoundary>\n );\n}\n","\"use client\";\n\nimport { ArchiveIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever, usePageUrlGenerator } from \"../../../../hooks\";\nimport {\n Button,\n Card,\n CardContent,\n Link,\n Skeleton,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../../../shadcnui\";\nimport { UserAvatar } from \"../../../user/components\";\nimport { NotificationInterface } from \"../../data\";\nimport { NotificationService } from \"../../data/notification.service\";\nimport { generateNotificationData } from \"../notifications/Notification\";\n\ntype NotificationsListProps = {\n archived: boolean;\n};\n\nexport function NotificationsList({ archived }: NotificationsListProps) {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n\n const data: DataListRetriever<NotificationInterface> = useDataListRetriever({\n retriever: (params) => NotificationService.findMany(params),\n retrieverParams: { isArchived: archived },\n module: Modules.Notification,\n });\n\n const archiveNotification = async (notification: NotificationInterface) => {\n await NotificationService.archive({ id: notification.id });\n data.removeElement(notification);\n };\n\n const LoadingSkeleton = () => (\n <div className=\"space-y-4\">\n {Array.from({ length: 3 }).map((_, i) => (\n <Card key={i}>\n <CardContent className=\"p-2\">\n <div className=\"flex w-full flex-row items-center\">\n <Skeleton className=\"mr-4 h-8 w-8 rounded-full\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n <Skeleton className=\"h-8 w-20\" />\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n );\n\n return (\n <div className=\"space-y-4\">\n {data.isLoaded ? (\n (data.data as NotificationInterface[])?.map((notification: NotificationInterface) => {\n const notificationData = generateNotificationData({ notification: notification, generateUrl: generateUrl });\n\n return (\n <Card key={notification.id}>\n <CardContent className=\"p-0\">\n <div className={`flex w-full flex-row items-center p-2`}>\n {notificationData.actor ? (\n <div className=\"flex w-12 max-w-12 px-2\">\n <Link href={generateUrl({ page: Modules.User, id: notificationData.actor.id })}>\n <UserAvatar user={notificationData.actor} className=\"h-8 w-8\" />\n </Link>\n </div>\n ) : (\n <div className=\"flex w-14 max-w-14 px-2\"></div>\n )}\n <div className=\"flex w-full flex-col\">\n <p className=\"text-sm\">\n {t.rich(`foundations.notification.${notification.notificationType}.description` as any, {\n strong: (chunks: any) => <strong>{chunks}</strong>,\n actor: notificationData.actor?.name ?? \"\",\n title: notificationData.title,\n })}\n </p>\n <div className=\"text-muted-foreground mt-1 w-full text-xs\">\n {new Date(notification.createdAt).toLocaleString()}\n </div>\n </div>\n <div className=\"flex flex-row items-center\">\n {notificationData.url ? (\n <Link href={notificationData.url}>\n <Button variant={`outline`} size={`sm`} onClick={(e) => e.stopPropagation()}>\n {t(`foundations.notification.${notification.notificationType}.buttons.action` as any)}\n </Button>\n </Link>\n ) : (\n <></>\n )}\n {!archived && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant={`link`}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n archiveNotification(notification);\n }}\n className=\"text-muted-foreground hover:text-destructive ml-2\"\n >\n <ArchiveIcon className=\"h-4 w-4 cursor-pointer\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>{t(`foundations.notification.buttons.archive`)}</TooltipContent>\n </Tooltip>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n );\n })\n ) : (\n <LoadingSkeleton />\n )}\n </div>\n );\n}\n","import { BellIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { Fragment, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { useSocketContext } from \"../../../../contexts\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport {\n Card,\n CardHeader,\n CardTitle,\n Popover,\n PopoverContent,\n PopoverTrigger,\n ScrollArea,\n Separator,\n SidebarMenuButton,\n} from \"../../../../shadcnui\";\nimport { useNotificationContext } from \"../../contexts/NotificationContext\";\nimport { NotificationInterface } from \"../../data\";\nimport { NotificationErrorBoundary } from \"../common\";\n\ninterface NotificationModalProps {\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n}\n\nfunction NotificationModalContent({ isOpen, setIsOpen }: NotificationModalProps) {\n const instanceId = useRef(Math.random().toString(36).substr(2, 9));\n const {\n notifications,\n addNotification,\n generateNotification,\n generateToastNotification,\n markNotificationsAsRead,\n isLoading,\n error,\n } = useNotificationContext();\n const { socketNotifications, removeSocketNotification, clearSocketNotifications } = useSocketContext();\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n const [newNotifications, setNewNotifications] = useState<boolean>(false);\n const preventAutoClose = useRef(false);\n\n const circuitBreakerRef = useRef({\n count: 0,\n resetTime: 0,\n isOpen: false,\n });\n\n const checkCircuitBreaker = useCallback(() => {\n const now = Date.now();\n const breaker = circuitBreakerRef.current;\n\n // Reset counter every 10 seconds\n if (now > breaker.resetTime) {\n breaker.count = 0;\n breaker.resetTime = now + 10000; // 10 seconds\n breaker.isOpen = false;\n }\n\n // Trip breaker if more than 20 notifications in 10 seconds\n breaker.count++;\n if (breaker.count > 20) {\n breaker.isOpen = true;\n return false;\n }\n\n return !breaker.isOpen;\n }, []);\n\n const { unreadCount, unreadIds } = useMemo(() => {\n const unreadNotifications = notifications.filter((notif) => !notif.isRead);\n return {\n unreadCount: unreadNotifications.length,\n unreadIds: unreadNotifications.map((notif) => notif.id),\n };\n }, [notifications]);\n\n useEffect(() => {\n setNewNotifications(unreadCount > 0);\n }, [unreadCount]);\n\n const processSocketNotificationsRef = useRef<NodeJS.Timeout | null>(null);\n\n const processSocketNotifications = useCallback(() => {\n if (socketNotifications.length === 0) {\n return;\n }\n\n if (!checkCircuitBreaker()) {\n clearSocketNotifications(); // Still clear to prevent memory leaks\n return;\n }\n\n const currentSocketNotifications = [...socketNotifications];\n clearSocketNotifications();\n\n // Process notifications in smaller batches to prevent UI freeze\n const batchSize = 3;\n const batches = [];\n for (let i = 0; i < currentSocketNotifications.length; i += batchSize) {\n batches.push(currentSocketNotifications.slice(i, i + batchSize));\n }\n\n batches.forEach((batch, batchIndex) => {\n setTimeout(() => {\n batch.forEach((notification) => {\n addNotification(notification);\n const toastNotification = generateToastNotification(notification, t, generateUrl);\n\n toast.message(toastNotification.title, {\n description: toastNotification.description,\n action: toastNotification.action,\n });\n });\n\n // Only set newNotifications on the last batch\n if (batchIndex === batches.length - 1) {\n setNewNotifications(true);\n }\n }, batchIndex * 100); // 100ms delay between batches\n });\n }, [\n socketNotifications,\n clearSocketNotifications,\n addNotification,\n generateToastNotification,\n t,\n generateUrl,\n checkCircuitBreaker,\n ]);\n\n // 🔗 SOCKET: Throttled processing with 300ms delay\n useEffect(() => {\n if (processSocketNotificationsRef.current) {\n clearTimeout(processSocketNotificationsRef.current);\n }\n\n processSocketNotificationsRef.current = setTimeout(() => {\n processSocketNotifications();\n }, 300); // 300ms throttle\n\n return () => {\n if (processSocketNotificationsRef.current) {\n clearTimeout(processSocketNotificationsRef.current);\n }\n };\n }, [processSocketNotifications]);\n\n const handleOpenChange = (newlyRequestedOpenState: boolean) => {\n if (!newlyRequestedOpenState && preventAutoClose.current) {\n return;\n }\n\n setIsOpen(newlyRequestedOpenState);\n\n if (newlyRequestedOpenState) {\n preventAutoClose.current = true;\n\n if (unreadIds.length > 0) {\n markNotificationsAsRead(unreadIds)\n .catch((error) => {\n console.error(\"❌ [NotificationModal] Failed to mark notifications as read:\", error);\n })\n .finally(() => {\n preventAutoClose.current = false;\n // Workaround: re-open if it was open before\n setIsOpen(true);\n });\n } else {\n preventAutoClose.current = false;\n }\n setNewNotifications(false);\n }\n };\n\n const unreadNotifications = newNotifications && unreadCount > 0;\n\n return (\n <Popover open={isOpen} onOpenChange={handleOpenChange} data-testid={`sidebar-notification button`}>\n <PopoverTrigger asChild>\n <SidebarMenuButton className=\"text-muted-foreground h-6\" disabled={isLoading}>\n <BellIcon\n className={`h-5 w-5 cursor-pointer ${unreadNotifications ? \"text-destructive\" : \"\"} ${isLoading ? \"animate-pulse\" : \"\"}`}\n />\n {t(`types.notifications`, { count: 2 })}\n </SidebarMenuButton>\n </PopoverTrigger>\n <PopoverContent className=\"relative left-10 w-80 border-0 p-0 shadow-none\">\n <Card>\n <CardHeader className=\"p-4\">\n <CardTitle>{t(`types.notifications`, { count: 2 })}</CardTitle>\n {isLoading && <div className=\"text-muted-foreground text-xs\">Loading...</div>}\n {error && <div className=\"text-destructive text-xs\">Error: {error}</div>}\n </CardHeader>\n <Separator />\n <ScrollArea className=\"h-96\">\n {notifications.length > 0 ? (\n notifications.map((notification: NotificationInterface) => (\n <Fragment key={notification.id}>{generateNotification(notification, () => setIsOpen(false))}</Fragment>\n ))\n ) : (\n <div className=\"p-4 text-center text-sm text-gray-500\">\n {t(`foundations.notification.empty`, { count: 2 })}\n </div>\n )}\n </ScrollArea>\n </Card>\n </PopoverContent>\n </Popover>\n );\n}\n\nexport function NotificationModal(props: NotificationModalProps) {\n return (\n <NotificationErrorBoundary>\n <NotificationModalContent {...props} />\n </NotificationErrorBoundary>\n );\n}\n","\"use client\";\n\nimport { ReactNode, type JSX } from \"react\";\nimport usePushNotifications from \"../../../../hooks/usePushNotifications\";\n\nexport function PushNotificationProvider({ children }: { children: ReactNode }): JSX.Element {\n usePushNotifications();\n return <>{children}</>;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { AttributeElement } from \"../../../../components\";\nimport { Card, CardContent } from \"../../../../shadcnui\";\nimport { useRoleContext } from \"../../contexts\";\n\nexport function RoleDetails() {\n const { role } = useRoleContext();\n const t = useTranslations();\n\n if (!role) return null;\n\n return (\n <Card className=\"w-full\">\n <CardContent className=\"p-4\">\n <AttributeElement title={t(`foundations.role.fields.description.label`)} value={role.description} />\n </CardContent>\n </Card>\n );\n}\n","\"use client\";\n\nimport { RoleUsersList } from \"../../../user/components/lists/RoleUsersList\";\nimport { useRoleContext } from \"../../contexts\";\nimport { RoleDetails } from \"../details\";\n\nexport function RoleContainer() {\n const { role } = useRoleContext();\n\n if (!role) return null;\n\n return (\n <>\n <RoleDetails />\n <RoleUsersList role={role} />\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport {\n Checkbox,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { RoleInterface } from \"../../data\";\n\ntype FormRolesProps = {\n form: any;\n id: string;\n name: string;\n roles: RoleInterface[];\n};\n\nexport function FormRoles({ form, id, name, roles }: FormRolesProps) {\n const t = useTranslations();\n const { hasAccesToFeature } = useCurrentUserContext<UserInterface>();\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n <FormControl>\n <div>\n <div className=\"text-sm font-semibold\">{name}</div>\n {roles\n .filter((role: RoleInterface) => role.isSelectable)\n .sort((a: RoleInterface, b: RoleInterface) => a.name.localeCompare(b.name))\n .map((role: RoleInterface) => {\n if (role.requiredFeature && !hasAccesToFeature(role.requiredFeature.id)) return null;\n\n return (\n <div key={role.id}>\n <Checkbox\n defaultChecked={(field.value as string[]).some((roleId: string) => roleId === role.id)}\n onCheckedChange={(checked) => {\n if (checked) {\n form.setValue(id, [...(field.value as string[]), role.id]);\n } else {\n form.setValue(\n id,\n (field.value as string[]).filter((roleId: string) => roleId !== role.id),\n );\n }\n }}\n />\n <Tooltip>\n <TooltipTrigger asChild>\n <FormLabel className=\"ml-3 font-normal\">\n {t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) })}\n </FormLabel>\n </TooltipTrigger>\n <TooltipContent>\n {t(`foundations.role.roles_descriptions`, { role: role.id.replaceAll(`-`, ``) })}\n </TooltipContent>\n </Tooltip>\n </div>\n );\n })}\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useState } from \"react\";\nimport { errorToast } from \"../../../../components\";\nimport { getRoleId } from \"../../../../roles\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { UserService } from \"../../../user/data/user.service\";\nimport { RoleInterface } from \"../../data\";\nimport { RoleService } from \"../../data/role.service\";\n\ntype RemoveUserFromRoleProps = {\n user: UserInterface;\n role: RoleInterface;\n refresh: () => Promise<void>;\n};\n\nexport function RemoveUserFromRole({ role, user, refresh }: RemoveUserFromRoleProps) {\n const [open, setOpen] = useState<boolean>(false);\n const [canRemove, setCanRemove] = useState<boolean>(false);\n const t = useTranslations();\n\n useEffect(() => {\n async function checkCompanyAdminDeletability(): Promise<void> {\n const roleUsers = await UserService.findAllUsersByRole({\n roleId: role.id,\n });\n\n if (roleUsers.length > 1) setCanRemove(true);\n }\n\n if (role.id !== getRoleId().CompanyAdministrator) {\n setCanRemove(true);\n return;\n }\n\n checkCompanyAdminDeletability();\n }, [role]);\n\n const remove = async () => {\n try {\n await RoleService.removeUserFromRole({\n roleId: role.id,\n userId: user.id,\n });\n\n setOpen(false);\n refresh();\n } catch (error) {\n errorToast({ title: t(`generic.errors.error`), error: error });\n }\n };\n\n const roleName = t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) });\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogTrigger\n onClick={(e) => {\n e.stopPropagation();\n e.preventDefault();\n setOpen(true);\n }}\n >\n <span className=\"hover:text-destructive cursor-pointer\">{t(`foundations.role.remove_user.title`)}</span>\n </DialogTrigger>\n <DialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>\n <DialogHeader>\n <DialogTitle>{t(`foundations.role.remove_user.title`)}</DialogTitle>\n <DialogDescription>\n {canRemove\n ? t(`foundations.role.remove_user.subtitle_allowed`)\n : t(`foundations.role.remove_user.subtitle_not_allowed`)}\n </DialogDescription>\n </DialogHeader>\n {canRemove ? (\n <>\n {t(`foundations.role.remove_user.description_allowed`, { role: roleName, user: user.name })}\n <div className=\"flex justify-end\">\n <Button className=\"mr-2\" variant={\"outline\"} type={`button`} onClick={() => setOpen(false)}>\n {t(`generic.buttons.cancel`)}\n </Button>\n <Button\n type=\"submit\"\n onClick={(e) => {\n e.preventDefault();\n remove();\n }}\n variant={\"destructive\"}\n >\n {t(`generic.buttons.confirm_delete`)}\n </Button>\n </div>\n </>\n ) : (\n <>{t(`foundations.role.remove_user.description_not_allowed`, { role: roleName, user: user.name })}</>\n )}\n </DialogContent>\n </Dialog>\n );\n}\n","\"use client\";\n\nimport { PlusCircle } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { useDebounce } from \"../../../../hooks\";\nimport {\n Button,\n Command,\n CommandDialog,\n CommandEmpty,\n CommandInput,\n CommandItem,\n CommandList,\n DialogDescription,\n DialogTitle,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { RoleInterface } from \"../../data\";\nimport { RoleService } from \"../../data/role.service\";\n\ntype UserRoleAddProps = {\n user: UserInterface;\n refresh: () => Promise<void>;\n};\n\nexport function UserRoleAdd({ user, refresh }: UserRoleAddProps) {\n const [open, setOpen] = useState<boolean>(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n const [roles, setRoles] = useState<RoleInterface[]>([]);\n const t = useTranslations();\n\n const addUserToRole = async (role: RoleInterface) => {\n await RoleService.addUserToRole({\n roleId: role.id,\n userId: user.id,\n });\n setRoles(roles.filter((u) => u.id !== role.id));\n\n toast.message(\n t(`generic.association.label`, {\n source: t(`types.roles`, { count: 1 }),\n destination: t(`types.users`, { count: 1 }),\n }),\n {\n description: t(`generic.association.success`, {\n source: t(`types.roles`, { count: 1 }),\n destination: t(`types.users`, { count: 1 }),\n source_name: role.name,\n destination_name: user.name,\n }),\n },\n );\n\n refresh();\n };\n\n const searchRoles = useCallback(\n async (term: string) => {\n setRoles(\n await RoleService.findAllRolesUserNotIn({\n search: term,\n userId: user.id,\n }),\n );\n },\n [searchTerm, user],\n );\n\n const updateSearchTerm = useDebounce(searchRoles, 500);\n\n useEffect(() => {\n if (open) updateSearchTerm(searchTerm);\n }, [open, searchTerm]);\n\n useEffect(() => {\n if (open) searchRoles(\"\");\n }, [open]);\n\n return (\n <>\n <Button size=\"sm\" onClick={() => setOpen(true)}>\n <PlusCircle className=\"mr-3 h-3.5 w-3.5\" />\n {t(`generic.association.label`, {\n source: t(`types.roles`, { count: 1 }),\n destination: t(`types.users`, { count: 1 }),\n })}\n </Button>\n <CommandDialog open={open} onOpenChange={setOpen}>\n <DialogTitle>\n {t(`generic.association.label`, {\n source: t(`types.roles`, { count: 1 }),\n destination: t(`types.users`, { count: 1 }),\n })}\n </DialogTitle>\n <DialogDescription>\n {t(`generic.association.description`, {\n source: t(`types.roles`, { count: 1 }),\n destination: t(`types.users`, { count: 1 }),\n destination_name: user.name,\n })}\n </DialogDescription>\n <Command shouldFilter={false}>\n <CommandInput\n placeholder={t(`generic.search.placeholder`, { type: t(`types.roles`, { count: 1 }) })}\n value={searchTerm}\n onValueChange={setSearchTerm}\n ref={inputRef}\n />\n <CommandList className=\"mt-3 h-auto max-h-96 min-h-96 max-w-full overflow-x-hidden overflow-y-auto\">\n <CommandEmpty>{t(`generic.search.no_results`, { type: t(`types.roles`, { count: 1 }) })}</CommandEmpty>\n {roles.map((role: RoleInterface) => (\n <CommandItem\n className=\"cursor-pointer\"\n key={role.id}\n onSelect={() => addUserToRole(role)}\n onClick={() => addUserToRole(role)}\n >\n {t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) })}\n </CommandItem>\n ))}\n </CommandList>\n </Command>\n </CommandDialog>\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { RoleFields, RoleInterface } from \"../../data\";\nimport { RoleService } from \"../../data/role.service\";\nimport \"../../hooks/useRoleTableStructure\";\n\nexport function RolesList() {\n const t = useTranslations();\n\n const data: DataListRetriever<RoleInterface> = useDataListRetriever({\n retriever: (params) => RoleService.findAllRoles(params),\n retrieverParams: {},\n module: Modules.Role,\n });\n\n return (\n <ContentListTable\n data={data}\n fields={[RoleFields.name, RoleFields.description]}\n tableGeneratorType={Modules.Role}\n title={t(`types.roles`, { count: 2 })}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { UserInterface } from \"../../../user\";\nimport { RoleFields, RoleInterface } from \"../../data\";\nimport { RoleService } from \"../../data/role.service\";\n\ntype UserRolesListProps = {\n user: UserInterface;\n};\n\nexport function UserRolesList({ user }: UserRolesListProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<RoleInterface> = useDataListRetriever({\n retriever: (params) => RoleService.findAllRolesByUser(params),\n retrieverParams: { userId: user.id },\n module: Modules.Role,\n });\n\n return (\n <ContentListTable\n data={data}\n fields={[RoleFields.name, RoleFields.description]}\n tableGeneratorType={Modules.Role}\n title={t(`types.roles`, { count: 2 })}\n />\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-ODZ2X6Y3.js","../src/components/navigations/Breadcrumb.tsx","../src/hooks/TableGeneratorRegistry.ts","../src/hooks/url.rewriter.ts","../src/hooks/usePageUrlGenerator.ts","../src/hooks/useDataListRetriever.ts","../src/hooks/useDebounce.ts","../src/hooks/useTableGenerator.ts","../src/hooks/useCustomD3Graph.tsx","../src/hooks/useNotificationSync.ts","../src/features/company/contexts/CompanyContext.tsx","../src/features/user/contexts/CurrentUserContext.tsx","../src/features/user/contexts/UserContext.tsx","../src/features/user/components/forms/RoleUserAdd.tsx","../src/features/user/components/forms/UserAvatarEditor.tsx","../src/shadcnui/ui/accordion.tsx","../src/shadcnui/ui/alert.tsx","../src/shadcnui/ui/alert-dialog.tsx","../src/shadcnui/ui/button.tsx","../src/shadcnui/ui/avatar.tsx","../src/shadcnui/ui/badge.tsx","../src/shadcnui/ui/breadcrumb.tsx","../src/shadcnui/ui/calendar.tsx","../src/shadcnui/ui/card.tsx","../src/shadcnui/ui/carousel.tsx","../src/shadcnui/ui/chart.tsx","../src/shadcnui/ui/checkbox.tsx","../src/shadcnui/ui/collapsible.tsx","../src/shadcnui/ui/command.tsx","../src/shadcnui/ui/dialog.tsx","../src/shadcnui/ui/context-menu.tsx","../src/shadcnui/ui/drawer.tsx","../src/shadcnui/ui/dropdown-menu.tsx","../src/shadcnui/ui/form.tsx","../src/shadcnui/ui/label.tsx","../src/shadcnui/ui/hover-card.tsx","../src/shadcnui/ui/input.tsx","../src/shadcnui/ui/navigation-menu.tsx","../src/shadcnui/ui/popover.tsx","../src/shadcnui/ui/progress.tsx","../src/shadcnui/ui/radio-group.tsx","../src/shadcnui/ui/resizable.tsx","../src/shadcnui/ui/scroll-area.tsx","../src/shadcnui/ui/select.tsx","../src/shadcnui/ui/separator.tsx","../src/shadcnui/ui/sheet.tsx","../src/shadcnui/ui/sidebar.tsx","../src/shadcnui/ui/skeleton.tsx","../src/shadcnui/ui/tooltip.tsx","../src/shadcnui/ui/slider.tsx","../src/shadcnui/ui/sonner.tsx","../src/shadcnui/ui/switch.tsx","../src/shadcnui/ui/table.tsx","../src/shadcnui/ui/tabs.tsx","../src/shadcnui/ui/textarea.tsx","../src/shadcnui/ui/toggle.tsx","../src/shadcnui/custom/kanban.tsx","../src/shadcnui/custom/link.tsx","../src/shadcnui/custom/multi-select.tsx","../src/features/user/components/forms/UserDeleter.tsx","../src/features/user/components/forms/UserEditor.tsx","../src/features/user/components/forms/UserMultiSelect.tsx","../src/features/user/components/forms/UserReactivator.tsx","../src/features/user/components/forms/UserResentInvitationEmail.tsx","../src/features/user/components/forms/UserSelector.tsx","../src/features/user/components/widgets/UserAvatar.tsx","../src/features/user/components/containers/UserContainer.tsx","../src/features/user/components/details/UserDetails.tsx","../src/features/user/components/details/UserIndexDetails.tsx","../src/features/user/components/containers/UserIndexContainer.tsx","../src/features/user/components/containers/UsersListContainer.tsx","../src/features/user/components/lists/AdminUsersList.tsx","../src/features/user/components/lists/CompanyUsersList.tsx","../src/features/user/components/lists/ContributorsList.tsx","../src/features/user/components/lists/RelevantUsersList.tsx","../src/features/user/components/lists/RoleUsersList.tsx","../src/features/user/components/lists/UserListInAdd.tsx","../src/features/user/components/lists/UsersList.tsx","../src/features/user/components/lists/UsersListByContentIds.tsx","../src/features/company/components/details/CompanyDetails.tsx","../src/features/company/components/containers/AdminCompanyContainer.tsx","../src/features/company/components/containers/CompanyContainer.tsx","../src/features/company/components/forms/CompanyConfigurationEditor.tsx","../src/features/company/components/forms/CompanyConfigurationSecurityForm.tsx","../src/features/company/components/forms/CompanyDeleter.tsx","../src/features/company/components/forms/CompanyEditor.tsx","../src/features/company/components/forms/CompanyLicense.tsx","../src/features/company/components/lists/CompaniesList.tsx","../src/features/notification/contexts/NotificationContext.tsx","../src/features/notification/components/notifications/Notification.tsx","../src/features/role/contexts/RoleContext.tsx","../src/contexts/CommonContext.tsx","../src/contexts/SharedContext.tsx","../src/contexts/SocketContext.tsx","../src/atoms/recentPagesAtom.ts","../src/hooks/usePageTracker.ts","../src/hooks/usePushNotifications.ts","../src/hooks/useSocket.ts","../src/components/navigations/ContentTitle.tsx","../src/components/navigations/Header.tsx","../src/components/navigations/ModeToggleSwitch.tsx","../src/components/navigations/PageSection.tsx","../src/components/navigations/RecentPagesNavigator.tsx","../src/components/containers/PageContainer.tsx","../src/components/containers/ReactMarkdownContainer.tsx","../src/components/containers/TabsContainer.tsx","../src/components/contents/AttributeElement.tsx","../src/components/details/AllowedUsersDetails.tsx","../src/components/editors/BlockNoteEditorContainer.tsx","../src/components/errors/ErrorDetails.tsx","../src/components/errors/errorToast.ts","../src/components/forms/CommonAssociationForm.tsx","../src/components/forms/CommonDeleter.tsx","../src/components/forms/CommonEditorButtons.tsx","../src/components/forms/CommonEditorHeader.tsx","../src/components/forms/CommonEditorTrigger.tsx","../src/components/forms/DatePickerPopover.tsx","../src/components/forms/DateRangeSelector.tsx","../src/components/forms/FileUploader.tsx","../src/components/forms/FormCheckbox.tsx","../src/components/forms/FormContainerGeneric.tsx","../src/components/forms/FormDate.tsx","../src/components/forms/FormDateTime.tsx","../src/components/forms/FormInput.tsx","../src/components/forms/PasswordInput.tsx","../src/components/forms/FormPassword.tsx","../src/components/forms/FormPlaceAutocomplete.tsx","../src/components/forms/FormSelect.tsx","../src/components/forms/FormSlider.tsx","../src/components/forms/FormSwitch.tsx","../src/components/forms/FormTextarea.tsx","../src/components/forms/MultiFileUploader.tsx","../src/features/feature/components/forms/FormFeatures.tsx","../src/components/pages/PageContainerContentDetails.tsx","../src/components/pages/PageContentContainer.tsx","../src/components/tables/cells/cell.component.tsx","../src/components/tables/cells/cell.date.tsx","../src/components/tables/cells/cell.id.tsx","../src/components/tables/cells/cell.link.tsx","../src/components/tables/cells/cell.url.tsx","../src/client/context/JsonApiContext.ts","../src/client/context/JsonApiProvider.tsx","../src/client/hooks/useJsonApiGet.ts","../src/client/hooks/useJsonApiMutation.ts","../src/client/hooks/useRehydration.ts","../src/features/company/hooks/useCompanyTableStructure.tsx","../src/features/role/hooks/useRoleTableStructure.tsx","../src/features/user/hooks/useUserSearch.ts","../src/features/user/hooks/useUserTableStructure.tsx","../src/features/content/hooks/useContentTableStructure.tsx","../src/client/index.ts","../src/components/tables/ContentListTable.tsx","../src/components/tables/ContentTableSearch.tsx","../src/features/auth/components/containers/AuthContainer.tsx","../src/features/auth/contexts/AuthContext.tsx","../src/features/auth/components/forms/Register.tsx","../src/features/auth/components/details/LandingComponent.tsx","../src/features/auth/components/forms/AcceptInvitation.tsx","../src/features/auth/components/forms/ActivateAccount.tsx","../src/features/auth/components/forms/Cookies.tsx","../src/features/auth/components/forms/ForgotPassword.tsx","../src/features/auth/components/forms/Login.tsx","../src/features/auth/components/forms/Logout.tsx","../src/features/auth/components/forms/RefreshUser.tsx","../src/features/auth/components/forms/ResetPassword.tsx","../src/features/content/components/lists/ContentsList.tsx","../src/features/content/components/lists/ContentsListById.tsx","../src/features/content/components/lists/RelevantContentsList.tsx","../src/features/notification/components/common/NotificationErrorBoundary.tsx","../src/features/notification/components/containers/NotificationsListContainer.tsx","../src/features/notification/components/lists/NotificationsList.tsx","../src/features/notification/components/modals/NotificationModal.tsx","../src/features/notification/components/notifications/PushNotificationProvider.tsx","../src/features/role/components/details/RoleDetails.tsx","../src/features/role/components/containers/RoleContainer.tsx","../src/features/role/components/forms/FormRoles.tsx","../src/features/role/components/forms/RemoveUserFromRole.tsx","../src/features/role/components/forms/UserRoleAdd.tsx","../src/features/role/components/lists/RolesList.tsx","../src/features/role/components/lists/UserRolesList.tsx"],"names":["Label","RadioGroup","Link"],"mappings":"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A;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-ODZ2X6Y3.js","sourcesContent":[null,"\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { Fragment, useState } from \"react\";\nimport { usePageUrlGenerator } from \"../../hooks\";\nimport { BreadcrumbItemData } from \"../../interfaces\";\nimport {\n BreadcrumbEllipsis,\n BreadcrumbItem,\n BreadcrumbList,\n BreadcrumbSeparator,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n Link,\n Breadcrumb as UIBreadcrumb,\n} from \"../../shadcnui\";\n\ntype BreadcrumbProps = { items: BreadcrumbItemData[] };\n\nconst ITEMS_TO_DISPLAY = 3;\n\nexport function BreadcrumbNavigation({ items }: BreadcrumbProps) {\n const generateUrl = usePageUrlGenerator();\n const t = useTranslations();\n\n const [open, setOpen] = useState<boolean>(false);\n\n return (\n <UIBreadcrumb>\n <BreadcrumbList>\n <BreadcrumbItem>\n <Link href={generateUrl({ page: `/` })}>{t(`generic.home`)}</Link>\n </BreadcrumbItem>\n {items.length > 0 && <BreadcrumbSeparator />}\n\n {items.length > ITEMS_TO_DISPLAY ? (\n <>\n <BreadcrumbItem>\n {items[0].href ? <Link href={items[0].href}>{items[0].name}</Link> : <>{items[0].name}</>}\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <DropdownMenu open={open} onOpenChange={setOpen}>\n <DropdownMenuTrigger className=\"flex items-center gap-1\" aria-label=\"Toggle menu\">\n <BreadcrumbEllipsis className=\"h-4 w-4\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n {items.slice(1, -ITEMS_TO_DISPLAY + 1).map((item, index) => (\n <DropdownMenuItem key={index}>\n <Link href={item.href ? item.href : \"#\"}>{item.name}</Link>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n {items.slice(-ITEMS_TO_DISPLAY + 1).map((item, index) => (\n <Fragment key={index}>\n <BreadcrumbItem>\n {item.href ? <Link href={item.href}>{item.name}</Link> : <>{item.name}</>}\n </BreadcrumbItem>\n {index < items.slice(-ITEMS_TO_DISPLAY + 1).length - 1 && <BreadcrumbSeparator />}\n </Fragment>\n ))}\n </>\n ) : (\n <>\n {items.map((item, index) => (\n <Fragment key={index}>\n <BreadcrumbItem>\n {item.href ? <Link href={item.href}>{item.name}</Link> : <>{item.name}</>}\n </BreadcrumbItem>\n {index < items.length - 1 && <BreadcrumbSeparator />}\n </Fragment>\n ))}\n </>\n )}\n </BreadcrumbList>\n </UIBreadcrumb>\n );\n}\n","\"use client\";\n\nimport { UseTableStructureHook, UseTableStructureHookParams, UseTableStructureHookReturn } from \"./types\";\n\ntype TableGeneratorHook = UseTableStructureHook<any, any>;\n\nexport class TableGeneratorRegistry {\n private static instance: TableGeneratorRegistry;\n private registry = new Map<string, TableGeneratorHook>();\n\n private constructor() {}\n\n public static getInstance(): TableGeneratorRegistry {\n if (!TableGeneratorRegistry.instance) {\n TableGeneratorRegistry.instance = new TableGeneratorRegistry();\n }\n return TableGeneratorRegistry.instance;\n }\n\n public register<T, U>(type: string, hook: UseTableStructureHook<T, U>): void {\n if (!this.registry.has(type)) this.registry.set(type, hook as TableGeneratorHook);\n }\n\n public get<T, U>(type: string, params: UseTableStructureHookParams<T, U>): UseTableStructureHookReturn<T> {\n const hook = this.registry.get(type);\n if (!hook) {\n throw new Error(\n `Table generator for type \"${type}\" is not registered. Available types: ${Array.from(this.registry.keys()).join(\n \", \",\n )}`,\n );\n }\n return hook(params);\n }\n\n public isRegistered(type: string): boolean {\n return this.registry.has(type);\n }\n\n public getRegisteredTypes(): string[] {\n return Array.from(this.registry.keys());\n }\n\n public unregister(type: string): boolean {\n return this.registry.delete(type);\n }\n\n public clear(): void {\n this.registry.clear();\n }\n}\n\nexport const tableGeneratorRegistry = TableGeneratorRegistry.getInstance();\n","\"use client\";\n\nimport { useLocale } from \"next-intl\";\nimport { useCallback } from \"react\";\nimport { ModuleWithPermissions } from \"../permissions\";\nimport { usePageUrlGenerator } from \"./usePageUrlGenerator\";\n\nexport function useUrlRewriter() {\n const locale = useLocale();\n const generateUrl = usePageUrlGenerator();\n\n return useCallback(\n (params: { page: ModuleWithPermissions | string; id?: string; childPage?: string }): void => {\n window.history.replaceState(\n null,\n \"\",\n generateUrl({ page: params.page, id: params.id, childPage: params.childPage, language: locale }),\n );\n },\n [locale, generateUrl],\n );\n}\n","import { PageUrl } from \"../permissions/types\";\n\nexport function usePageUrlGenerator(): (params: {\n page?: PageUrl | string;\n id?: string;\n childPage?: PageUrl | string;\n childId?: string;\n additionalParameters?: { [key: string]: string | string[] | undefined };\n language?: string;\n}) => string {\n const generateUrl = (params: {\n page?: PageUrl | string;\n id?: string;\n childPage?: PageUrl | string;\n childId?: string;\n additionalParameters?: { [key: string]: string | string[] | undefined };\n language?: string;\n }): string => {\n if (!params.page) return \"/\";\n\n const pathParams: string[] = [\n `${params.language ? `/${params.language}` : \"\"}${typeof params.page === \"string\" ? params.page : params.page.pageUrl}`,\n ];\n\n if (params.id) {\n pathParams.push(params.id);\n if (params.childPage) {\n pathParams.push(typeof params.childPage === \"string\" ? params.childPage : (params.childPage.pageUrl ?? \"\"));\n if (params.childId) {\n pathParams.push(params.childId);\n }\n }\n }\n const response = pathParams.join(`/`);\n\n if (params.additionalParameters) {\n const searchParams = new URLSearchParams();\n for (const key in params.additionalParameters) {\n if (params.additionalParameters[key]) {\n searchParams.append(key, params.additionalParameters[key] as string);\n }\n }\n return `${response}?${searchParams.toString()}`;\n }\n\n return response;\n };\n\n return generateUrl;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { ClientAbstractService } from \"../core/abstracts/ClientAbstractService\";\n\nexport type PageInfo = {\n startItem: number;\n endItem: number;\n pageSize: number;\n};\n\nexport type DataListRetriever<T> = {\n ready?: boolean;\n setReady: (state: boolean) => void;\n isLoaded: boolean;\n data: T[] | undefined;\n next?: (onlyNewRecords?: boolean) => Promise<void>;\n previous?: (onlyNewRecords?: boolean) => Promise<void>;\n search: (search: string) => Promise<void>;\n refresh: () => Promise<void>;\n addAdditionalParameter: (key: string, value: any | null) => void;\n removeAdditionalParameter: (key: string) => void;\n setRefreshedElement: (element: T) => void;\n removeElement: (element: T) => void;\n isSearch: boolean;\n pageInfo?: PageInfo;\n};\n\nexport function useDataListRetriever<T>(params: {\n ready?: boolean;\n retriever: (params: any) => Promise<T[]>;\n retrieverParams?: any;\n search?: string;\n addAdditionalParameter?: (key: string, value: any | null) => void;\n requiresSearch?: boolean;\n module: any;\n}): DataListRetriever<T> {\n const [data, setData] = useState<T[] | undefined>(undefined);\n const [nextPage, setNextPage] = useState<string | undefined>(undefined);\n const [previousPage, setPreviousPage] = useState<string | undefined>(undefined);\n const [isLoaded, setIsLoaded] = useState(false);\n const [ready, setReady] = useState<boolean>(params.ready ?? true);\n const searchTermRef = useRef<string>(\"\");\n const additionalParamsRef = useRef<any>({});\n const requestIdRef = useRef(0);\n const abortControllerRef = useRef<AbortController | null>(null);\n const isFetchingRef = useRef(false);\n\n const resolvedType = params.module;\n const resolvedService = ClientAbstractService; // We'll just use ClientAbstractService directly for pagination\n\n // Helper to parse page params from pagination URLs\n const parsePageParams = useCallback((url: string | undefined): { offset: number; size: number } | null => {\n if (!url) return null;\n try {\n const urlObj = new URL(url);\n const offset = parseInt(urlObj.searchParams.get(\"page[offset]\") || \"0\", 10);\n const size = parseInt(urlObj.searchParams.get(\"page[size]\") || \"25\", 10);\n return { offset, size };\n } catch {\n return null;\n }\n }, []);\n\n // Helper to adjust pagination URL offset (used when removing elements)\n const adjustPaginationUrl = useCallback((url: string | undefined, delta: number): string | undefined => {\n if (!url) return undefined;\n try {\n const urlObj = new URL(url);\n const currentOffset = parseInt(urlObj.searchParams.get(\"page[offset]\") || \"0\", 10);\n const newOffset = Math.max(0, currentOffset + delta);\n urlObj.searchParams.set(\"page[offset]\", String(newOffset));\n return urlObj.toString();\n } catch {\n return url;\n }\n }, []);\n\n // Calculate pageInfo from pagination URLs and current data\n const pageInfo = useMemo((): PageInfo | undefined => {\n if (!data || data.length === 0) return undefined;\n\n // Try to determine current offset and page size from pagination URLs\n const nextParams = parsePageParams(nextPage);\n const prevParams = parsePageParams(previousPage);\n\n let currentOffset = 0;\n let pageSize = 25; // default\n\n if (nextParams) {\n // If we have a next page, current offset = next offset - page size\n pageSize = nextParams.size;\n currentOffset = Math.max(0, nextParams.offset - pageSize);\n } else if (prevParams) {\n // If we only have a previous page (we're on the last page)\n pageSize = prevParams.size;\n currentOffset = prevParams.offset + pageSize;\n }\n\n const startItem = currentOffset + 1;\n const endItem = currentOffset + data.length;\n\n return { startItem, endItem, pageSize };\n }, [data, nextPage, previousPage, parsePageParams]);\n\n const stableParams = useMemo(\n () => ({\n service: resolvedService,\n type: resolvedType,\n retriever: params.retriever,\n retrieverParams: params.retrieverParams,\n requiresSearch: params.requiresSearch,\n }),\n [resolvedService, resolvedType, params.retriever, params.retrieverParams, params.requiresSearch],\n );\n\n const fetchData = useCallback(\n async (fetchParams?: { isRefine?: boolean; isRefresh?: boolean; callNext?: boolean; callPrevious?: boolean }) => {\n if (ready === false) {\n return;\n }\n\n // Prevent concurrent fetches (unless it's a pagination call)\n if (isFetchingRef.current && !fetchParams?.callNext && !fetchParams?.callPrevious) {\n return;\n }\n\n const thisRequestId = ++requestIdRef.current;\n isFetchingRef.current = true;\n\n if (stableParams.requiresSearch === true && fetchParams?.isRefine !== true && fetchParams?.isRefresh !== true)\n return;\n\n if (\n !nextPage &&\n !previousPage &&\n isLoaded &&\n fetchParams?.callNext !== true &&\n fetchParams?.callPrevious !== true &&\n params.search === searchTermRef.current\n )\n return;\n\n const currentSearchTerm = searchTermRef.current;\n\n setIsLoaded(false);\n\n try {\n let response: T[];\n const nextRef = { next: undefined };\n const previousRef = { previous: undefined };\n const selfRef = { self: undefined };\n\n if (nextPage && fetchParams?.callNext && fetchParams?.isRefine !== true) {\n const ServiceClass = stableParams.service as typeof ClientAbstractService;\n\n response = await ServiceClass.next<T[]>({\n type: stableParams.type,\n endpoint: nextPage,\n next: nextRef,\n previous: previousRef,\n self: selfRef,\n });\n } else if (previousPage && fetchParams?.callPrevious && fetchParams?.isRefine !== true) {\n const ServiceClass = stableParams.service as typeof ClientAbstractService;\n\n response = await ServiceClass.previous<T[]>({\n type: stableParams.type,\n endpoint: previousPage,\n next: nextRef,\n previous: previousRef,\n self: selfRef,\n });\n } else {\n let retrieverParams = stableParams.retrieverParams ? { ...stableParams.retrieverParams } : {};\n\n retrieverParams = {\n ...retrieverParams,\n ...additionalParamsRef.current,\n };\n\n retrieverParams.search = currentSearchTerm;\n retrieverParams.next = nextRef;\n retrieverParams.previous = previousRef;\n retrieverParams.self = selfRef;\n\n response = await stableParams.retriever(retrieverParams);\n }\n\n // Only update state if this is still the latest request and wasn't aborted\n if (thisRequestId === requestIdRef.current && !abortControllerRef.current?.signal.aborted) {\n if (fetchParams?.isRefresh === true) {\n setData(response);\n } else {\n setData((prevData) => [...(prevData ? (prevData as T[]) : []), ...response]);\n }\n setIsLoaded(true);\n setNextPage(nextRef.next ? nextRef.next : undefined);\n setPreviousPage(previousRef.previous ? previousRef.previous : undefined);\n }\n } catch (error) {\n // Don't update state if request was aborted (AbortController disabled)\n if (thisRequestId === requestIdRef.current) {\n setIsLoaded(true);\n console.error(\"Error fetching data:\", error);\n }\n } finally {\n // Always reset fetching flag when done\n if (thisRequestId === requestIdRef.current) {\n isFetchingRef.current = false;\n }\n }\n },\n [stableParams, ready, params.search],\n );\n\n const setRefreshedElement = useCallback(\n (element: T) => {\n setData((prevData) => {\n if (!prevData) return prevData;\n\n const index = prevData.findIndex((data) => (data as any).id === (element as any).id);\n if (index === -1) return prevData;\n\n // Use immutable update pattern instead of mutation\n return prevData.map((item, i) => (i === index ? element : item));\n });\n },\n [setData],\n );\n\n const removeElement = useCallback(\n (element: T) => {\n setData((prevData) => {\n if (!prevData) return prevData;\n\n const index = prevData.findIndex((data) => (data as any).id === (element as any).id);\n\n if (index === -1) return prevData;\n\n // Adjust nextPage offset since we're removing an item\n setNextPage((prev) => adjustPaginationUrl(prev, -1));\n\n const newData = [...prevData];\n newData.splice(index, 1);\n return newData;\n });\n },\n [adjustPaginationUrl],\n );\n\n // Consolidated effect: Only fetch once when ready and not loaded\n // This prevents the duplicate API calls that occurred when both the mount effect\n // and ready effect fired simultaneously on initial render\n useEffect(() => {\n // Only fetch if ready and haven't loaded yet\n if (ready && !isLoaded) {\n fetchData({ isRefresh: true });\n }\n }, [ready, fetchData]);\n\n const loadNext = useCallback(\n async (onlyNewRecords?: boolean) => {\n if (nextPage) fetchData({ isRefresh: onlyNewRecords, callNext: true });\n },\n [fetchData, nextPage],\n );\n\n const loadPrevious = useCallback(\n async (onlyNewRecords?: boolean) => {\n if (previousPage) fetchData({ isRefresh: onlyNewRecords, callPrevious: true });\n },\n [fetchData, previousPage],\n );\n\n const addAdditionalParameter = useCallback(\n (key: string, value: any | null) => {\n if (value === null) {\n delete additionalParamsRef.current[key];\n } else {\n additionalParamsRef.current[key] = value;\n }\n\n setReady(true);\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefine: true, isRefresh: true });\n },\n [fetchData],\n );\n\n const removeAdditionalParameter = useCallback(\n (key: string) => {\n if (additionalParamsRef.current[key] !== undefined) {\n delete additionalParamsRef.current[key];\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefine: true, isRefresh: true });\n }\n },\n [fetchData],\n );\n\n const search = useCallback(\n async (search: string) => {\n if (search === searchTermRef.current) return;\n\n setNextPage(undefined);\n setPreviousPage(undefined);\n searchTermRef.current = search;\n fetchData({ isRefine: true, isRefresh: true });\n },\n [fetchData],\n );\n\n const isSearch = !!searchTermRef.current;\n\n const refresh = useCallback(async () => {\n setNextPage(undefined);\n setPreviousPage(undefined);\n fetchData({ isRefresh: true });\n }, [fetchData]);\n\n // Cleanup abort controller on unmount\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n return {\n ready,\n setReady,\n isLoaded: isLoaded,\n data: data as T[],\n next: nextPage ? loadNext : undefined,\n previous: previousPage ? loadPrevious : undefined,\n search: search,\n addAdditionalParameter: addAdditionalParameter,\n removeAdditionalParameter: removeAdditionalParameter,\n refresh: refresh,\n setRefreshedElement: setRefreshedElement,\n isSearch: isSearch,\n removeElement: removeElement,\n pageInfo: pageInfo,\n };\n}\n","import { useCallback, useEffect, useRef } from \"react\";\n\nexport function useDebounce<T extends (...args: any[]) => any>(callback: T, delay: number): T & { cancel: () => void } {\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const callbackRef = useRef(callback);\n\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n const debouncedFunction = useCallback(\n (...args: Parameters<T>) => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = setTimeout(() => {\n callbackRef.current(...args);\n }, delay);\n },\n [delay],\n );\n\n // Attach a cancel method to clear pending timeout\n const cancel = () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n\n return Object.assign(debouncedFunction, { cancel }) as T & { cancel: () => void };\n}\n\nexport default useDebounce;\n","\"use client\";\n\nimport { UseTableStructureHook, UseTableStructureHookParams, UseTableStructureHookReturn } from \"./types\";\nimport { ModuleWithPermissions } from \"../permissions\";\nimport { tableGeneratorRegistry } from \"./TableGeneratorRegistry\";\n\nexport function registerTableGenerator<T, U>(\n type: string | ModuleWithPermissions,\n hook: UseTableStructureHook<T, U>,\n): void {\n const name = typeof type === \"string\" ? type : type.name;\n tableGeneratorRegistry.register(name, hook);\n}\n\nexport function useTableGenerator<T, U>(\n type: ModuleWithPermissions,\n params: UseTableStructureHookParams<T, U>,\n): UseTableStructureHookReturn<T> {\n return tableGeneratorRegistry.get(type.name, params);\n}\n","\"use client\";\n\nimport * as d3 from \"d3\";\nimport { Loader2 } from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\nimport { D3Link, D3Node } from \"../interfaces\";\n\n/**\n * Custom hook for D3 graph visualization with larger circles and more interactive features\n */\nexport function useCustomD3Graph(\n nodes: D3Node[],\n links: D3Link[],\n onNodeClick: (nodeId: string) => void,\n visibleNodeIds?: Set<string>,\n loadingNodeIds?: Set<string>,\n containerKey?: string | number,\n) {\n const svgRef = useRef<SVGSVGElement | null>(null);\n const zoomRef = useRef<d3.ZoomTransform | null>(null);\n const zoomBehaviorRef = useRef<d3.ZoomBehavior<SVGSVGElement, unknown> | null>(null);\n const nodePositionsRef = useRef<Map<string, { x: number; y: number }>>(new Map());\n const prevContainerKeyRef = useRef<string | number | undefined>(containerKey);\n\n const zoomToNode = useCallback(\n (nodeId: string, childIds: string[] = []) => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const targetNode = nodes.find((n) => n.id === nodeId);\n const childNodes = nodes.filter((n) => childIds.includes(n.id));\n\n if (!targetNode) return;\n\n const positions: { x: number; y: number }[] = [];\n\n if (\n targetNode.fx !== undefined &&\n targetNode.fy !== undefined &&\n targetNode.fx !== null &&\n targetNode.fy !== null\n ) {\n positions.push({ x: targetNode.fx, y: targetNode.fy });\n } else if (\n targetNode.x !== undefined &&\n targetNode.y !== undefined &&\n targetNode.x !== null &&\n targetNode.y !== null\n ) {\n positions.push({ x: targetNode.x, y: targetNode.y });\n }\n\n childNodes.forEach((child) => {\n if (child.fx !== undefined && child.fy !== undefined && child.fx !== null && child.fy !== null) {\n positions.push({ x: child.fx, y: child.fy });\n } else if (child.x !== undefined && child.y !== undefined && child.x !== null && child.y !== null) {\n positions.push({ x: child.x, y: child.y });\n }\n });\n\n if (positions.length === 0) return;\n\n const bounds = {\n xMin: Math.min(...positions.map((p) => p.x)),\n xMax: Math.max(...positions.map((p) => p.x)),\n yMin: Math.min(...positions.map((p) => p.y)),\n yMax: Math.max(...positions.map((p) => p.y)),\n };\n\n const padding = 150;\n bounds.xMin -= padding;\n bounds.xMax += padding;\n bounds.yMin -= padding;\n bounds.yMax += padding;\n\n const width = svgRef.current.clientWidth;\n const height = svgRef.current.clientHeight;\n\n const contentWidth = bounds.xMax - bounds.xMin;\n const contentHeight = bounds.yMax - bounds.yMin;\n\n const scaleX = width / contentWidth;\n const scaleY = height / contentHeight;\n\n let scale = Math.min(scaleX, scaleY);\n\n scale = Math.min(Math.max(scale, 0.2), 1.5);\n\n const centerX = (bounds.xMin + bounds.xMax) / 2;\n const centerY = (bounds.yMin + bounds.yMax) / 2;\n\n const translateX = width / 2 - centerX * scale;\n const translateY = height / 2 - centerY * scale;\n\n svg\n .transition()\n .duration(750)\n .call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(scale));\n },\n [nodes],\n );\n\n const colorScale = useMemo(() => {\n const accentColor = \"var(--accent)\";\n\n // Define unified color for all content types\n const contentColor = \"hsl(30, 80%, 55%)\"; // Orange for all content\n\n const groupTypes = new Set<string>();\n nodes.forEach((node) => {\n groupTypes.add(node.instanceType);\n });\n\n const typeColorMap = new Map<string, string>();\n\n Array.from(groupTypes).forEach((type, index) => {\n if (type === nodes[0]?.instanceType) {\n // Root node\n typeColorMap.set(type, accentColor);\n } else if (type === \"documents\" || type === \"articles\" || type === \"hyperlinks\") {\n // All content types get the same orange color\n typeColorMap.set(type, contentColor);\n } else {\n // Topics, Expertises, etc. - use golden angle\n const hueShift = (index * 137.508) % 360;\n typeColorMap.set(type, `hsl(${hueShift}, 32%, 52%)`);\n }\n });\n\n return typeColorMap;\n }, [nodes]);\n\n const washOutColor = useCallback((color: string): string => {\n // Parse HSL color and make it lighter and more desaturated\n const hslMatch = color.match(/hsl\\((\\d+\\.?\\d*),\\s*(\\d+\\.?\\d*)%,\\s*(\\d+\\.?\\d*)%\\)/);\n if (hslMatch) {\n const hue = parseFloat(hslMatch[1]);\n\n // Reduce saturation to 15% and increase lightness to 80%\n return `hsl(${hue}, 15%, 80%)`;\n }\n\n // For var(--accent), return a lighter version\n if (color.includes(\"var(--accent)\")) {\n return \"hsl(0, 0%, 80%)\"; // Light gray for washed out accent\n }\n\n // Fallback\n return \"hsl(0, 0%, 80%)\";\n }, []);\n\n const getNodeColor = useCallback(\n (node: D3Node) => {\n const baseColor = colorScale.get(node.instanceType) || \"gray\";\n if (node.washedOut) {\n return washOutColor(baseColor);\n }\n return baseColor;\n },\n [colorScale, washOutColor],\n );\n\n useEffect(() => {\n if (!nodes.length || !svgRef.current) return;\n\n const visibleNodes = visibleNodeIds\n ? nodes.filter((node) => visibleNodeIds.has(node.id))\n : nodes.filter((node) => node.visible !== false);\n\n const visibleNodeIdSet = new Set(visibleNodes.map((node) => node.id));\n const visibleLinks = links.filter((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n return visibleNodeIdSet.has(sourceId) && visibleNodeIdSet.has(targetId);\n });\n\n const svg = d3.select<SVGSVGElement, unknown>(svgRef.current);\n svg.selectAll(\"*\").remove();\n\n const container = svgRef.current?.parentElement;\n if (!container) return;\n\n const width = container.clientWidth;\n const height = container.clientHeight;\n\n svg.attr(\"width\", width).attr(\"height\", height).attr(\"viewBox\", `0 0 ${width} ${height}`);\n\n const graphGroup = svg.append(\"g\").attr(\"class\", \"graph-content\");\n\n const zoom = d3\n .zoom<SVGSVGElement, unknown>()\n .scaleExtent([0.1, 4])\n .on(\"zoom\", (event) => {\n const transform = event.transform;\n graphGroup.attr(\"transform\", transform.toString());\n zoomRef.current = transform;\n });\n\n zoomBehaviorRef.current = zoom;\n\n svg\n .call(zoom as any)\n .on(\"wheel.zoom\", null)\n .on(\"dblclick.zoom\", null);\n\n const nodeRadius = 40;\n\n const childDistanceFromRoot = Math.min(width, height) * 0.4;\n const grandchildDistanceFromChild = nodeRadius * 10;\n\n const centralNodeId = nodes[0].id;\n\n const nodeHierarchy = new Map<\n string,\n {\n depth: number;\n parent: string | null;\n children: string[];\n angle?: number;\n x?: number;\n y?: number;\n }\n >();\n\n nodeHierarchy.set(centralNodeId, {\n depth: 0,\n parent: null,\n children: [],\n });\n\n visibleLinks.forEach((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n\n if (sourceId === centralNodeId) {\n nodeHierarchy.set(targetId, { depth: 1, parent: centralNodeId, children: [] });\n const rootNode = nodeHierarchy.get(centralNodeId);\n if (rootNode) {\n rootNode.children.push(targetId);\n }\n }\n });\n\n visibleLinks.forEach((link) => {\n const sourceId = typeof link.source === \"string\" ? link.source : link.source.id;\n const targetId = typeof link.target === \"string\" ? link.target : link.target.id;\n\n const sourceNode = nodeHierarchy.get(sourceId);\n if (sourceNode && sourceNode.depth === 1 && !nodeHierarchy.has(targetId)) {\n nodeHierarchy.set(targetId, { depth: 2, parent: sourceId, children: [] });\n sourceNode.children.push(targetId);\n }\n });\n\n const rootChildren = nodeHierarchy.get(centralNodeId)?.children || [];\n\n const childAngleStep = (2 * Math.PI) / Math.max(rootChildren.length, 1);\n\n rootChildren.forEach((childId, index) => {\n const childNode = nodeHierarchy.get(childId);\n if (childNode) {\n const angle = index * childAngleStep;\n childNode.angle = angle;\n childNode.x = width / 2 + childDistanceFromRoot * Math.cos(angle);\n childNode.y = height / 2 + childDistanceFromRoot * Math.sin(angle);\n }\n });\n\n for (const [nodeId, node] of nodeHierarchy.entries()) {\n if (node.depth === 1 && node.angle !== undefined && node.x !== undefined && node.y !== undefined) {\n const childAngle = node.angle;\n const childX = node.x;\n const childY = node.y;\n const grandchildren = node.children;\n\n if (grandchildren.length === 0) continue;\n\n const dirX = childX - width / 2;\n const dirY = childY - height / 2;\n const dirLength = Math.sqrt(dirX * dirX + dirY * dirY);\n\n const normDirX = dirX / dirLength;\n const normDirY = dirY / dirLength;\n\n if (grandchildren.length === 1) {\n const grandchildId = grandchildren[0];\n const grandchildNode = nodeHierarchy.get(grandchildId);\n if (grandchildNode) {\n grandchildNode.x = childX + normDirX * grandchildDistanceFromChild;\n grandchildNode.y = childY + normDirY * grandchildDistanceFromChild;\n grandchildNode.angle = childAngle;\n }\n } else {\n // Multiple grandchildren - arrange in semicircular arc\n const numChildren = grandchildren.length;\n\n // Dynamic arc span: scale from 60° (2 children) to 180° (7+ children)\n const minArc = Math.PI / 3; // 60 degrees\n const maxArc = Math.PI; // 180 degrees\n const arcProgress = Math.min(1, (numChildren - 2) / 5);\n const arcSpan = minArc + arcProgress * (maxArc - minArc);\n\n // Calculate starting angle (center the arc around the radial direction)\n const startAngle = childAngle - arcSpan / 2;\n\n grandchildren.forEach((grandchildId, index) => {\n const grandchildNode = nodeHierarchy.get(grandchildId);\n if (!grandchildNode) return;\n\n // Calculate angle for this child\n const angleOffset = numChildren > 1 ? (index / (numChildren - 1)) * arcSpan : 0;\n const angle = startAngle + angleOffset;\n\n // Position at constant radius from parent\n grandchildNode.x = childX + grandchildDistanceFromChild * Math.cos(angle);\n grandchildNode.y = childY + grandchildDistanceFromChild * Math.sin(angle);\n grandchildNode.angle = angle;\n });\n }\n }\n }\n\n visibleNodes.forEach((node) => {\n const savedPosition = nodePositionsRef.current.get(node.id);\n\n if (savedPosition) {\n node.fx = savedPosition.x;\n node.fy = savedPosition.y;\n } else {\n const hierarchyNode = nodeHierarchy.get(node.id);\n if (hierarchyNode && hierarchyNode.x !== undefined && hierarchyNode.y !== undefined) {\n node.fx = hierarchyNode.x;\n node.fy = hierarchyNode.y;\n // Save the calculated position so it persists across re-renders\n nodePositionsRef.current.set(node.id, { x: hierarchyNode.x, y: hierarchyNode.y });\n } else if (node.id === centralNodeId) {\n node.fx = width / 2;\n node.fy = height / 2;\n // Save the center position\n nodePositionsRef.current.set(node.id, { x: width / 2, y: height / 2 });\n }\n }\n });\n\n const simulation = d3\n .forceSimulation<D3Node>(visibleNodes)\n .force(\n \"link\",\n d3\n .forceLink<D3Node, D3Link>(visibleLinks)\n .id((d) => d.id)\n .distance(nodeRadius * 3)\n .strength(0.1),\n )\n .force(\"charge\", d3.forceManyBody().strength(-500).distanceMax(300))\n .force(\"collision\", d3.forceCollide().radius(nodeRadius * 1.2))\n .force(\"center\", d3.forceCenter(width / 2, height / 2).strength(0.1));\n\n simulation.stop();\n for (let i = 0; i < 100; i++) {\n simulation.tick();\n }\n\n visibleNodes.forEach((node) => {\n if (node.fx === undefined) {\n node.fx = node.x;\n node.fy = node.y;\n }\n });\n\n const link = graphGroup\n .append(\"g\")\n .attr(\"stroke\", \"#999\")\n .attr(\"stroke-opacity\", 0.6)\n .selectAll(\"line\")\n .data(visibleLinks)\n .join(\"line\")\n .attr(\"x1\", (d) => (d.source as D3Node).x || 0)\n .attr(\"y1\", (d) => (d.source as D3Node).y || 0)\n .attr(\"x2\", (d) => (d.target as D3Node).x || 0)\n .attr(\"y2\", (d) => (d.target as D3Node).y || 0)\n .attr(\"stroke-width\", 1.5);\n\n const node = graphGroup\n .append(\"g\")\n .selectAll(\"g\")\n .data(visibleNodes)\n .join(\"g\")\n .attr(\"class\", \"node-group\")\n .attr(\"cursor\", \"pointer\")\n .attr(\"transform\", (d) => `translate(${d.x || 0}, ${d.y || 0})`)\n .call(\n d3\n .drag<SVGGElement, D3Node>()\n .subject(function (d) {\n return d;\n })\n .on(\"start\", function (event, d) {\n d.fx = d.x;\n d.fy = d.y;\n })\n .on(\"drag\", function (event, d) {\n d.fx = event.x;\n d.fy = event.y;\n\n d3.select(this).attr(\"transform\", `translate(${event.x}, ${event.y})`);\n\n d3.select(this).attr(\"transform\", `translate(${event.x}, ${event.y})`);\n\n nodePositionsRef.current.set(d.id, { x: event.x, y: event.y });\n\n link\n .attr(\"x1\", (l) => {\n const source = l.source as D3Node;\n return source.fx || source.x || 0;\n })\n .attr(\"y1\", (l) => {\n const source = l.source as D3Node;\n return source.fy || source.y || 0;\n })\n .attr(\"x2\", (l) => {\n const target = l.target as D3Node;\n return target.fx || target.x || 0;\n })\n .attr(\"y2\", (l) => {\n const target = l.target as D3Node;\n return target.fy || target.y || 0;\n });\n })\n .on(\"end\", function (event, d) {\n d.fx = event.x;\n d.fy = event.y;\n }) as any,\n )\n .on(\"mouseenter\", function (_event, d) {\n // Skip hover effect for root node\n if (d.instanceType === \"root\") return;\n\n const currentNode = d3.select(this);\n\n // Bring node to front\n currentNode.raise();\n\n // Get current zoom scale for counter-scaling text\n const currentZoom = zoomRef.current?.k || 1;\n const targetScreenFontSize = 20; // Target font size in screen pixels\n const baseFontSize = 12; // Base font size in graph coordinates\n\n // Calculate smooth scale factor for transform\n const textScale = targetScreenFontSize / (baseFontSize * currentZoom);\n\n // Calculate text position offset - circle stays in graph coords, only gap is counter-scaled\n const hoverTextOffset = nodeRadius * 1.4 + 5 / currentZoom;\n\n // Scale up the circle with smooth transition (unchanged)\n currentNode\n .select(\"circle\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"r\", nodeRadius * 1.4)\n .attr(\"filter\", \"drop-shadow(0px 4px 12px rgba(0, 0, 0, 0.3))\");\n\n // Scale up the text with smooth transform scaling around its anchor point\n currentNode\n .select(\"text\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"dy\", -hoverTextOffset)\n .attr(\"transform\", `translate(0, ${-hoverTextOffset}) scale(${textScale}) translate(0, ${hoverTextOffset})`);\n })\n .on(\"mouseleave\", function (_event, d) {\n // Skip hover effect for root node\n if (d.instanceType === \"root\") return;\n\n const currentNode = d3.select(this);\n\n // Return circle to normal size\n currentNode\n .select(\"circle\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"r\", nodeRadius)\n .attr(\"filter\", null);\n\n // Return text to normal size with smooth transform\n const normalOffset = nodeRadius + 5;\n currentNode\n .select(\"text\")\n .transition()\n .duration(250)\n .ease(d3.easeExpOut)\n .attr(\"dy\", -normalOffset)\n .attr(\"transform\", `translate(0, ${-normalOffset}) scale(1) translate(0, ${normalOffset})`);\n });\n\n node\n .append(\"circle\")\n .attr(\"r\", nodeRadius)\n .attr(\"fill\", (d) => getNodeColor(d))\n .attr(\"stroke\", \"#fff\")\n .attr(\"stroke-width\", 1.5)\n .on(\"click\", (event, d) => {\n event.preventDefault();\n event.stopPropagation();\n if (zoomBehaviorRef.current) {\n svg.on(\".zoom\", null);\n setTimeout(() => {\n if (zoomBehaviorRef.current) {\n svg\n .call(zoomBehaviorRef.current as any)\n .on(\"wheel.zoom\", null)\n .on(\"dblclick.zoom\", null);\n }\n }, 100);\n }\n onNodeClick(d.id);\n });\n\n node.each(function (d: D3Node) {\n if (d.icon) {\n const Icon = d.icon as React.FC<{ size: number; color: string }>;\n const iconSvg = renderToStaticMarkup(<Icon size={nodeRadius / 2} color=\"white\" />);\n\n const iconGroup = d3\n .select(this)\n .append(\"g\")\n .html(iconSvg)\n .attr(\"transform\", `translate(${-nodeRadius / 4}, ${-nodeRadius / 4})`)\n .style(\"pointer-events\", \"all\")\n .on(\"click\", (event) => {\n event.stopPropagation();\n onNodeClick(d.id);\n });\n }\n });\n\n // Add loading spinner for nodes that are fetching children\n node.each(function (d: D3Node) {\n if (loadingNodeIds && loadingNodeIds.has(d.id)) {\n // Remove existing icon\n d3.select(this).selectAll(\"g\").remove();\n\n // Add spinner\n const spinnerSvg = renderToStaticMarkup(<Loader2 size={nodeRadius / 2} color=\"white\" />);\n\n d3.select(this)\n .append(\"g\")\n .html(spinnerSvg)\n .attr(\"class\", \"animate-spin\")\n .attr(\"transform\", `translate(${-nodeRadius / 4}, ${-nodeRadius / 4})`)\n .style(\"pointer-events\", \"none\");\n }\n });\n\n node.each(function (d: D3Node) {\n const textElement = d3\n .select(this)\n .append(\"text\")\n .attr(\"text-anchor\", \"middle\")\n .attr(\"font-size\", 12)\n .attr(\"pointer-events\", \"none\");\n\n if (d.instanceType === \"root\") {\n // Split text by spaces for multi-line display\n const words = d.name.split(\" \");\n const lineHeight = 1.2; // em units\n const numLines = words.length;\n // Calculate starting position to center the text block vertically\n // Account for the fact that we want the middle of the entire text block at y=0\n const startY = -((numLines - 1) * lineHeight) / 2;\n\n textElement.attr(\"fill\", \"var(--accent-foreground)\").attr(\"dominant-baseline\", \"middle\");\n\n words.forEach((word, index) => {\n textElement\n .append(\"tspan\")\n .attr(\"x\", 0)\n .attr(\"dy\", index === 0 ? `${startY}em` : `${lineHeight}em`)\n .text(word);\n });\n } else {\n // Non-root nodes: single line text above the circle\n textElement\n .attr(\"dy\", -nodeRadius - 5)\n .attr(\"fill\", \"currentColor\")\n .text(d.name);\n }\n });\n\n return () => {\n simulation.stop();\n };\n }, [nodes, links, colorScale, visibleNodeIds, loadingNodeIds, onNodeClick]);\n\n const zoomIn = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const currentTransform = zoomRef.current || d3.zoomIdentity;\n const newScale = Math.min(currentTransform.k * 1.3, 4);\n\n svg\n .transition()\n .duration(300)\n .call(zoom.transform, d3.zoomIdentity.translate(currentTransform.x, currentTransform.y).scale(newScale));\n }, []);\n\n const zoomOut = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n const currentTransform = zoomRef.current || d3.zoomIdentity;\n const newScale = Math.max(currentTransform.k * 0.7, 0.1);\n\n svg\n .transition()\n .duration(300)\n .call(zoom.transform, d3.zoomIdentity.translate(currentTransform.x, currentTransform.y).scale(newScale));\n }, []);\n\n const zoomToFitAll = useCallback(() => {\n if (!svgRef.current || !zoomBehaviorRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const zoom = zoomBehaviorRef.current;\n\n // Get all visible nodes\n const visibleNodes = visibleNodeIds\n ? nodes.filter((node) => visibleNodeIds.has(node.id))\n : nodes.filter((node) => node.visible !== false);\n\n if (visibleNodes.length === 0) return;\n\n // Calculate bounds of all visible nodes\n const positions: { x: number; y: number }[] = [];\n visibleNodes.forEach((node) => {\n if (node.fx !== undefined && node.fy !== undefined && node.fx !== null && node.fy !== null) {\n positions.push({ x: node.fx, y: node.fy });\n } else if (node.x !== undefined && node.y !== undefined && node.x !== null && node.y !== null) {\n positions.push({ x: node.x, y: node.y });\n }\n });\n\n if (positions.length === 0) return;\n\n const bounds = {\n xMin: Math.min(...positions.map((p) => p.x)),\n xMax: Math.max(...positions.map((p) => p.x)),\n yMin: Math.min(...positions.map((p) => p.y)),\n yMax: Math.max(...positions.map((p) => p.y)),\n };\n\n // Add padding\n const padding = 150;\n bounds.xMin -= padding;\n bounds.xMax += padding;\n bounds.yMin -= padding;\n bounds.yMax += padding;\n\n const width = svgRef.current.clientWidth;\n const height = svgRef.current.clientHeight;\n\n const contentWidth = bounds.xMax - bounds.xMin;\n const contentHeight = bounds.yMax - bounds.yMin;\n\n const scaleX = width / contentWidth;\n const scaleY = height / contentHeight;\n\n let scale = Math.min(scaleX, scaleY);\n scale = Math.min(Math.max(scale, 0.1), 2); // Clamp between 0.1 and 2\n\n const centerX = (bounds.xMin + bounds.xMax) / 2;\n const centerY = (bounds.yMin + bounds.yMax) / 2;\n\n const translateX = width / 2 - centerX * scale;\n const translateY = height / 2 - centerY * scale;\n\n svg.transition().duration(750).call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(scale));\n }, [nodes, visibleNodeIds]);\n\n // When container size changes (full-screen toggle), zoom to fit all nodes\n // This scales the view instead of recalculating positions, maintaining relative layout\n useEffect(() => {\n if (containerKey !== undefined && containerKey !== prevContainerKeyRef.current) {\n // Small delay to allow the container to finish resizing\n const timeoutId = setTimeout(() => {\n zoomToFitAll();\n }, 100);\n\n prevContainerKeyRef.current = containerKey;\n\n return () => clearTimeout(timeoutId);\n }\n }, [containerKey, zoomToFitAll]);\n\n return { svgRef, zoomIn, zoomOut, zoomToNode, zoomToFitAll };\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useNotificationContext, useSocketContext } from \"../contexts\";\n\nexport function useNotificationSync() {\n const { socketNotifications, clearSocketNotifications } = useSocketContext();\n const { addSocketNotifications } = useNotificationContext();\n\n useEffect(() => {\n if (socketNotifications.length > 0) {\n try {\n addSocketNotifications(socketNotifications);\n clearSocketNotifications();\n } catch (error) {\n console.error(\"💥 [useNotificationSync] Error processing notifications:\", error);\n }\n }\n }, [socketNotifications, addSocketNotifications, clearSocketNotifications]);\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { createContext, ReactNode, useContext, useState } from \"react\";\nimport { SharedProvider } from \"../../../contexts\";\nimport { JsonApiHydratedDataInterface, Modules, rehydrate } from \"../../../core\";\nimport { usePageUrlGenerator } from \"../../../hooks\";\nimport { BreadcrumbItemData } from \"../../../interfaces\";\nimport { Action } from \"../../../permissions\";\nimport { getRoleId } from \"../../../roles\";\nimport { UserInterface } from \"../../user\";\nimport { useCurrentUserContext } from \"../../user/contexts\";\nimport { CompanyConfigurationEditor, CompanyDeleter, CompanyEditor } from \"../components\";\nimport { CompanyInterface } from \"../data\";\n\ninterface CompanyContextType {\n company: CompanyInterface | undefined;\n setCompany: (value: CompanyInterface | undefined) => void;\n}\n\nconst CompanyContext = createContext<CompanyContextType | undefined>(undefined);\n\ntype CompanyProviderProps = {\n children: ReactNode;\n dehydratedCompany?: JsonApiHydratedDataInterface;\n};\n\nconst defaultContextValue: CompanyContextType = {\n company: undefined,\n setCompany: () => {},\n};\n\nexport const CompanyProvider = ({ children, dehydratedCompany }: CompanyProviderProps) => {\n const generateUrl = usePageUrlGenerator();\n const t = useTranslations();\n const { hasPermissionToModule, hasRole } = useCurrentUserContext<UserInterface>();\n\n const [company, setCompany] = useState<CompanyInterface | undefined>(\n dehydratedCompany ? rehydrate<CompanyInterface>(Modules.Company, dehydratedCompany) : undefined,\n );\n\n const breadcrumb = () => {\n const response: BreadcrumbItemData[] = [];\n\n if (company)\n response.push({\n name: company.name,\n href: generateUrl({ page: Modules.Company }),\n });\n\n return response;\n };\n\n const title = () => {\n const response: any = {\n type: t(`types.companies`, { count: company ? 1 : 2 }),\n };\n\n if (company) response.element = company.name;\n\n const functions: ReactNode[] = [];\n\n if (\n company &&\n hasRole(getRoleId().Administrator) &&\n hasPermissionToModule({ module: Modules.Company, action: Action.Delete })\n )\n functions.push(<CompanyDeleter key=\"companyDeleter\" company={company} />);\n\n if (\n hasRole(getRoleId().Administrator) ||\n hasPermissionToModule({ module: Modules.Company, action: Action.Update })\n ) {\n if (company) functions.push(<CompanyConfigurationEditor key=\"companyConfigurationEditor\" company={company} />);\n functions.push(<CompanyEditor key=\"companyEditor\" company={company} propagateChanges={setCompany} />);\n }\n\n if (functions.length > 0) response.functions = functions;\n\n return response;\n };\n\n return (\n <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>\n <CompanyContext.Provider\n value={{\n company: company,\n setCompany: setCompany,\n }}\n >\n {children}\n </CompanyContext.Provider>\n </SharedProvider>\n );\n};\n\nexport const useCompanyContext = (): CompanyContextType => {\n return useContext(CompanyContext) ?? defaultContextValue;\n};\n","\"use client\";\n\nimport { getCookie } from \"cookies-next\";\nimport { useAtom } from \"jotai\";\nimport { atomWithStorage } from \"jotai/utils\";\nimport { usePathname } from \"next/navigation\";\nimport React, { createContext, useContext, useEffect } from \"react\";\nimport { Modules, rehydrate } from \"../../../core\";\nimport { Action, checkPermissions, ModuleWithPermissions } from \"../../../permissions\";\nimport { getRoleId } from \"../../../roles\";\nimport { CompanyInterface } from \"../../company\";\nimport { FeatureInterface } from \"../../feature\";\nimport { RoleInterface } from \"../../role\";\nimport { UserInterface } from \"../data\";\n\nexport interface CurrentUserContextType<T extends UserInterface = UserInterface> {\n currentUser: T | null;\n company: CompanyInterface | null;\n setUser: (user?: T) => void;\n hasPermissionToModule: <M extends ModuleWithPermissions>(params: {\n module: M;\n action: Action;\n data?: any;\n }) => boolean;\n hasPermissionToModules: <M extends ModuleWithPermissions>(params: {\n modules: M[];\n action: Action;\n data?: any;\n }) => boolean;\n hasPermissionToPath: (path: string) => boolean;\n hasAccesToFeature: (featureIdentifier: string) => boolean;\n matchUrlToModule: (prarms?: { path: string }) => ModuleWithPermissions | undefined;\n hasRole: (roleId: string) => boolean;\n}\n\nconst userAtom = atomWithStorage(\"user\", null);\n\nconst CurrentUserContext = createContext<CurrentUserContextType | undefined>(undefined);\n\nexport const CurrentUserProvider = ({ children }: { children: React.ReactNode }) => {\n const path = usePathname();\n\n const [dehydratedUser, setDehydratedUser] = useAtom(userAtom);\n\n useEffect(() => {\n const token = getCookie(\"token\");\n if (!token && dehydratedUser) setDehydratedUser(null);\n }, [dehydratedUser, setDehydratedUser]);\n\n const matchUrlToModule = (params?: { path: string }): ModuleWithPermissions | undefined => {\n const moduleKeys = Object.getOwnPropertyNames(Modules).filter(\n (key) => key !== \"prototype\" && key !== \"_factory\" && key !== \"length\" && key !== \"name\",\n );\n\n const matchedModuleKey = moduleKeys.find((key) => {\n const descriptor = Object.getOwnPropertyDescriptor(Modules, key);\n\n if (!descriptor?.get) return false;\n\n const selectedModule = descriptor.get.call(Modules);\n\n return path.toLowerCase().startsWith(selectedModule.pageUrl?.toLowerCase());\n });\n\n if (!matchedModuleKey) return undefined;\n\n const descriptor = Object.getOwnPropertyDescriptor(Modules, matchedModuleKey);\n return descriptor?.get?.call(Modules);\n };\n\n const currentUser = dehydratedUser ? rehydrate<UserInterface>(Modules.User, dehydratedUser) : null;\n\n const company = currentUser?.company ?? null;\n\n const setUser = (user?: UserInterface): void => {\n if (user) setDehydratedUser(user.dehydrate() as any);\n else setDehydratedUser(null);\n };\n\n const hasRole = (roleId: string): boolean => {\n if (!currentUser) return false;\n\n return !!currentUser.roles?.some((userRole: RoleInterface) => userRole.id === roleId);\n };\n\n const hasAccesToFeature = (featureIdentifier: string): boolean => {\n if (hasRole(getRoleId().Administrator)) return true;\n if (!company) return false;\n\n return company.features.some((feature: FeatureInterface) => feature.id === featureIdentifier);\n };\n\n function hasPermissionToModule<M extends ModuleWithPermissions>(params: {\n module: M;\n action: Action;\n data?: M extends ModuleWithPermissions ? any : never;\n }): boolean {\n if (!currentUser) return false;\n\n if (!!params.module.feature && !hasAccesToFeature(params.module.feature)) return false;\n\n return checkPermissions({ module: params.module, action: params.action, data: params.data, user: currentUser });\n }\n\n function hasPermissionToModules<M extends ModuleWithPermissions>(params: {\n modules: M[];\n action: Action;\n data?: M extends ModuleWithPermissions ? any : never;\n }): boolean {\n if (!currentUser) return false;\n\n if (!params.modules.every((module) => !module.feature || hasAccesToFeature(module.feature))) return false;\n\n return params.modules.every((module) =>\n checkPermissions({ module: module, action: params.action, data: params.data, user: currentUser }),\n );\n }\n\n function hasPermissionToPath(path: string): boolean {\n if (!currentUser) return false;\n if (path === \"#\" || path === \"/\") return true;\n\n const selectedModule = matchUrlToModule({ path: path });\n if (!selectedModule) return true;\n\n const response = hasPermissionToModule({ module: selectedModule, action: Action.Read });\n\n return response;\n }\n\n return (\n <CurrentUserContext.Provider\n value={{\n currentUser: currentUser,\n company: company,\n setUser: setUser,\n hasPermissionToModule: hasPermissionToModule,\n hasPermissionToModules: hasPermissionToModules,\n hasPermissionToPath: hasPermissionToPath,\n hasAccesToFeature: hasAccesToFeature,\n matchUrlToModule: matchUrlToModule,\n hasRole: hasRole,\n }}\n >\n {children}\n </CurrentUserContext.Provider>\n );\n};\n\nexport function useCurrentUserContext<T extends UserInterface = UserInterface>(): CurrentUserContextType<T> {\n const context = useContext(CurrentUserContext);\n if (context === undefined) {\n throw new Error(\"useCurrentUserContext must be used within a UserProvider\");\n }\n return context as unknown as CurrentUserContextType<T>;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { createContext, ReactNode, useContext, useState } from \"react\";\nimport { SharedProvider } from \"../../../contexts\";\nimport { JsonApiHydratedDataInterface, Modules, rehydrate } from \"../../../core\";\nimport { usePageUrlGenerator } from \"../../../hooks\";\nimport { BreadcrumbItemData } from \"../../../interfaces\";\nimport { Action } from \"../../../permissions\";\nimport { UserDeleter, UserEditor, UserReactivator, UserResentInvitationEmail } from \"../components/forms\";\nimport { UserInterface } from \"../data\";\nimport { useCurrentUserContext } from \"./CurrentUserContext\";\n\ninterface UserContextType {\n user: UserInterface | undefined;\n setUser: (value: UserInterface | undefined) => void;\n}\n\nconst UserContext = createContext<UserContextType | undefined>(undefined);\n\ntype UserProviderProps = {\n children: ReactNode;\n dehydratedUser?: JsonApiHydratedDataInterface;\n};\n\nexport const UserProvider = ({ children, dehydratedUser }: UserProviderProps) => {\n const generateUrl = usePageUrlGenerator();\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n const t = useTranslations();\n\n const [user, setUser] = useState<UserInterface | undefined>(\n dehydratedUser ? rehydrate<UserInterface>(Modules.User, dehydratedUser) : undefined,\n );\n\n const breadcrumb = () => {\n const response: BreadcrumbItemData[] = [];\n\n if (hasPermissionToModule({ module: Modules.User, action: Action.Update })) {\n response.push({\n name: t(`generic.settings`),\n href: generateUrl({ page: `/settings` }),\n });\n\n response.push({\n name: t(`types.users`, { count: 2 }),\n href: generateUrl({ page: `/settings`, id: Modules.User.pageUrl }),\n });\n }\n\n if (user)\n response.push({\n name: `${user.name}${user.isDeleted ? ` (${t(`foundations.user.deleted`)})` : \"\"}`,\n href: generateUrl({ page: Modules.User, id: user.id }),\n });\n\n return response;\n };\n\n const title = () => {\n const response: any = {\n type: t(`types.users`, { count: user ? 1 : 2 }),\n };\n\n const functions: ReactNode[] = [];\n\n if (user) {\n response.element = `${user.name}${user.isDeleted ? ` (${t(`foundations.user.deleted`)})` : \"\"}`;\n\n if (user.isDeleted) {\n functions.push(<UserReactivator key={`UserReactivator`} user={user} propagateChanges={setUser} />);\n } else {\n if (!user.isActivated)\n functions.push(<UserResentInvitationEmail key={`UserResentInvitationEmail`} user={user} />);\n\n functions.push(<UserDeleter key={`UserDeleter`} user={user} />);\n }\n\n functions.push(<UserEditor key={`UserEditor`} user={user} propagateChanges={setUser} />);\n }\n\n if (functions.length > 0) response.functions = functions;\n\n return response;\n };\n\n return (\n <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>\n <UserContext.Provider\n value={{\n user: user,\n setUser: setUser,\n }}\n >\n {children}\n </UserContext.Provider>\n </SharedProvider>\n );\n};\n\nexport const useUserContext = (): UserContextType => {\n const context = useContext(UserContext);\n if (context === undefined) {\n throw new Error(\"useUserContext must be used within a UserProvider\");\n }\n return context;\n};\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useState } from \"react\";\nimport {\n CommonAssociationCommandDialog,\n CommonAssociationTrigger,\n triggerAssociationToast,\n UserListInAdd,\n} from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { RoleInterface } from \"../../../role\";\nimport { RoleService } from \"../../../role/data/role.service\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype AddUserToRoleProps = {\n role: RoleInterface;\n refresh: () => Promise<void>;\n};\n\nfunction AddUserToRoleInternal({ role, refresh }: AddUserToRoleProps) {\n const { company } = useCurrentUserContext<UserInterface>();\n const [show, setShow] = useState<boolean>(false);\n const [users, setUsers] = useState<UserInterface[]>([]);\n const t = useTranslations();\n\n const [existingUsers, setExistingUsers] = useState<UserInterface[] | null>(null);\n useEffect(() => {\n const fetchExistingUsers = async () => {\n setExistingUsers(await UserService.findMany({ roleId: role.id, fetchAll: true }));\n };\n if (show) {\n setExistingUsers(null);\n fetchExistingUsers();\n }\n }, [show]);\n\n const addUserToRole = async (user: UserInterface) => {\n await RoleService.addUserToRole({\n roleId: role.id,\n userId: user.id,\n });\n setUsers(users.filter((u) => u.id !== user.id));\n\n triggerAssociationToast({\n t: t,\n source: t(`types.users`, { count: 1 }),\n destination: t(`types.roles`, { count: 1 }),\n source_name: user.name,\n destination_name: t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) }),\n });\n\n refresh();\n };\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n ready: !!company && show,\n retriever: (params) => UserService.findAllUsers(params),\n retrieverParams: { companyId: company?.id },\n module: Modules.User,\n }) as DataListRetriever<UserInterface>;\n\n useEffect(() => {\n if (!!company && show) {\n data.setReady(true);\n }\n }, [data, company, show]);\n\n return (\n <>\n <CommonAssociationTrigger\n sourceType={t(`types.users`, { count: 1 })}\n destinationType={t(`types.roles`, { count: 1 })}\n onTrigger={() => setShow(true)}\n />\n <CommonAssociationCommandDialog\n show={show}\n setShow={setShow}\n data={data}\n source={t(`types.users`, { count: 1 })}\n destination={t(`types.roles`, { count: 1 })}\n destinationName={t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) })}\n >\n <UserListInAdd data={data} existingUsers={existingUsers} setSelectedUser={addUserToRole} />\n </CommonAssociationCommandDialog>\n </>\n );\n}\n\nexport function AddUserToRole(props: AddUserToRoleProps) {\n return <AddUserToRoleInternal {...props} />;\n}\n","\"use client\";\n\nimport { UploadIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { DropzoneOptions } from \"react-dropzone\";\nimport { FileInput, FileUploader } from \"../../../../components\";\nimport { Button } from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../data\";\n\ntype UserAvatarEditorProps = {\n user?: UserInterface;\n file?: File | null;\n setFile: (file: File | null) => void;\n resetImage: boolean;\n setResetImage: (reset: boolean) => void;\n};\n\nexport function UserAvatarEditor({ user, file, setFile, resetImage, setResetImage }: UserAvatarEditorProps) {\n const [files, setFiles] = useState<File[] | null>(null);\n const t = useTranslations();\n\n useEffect(() => {\n if (files && files.length > 0) {\n setResetImage(false);\n setFile(files[0]);\n }\n }, [files]);\n\n const dropzone = {\n multiple: false,\n maxSize: 100 * 1024 * 1024,\n preventDropOnDocument: false,\n accept: {\n \"application/images\": [\".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".svg\"],\n },\n } satisfies DropzoneOptions;\n\n return (\n <div className=\"flex w-40 flex-col gap-y-4\">\n <FileUploader\n value={files}\n onValueChange={setFiles}\n dropzoneOptions={dropzone}\n className=\"h-40 w-40 rounded-full p-0\"\n >\n <FileInput className=\"bg-muted text-muted-foreground flex h-full w-full flex-col items-center justify-center\">\n {!resetImage && (file || user?.avatar) ? (\n <Image\n src={file ? URL.createObjectURL(file) : user?.avatar || \"\"}\n alt={t(`generic.avatar`)}\n width={200}\n height={200}\n />\n ) : (\n <UploadIcon className=\"my-4 h-8 w-8\" />\n )}\n </FileInput>\n </FileUploader>\n {!resetImage && (file || user?.avatar) && (\n <Button\n className=\"\"\n size={`sm`}\n variant={`outline`}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setFile(null);\n setResetImage(true);\n }}\n >\n {t(`generic.buttons.remove`)}\n </Button>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDownIcon } from \"@radix-ui/react-icons\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item ref={ref} className={cn(\"border-b\", className)} {...props} />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\" asChild>\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all\", className)}\n {...props}\n >\n <div className=\"flex items-center\">\n {children}\n <ChevronDownIcon className=\"h-4 w-4 shrink-0 bg-transparent text-muted-foreground transition-transform duration-200 [&[data-state=open]>svg]:rotate-180\" />\n </div>\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionContent, AccordionItem, AccordionTrigger };\n","import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive: \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div ref={ref} role=\"alert\" className={cn(alertVariants({ variant }), className)} {...props} />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(\n ({ className, ...props }, ref) => (\n <h5 ref={ref} className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)} {...props} />\n ),\n);\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"text-sm [&_p]:leading-relaxed\", className)} {...props} />\n ),\n);\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertDescription, AlertTitle };\n","\"use client\";\n\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\nimport * as React from \"react\";\n\nimport { buttonVariants } from \"./button\";\nimport { cn } from \"../../utils/cn\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n};\n","import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary: \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n ghostdestructive: \"hover:bg-destructive hover:text-primary-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot : \"button\";\n\n return <Comp data-slot=\"button\" className={cn(buttonVariants({ variant, size, className }))} {...props} />;\n}\n\nexport { Button, buttonVariants };\n","\"use client\";\n\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(\n \"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full\",\n className,\n )}\n {...props}\n />\n));\nAvatar.displayName = AvatarPrimitive.Root.displayName;\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn(\"aspect-square h-full w-full\", className)}\n {...props}\n />\n));\nAvatarImage.displayName = AvatarPrimitive.Image.displayName;\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n \"flex h-full w-full items-center justify-center rounded-full bg-muted\",\n className,\n )}\n {...props}\n />\n));\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;\n\nexport { Avatar, AvatarFallback, AvatarImage };\n","import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst badgeVariants = cva(\n \"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\",\n {\n variants: {\n variant: {\n default: \"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80\",\n secondary: \"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n destructive: \"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80\",\n outline: \"text-foreground\",\n\n blue: \"border-transparent bg-sky-500 text-primary-foreground rounded-full\",\n green: \"border-transparent bg-emerald-500 text-primary-foreground rounded-full\",\n red: \"border-transparent bg-red-500 text-primary-foreground rounded-full\",\n yellow: \"border-transparent bg-yellow-500 text-primary-foreground rounded-full\",\n purple: \"border-transparent bg-purple-500 text-primary-foreground rounded-full\",\n pink: \"border-transparent bg-pink-500 text-primary-foreground rounded-full\",\n gray: \"border-transparent bg-gray-500 text-primary-foreground rounded-full\",\n orange: \"border-transparent bg-orange-500 text-primary-foreground rounded-full\",\n teal: \"border-transparent bg-teal-500 text-primary-foreground rounded-full\",\n lime: \"border-transparent bg-lime-500 text-primary-foreground rounded-full\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return <div className={cn(badgeVariants({ variant }), className)} {...props} />;\n}\n\nexport { Badge, badgeVariants };\n","import { ChevronRightIcon, DotsHorizontalIcon } from \"@radix-ui/react-icons\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Breadcrumb = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<\"nav\"> & {\n separator?: React.ReactNode;\n }\n>(({ ...props }, ref) => <nav ref={ref} aria-label=\"breadcrumb\" {...props} />);\nBreadcrumb.displayName = \"Breadcrumb\";\n\nconst BreadcrumbList = React.forwardRef<\n HTMLOListElement,\n React.ComponentPropsWithoutRef<\"ol\">\n>(({ className, ...props }, ref) => (\n <ol\n ref={ref}\n className={cn(\n \"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5\",\n className,\n )}\n {...props}\n />\n));\nBreadcrumbList.displayName = \"BreadcrumbList\";\n\nconst BreadcrumbItem = React.forwardRef<\n HTMLLIElement,\n React.ComponentPropsWithoutRef<\"li\">\n>(({ className, ...props }, ref) => (\n <li\n ref={ref}\n className={cn(\"inline-flex items-center gap-1.5\", className)}\n {...props}\n />\n));\nBreadcrumbItem.displayName = \"BreadcrumbItem\";\n\nconst BreadcrumbLink = React.forwardRef<\n HTMLAnchorElement,\n React.ComponentPropsWithoutRef<\"a\"> & {\n asChild?: boolean;\n }\n>(({ asChild, className, ...props }, ref) => {\n const Comp = asChild ? Slot : \"a\";\n\n return (\n <Comp\n ref={ref}\n className={cn(\"transition-colors hover:text-foreground\", className)}\n {...props}\n />\n );\n});\nBreadcrumbLink.displayName = \"BreadcrumbLink\";\n\nconst BreadcrumbPage = React.forwardRef<\n HTMLSpanElement,\n React.ComponentPropsWithoutRef<\"span\">\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n role=\"link\"\n aria-disabled=\"true\"\n aria-current=\"page\"\n className={cn(\"font-normal text-foreground\", className)}\n {...props}\n />\n));\nBreadcrumbPage.displayName = \"BreadcrumbPage\";\n\nconst BreadcrumbSeparator = ({\n children,\n className,\n ...props\n}: React.ComponentProps<\"li\">) => (\n <li\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"[&>svg]:h-3.5 [&>svg]:w-3.5\", className)}\n {...props}\n >\n {children ?? <ChevronRightIcon />}\n </li>\n);\nBreadcrumbSeparator.displayName = \"BreadcrumbSeparator\";\n\nconst BreadcrumbEllipsis = ({\n className,\n ...props\n}: React.ComponentProps<\"span\">) => (\n <span\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"flex h-9 w-9 items-center justify-center\", className)}\n {...props}\n >\n <DotsHorizontalIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">More</span>\n </span>\n);\nBreadcrumbEllipsis.displayName = \"BreadcrumbElipssis\";\n\nexport {\n Breadcrumb,\n BreadcrumbEllipsis,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n};\n","\"use client\";\n\nimport * as React from \"react\";\nimport { DayPicker, getDefaultClassNames } from \"react-day-picker\";\n\nimport { cn } from \"../../utils/cn\";\nimport { buttonVariants } from \"./button\";\n// import \"react-day-picker/style.css\";\n\nfunction Calendar({ className, classNames, showOutsideDays = true, ...props }: React.ComponentProps<typeof DayPicker>) {\n const defaultClassNames = getDefaultClassNames();\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\"p-3\", className)}\n classNames={{\n months: `relative flex ${defaultClassNames.month}`,\n month_caption: `relative mx-10 flex h-7 items-center justify-center ${defaultClassNames.month_caption}`,\n weekdays: cn(\"flex flex-row\", classNames?.weekdays),\n weekday: cn(\"w-8 text-sm font-normal text-muted-foreground\", classNames?.weekday),\n month: cn(\"w-full\", classNames?.month),\n\n caption_label: cn(\"truncate text-sm font-medium\", classNames?.caption_label),\n button_next: cn(\n buttonVariants({ variant: \"outline\" }),\n \"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute right-1 [&_svg]:fill-foreground\",\n classNames?.button_next,\n ),\n button_previous: cn(\n buttonVariants({ variant: \"outline\" }),\n \"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 absolute left-1 [&_svg]:fill-foreground\",\n classNames?.button_previous,\n ),\n nav: cn(\"flex items-start\", classNames?.nav),\n month_grid: cn(\"mx-auto mt-4\", classNames?.month_grid),\n week: cn(\"mt-2 flex w-max items-start\", classNames?.week),\n day: cn(\"flex size-8 flex-1 items-center justify-center p-0 text-sm\", classNames?.day),\n day_button: cn(\n \"size-8 rounded-md p-0 font-normal transition-none aria-selected:opacity-100\",\n classNames?.day_button,\n ),\n range_start: cn(\n \"bg-accent [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground day-range-start rounded-s-md\",\n classNames?.range_start,\n ),\n range_middle: cn(\n \"bg-accent !text-foreground [&>button]:bg-transparent [&>button]:!text-foreground [&>button]:hover:bg-transparent [&>button]:hover:!text-foreground\",\n classNames?.range_middle,\n ),\n range_end: cn(\n \"bg-accent [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground day-range-end rounded-e-md\",\n classNames?.range_end,\n ),\n selected: cn(\n \"[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground\",\n classNames?.selected,\n ),\n today: cn(\"[&>button]:bg-accent [&>button]:text-accent-foreground\", classNames?.today),\n outside: cn(\n \"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30\",\n classNames?.outside,\n ),\n disabled: cn(\"text-muted-foreground opacity-50\", classNames?.disabled),\n hidden: cn(\"invisible flex-1\", classNames?.hidden),\n ...classNames,\n }}\n {...props}\n />\n );\n}\nCalendar.displayName = \"Calendar\";\n\nexport { Calendar };\n","import * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"rounded-xl border bg-card text-card-foreground shadow\", className)} {...props} />\n));\nCard.displayName = \"Card\";\n\nconst CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"flex flex-col space-y-1.5 p-6\", className)} {...props} />\n ),\n);\nCardHeader.displayName = \"CardHeader\";\n\nconst CardTitle = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"font-semibold leading-none tracking-tight\", className)} {...props} />\n ),\n);\nCardTitle.displayName = \"CardTitle\";\n\nconst CardDescription = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"text-sm text-muted-foreground\", className)} {...props} />\n ),\n);\nCardDescription.displayName = \"CardDescription\";\n\nconst CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => <div ref={ref} className={cn(\"p-6 pt-0\", className)} {...props} />,\n);\nCardContent.displayName = \"CardContent\";\n\nconst CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"flex items-center p-6 pt-0\", className)} {...props} />\n ),\n);\nCardFooter.displayName = \"CardFooter\";\n\nexport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };\n","\"use client\";\n\nimport { Button } from \"./button\";\nimport { cn } from \"../../utils/cn\";\nimport { ArrowLeftIcon, ArrowRightIcon } from \"@radix-ui/react-icons\";\nimport useEmblaCarousel, { type UseEmblaCarouselType } from \"embla-carousel-react\";\nimport * as React from \"react\";\n\ntype CarouselApi = UseEmblaCarouselType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\ntype CarouselOptions = UseCarouselParameters[0];\ntype CarouselPlugin = UseCarouselParameters[1];\n\ntype CarouselProps = {\n opts?: CarouselOptions;\n plugins?: CarouselPlugin;\n orientation?: \"horizontal\" | \"vertical\";\n setApi?: (api: CarouselApi) => void;\n};\n\ntype CarouselContextProps = {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0];\n api: ReturnType<typeof useEmblaCarousel>[1];\n scrollPrev: () => void;\n scrollNext: () => void;\n canScrollPrev: boolean;\n canScrollNext: boolean;\n} & CarouselProps;\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null);\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext);\n\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\");\n }\n\n return context;\n}\n\nconst Carousel = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & CarouselProps>(\n ({ orientation = \"horizontal\", opts, setApi, plugins, className, children, ...props }, ref) => {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n },\n plugins,\n );\n const [canScrollPrev, setCanScrollPrev] = React.useState(false);\n const [canScrollNext, setCanScrollNext] = React.useState(false);\n\n const onSelect = React.useCallback((api: CarouselApi) => {\n if (!api) {\n return;\n }\n\n setCanScrollPrev(api.canScrollPrev());\n setCanScrollNext(api.canScrollNext());\n }, []);\n\n const scrollPrev = React.useCallback(() => {\n api?.scrollPrev();\n }, [api]);\n\n const scrollNext = React.useCallback(() => {\n api?.scrollNext();\n }, [api]);\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n scrollPrev();\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n scrollNext();\n }\n },\n [scrollPrev, scrollNext],\n );\n\n React.useEffect(() => {\n if (!api || !setApi) {\n return;\n }\n\n setApi(api);\n }, [api, setApi]);\n\n React.useEffect(() => {\n if (!api) {\n return;\n }\n\n onSelect(api);\n api.on(\"reInit\", onSelect);\n api.on(\"select\", onSelect);\n\n return () => {\n api?.off(\"select\", onSelect);\n };\n }, [api, onSelect]);\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api: api,\n opts,\n orientation: orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n ref={ref}\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n );\n },\n);\nCarousel.displayName = \"Carousel\";\n\nconst CarouselContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const { carouselRef, orientation } = useCarousel();\n\n return (\n <div ref={carouselRef} className=\"overflow-hidden\">\n <div\n ref={ref}\n className={cn(\"flex\", orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\", className)}\n {...props}\n />\n </div>\n );\n },\n);\nCarouselContent.displayName = \"CarouselContent\";\n\nconst CarouselItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const { orientation } = useCarousel();\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-roledescription=\"slide\"\n className={cn(\"min-w-0 shrink-0 grow-0 basis-full\", orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\", className)}\n {...props}\n />\n );\n },\n);\nCarouselItem.displayName = \"CarouselItem\";\n\nconst CarouselPrevious = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(\n ({ className, variant = \"outline\", size = \"icon\", ...props }, ref) => {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel();\n\n return (\n <Button\n ref={ref}\n variant={variant}\n size={size}\n className={cn(\n \"absolute h-8 w-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"-left-12 top-1/2 -translate-y-1/2\"\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n className,\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <ArrowLeftIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n );\n },\n);\nCarouselPrevious.displayName = \"CarouselPrevious\";\n\nconst CarouselNext = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(\n ({ className, variant = \"outline\", size = \"icon\", ...props }, ref) => {\n const { orientation, scrollNext, canScrollNext } = useCarousel();\n\n return (\n <Button\n ref={ref}\n variant={variant}\n size={size}\n className={cn(\n \"absolute h-8 w-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"-right-12 top-1/2 -translate-y-1/2\"\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n className,\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <ArrowRightIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n );\n },\n);\nCarouselNext.displayName = \"CarouselNext\";\n\nexport { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type CarouselApi };\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as RechartsPrimitive from \"recharts\";\nimport type { LegendPayload } from \"recharts/types/component/DefaultLegendContent\";\nimport { NameType, Payload, ValueType } from \"recharts/types/component/DefaultTooltipContent\";\nimport type { Props as LegendProps } from \"recharts/types/component/Legend\";\nimport { TooltipContentProps } from \"recharts/types/component/Tooltip\";\n\nimport { cn } from \"../../utils/cn\";\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const;\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode;\n icon?: React.ComponentType;\n } & ({ color?: string; theme?: never } | { color?: never; theme: Record<keyof typeof THEMES, string> });\n};\n\ntype ChartContextProps = {\n config: ChartConfig;\n};\n\nconst ChartContext = React.createContext<ChartContextProps | null>(null);\n\nfunction useChart() {\n const context = React.useContext(ChartContext);\n\n if (!context) {\n throw new Error(\"useChart must be used within a <ChartContainer />\");\n }\n\n return context;\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig;\n children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>[\"children\"];\n}) {\n const uniqueId = React.useId();\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`;\n\n return (\n <ChartContext.Provider value={{ config }}>\n <div\n data-slot=\"chart\"\n data-chart={chartId}\n className={cn(\n \"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden\",\n className,\n )}\n {...props}\n >\n <ChartStyle id={chartId} config={config} />\n <RechartsPrimitive.ResponsiveContainer>{children}</RechartsPrimitive.ResponsiveContainer>\n </div>\n </ChartContext.Provider>\n );\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(([, config]) => config.theme || config.color);\n\n if (!colorConfig.length) {\n return null;\n }\n\n return (\n <style\n dangerouslySetInnerHTML={{\n __html: Object.entries(THEMES)\n .map(\n ([theme, prefix]) => `\n ${prefix} [data-chart=${id}] {\n ${colorConfig\n .map(([key, itemConfig]) => {\n const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || itemConfig.color;\n return color ? ` --color-${key}: ${color};` : null;\n })\n .join(\"\\n\")}\n }\n `,\n )\n .join(\"\\n\"),\n }}\n />\n );\n};\n\nconst ChartTooltip = RechartsPrimitive.Tooltip;\n\ntype CustomTooltipProps = TooltipContentProps<ValueType, NameType> & {\n className?: string;\n hideLabel?: boolean;\n hideIndicator?: boolean;\n indicator?: \"line\" | \"dot\" | \"dashed\";\n nameKey?: string;\n labelKey?: string;\n labelFormatter?: (\n label: TooltipContentProps<number, string>[\"label\"],\n payload: TooltipContentProps<number, string>[\"payload\"],\n ) => React.ReactNode;\n formatter?: (\n value: number | string,\n name: string,\n item: Payload<number | string, string>,\n index: number,\n payload: ReadonlyArray<Payload<number | string, string>>,\n ) => React.ReactNode;\n labelClassName?: string;\n color?: string;\n};\n\nfunction ChartTooltipContent({\n active,\n payload,\n label,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n labelFormatter,\n formatter,\n labelClassName,\n color,\n nameKey,\n labelKey,\n}: CustomTooltipProps) {\n const { config } = useChart();\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null;\n }\n\n const [item] = payload;\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const value = (() => {\n const v =\n !labelKey && typeof label === \"string\"\n ? (config[label as keyof typeof config]?.label ?? label)\n : itemConfig?.label;\n\n return typeof v === \"string\" || typeof v === \"number\" ? v : undefined;\n })();\n\n if (labelFormatter) {\n return <div className={cn(\"font-medium\", labelClassName)}>{labelFormatter(value, payload)}</div>;\n }\n\n if (!value) {\n return null;\n }\n\n return <div className={cn(\"font-medium\", labelClassName)}>{value}</div>;\n }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);\n\n if (!active || !payload?.length) {\n return null;\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\";\n\n return (\n <div\n className={cn(\n \"border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl\",\n className,\n )}\n >\n {!nestLabel ? tooltipLabel : null}\n <div className=\"grid gap-1.5\">\n {payload.map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const indicatorColor = color || item.payload.fill || item.color;\n\n return (\n <div\n key={item.dataKey}\n className={cn(\n \"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5\",\n indicator === \"dot\" && \"items-center\",\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n <itemConfig.icon />\n ) : (\n !hideIndicator && (\n <div\n className={cn(\"shrink-0 rounded-[2px] border-[var(--color-border)] bg-[var(--color-bg)]\", {\n \"h-2.5 w-2.5\": indicator === \"dot\",\n \"w-1\": indicator === \"line\",\n \"w-0 border-[1.5px] border-dashed bg-transparent\": indicator === \"dashed\",\n \"my-0.5\": nestLabel && indicator === \"dashed\",\n })}\n style={\n {\n \"--color-bg\": indicatorColor,\n \"--color-border\": indicatorColor,\n } as React.CSSProperties\n }\n />\n )\n )}\n <div\n className={cn(\"flex flex-1 justify-between leading-none\", nestLabel ? \"items-end\" : \"items-center\")}\n >\n <div className=\"grid gap-1.5\">\n {nestLabel ? tooltipLabel : null}\n <span className=\"text-muted-foreground\">{itemConfig?.label || item.name}</span>\n </div>\n {item.value && (\n <span className=\"text-foreground font-mono font-medium tabular-nums\">\n {item.value.toLocaleString()}\n </span>\n )}\n </div>\n </>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nconst ChartLegend = RechartsPrimitive.Legend;\n\ntype ChartLegendContentProps = {\n className?: string;\n hideIcon?: boolean;\n verticalAlign?: LegendProps[\"verticalAlign\"];\n payload?: LegendPayload[];\n nameKey?: string;\n};\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: ChartLegendContentProps) {\n const { config } = useChart();\n\n if (!payload?.length) {\n return null;\n }\n\n return (\n <div className={cn(\"flex items-center justify-center gap-4\", verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\", className)}>\n {payload.map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n\n return (\n <div\n key={item.value}\n className={cn(\"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3\")}\n >\n {itemConfig?.icon && !hideIcon ? (\n <itemConfig.icon />\n ) : (\n <div\n className=\"h-2 w-2 shrink-0 rounded-[2px]\"\n style={{\n backgroundColor: item.color,\n }}\n />\n )}\n {itemConfig?.label}\n </div>\n );\n })}\n </div>\n );\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined;\n }\n\n const payloadPayload =\n \"payload\" in payload && typeof payload.payload === \"object\" && payload.payload !== null\n ? payload.payload\n : undefined;\n\n let configLabelKey: string = key;\n\n if (key in payload && typeof payload[key as keyof typeof payload] === \"string\") {\n configLabelKey = payload[key as keyof typeof payload] as string;\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string;\n }\n\n return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config];\n}\n\nexport { ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent };\n","\"use client\";\n\nimport { cn } from \"../../utils/cn\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport * as React from \"react\";\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n \"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground\",\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className={cn(\"flex items-center justify-center text-current\")}\n >\n <CheckIcon className=\"h-4 w-4\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n));\nCheckbox.displayName = CheckboxPrimitive.Root.displayName;\n\nexport { Checkbox };\n","\"use client\";\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\";\n\nconst Collapsible = CollapsiblePrimitive.Root;\n\nconst CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;\n\nconst CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;\n\nexport { Collapsible, CollapsibleContent, CollapsibleTrigger };\n","\"use client\";\n\nimport { type DialogProps } from \"@radix-ui/react-dialog\";\nimport { MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport * as React from \"react\";\n\nimport { Dialog, DialogContent } from \"./dialog\";\nimport { cn } from \"../../utils/cn\";\n\nconst Command = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive\n ref={ref}\n className={cn(\n \"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground\",\n className,\n )}\n {...props}\n />\n));\nCommand.displayName = CommandPrimitive.displayName;\n\ninterface CommandDialogProps extends DialogProps {}\n\nconst CommandDialog = ({ children, ...props }: CommandDialogProps) => {\n return (\n <Dialog {...props}>\n <DialogContent className=\"overflow-hidden p-0\">\n <Command className=\"[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5\">\n {children}\n </Command>\n </DialogContent>\n </Dialog>\n );\n};\n\nconst CommandInput = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Input>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>\n>(({ className, ...props }, ref) => (\n <div className=\"flex items-center border-b px-3\" cmdk-input-wrapper=\"\">\n <MagnifyingGlassIcon className=\"mr-2 h-4 w-4 shrink-0 opacity-50\" />\n <CommandPrimitive.Input\n ref={ref}\n className={cn(\n \"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n </div>\n));\n\nCommandInput.displayName = CommandPrimitive.Input.displayName;\n\nconst CommandList = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.List\n ref={ref}\n className={cn(\"max-h-[300px] overflow-y-auto overflow-x-hidden\", className)}\n {...props}\n />\n));\n\nCommandList.displayName = CommandPrimitive.List.displayName;\n\nconst CommandEmpty = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Empty>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>\n>((props, ref) => (\n <CommandPrimitive.Empty\n ref={ref}\n className=\"py-6 text-center text-sm\"\n {...props}\n />\n));\n\nCommandEmpty.displayName = CommandPrimitive.Empty.displayName;\n\nconst CommandGroup = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Group\n ref={ref}\n className={cn(\n \"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground\",\n className,\n )}\n {...props}\n />\n));\n\nCommandGroup.displayName = CommandPrimitive.Group.displayName;\n\nconst CommandSeparator = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 h-px bg-border\", className)}\n {...props}\n />\n));\nCommandSeparator.displayName = CommandPrimitive.Separator.displayName;\n\nconst CommandItem = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n className,\n )}\n {...props}\n />\n));\n\nCommandItem.displayName = CommandPrimitive.Item.displayName;\n\nconst CommandShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className,\n )}\n {...props}\n />\n );\n};\nCommandShortcut.displayName = \"CommandShortcut\";\n\nexport {\n Command,\n CommandDialog,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n CommandShortcut,\n};\n","\"use client\";\n\nimport { cn } from \"../../utils/cn\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { Cross2Icon } from \"@radix-ui/react-icons\";\nimport * as React from \"react\";\n\nconst Dialog = DialogPrimitive.Root;\n\nconst DialogTrigger = DialogPrimitive.Trigger;\n\nconst DialogPortal = DialogPrimitive.Portal;\n\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <Cross2Icon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn(\"flex flex-col space-y-1.5 text-center sm:text-left\", className)} {...props} />\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nconst DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn(\"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\", className)} {...props} />\n);\nDialogFooter.displayName = \"DialogFooter\";\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold leading-none tracking-tight\", className)}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description ref={ref} className={cn(\"text-sm text-muted-foreground\", className)} {...props} />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","\"use client\";\n\nimport { cn } from \"../../utils/cn\";\nimport * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\";\nimport { CheckIcon, ChevronRightIcon, DotFilledIcon } from \"@radix-ui/react-icons\";\nimport * as React from \"react\";\n\nconst ContextMenu = ContextMenuPrimitive.Root;\n\nconst ContextMenuTrigger = ContextMenuPrimitive.Trigger;\n\nconst ContextMenuGroup = ContextMenuPrimitive.Group;\n\nconst ContextMenuPortal = ContextMenuPrimitive.Portal;\n\nconst ContextMenuSub = ContextMenuPrimitive.Sub;\n\nconst ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;\n\nconst ContextMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <ContextMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto h-4 w-4\" />\n </ContextMenuPrimitive.SubTrigger>\n));\nContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;\n\nconst ContextMenuSubContent = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n));\nContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;\n\nconst ContextMenuContent = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Content\n ref={ref}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n));\nContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;\n\nconst ContextMenuItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <ContextMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;\n\nconst ContextMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <ContextMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"h-4 w-4\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n));\nContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;\n\nconst ContextMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <ContextMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <DotFilledIcon className=\"h-4 w-4 fill-current\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n));\nContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;\n\nconst ContextMenuLabel = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <ContextMenuPrimitive.Label\n ref={ref}\n className={cn(\"px-2 py-1.5 text-sm font-semibold text-foreground\", inset && \"pl-8\", className)}\n {...props}\n />\n));\nContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;\n\nconst ContextMenuSeparator = React.forwardRef<\n React.ElementRef<typeof ContextMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.Separator ref={ref} className={cn(\"-mx-1 my-1 h-px bg-border\", className)} {...props} />\n));\nContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;\n\nconst ContextMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {\n return <span className={cn(\"ml-auto text-xs tracking-widest text-muted-foreground\", className)} {...props} />;\n};\nContextMenuShortcut.displayName = \"ContextMenuShortcut\";\n\nexport {\n ContextMenu,\n ContextMenuCheckboxItem,\n ContextMenuContent,\n ContextMenuGroup,\n ContextMenuItem,\n ContextMenuLabel,\n ContextMenuPortal,\n ContextMenuRadioGroup,\n ContextMenuRadioItem,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuTrigger,\n};\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Drawer as DrawerPrimitive } from \"vaul\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Drawer = ({ shouldScaleBackground = true, ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>) => (\n <DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} />\n);\nDrawer.displayName = \"Drawer\";\n\nconst DrawerTrigger = DrawerPrimitive.Trigger;\n\nconst DrawerPortal = DrawerPrimitive.Portal;\n\nconst DrawerClose = DrawerPrimitive.Close;\n\nconst DrawerOverlay = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DrawerPrimitive.Overlay ref={ref} className={cn(\"fixed inset-0 z-50 bg-black/80\", className)} {...props} />\n));\nDrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;\n\nconst DrawerContent = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DrawerPortal>\n <DrawerOverlay />\n <DrawerPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background\",\n className,\n )}\n {...props}\n >\n <div className=\"mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n));\nDrawerContent.displayName = \"DrawerContent\";\n\nconst DrawerHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn(\"grid gap-1.5 p-4 text-center sm:text-left\", className)} {...props} />\n);\nDrawerHeader.displayName = \"DrawerHeader\";\n\nconst DrawerFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)} {...props} />\n);\nDrawerFooter.displayName = \"DrawerFooter\";\n\nconst DrawerTitle = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DrawerPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold leading-none tracking-tight\", className)}\n {...props}\n />\n));\nDrawerTitle.displayName = DrawerPrimitive.Title.displayName;\n\nconst DrawerDescription = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DrawerPrimitive.Description ref={ref} className={cn(\"text-sm text-muted-foreground\", className)} {...props} />\n));\nDrawerDescription.displayName = DrawerPrimitive.Description.displayName;\n\nexport {\n Drawer,\n DrawerClose,\n DrawerContent,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerOverlay,\n DrawerPortal,\n DrawerTitle,\n DrawerTrigger,\n};\n","\"use client\";\n\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport {\n CheckIcon,\n ChevronRightIcon,\n DotFilledIcon,\n} from \"@radix-ui/react-icons\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group;\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal;\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub;\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto h-4 w-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n));\nDropdownMenuSubTrigger.displayName =\n DropdownMenuPrimitive.SubTrigger.displayName;\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuSubContent.displayName =\n DropdownMenuPrimitive.SubContent.displayName;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md\",\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"h-4 w-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName =\n DropdownMenuPrimitive.CheckboxItem.displayName;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <DotFilledIcon className=\"h-4 w-4 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\n \"px-2 py-1.5 text-sm font-semibold\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nconst DropdownMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\"ml-auto text-xs tracking-widest opacity-60\", className)}\n {...props}\n />\n );\n};\nDropdownMenuShortcut.displayName = \"DropdownMenuShortcut\";\n\nexport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n};\n","\"use client\";\n\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { Controller, ControllerProps, FieldPath, FieldValues, FormProvider, useFormContext } from \"react-hook-form\";\n\nimport { Label } from \"./label\";\nimport { cn } from \"../../utils/cn\";\n\nconst Form = FormProvider;\n\ntype FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n name: TName;\n};\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n ...props\n}: ControllerProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\nconst useFormField = () => {\n const fieldContext = React.useContext(FormFieldContext);\n const itemContext = React.useContext(FormItemContext);\n const { getFieldState, formState } = useFormContext();\n\n const fieldState = getFieldState(fieldContext.name, formState);\n\n if (!fieldContext) {\n throw new Error(\"useFormField should be used within <FormField>\");\n }\n\n const { id } = itemContext;\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n };\n};\n\ntype FormItemContextValue = {\n id: string;\n};\n\nconst FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);\n\nconst FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const id = React.useId();\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <div ref={ref} className={cn(\"space-y-2\", className)} {...props} />\n </FormItemContext.Provider>\n );\n },\n);\nFormItem.displayName = \"FormItem\";\n\nconst FormLabel = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>\n>(({ className, ...props }, ref) => {\n const { error, formItemId } = useFormField();\n\n return <Label ref={ref} className={cn(error && \"text-destructive\", className)} htmlFor={formItemId} {...props} />;\n});\nFormLabel.displayName = \"FormLabel\";\n\nconst FormControl = React.forwardRef<React.ElementRef<typeof Slot>, React.ComponentPropsWithoutRef<typeof Slot>>(\n ({ ...props }, ref) => {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n return (\n <Slot\n ref={ref}\n id={formItemId}\n aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n aria-invalid={!!error}\n {...props}\n />\n );\n },\n);\nFormControl.displayName = \"FormControl\";\n\nconst FormDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(\n ({ className, ...props }, ref) => {\n const { formDescriptionId } = useFormField();\n\n return (\n <p ref={ref} id={formDescriptionId} className={cn(\"text-muted-foreground text-[0.8rem]\", className)} {...props} />\n );\n },\n);\nFormDescription.displayName = \"FormDescription\";\n\nconst FormMessage = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(\n ({ className, children, ...props }, ref) => {\n const { error, formMessageId } = useFormField();\n const body = error ? String(error?.message) : children;\n\n if (!body) {\n return null;\n }\n\n return (\n <p\n ref={ref}\n id={formMessageId}\n className={cn(\"text-destructive text-[0.8rem] font-medium\", className)}\n {...props}\n >\n {body}\n </p>\n );\n },\n);\nFormMessage.displayName = \"FormMessage\";\n\nexport { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };\n","\"use client\";\n\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst labelVariants = cva(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(labelVariants(), className)}\n {...props}\n />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","\"use client\";\n\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst HoverCard = HoverCardPrimitive.Root;\n\nconst HoverCardTrigger = HoverCardPrimitive.Trigger;\n\nconst HoverCardContent = React.forwardRef<\n React.ElementRef<typeof HoverCardPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n <HoverCardPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n));\nHoverCardContent.displayName = HoverCardPrimitive.Content.displayName;\n\nexport { HoverCard, HoverCardContent, HoverCardTrigger };\n","import * as React from \"react\"\n\nimport { cn } from \"../../utils/cn\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n","import * as React from \"react\"\nimport * as NavigationMenuPrimitive from \"@radix-ui/react-navigation-menu\"\nimport { cva } from \"class-variance-authority\"\nimport { ChevronDownIcon } from \"lucide-react\"\n\nimport { cn } from \"../../utils/cn\"\n\nfunction NavigationMenu({\n className,\n children,\n viewport = true,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {\n viewport?: boolean\n}) {\n return (\n <NavigationMenuPrimitive.Root\n data-slot=\"navigation-menu\"\n data-viewport={viewport}\n className={cn(\n \"group/navigation-menu relative flex max-w-max flex-1 items-center justify-center\",\n className\n )}\n {...props}\n >\n {children}\n {viewport && <NavigationMenuViewport />}\n </NavigationMenuPrimitive.Root>\n )\n}\n\nfunction NavigationMenuList({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {\n return (\n <NavigationMenuPrimitive.List\n data-slot=\"navigation-menu-list\"\n className={cn(\n \"group flex flex-1 list-none items-center justify-center gap-1\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction NavigationMenuItem({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {\n return (\n <NavigationMenuPrimitive.Item\n data-slot=\"navigation-menu-item\"\n className={cn(\"relative\", className)}\n {...props}\n />\n )\n}\n\nconst navigationMenuTriggerStyle = cva(\n \"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1\"\n)\n\nfunction NavigationMenuTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {\n return (\n <NavigationMenuPrimitive.Trigger\n data-slot=\"navigation-menu-trigger\"\n className={cn(navigationMenuTriggerStyle(), \"group\", className)}\n {...props}\n >\n {children}{\" \"}\n <ChevronDownIcon\n className=\"relative top-[1px] ml-1 size-3 transition duration-300 group-data-[state=open]:rotate-180\"\n aria-hidden=\"true\"\n />\n </NavigationMenuPrimitive.Trigger>\n )\n}\n\nfunction NavigationMenuContent({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {\n return (\n <NavigationMenuPrimitive.Content\n data-slot=\"navigation-menu-content\"\n className={cn(\n \"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 top-0 left-0 w-full p-2 pr-2.5 md:absolute md:w-auto\",\n \"group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:border group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:duration-200 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction NavigationMenuViewport({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {\n return (\n <div\n className={cn(\n \"absolute top-full left-0 isolate z-50 flex justify-center\"\n )}\n >\n <NavigationMenuPrimitive.Viewport\n data-slot=\"navigation-menu-viewport\"\n className={cn(\n \"origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border shadow md:w-[var(--radix-navigation-menu-viewport-width)]\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction NavigationMenuLink({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {\n return (\n <NavigationMenuPrimitive.Link\n data-slot=\"navigation-menu-link\"\n className={cn(\n \"data-[active=true]:focus:bg-accent data-[active=true]:hover:bg-accent data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:ring-ring/50 [&_svg:not([class*='text-'])]:text-muted-foreground flex flex-col gap-1 rounded-sm p-2 text-sm transition-all outline-none focus-visible:ring-[3px] focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction NavigationMenuIndicator({\n className,\n ...props\n}: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {\n return (\n <NavigationMenuPrimitive.Indicator\n data-slot=\"navigation-menu-indicator\"\n className={cn(\n \"data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden\",\n className\n )}\n {...props}\n >\n <div className=\"bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md\" />\n </NavigationMenuPrimitive.Indicator>\n )\n}\n\nexport {\n NavigationMenu,\n NavigationMenuList,\n NavigationMenuItem,\n NavigationMenuContent,\n NavigationMenuTrigger,\n NavigationMenuLink,\n NavigationMenuIndicator,\n NavigationMenuViewport,\n navigationMenuTriggerStyle,\n}\n","\"use client\";\n\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };\n","\"use client\";\n\nimport * as ProgressPrimitive from \"@radix-ui/react-progress\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Progress = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n <ProgressPrimitive.Root\n ref={ref}\n className={cn(\"relative h-2 w-full overflow-hidden rounded-full bg-primary/20\", className)}\n {...props}\n >\n <ProgressPrimitive.Indicator\n className=\"h-full w-full flex-1 bg-primary transition-all\"\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n));\nProgress.displayName = ProgressPrimitive.Root.displayName;\n\nexport { Progress };\n","\"use client\";\n\nimport { cn } from \"../../utils/cn\";\nimport { DotFilledIcon } from \"@radix-ui/react-icons\";\nimport * as RadioGroupPrimitive from \"@radix-ui/react-radio-group\";\nimport * as React from \"react\";\n\nconst RadioGroup = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>\n>(({ className, ...props }, ref) => {\n return <RadioGroupPrimitive.Root className={cn(\"grid gap-2\", className)} {...props} ref={ref} />;\n});\nRadioGroup.displayName = RadioGroupPrimitive.Root.displayName;\n\nconst RadioGroupItem = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>\n>(({ className, ...props }, ref) => {\n return (\n <RadioGroupPrimitive.Item\n ref={ref}\n className={cn(\n \"aspect-square h-4 w-4 rounded-full border border-primary text-primary shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator className=\"flex items-center justify-center\">\n <DotFilledIcon className=\"h-3.5 w-3.5 fill-primary\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n );\n});\nRadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;\n\nexport { RadioGroup, RadioGroupItem };\n","\"use client\";\n\nimport { GripVerticalIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport * as ResizablePrimitive from \"react-resizable-panels\";\nimport { cn } from \"../../utils\";\n\nfunction ResizablePanelGroup({ className, ...props }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) {\n return (\n <ResizablePrimitive.PanelGroup\n data-slot=\"resizable-panel-group\"\n className={cn(\"flex h-full w-full data-[panel-group-direction=vertical]:flex-col\", className)}\n {...props}\n />\n );\n}\n\nfunction ResizablePanel({ ...props }: React.ComponentProps<typeof ResizablePrimitive.Panel>) {\n return <ResizablePrimitive.Panel data-slot=\"resizable-panel\" {...props} />;\n}\n\nfunction ResizableHandle({\n withHandle,\n className,\n ...props\n}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {\n withHandle?: boolean;\n}) {\n return (\n <ResizablePrimitive.PanelResizeHandle\n data-slot=\"resizable-handle\"\n className={cn(\n \"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90\",\n className,\n )}\n {...props}\n >\n {withHandle && (\n <div className=\"bg-border z-10 flex h-4 w-3 items-center justify-center rounded-xs border\">\n <GripVerticalIcon className=\"size-2.5\" />\n </div>\n )}\n </ResizablePrimitive.PanelResizeHandle>\n );\n}\n\nexport { ResizableHandle, ResizablePanel, ResizablePanelGroup };\n","\"use client\";\n\nimport * as ScrollAreaPrimitive from \"@radix-ui/react-scroll-area\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst ScrollArea = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>\n>(({ className, children, ...props }, ref) => (\n <ScrollAreaPrimitive.Root ref={ref} className={cn(\"relative overflow-hidden\", className)} {...props}>\n <ScrollAreaPrimitive.Viewport className=\"h-full w-full rounded-[inherit]\">{children}</ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n));\nScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;\n\nconst ScrollBar = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>\n>(({ className, orientation = \"vertical\", ...props }, ref) => (\n <ScrollAreaPrimitive.ScrollAreaScrollbar\n ref={ref}\n orientation={orientation}\n className={cn(\n \"flex touch-none select-none transition-colors\",\n orientation === \"vertical\" && \"h-full w-2.5 border-l border-l-transparent p-[1px]\",\n orientation === \"horizontal\" && \"h-2.5 flex-col border-t border-t-transparent p-[1px]\",\n className,\n )}\n {...props}\n >\n <ScrollAreaPrimitive.ScrollAreaThumb className=\"relative flex-1 rounded-full bg-border\" />\n </ScrollAreaPrimitive.ScrollAreaScrollbar>\n));\nScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;\n\nexport { ScrollArea, ScrollBar };\n","\"use client\";\n\nimport {\n CaretSortIcon,\n CheckIcon,\n ChevronDownIcon,\n ChevronUpIcon,\n} from \"@radix-ui/react-icons\";\nimport * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Select = SelectPrimitive.Root;\n\nconst SelectGroup = SelectPrimitive.Group;\n\nconst SelectValue = SelectPrimitive.Value;\n\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1\",\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <CaretSortIcon className=\"h-4 w-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n));\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName;\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className,\n )}\n {...props}\n >\n <ChevronUpIcon />\n </SelectPrimitive.ScrollUpButton>\n));\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className,\n )}\n {...props}\n >\n <ChevronDownIcon />\n </SelectPrimitive.ScrollDownButton>\n));\nSelectScrollDownButton.displayName =\n SelectPrimitive.ScrollDownButton.displayName;\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = \"popper\", ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n className={cn(\n \"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n position === \"popper\" &&\n \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n className,\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n \"p-1\",\n position === \"popper\" &&\n \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]\",\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\nSelectContent.displayName = SelectPrimitive.Content.displayName;\n\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\"px-2 py-1.5 text-sm font-semibold\", className)}\n {...props}\n />\n));\nSelectLabel.displayName = SelectPrimitive.Label.displayName;\n\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n));\nSelectItem.displayName = SelectPrimitive.Item.displayName;\n\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n {...props}\n />\n));\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName;\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as SeparatorPrimitive from \"@radix-ui/react-separator\"\n\nimport { cn } from \"../../utils/cn\"\n\nfunction Separator({\n className,\n orientation = \"horizontal\",\n decorative = true,\n ...props\n}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {\n return (\n <SeparatorPrimitive.Root\n data-slot=\"separator\"\n decorative={decorative}\n orientation={orientation}\n className={cn(\n \"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Separator }\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"../../utils/cn\"\n\nfunction Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />\n}\n\nfunction SheetTrigger({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Close>) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetPortal({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Portal>) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />\n}\n\nfunction SheetOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {\n return (\n <SheetPrimitive.Overlay\n data-slot=\"sheet-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Content> & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Content\n data-slot=\"sheet-content\"\n className={cn(\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500\",\n side === \"right\" &&\n \"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm\",\n side === \"left\" &&\n \"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm\",\n side === \"top\" &&\n \"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b\",\n side === \"bottom\" &&\n \"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t\",\n className\n )}\n {...props}\n >\n {children}\n <SheetPrimitive.Close className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none\">\n <XIcon className=\"size-4\" />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n </SheetPrimitive.Content>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"flex flex-col gap-1.5 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Title>) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Description>) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n","\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, VariantProps } from \"class-variance-authority\";\nimport { PanelLeftIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\nimport { Input } from \"./input\";\nimport { Separator } from \"./separator\";\nimport { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from \"./sheet\";\nimport { Skeleton } from \"./skeleton\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"./tooltip\";\nimport { useIsMobile } from \"../../utils/use-mobile\";\nimport { cn } from \"../../utils/cn\";\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\";\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;\nexport const SIDEBAR_WIDTH = \"16rem\";\nexport const SIDEBAR_WIDTH_MOBILE = \"18rem\";\nexport const SIDEBAR_WIDTH_ICON = \"3rem\";\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"\";\n\ntype SidebarContextProps = {\n state: \"expanded\" | \"collapsed\";\n open: boolean;\n setOpen: (open: boolean) => void;\n openMobile: boolean;\n setOpenMobile: (open: boolean) => void;\n isMobile: boolean;\n toggleSidebar: () => void;\n};\n\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null);\n\nfunction useSidebar() {\n const context = React.useContext(SidebarContext);\n if (!context) {\n throw new Error(\"useSidebar must be used within a SidebarProvider.\");\n }\n\n return context;\n}\n\nfunction SidebarProvider({\n defaultOpen = true,\n open: openProp,\n onOpenChange: setOpenProp,\n className,\n style,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n defaultOpen?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}) {\n const isMobile = useIsMobile();\n const [openMobile, setOpenMobile] = React.useState(false);\n\n // This is the internal state of the sidebar.\n // We use openProp and setOpenProp for control from outside the component.\n const [_open, _setOpen] = React.useState(defaultOpen);\n const open = openProp ?? _open;\n const setOpen = React.useCallback(\n (value: boolean | ((value: boolean) => boolean)) => {\n const openState = typeof value === \"function\" ? value(open) : value;\n if (setOpenProp) {\n setOpenProp(openState);\n } else {\n _setOpen(openState);\n }\n\n // This sets the cookie to keep the sidebar state.\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;\n },\n [setOpenProp, open],\n );\n\n // Helper to toggle the sidebar.\n const toggleSidebar = React.useCallback(() => {\n return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open);\n }, [isMobile, setOpen, setOpenMobile]);\n\n // Adds a keyboard shortcut to toggle the sidebar.\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {\n event.preventDefault();\n toggleSidebar();\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [toggleSidebar]);\n\n // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\n // This makes it easier to style the sidebar with Tailwind classes.\n const state = open ? \"expanded\" : \"collapsed\";\n\n const contextValue = React.useMemo<SidebarContextProps>(\n () => ({\n state,\n open,\n setOpen,\n isMobile,\n openMobile,\n setOpenMobile,\n toggleSidebar,\n }),\n [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar],\n );\n\n return (\n <SidebarContext.Provider value={contextValue}>\n <TooltipProvider delayDuration={0}>\n <div\n data-slot=\"sidebar-wrapper\"\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH,\n \"--sidebar-width-icon\": SIDEBAR_WIDTH_ICON,\n ...style,\n } as React.CSSProperties\n }\n className={cn(\"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full\", className)}\n {...props}\n >\n {children}\n </div>\n </TooltipProvider>\n </SidebarContext.Provider>\n );\n}\n\nfunction Sidebar({\n side = \"left\",\n variant = \"sidebar\",\n collapsible = \"offcanvas\",\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n side?: \"left\" | \"right\";\n variant?: \"sidebar\" | \"floating\" | \"inset\";\n collapsible?: \"offcanvas\" | \"icon\" | \"none\";\n}) {\n const { isMobile, state, openMobile, setOpenMobile } = useSidebar();\n\n if (collapsible === \"none\") {\n return (\n <div\n data-slot=\"sidebar\"\n className={cn(\"bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col\", className)}\n {...props}\n >\n {children}\n </div>\n );\n }\n\n if (isMobile) {\n return (\n <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>\n <SheetContent\n data-sidebar=\"sidebar\"\n data-slot=\"sidebar\"\n data-mobile=\"true\"\n className=\"bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden\"\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH_MOBILE,\n } as React.CSSProperties\n }\n side={side}\n >\n <SheetHeader className=\"sr-only\">\n <SheetTitle>Sidebar</SheetTitle>\n <SheetDescription>Displays the mobile sidebar.</SheetDescription>\n </SheetHeader>\n <div className=\"flex h-full w-full flex-col\">{children}</div>\n </SheetContent>\n </Sheet>\n );\n }\n\n return (\n <div\n className=\"group peer text-sidebar-foreground hidden md:block\"\n data-state={state}\n data-collapsible={state === \"collapsed\" ? collapsible : \"\"}\n data-variant={variant}\n data-side={side}\n data-slot=\"sidebar\"\n >\n {/* This is what handles the sidebar gap on desktop */}\n <div\n data-slot=\"sidebar-gap\"\n className={cn(\n \"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear\",\n \"group-data-[collapsible=offcanvas]:w-0\",\n \"group-data-[side=right]:rotate-180\",\n variant === \"floating\" || variant === \"inset\"\n ? \"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon)\",\n )}\n />\n <div\n data-slot=\"sidebar-container\"\n className={cn(\n \"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex\",\n side === \"left\"\n ? \"left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]\"\n : \"right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]\",\n // Adjust the padding for floating and inset variants.\n variant === \"floating\" || variant === \"inset\"\n ? \"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l\",\n className,\n )}\n {...props}\n >\n <div\n data-sidebar=\"sidebar\"\n data-slot=\"sidebar-inner\"\n className=\"bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm\"\n >\n {children}\n </div>\n </div>\n </div>\n );\n}\n\nfunction SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<typeof Button>) {\n const { toggleSidebar } = useSidebar();\n\n return (\n <Button\n data-sidebar=\"trigger\"\n data-slot=\"sidebar-trigger\"\n variant=\"ghost\"\n size=\"icon\"\n className={cn(\"size-7\", className)}\n onClick={(event) => {\n onClick?.(event);\n toggleSidebar();\n }}\n {...props}\n >\n <PanelLeftIcon />\n <span className=\"sr-only\">Toggle Sidebar</span>\n </Button>\n );\n}\n\nfunction SidebarRail({ className, ...props }: React.ComponentProps<\"button\">) {\n const { toggleSidebar } = useSidebar();\n\n return (\n <button\n data-sidebar=\"rail\"\n data-slot=\"sidebar-rail\"\n aria-label=\"Toggle Sidebar\"\n tabIndex={-1}\n onClick={toggleSidebar}\n title=\"Toggle Sidebar\"\n className={cn(\n \"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex\",\n \"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize\",\n \"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize\",\n \"hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full\",\n \"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2\",\n \"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarInset({ className, ...props }: React.ComponentProps<\"main\">) {\n return (\n <main\n data-slot=\"sidebar-inset\"\n className={cn(\n \"bg-background relative flex w-full flex-1 flex-col\",\n \"md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarInput({ className, ...props }: React.ComponentProps<typeof Input>) {\n return (\n <Input\n data-slot=\"sidebar-input\"\n data-sidebar=\"input\"\n className={cn(\"bg-background h-8 w-full shadow-none\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-header\"\n data-sidebar=\"header\"\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-footer\"\n data-sidebar=\"footer\"\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarSeparator({ className, ...props }: React.ComponentProps<typeof Separator>) {\n return (\n <Separator\n data-slot=\"sidebar-separator\"\n data-sidebar=\"separator\"\n className={cn(\"bg-sidebar-border mx-2 w-auto\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-content\"\n data-sidebar=\"content\"\n className={cn(\n \"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-group\"\n data-sidebar=\"group\"\n className={cn(\"relative flex w-full min-w-0 flex-col p-2\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarGroupLabel({\n className,\n asChild = false,\n ...props\n}: React.ComponentProps<\"div\"> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"div\";\n\n return (\n <Comp\n data-slot=\"sidebar-group-label\"\n data-sidebar=\"group-label\"\n className={cn(\n \"text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0\",\n \"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarGroupAction({\n className,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp\n data-slot=\"sidebar-group-action\"\n data-sidebar=\"group-action\"\n className={cn(\n \"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0\",\n // Increases the hit area of the button on mobile.\n \"after:absolute after:-inset-2 md:after:hidden\",\n \"group-data-[collapsible=icon]:hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarGroupContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-group-content\"\n data-sidebar=\"group-content\"\n className={cn(\"w-full text-sm\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarMenu({ className, ...props }: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"sidebar-menu\"\n data-sidebar=\"menu\"\n className={cn(\"flex w-full min-w-0 flex-col gap-1\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarMenuItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"sidebar-menu-item\"\n data-sidebar=\"menu-item\"\n className={cn(\"group/menu-item relative\", className)}\n {...props}\n />\n );\n}\n\nconst sidebarMenuButtonVariants = cva(\n \"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n outline:\n \"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]\",\n },\n size: {\n default: \"h-8 text-sm\",\n sm: \"h-7 text-xs\",\n lg: \"h-12 text-sm group-data-[collapsible=icon]:p-0!\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction SidebarMenuButton({\n asChild = false,\n isActive = false,\n variant = \"default\",\n size = \"default\",\n tooltip,\n className,\n ...props\n}: React.ComponentProps<\"button\"> & {\n asChild?: boolean;\n isActive?: boolean;\n tooltip?: string | React.ComponentProps<typeof TooltipContent>;\n} & VariantProps<typeof sidebarMenuButtonVariants>) {\n const Comp = asChild ? Slot : \"button\";\n const { isMobile, state } = useSidebar();\n\n const button = (\n <Comp\n data-slot=\"sidebar-menu-button\"\n data-sidebar=\"menu-button\"\n data-size={size}\n data-active={isActive}\n className={cn(sidebarMenuButtonVariants({ variant, size }), className)}\n {...props}\n />\n );\n\n if (!tooltip) {\n return button;\n }\n\n if (typeof tooltip === \"string\") {\n tooltip = {\n children: tooltip,\n };\n }\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent side=\"right\" align=\"center\" hidden={state !== \"collapsed\" || isMobile} {...tooltip} />\n </Tooltip>\n );\n}\n\nfunction SidebarMenuAction({\n className,\n asChild = false,\n showOnHover = false,\n ...props\n}: React.ComponentProps<\"button\"> & {\n asChild?: boolean;\n showOnHover?: boolean;\n}) {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp\n data-slot=\"sidebar-menu-action\"\n data-sidebar=\"menu-action\"\n className={cn(\n \"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0\",\n // Increases the hit area of the button on mobile.\n \"after:absolute after:-inset-2 md:after:hidden\",\n \"peer-data-[size=sm]/menu-button:top-1\",\n \"peer-data-[size=default]/menu-button:top-1.5\",\n \"peer-data-[size=lg]/menu-button:top-2.5\",\n \"group-data-[collapsible=icon]:hidden\",\n showOnHover &&\n \"peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarMenuBadge({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-menu-badge\"\n data-sidebar=\"menu-badge\"\n className={cn(\n \"text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none\",\n \"peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground\",\n \"peer-data-[size=sm]/menu-button:top-1\",\n \"peer-data-[size=default]/menu-button:top-1.5\",\n \"peer-data-[size=lg]/menu-button:top-2.5\",\n \"group-data-[collapsible=icon]:hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarMenuSkeleton({\n className,\n showIcon = false,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showIcon?: boolean;\n}) {\n // Random width between 50 to 90%.\n const width = React.useMemo(() => {\n return `${Math.floor(Math.random() * 40) + 50}%`;\n }, []);\n\n return (\n <div\n data-slot=\"sidebar-menu-skeleton\"\n data-sidebar=\"menu-skeleton\"\n className={cn(\"flex h-8 items-center gap-2 rounded-md px-2\", className)}\n {...props}\n >\n {showIcon && <Skeleton className=\"size-4 rounded-md\" data-sidebar=\"menu-skeleton-icon\" />}\n <Skeleton\n className=\"h-4 max-w-(--skeleton-width) flex-1\"\n data-sidebar=\"menu-skeleton-text\"\n style={\n {\n \"--skeleton-width\": width,\n } as React.CSSProperties\n }\n />\n </div>\n );\n}\n\nfunction SidebarMenuSub({ className, ...props }: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"sidebar-menu-sub\"\n data-sidebar=\"menu-sub\"\n className={cn(\n \"border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5\",\n \"group-data-[collapsible=icon]:hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SidebarMenuSubItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"sidebar-menu-sub-item\"\n data-sidebar=\"menu-sub-item\"\n className={cn(\"group/menu-sub-item relative\", className)}\n {...props}\n />\n );\n}\n\nfunction SidebarMenuSubButton({\n asChild = false,\n size = \"md\",\n isActive = false,\n className,\n ...props\n}: React.ComponentProps<\"a\"> & {\n asChild?: boolean;\n size?: \"sm\" | \"md\";\n isActive?: boolean;\n}) {\n const Comp = asChild ? Slot : \"a\";\n\n return (\n <Comp\n data-slot=\"sidebar-menu-sub-button\"\n data-sidebar=\"menu-sub-button\"\n data-size={size}\n data-active={isActive}\n className={cn(\n \"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0\",\n \"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground\",\n size === \"sm\" && \"text-xs\",\n size === \"md\" && \"text-sm\",\n \"group-data-[collapsible=icon]:hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n Sidebar,\n SidebarContent,\n SidebarFooter,\n SidebarGroup,\n SidebarGroupAction,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarHeader,\n SidebarInput,\n SidebarInset,\n SidebarMenu,\n SidebarMenuAction,\n SidebarMenuBadge,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarMenuSkeleton,\n SidebarMenuSub,\n SidebarMenuSubButton,\n SidebarMenuSubItem,\n SidebarProvider,\n SidebarRail,\n SidebarSeparator,\n SidebarTrigger,\n useSidebar,\n};\n","import { cn } from \"../../utils/cn\"\n\nfunction Skeleton({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"skeleton\"\n className={cn(\"bg-accent animate-pulse rounded-md\", className)}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\"\n\nimport { cn } from \"../../utils/cn\"\n\nfunction TooltipProvider({\n delayDuration = 0,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delayDuration={delayDuration}\n {...props}\n />\n )\n}\n\nfunction Tooltip({\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Root>) {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n )\n}\n\nfunction TooltipTrigger({\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />\n}\n\nfunction TooltipContent({\n className,\n sideOffset = 0,\n children,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Content>) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n \"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance\",\n className\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]\" />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n )\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n","\"use client\";\n\nimport * as SliderPrimitive from \"@radix-ui/react-slider\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Slider = React.forwardRef<\n React.ElementRef<typeof SliderPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <SliderPrimitive.Root\n ref={ref}\n className={cn(\"relative flex w-full touch-none select-none items-center\", className)}\n {...props}\n >\n <SliderPrimitive.Track className=\"relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20\">\n <SliderPrimitive.Range className=\"absolute h-full bg-primary\" />\n </SliderPrimitive.Track>\n <SliderPrimitive.Thumb className=\"block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50\" />\n </SliderPrimitive.Root>\n));\nSlider.displayName = SliderPrimitive.Root.displayName;\n\nexport { Slider };\n","\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, ToasterProps } from \"sonner\"\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n style={\n {\n \"--normal-bg\": \"var(--popover)\",\n \"--normal-text\": \"var(--popover-foreground)\",\n \"--normal-border\": \"var(--border)\",\n } as React.CSSProperties\n }\n {...props}\n />\n )\n}\n\nexport { Toaster }\n","\"use client\";\n\nimport * as SwitchPrimitives from \"@radix-ui/react-switch\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitives.Root>,\n React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>\n>(({ className, children, ...props }, ref) => (\n <SwitchPrimitives.Root\n className={cn(\n \"bg-accent focus-visible:ring-ring focus-visible:ring-offset-background data-[state=checked]:bg-primary data-[state=unchecked]:bg-accent peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n ref={ref}\n >\n <SwitchPrimitives.Thumb\n className={cn(\n \"text-title pointer-events-none block flex h-5 w-5 items-center justify-center rounded-full bg-white shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0\",\n )}\n >\n {children}\n </SwitchPrimitives.Thumb>\n </SwitchPrimitives.Root>\n));\nSwitch.displayName = SwitchPrimitives.Root.displayName;\n\nexport { Switch };\n","import * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement>\n>(({ className, ...props }, ref) => (\n <div className=\"relative w-full overflow-auto\">\n <table\n ref={ref}\n className={cn(\"w-full caption-bottom text-sm\", className)}\n {...props}\n />\n </div>\n));\nTable.displayName = \"Table\";\n\nconst TableHeader = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <thead ref={ref} className={cn(\"[&_tr]:border-b\", className)} {...props} />\n));\nTableHeader.displayName = \"TableHeader\";\n\nconst TableBody = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tbody\n ref={ref}\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n));\nTableBody.displayName = \"TableBody\";\n\nconst TableFooter = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n className,\n )}\n {...props}\n />\n));\nTableFooter.displayName = \"TableFooter\";\n\nconst TableRow = React.forwardRef<\n HTMLTableRowElement,\n React.HTMLAttributes<HTMLTableRowElement>\n>(({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\n \"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted\",\n className,\n )}\n {...props}\n />\n));\nTableRow.displayName = \"TableRow\";\n\nconst TableHead = React.forwardRef<\n HTMLTableCellElement,\n React.ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n \"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]\",\n className,\n )}\n {...props}\n />\n));\nTableHead.displayName = \"TableHead\";\n\nconst TableCell = React.forwardRef<\n HTMLTableCellElement,\n React.TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <td\n ref={ref}\n className={cn(\n \"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]\",\n className,\n )}\n {...props}\n />\n));\nTableCell.displayName = \"TableCell\";\n\nconst TableCaption = React.forwardRef<\n HTMLTableCaptionElement,\n React.HTMLAttributes<HTMLTableCaptionElement>\n>(({ className, ...props }, ref) => (\n <caption\n ref={ref}\n className={cn(\"mt-4 text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nTableCaption.displayName = \"TableCaption\";\n\nexport {\n Table,\n TableBody,\n TableCaption,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n};\n","\"use client\";\n\nimport * as TabsPrimitive from \"@radix-ui/react-tabs\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst Tabs = TabsPrimitive.Root;\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.List\n ref={ref}\n className={cn(\n \"inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground\",\n className,\n )}\n {...props}\n />\n));\nTabsList.displayName = TabsPrimitive.List.displayName;\n\nconst TabsTrigger = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\n \"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow\",\n className,\n )}\n {...props}\n />\n));\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName;\n\nconst TabsContent = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n \"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n className,\n )}\n {...props}\n />\n));\nTabsContent.displayName = TabsPrimitive.Content.displayName;\n\nexport { Tabs, TabsContent, TabsList, TabsTrigger };\n","import * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n \"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n },\n);\nTextarea.displayName = \"Textarea\";\n\nexport { Textarea };\n","\"use client\";\n\nimport * as TogglePrimitive from \"@radix-ui/react-toggle\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nconst toggleVariants = cva(\n \"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n outline: \"border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground\",\n },\n size: {\n default: \"h-9 px-2 min-w-9\",\n sm: \"h-8 px-1.5 min-w-8\",\n lg: \"h-10 px-2.5 min-w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nconst Toggle = React.forwardRef<\n React.ElementRef<typeof TogglePrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>\n>(({ className, variant, size, ...props }, ref) => (\n <TogglePrimitive.Root ref={ref} className={cn(toggleVariants({ variant, size, className }))} {...props} />\n));\n\nToggle.displayName = TogglePrimitive.Root.displayName;\n\nexport { Toggle, toggleVariants };\n","\"use client\";\n\nimport {\n type Announcements,\n type CollisionDetection,\n DndContext,\n type DndContextProps,\n type DragCancelEvent,\n type DragEndEvent,\n type DragOverEvent,\n DragOverlay,\n type DragStartEvent,\n type DraggableAttributes,\n type DraggableSyntheticListeners,\n type DropAnimation,\n type DroppableContainer,\n KeyboardCode,\n type KeyboardCoordinateGetter,\n KeyboardSensor,\n MeasuringStrategy,\n MouseSensor,\n TouchSensor,\n type UniqueIdentifier,\n closestCenter,\n closestCorners,\n defaultDropAnimationSideEffects,\n getFirstCollision,\n pointerWithin,\n rectIntersection,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport {\n type AnimateLayoutChanges,\n SortableContext,\n type SortableContextProps,\n arrayMove,\n defaultAnimateLayoutChanges,\n horizontalListSortingStrategy,\n useSortable,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport * as ReactDOM from \"react-dom\";\n\nimport { useComposedRefs } from \"../../utils/compose-refs\";\nimport { cn } from \"../../utils/cn\";\n\nconst directions: string[] = [KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left];\n\nconst coordinateGetter: KeyboardCoordinateGetter = (event, { context }) => {\n const { active, droppableRects, droppableContainers, collisionRect } = context;\n\n if (directions.includes(event.code)) {\n event.preventDefault();\n\n if (!active || !collisionRect) return;\n\n const filteredContainers: DroppableContainer[] = [];\n\n for (const entry of droppableContainers.getEnabled()) {\n if (!entry || entry?.disabled) return;\n\n const rect = droppableRects.get(entry.id);\n\n if (!rect) return;\n\n const data = entry.data.current;\n\n if (data) {\n const { type, children } = data;\n\n if (type === \"container\" && children?.length > 0) {\n if (active.data.current?.type !== \"container\") {\n return;\n }\n }\n }\n\n switch (event.code) {\n case KeyboardCode.Down:\n if (collisionRect.top < rect.top) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Up:\n if (collisionRect.top > rect.top) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Left:\n if (collisionRect.left >= rect.left + rect.width) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Right:\n if (collisionRect.left + collisionRect.width <= rect.left) {\n filteredContainers.push(entry);\n }\n break;\n }\n }\n\n const collisions = closestCorners({\n active,\n collisionRect: collisionRect,\n droppableRects,\n droppableContainers: filteredContainers,\n pointerCoordinates: null,\n });\n const closestId = getFirstCollision(collisions, \"id\");\n\n if (closestId != null) {\n const newDroppable = droppableContainers.get(closestId);\n const newNode = newDroppable?.node.current;\n const newRect = newDroppable?.rect.current;\n\n if (newNode && newRect) {\n if (newDroppable.id === \"placeholder\") {\n return {\n x: newRect.left + (newRect.width - collisionRect.width) / 2,\n y: newRect.top + (newRect.height - collisionRect.height) / 2,\n };\n }\n\n if (newDroppable.data.current?.type === \"container\") {\n return {\n x: newRect.left + 20,\n y: newRect.top + 74,\n };\n }\n\n return {\n x: newRect.left,\n y: newRect.top,\n };\n }\n }\n }\n\n return undefined;\n};\n\nconst ROOT_NAME = \"Kanban\";\nconst BOARD_NAME = \"KanbanBoard\";\nconst COLUMN_NAME = \"KanbanColumn\";\nconst COLUMN_HANDLE_NAME = \"KanbanColumnHandle\";\nconst ITEM_NAME = \"KanbanItem\";\nconst ITEM_HANDLE_NAME = \"KanbanItemHandle\";\nconst OVERLAY_NAME = \"KanbanOverlay\";\n\ninterface KanbanContextValue<T> {\n id: string;\n items: Record<UniqueIdentifier, T[]>;\n modifiers: DndContextProps[\"modifiers\"];\n strategy: SortableContextProps[\"strategy\"];\n orientation: \"horizontal\" | \"vertical\";\n activeId: UniqueIdentifier | null;\n setActiveId: (id: UniqueIdentifier | null) => void;\n getItemValue: (item: T) => UniqueIdentifier;\n flatCursor: boolean;\n}\n\nconst KanbanContext = React.createContext<KanbanContextValue<unknown> | null>(null);\nKanbanContext.displayName = ROOT_NAME;\n\nfunction useKanbanContext(consumerName: string) {\n const context = React.useContext(KanbanContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` must be used within \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\ninterface GetItemValue<T> {\n /**\n * Callback that returns a unique identifier for each kanban item. Required for array of objects.\n * @example getItemValue={(item) => item.id}\n */\n getItemValue: (item: T) => UniqueIdentifier;\n}\n\ntype KanbanRootProps<T> = Omit<DndContextProps, \"collisionDetection\"> &\n GetItemValue<T> & {\n value: Record<UniqueIdentifier, T[]>;\n onValueChange?: (columns: Record<UniqueIdentifier, T[]>) => void;\n onMove?: (event: DragEndEvent & { activeIndex: number; overIndex: number }) => void;\n strategy?: SortableContextProps[\"strategy\"];\n orientation?: \"horizontal\" | \"vertical\";\n flatCursor?: boolean;\n } & (T extends object ? GetItemValue<T> : Partial<GetItemValue<T>>);\n\nfunction KanbanRoot<T>(props: KanbanRootProps<T>) {\n const {\n value,\n onValueChange,\n modifiers,\n strategy = verticalListSortingStrategy,\n orientation = \"horizontal\",\n onMove,\n getItemValue: getItemValueProp,\n accessibility,\n flatCursor = false,\n ...kanbanProps\n } = props;\n\n const id = React.useId();\n const [activeId, setActiveId] = React.useState<UniqueIdentifier | null>(null);\n const lastOverIdRef = React.useRef<UniqueIdentifier | null>(null);\n const hasMovedRef = React.useRef(false);\n const sensors = useSensors(\n useSensor(MouseSensor),\n useSensor(TouchSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter,\n }),\n );\n\n const getItemValue = React.useCallback(\n (item: T): UniqueIdentifier => {\n if (typeof item === \"object\" && !getItemValueProp) {\n throw new Error(\"getItemValue is required when using array of objects\");\n }\n return getItemValueProp ? getItemValueProp(item) : (item as UniqueIdentifier);\n },\n [getItemValueProp],\n );\n\n const getColumn = React.useCallback(\n (id: UniqueIdentifier) => {\n if (id in value) return id;\n\n for (const [columnId, items] of Object.entries(value)) {\n if (items.some((item) => getItemValue(item) === id)) {\n return columnId;\n }\n }\n\n return null;\n },\n [value, getItemValue],\n );\n\n const collisionDetection: CollisionDetection = React.useCallback(\n (args) => {\n if (activeId && activeId in value) {\n return closestCenter({\n ...args,\n droppableContainers: args.droppableContainers.filter((container) => container.id in value),\n });\n }\n\n const pointerIntersections = pointerWithin(args);\n const intersections = pointerIntersections.length > 0 ? pointerIntersections : rectIntersection(args);\n let overId = getFirstCollision(intersections, \"id\");\n\n if (!overId) {\n if (hasMovedRef.current) {\n lastOverIdRef.current = activeId;\n }\n return lastOverIdRef.current ? [{ id: lastOverIdRef.current }] : [];\n }\n\n if (overId in value) {\n const containerItems = value[overId];\n if (containerItems && containerItems.length > 0) {\n const closestItem = closestCenter({\n ...args,\n droppableContainers: args.droppableContainers.filter(\n (container) =>\n container.id !== overId && containerItems.some((item) => getItemValue(item) === container.id),\n ),\n });\n\n if (closestItem.length > 0) {\n overId = closestItem[0]?.id ?? overId;\n }\n }\n }\n\n lastOverIdRef.current = overId;\n return [{ id: overId }];\n },\n [activeId, value, getItemValue],\n );\n\n const onDragStart = React.useCallback(\n (event: DragStartEvent) => {\n kanbanProps.onDragStart?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n setActiveId(event.active.id);\n },\n [kanbanProps.onDragStart],\n );\n\n const onDragOver = React.useCallback(\n (event: DragOverEvent) => {\n kanbanProps.onDragOver?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n\n const { active, over } = event;\n if (!over) return;\n\n const activeColumn = getColumn(active.id);\n const overColumn = getColumn(over.id);\n\n if (!activeColumn || !overColumn) return;\n\n if (activeColumn === overColumn) {\n const items = value[activeColumn];\n if (!items) return;\n\n const activeIndex = items.findIndex((item) => getItemValue(item) === active.id);\n const overIndex = items.findIndex((item) => getItemValue(item) === over.id);\n\n if (activeIndex !== overIndex) {\n const newColumns = { ...value };\n newColumns[activeColumn] = arrayMove(items, activeIndex, overIndex);\n onValueChange?.(newColumns);\n }\n } else {\n const activeItems = value[activeColumn];\n const overItems = value[overColumn];\n\n if (!activeItems || !overItems) return;\n\n const activeIndex = activeItems.findIndex((item) => getItemValue(item) === active.id);\n\n if (activeIndex === -1) return;\n\n const activeItem = activeItems[activeIndex];\n if (!activeItem) return;\n\n const updatedItems = {\n ...value,\n [activeColumn]: activeItems.filter((item) => getItemValue(item) !== active.id),\n [overColumn]: [...overItems, activeItem],\n };\n\n onValueChange?.(updatedItems);\n hasMovedRef.current = true;\n }\n },\n [value, getColumn, getItemValue, onValueChange, kanbanProps.onDragOver],\n );\n\n const onDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n kanbanProps.onDragEnd?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n\n const { active, over } = event;\n\n if (!over) {\n setActiveId(null);\n return;\n }\n\n if (active.id in value && over.id in value) {\n const activeIndex = Object.keys(value).indexOf(active.id as string);\n const overIndex = Object.keys(value).indexOf(over.id as string);\n\n if (activeIndex !== overIndex) {\n const orderedColumns = Object.keys(value);\n const newOrder = arrayMove(orderedColumns, activeIndex, overIndex);\n\n const newColumns: Record<UniqueIdentifier, T[]> = {};\n for (const key of newOrder) {\n const items = value[key];\n if (items) {\n newColumns[key] = items;\n }\n }\n\n if (onMove) {\n onMove({ ...event, activeIndex, overIndex });\n } else {\n onValueChange?.(newColumns);\n }\n }\n } else {\n const activeColumn = getColumn(active.id);\n const overColumn = getColumn(over.id);\n\n if (!activeColumn || !overColumn) {\n setActiveId(null);\n return;\n }\n\n if (activeColumn === overColumn) {\n const items = value[activeColumn];\n if (!items) {\n setActiveId(null);\n return;\n }\n\n const activeIndex = items.findIndex((item) => getItemValue(item) === active.id);\n const overIndex = items.findIndex((item) => getItemValue(item) === over.id);\n\n if (activeIndex !== overIndex) {\n const newColumns = { ...value };\n newColumns[activeColumn] = arrayMove(items, activeIndex, overIndex);\n if (onMove) {\n onMove({\n ...event,\n activeIndex,\n overIndex,\n });\n } else {\n onValueChange?.(newColumns);\n }\n }\n }\n }\n\n setActiveId(null);\n hasMovedRef.current = false;\n },\n [value, getColumn, getItemValue, onValueChange, onMove, kanbanProps.onDragEnd],\n );\n\n const onDragCancel = React.useCallback(\n (event: DragCancelEvent) => {\n kanbanProps.onDragCancel?.(event);\n\n if (event.activatorEvent.defaultPrevented) return;\n\n setActiveId(null);\n hasMovedRef.current = false;\n },\n [kanbanProps.onDragCancel],\n );\n\n const announcements: Announcements = React.useMemo(\n () => ({\n onDragStart({ active }) {\n const isColumn = active.id in value;\n const itemType = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(active.id as string) + 1\n : (() => {\n const column = getColumn(active.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === active.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(active.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n return `Picked up ${itemType} at position ${position} of ${total}`;\n },\n onDragOver({ active, over }) {\n if (!over) return;\n\n const isColumn = active.id in value;\n const itemType = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(over.id as string) + 1\n : (() => {\n const column = getColumn(over.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === over.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(over.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n const overColumn = getColumn(over.id);\n const activeColumn = getColumn(active.id);\n\n if (isColumn) {\n return `${itemType} is now at position ${position} of ${total}`;\n }\n\n if (activeColumn !== overColumn) {\n return `${itemType} is now at position ${position} of ${total} in ${overColumn}`;\n }\n\n return `${itemType} is now at position ${position} of ${total}`;\n },\n onDragEnd({ active, over }) {\n if (!over) return;\n\n const isColumn = active.id in value;\n const itemType = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(over.id as string) + 1\n : (() => {\n const column = getColumn(over.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === over.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(over.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n const overColumn = getColumn(over.id);\n const activeColumn = getColumn(active.id);\n\n if (isColumn) {\n return `${itemType} was dropped at position ${position} of ${total}`;\n }\n\n if (activeColumn !== overColumn) {\n return `${itemType} was dropped at position ${position} of ${total} in ${overColumn}`;\n }\n\n return `${itemType} was dropped at position ${position} of ${total}`;\n },\n onDragCancel({ active }) {\n const isColumn = active.id in value;\n const itemType = isColumn ? \"column\" : \"item\";\n return `Dragging was cancelled. ${itemType} was dropped.`;\n },\n }),\n [value, getColumn, getItemValue],\n );\n\n const contextValue = React.useMemo<KanbanContextValue<T>>(\n () => ({\n id,\n items: value,\n modifiers,\n strategy,\n orientation,\n activeId,\n setActiveId,\n getItemValue,\n flatCursor,\n }),\n [id, value, activeId, modifiers, strategy, orientation, getItemValue, flatCursor],\n );\n\n return (\n <KanbanContext.Provider value={contextValue as KanbanContextValue<unknown>}>\n <DndContext\n collisionDetection={collisionDetection}\n modifiers={modifiers}\n sensors={sensors}\n {...kanbanProps}\n id={id}\n measuring={{\n droppable: {\n strategy: MeasuringStrategy.Always,\n },\n }}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDragEnd={onDragEnd}\n onDragCancel={onDragCancel}\n accessibility={{\n announcements,\n screenReaderInstructions: {\n draggable: `\n To pick up a kanban item or column, press space or enter.\n While dragging, use the arrow keys to move the item.\n Press space or enter again to drop the item in its new position, or press escape to cancel.\n `,\n },\n ...accessibility,\n }}\n />\n </KanbanContext.Provider>\n );\n}\n\nconst KanbanBoardContext = React.createContext<boolean>(false);\nKanbanBoardContext.displayName = BOARD_NAME;\n\ninterface KanbanBoardProps extends React.ComponentPropsWithoutRef<\"div\"> {\n children: React.ReactNode;\n asChild?: boolean;\n}\n\nconst KanbanBoard = React.forwardRef<HTMLDivElement, KanbanBoardProps>((props, forwardedRef) => {\n const { asChild, className, ...boardProps } = props;\n\n const context = useKanbanContext(BOARD_NAME);\n\n const columns = React.useMemo(() => {\n return Object.keys(context.items);\n }, [context.items]);\n\n const BoardPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanBoardContext.Provider value={true}>\n <SortableContext\n items={columns}\n strategy={context.orientation === \"horizontal\" ? horizontalListSortingStrategy : verticalListSortingStrategy}\n >\n <BoardPrimitive\n aria-orientation={context.orientation}\n data-orientation={context.orientation}\n data-slot=\"kanban-board\"\n {...boardProps}\n ref={forwardedRef}\n className={cn(\n \"flex size-full gap-4\",\n context.orientation === \"horizontal\" ? \"flex-row\" : \"flex-col\",\n className,\n )}\n />\n </SortableContext>\n </KanbanBoardContext.Provider>\n );\n});\nKanbanBoard.displayName = BOARD_NAME;\n\ninterface KanbanColumnContextValue {\n id: string;\n attributes: DraggableAttributes;\n listeners: DraggableSyntheticListeners | undefined;\n setActivatorNodeRef: (node: HTMLElement | null) => void;\n isDragging?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanColumnContext = React.createContext<KanbanColumnContextValue | null>(null);\nKanbanColumnContext.displayName = COLUMN_NAME;\n\nfunction useKanbanColumnContext(consumerName: string) {\n const context = React.useContext(KanbanColumnContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` must be used within \\`${COLUMN_NAME}\\``);\n }\n return context;\n}\n\nconst animateLayoutChanges: AnimateLayoutChanges = (args) =>\n defaultAnimateLayoutChanges({ ...args, wasDragging: true });\n\ninterface KanbanColumnProps extends React.ComponentPropsWithoutRef<\"div\"> {\n value: UniqueIdentifier;\n children: React.ReactNode;\n asChild?: boolean;\n asHandle?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanColumn = React.forwardRef<HTMLDivElement, KanbanColumnProps>((props, forwardedRef) => {\n const { value, asChild, asHandle, disabled, className, style, ...columnProps } = props;\n\n const id = React.useId();\n const context = useKanbanContext(COLUMN_NAME);\n const inBoard = React.useContext(KanbanBoardContext);\n const inOverlay = React.useContext(KanbanOverlayContext);\n\n if (!inBoard && !inOverlay) {\n throw new Error(`\\`${COLUMN_NAME}\\` must be used within \\`${BOARD_NAME}\\` or \\`${OVERLAY_NAME}\\``);\n }\n\n if (value === \"\") {\n throw new Error(`\\`${COLUMN_NAME}\\` value cannot be an empty string`);\n }\n\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n disabled,\n animateLayoutChanges,\n });\n\n const composedRef = useComposedRefs(forwardedRef, (node) => {\n if (disabled) return;\n setNodeRef(node);\n });\n\n const composedStyle = React.useMemo<React.CSSProperties>(() => {\n return {\n transform: CSS.Transform.toString(transform),\n transition,\n ...style,\n };\n }, [transform, transition, style]);\n\n const items = React.useMemo(() => {\n const items = context.items[value] ?? [];\n return items.map((item) => context.getItemValue(item));\n }, [context.items, value, context.getItemValue]);\n\n const columnContext = React.useMemo<KanbanColumnContextValue>(\n () => ({\n id,\n attributes,\n listeners,\n setActivatorNodeRef,\n isDragging,\n disabled,\n }),\n [id, attributes, listeners, setActivatorNodeRef, isDragging, disabled],\n );\n\n const ColumnPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanColumnContext.Provider value={columnContext}>\n <SortableContext\n items={items}\n strategy={context.orientation === \"horizontal\" ? horizontalListSortingStrategy : verticalListSortingStrategy}\n >\n <ColumnPrimitive\n id={id}\n data-disabled={disabled}\n data-dragging={isDragging ? \"\" : undefined}\n data-slot=\"kanban-column\"\n {...columnProps}\n {...(asHandle && !disabled ? attributes : {})}\n {...(asHandle && !disabled ? listeners : {})}\n ref={composedRef}\n style={composedStyle}\n className={cn(\n \"flex size-full w-full flex-col gap-2 rounded-lg border bg-zinc-100 p-2.5 aria-disabled:pointer-events-none aria-disabled:opacity-50 dark:bg-zinc-900\",\n {\n \"touch-none select-none\": asHandle,\n \"cursor-default\": context.flatCursor,\n \"data-dragging:cursor-grabbing\": !context.flatCursor,\n \"cursor-grab\": !isDragging && asHandle && !context.flatCursor,\n \"opacity-50\": isDragging,\n \"pointer-events-none opacity-50\": disabled,\n },\n className,\n )}\n />\n </SortableContext>\n </KanbanColumnContext.Provider>\n );\n});\nKanbanColumn.displayName = COLUMN_NAME;\n\ninterface KanbanColumnHandleProps extends React.ComponentPropsWithoutRef<\"button\"> {\n asChild?: boolean;\n}\n\nconst KanbanColumnHandle = React.forwardRef<HTMLButtonElement, KanbanColumnHandleProps>((props, forwardedRef) => {\n const { asChild, disabled, className, ...columnHandleProps } = props;\n\n const context = useKanbanContext(COLUMN_NAME);\n const columnContext = useKanbanColumnContext(COLUMN_HANDLE_NAME);\n\n const isDisabled = disabled ?? columnContext.disabled;\n\n const composedRef = useComposedRefs(forwardedRef, (node) => {\n if (isDisabled) return;\n columnContext.setActivatorNodeRef(node);\n });\n\n const HandlePrimitive = asChild ? Slot : \"button\";\n\n return (\n <HandlePrimitive\n type=\"button\"\n aria-controls={columnContext.id}\n data-disabled={isDisabled}\n data-dragging={columnContext.isDragging ? \"\" : undefined}\n data-slot=\"kanban-column-handle\"\n {...columnHandleProps}\n {...(isDisabled ? {} : columnContext.attributes)}\n {...(isDisabled ? {} : columnContext.listeners)}\n ref={composedRef}\n className={cn(\n \"select-none disabled:pointer-events-none disabled:opacity-50\",\n context.flatCursor ? \"cursor-default\" : \"cursor-grab data-dragging:cursor-grabbing\",\n className,\n )}\n disabled={isDisabled}\n />\n );\n});\nKanbanColumnHandle.displayName = COLUMN_HANDLE_NAME;\n\ninterface KanbanItemContextValue {\n id: string;\n attributes: DraggableAttributes;\n listeners: DraggableSyntheticListeners | undefined;\n setActivatorNodeRef: (node: HTMLElement | null) => void;\n isDragging?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanItemContext = React.createContext<KanbanItemContextValue | null>(null);\nKanbanItemContext.displayName = ITEM_NAME;\n\nfunction useKanbanItemContext(consumerName: string) {\n const context = React.useContext(KanbanItemContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` must be used within \\`${ITEM_NAME}\\``);\n }\n return context;\n}\n\ninterface KanbanItemProps extends React.ComponentPropsWithoutRef<\"div\"> {\n value: UniqueIdentifier;\n asHandle?: boolean;\n asChild?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanItem = React.forwardRef<HTMLDivElement, KanbanItemProps>((props, forwardedRef) => {\n const { value, style, asHandle, asChild, disabled, className, ...itemProps } = props;\n\n const id = React.useId();\n const context = useKanbanContext(ITEM_NAME);\n const inBoard = React.useContext(KanbanBoardContext);\n const inOverlay = React.useContext(KanbanOverlayContext);\n\n if (!inBoard && !inOverlay) {\n throw new Error(`\\`${ITEM_NAME}\\` must be used within \\`${BOARD_NAME}\\``);\n }\n\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n disabled,\n });\n\n if (value === \"\") {\n throw new Error(`\\`${ITEM_NAME}\\` value cannot be an empty string`);\n }\n\n const composedRef = useComposedRefs(forwardedRef, (node) => {\n if (disabled) return;\n setNodeRef(node);\n });\n\n const composedStyle = React.useMemo<React.CSSProperties>(() => {\n return {\n transform: CSS.Transform.toString(transform),\n transition,\n ...style,\n };\n }, [transform, transition, style]);\n\n const itemContext = React.useMemo<KanbanItemContextValue>(\n () => ({\n id,\n attributes,\n listeners,\n setActivatorNodeRef,\n isDragging,\n disabled,\n }),\n [id, attributes, listeners, setActivatorNodeRef, isDragging, disabled],\n );\n\n const ItemPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanItemContext.Provider value={itemContext}>\n <ItemPrimitive\n id={id}\n data-disabled={disabled}\n data-dragging={isDragging ? \"\" : undefined}\n data-slot=\"kanban-item\"\n {...itemProps}\n {...(asHandle && !disabled ? attributes : {})}\n {...(asHandle && !disabled ? listeners : {})}\n ref={composedRef}\n style={composedStyle}\n className={cn(\n \"focus-visible:ring-ring focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden\",\n {\n \"touch-none select-none\": asHandle,\n \"cursor-default\": context.flatCursor,\n \"data-dragging:cursor-grabbing\": !context.flatCursor,\n \"cursor-grab\": !isDragging && asHandle && !context.flatCursor,\n \"opacity-50\": isDragging,\n \"pointer-events-none opacity-50\": disabled,\n },\n className,\n )}\n />\n </KanbanItemContext.Provider>\n );\n});\nKanbanItem.displayName = ITEM_NAME;\n\ninterface KanbanItemHandleProps extends React.ComponentPropsWithoutRef<\"button\"> {\n asChild?: boolean;\n}\n\nconst KanbanItemHandle = React.forwardRef<HTMLButtonElement, KanbanItemHandleProps>((props, forwardedRef) => {\n const { asChild, disabled, className, ...itemHandleProps } = props;\n\n const context = useKanbanContext(ITEM_HANDLE_NAME);\n const itemContext = useKanbanItemContext(ITEM_HANDLE_NAME);\n\n const isDisabled = disabled ?? itemContext.disabled;\n\n const composedRef = useComposedRefs(forwardedRef, (node) => {\n if (isDisabled) return;\n itemContext.setActivatorNodeRef(node);\n });\n\n const HandlePrimitive = asChild ? Slot : \"button\";\n\n return (\n <HandlePrimitive\n type=\"button\"\n aria-controls={itemContext.id}\n data-disabled={isDisabled}\n data-dragging={itemContext.isDragging ? \"\" : undefined}\n data-slot=\"kanban-item-handle\"\n {...itemHandleProps}\n {...(isDisabled ? {} : itemContext.attributes)}\n {...(isDisabled ? {} : itemContext.listeners)}\n ref={composedRef}\n className={cn(\n \"select-none disabled:pointer-events-none disabled:opacity-50\",\n context.flatCursor ? \"cursor-default\" : \"cursor-grab data-dragging:cursor-grabbing\",\n className,\n )}\n disabled={isDisabled}\n />\n );\n});\nKanbanItemHandle.displayName = ITEM_HANDLE_NAME;\n\nconst KanbanOverlayContext = React.createContext(false);\nKanbanOverlayContext.displayName = OVERLAY_NAME;\n\nconst dropAnimation: DropAnimation = {\n sideEffects: defaultDropAnimationSideEffects({\n styles: {\n active: {\n opacity: \"0.4\",\n },\n },\n }),\n};\n\ninterface KanbanOverlayProps extends Omit<React.ComponentPropsWithoutRef<typeof DragOverlay>, \"children\"> {\n container?: Element | DocumentFragment | null;\n children?: ((params: { value: UniqueIdentifier; variant: \"column\" | \"item\" }) => React.ReactNode) | React.ReactNode;\n}\n\nfunction KanbanOverlay(props: KanbanOverlayProps) {\n const { container: containerProp, children, ...overlayProps } = props;\n\n const context = useKanbanContext(OVERLAY_NAME);\n\n const [mounted, setMounted] = React.useState(false);\n React.useLayoutEffect(() => setMounted(true), []);\n\n const container = containerProp ?? (mounted ? globalThis.document?.body : null);\n\n if (!container) return null;\n\n const variant = context.activeId && context.activeId in context.items ? \"column\" : \"item\";\n\n return ReactDOM.createPortal(\n <DragOverlay\n dropAnimation={dropAnimation}\n modifiers={context.modifiers}\n className={cn(!context.flatCursor && \"cursor-grabbing\")}\n {...overlayProps}\n >\n <KanbanOverlayContext.Provider value={true}>\n {context.activeId && children\n ? typeof children === \"function\"\n ? children({\n value: context.activeId,\n variant,\n })\n : children\n : null}\n </KanbanOverlayContext.Provider>\n </DragOverlay>,\n container,\n );\n}\n\nexport {\n KanbanBoard as Board,\n KanbanColumn as Column,\n KanbanColumnHandle as ColumnHandle,\n KanbanItem as Item,\n KanbanItemHandle as ItemHandle,\n KanbanRoot as Kanban,\n KanbanBoard,\n KanbanColumn,\n KanbanColumnHandle,\n KanbanItem,\n KanbanItemHandle,\n KanbanOverlay,\n KanbanOverlay as Overlay,\n //\n KanbanRoot as Root,\n};\n","\"use client\";\n\nimport NextLink from \"next/link\";\nimport { cn } from \"../../utils/cn\";\nimport * as React from \"react\";\n\n// Create our custom Link props interface that extends Next.js Link\nexport interface LinkProps extends React.ComponentPropsWithoutRef<typeof NextLink> {\n className?: string;\n}\n\nconst Link = React.forwardRef<HTMLAnchorElement, LinkProps>(({ className, ...props }, ref) => {\n return <NextLink ref={ref} className={cn(`font-medium`, className)} {...props} />;\n});\n\nLink.displayName = \"Link\";\n\nexport { Link };\n","\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { CheckIcon, ChevronDown, WandSparkles, XCircle, XIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Badge } from \"../ui/badge\";\nimport { Button } from \"../ui/button\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n} from \"../ui/command\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/popover\";\nimport { Separator } from \"../ui/separator\";\nimport { cn } from \"../../utils/cn\";\n\n/**\n * Variants for the multi-select component to handle different styles.\n * Uses class-variance-authority (cva) to define different styles based on \"variant\" prop.\n */\nconst multiSelectVariants = cva(\n \"m-1 transition ease-in-out delay-150 hover:-translate-y-1 hover:scale-110 duration-300\",\n {\n variants: {\n variant: {\n default: \"border-foreground/10 text-foreground bg-card hover:bg-card/80\",\n secondary: \"border-foreground/10 bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n destructive: \"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80\",\n inverted: \"inverted\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\n/**\n * Props for MultiSelect component\n */\ninterface MultiSelectProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof multiSelectVariants> {\n /**\n * An array of option objects to be displayed in the multi-select component.\n * Each option object has a label, value, and an optional icon.\n */\n options: {\n /** The text to display for the option. */\n label: string;\n /** The unique value associated with the option. */\n value: string;\n /** Optional icon component to display alongside the option. */\n icon?: React.ComponentType<{ className?: string }>;\n }[];\n\n /**\n * Callback function triggered when the selected values change.\n * Receives an array of the new selected values.\n */\n onValueChange: (value: string[]) => void;\n\n /** The default selected values when the component mounts. */\n defaultValue?: string[];\n\n /**\n * The controlled value for the component. When provided, the component\n * will be controlled rather than using internal state.\n */\n value?: string[];\n\n /**\n * Placeholder text to be displayed when no values are selected.\n * Optional, defaults to \"Select options\".\n */\n placeholder?: string;\n\n /**\n * Animation duration in seconds for the visual effects (e.g., bouncing badges).\n * Optional, defaults to 0 (no animation).\n */\n animation?: number;\n\n /**\n * Maximum number of items to display. Extra selected items will be summarized.\n * Optional, defaults to 3.\n */\n maxCount?: number;\n\n /**\n * The modality of the popover. When set to true, interaction with outside elements\n * will be disabled and only popover content will be visible to screen readers.\n * Optional, defaults to false.\n */\n modalPopover?: boolean;\n\n /**\n * If true, renders the multi-select component as a child of another component.\n * Optional, defaults to false.\n */\n asChild?: boolean;\n\n /**\n * Additional class names to apply custom styles to the multi-select component.\n * Optional, can be used to add custom styles.\n */\n className?: string;\n\n /**\n * Callback function triggered when the search input value changes.\n * Optional, receives the search string.\n */\n onSearchChange?: (search: string) => void;\n}\n\nexport const MultiSelect = React.forwardRef<HTMLButtonElement, MultiSelectProps>(\n (\n {\n options,\n onValueChange,\n variant,\n defaultValue = [],\n value,\n placeholder = \"Select options\",\n animation = 0,\n maxCount = 3,\n modalPopover = false,\n asChild = false,\n className,\n onSearchChange,\n ...props\n },\n ref,\n ) => {\n // Using internal state only if value prop is not provided (uncontrolled mode)\n const [internalSelectedValues, setInternalSelectedValues] = React.useState<string[]>(defaultValue);\n\n // If value prop is provided, use it (controlled mode), otherwise use internal state\n const selectedValues = value !== undefined ? value : internalSelectedValues;\n\n const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);\n const [isAnimating, setIsAnimating] = React.useState(false);\n\n const handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Enter\") {\n setIsPopoverOpen(true);\n } else if (event.key === \"Backspace\" && !event.currentTarget.value) {\n const newSelectedValues = [...selectedValues];\n newSelectedValues.pop();\n\n // If in uncontrolled mode, update internal state\n if (value === undefined) {\n setInternalSelectedValues(newSelectedValues);\n }\n\n // Always call the callback\n onValueChange(newSelectedValues);\n }\n };\n\n const toggleOption = (option: string) => {\n const newSelectedValues = selectedValues.includes(option)\n ? selectedValues.filter((value) => value !== option)\n : [...selectedValues, option];\n\n // If in uncontrolled mode, update internal state\n if (value === undefined) {\n setInternalSelectedValues(newSelectedValues);\n }\n\n // Always call the callback\n onValueChange(newSelectedValues);\n };\n\n const handleClear = () => {\n // If in uncontrolled mode, update internal state\n if (value === undefined) {\n setInternalSelectedValues([]);\n }\n\n // Always call the callback\n onValueChange([]);\n };\n\n const handleTogglePopover = () => {\n setIsPopoverOpen((prev) => !prev);\n };\n\n const clearExtraOptions = () => {\n const newSelectedValues = selectedValues.slice(0, maxCount);\n\n // If in uncontrolled mode, update internal state\n if (value === undefined) {\n setInternalSelectedValues(newSelectedValues);\n }\n\n // Always call the callback\n onValueChange(newSelectedValues);\n };\n\n const toggleAll = () => {\n let newSelectedValues: string[];\n\n if (selectedValues.length === options.length) {\n newSelectedValues = [];\n } else {\n newSelectedValues = options.map((option) => option.value);\n }\n\n // If in uncontrolled mode, update internal state\n if (value === undefined) {\n setInternalSelectedValues(newSelectedValues);\n }\n\n // Always call the callback\n onValueChange(newSelectedValues);\n };\n\n return (\n <Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen} modal={modalPopover}>\n <PopoverTrigger asChild>\n <Button\n ref={ref}\n {...props}\n onClick={handleTogglePopover}\n className={cn(\n \"flex h-auto min-h-10 w-full items-center justify-between rounded-md border bg-inherit p-1 hover:bg-inherit [&_svg]:pointer-events-auto\",\n className,\n )}\n >\n {selectedValues.length > 0 ? (\n <div className=\"flex w-full items-center justify-between\">\n <div className=\"flex flex-wrap items-center\">\n {selectedValues.slice(0, maxCount).map((value) => {\n const option = options.find((o) => o.value === value);\n const IconComponent = option?.icon;\n return (\n <Badge\n key={value}\n className={cn(isAnimating ? \"animate-bounce\" : \"\", multiSelectVariants({ variant }))}\n style={{ animationDuration: `${animation}s` }}\n >\n {IconComponent && <IconComponent className=\"mr-2 h-4 w-4\" />}\n {option?.label}\n <XCircle\n className=\"ml-2 h-4 w-4 cursor-pointer\"\n onClick={(event) => {\n event.stopPropagation();\n toggleOption(value);\n }}\n />\n </Badge>\n );\n })}\n {selectedValues.length > maxCount && (\n <Badge\n className={cn(\n \"text-foreground border-foreground/1 bg-transparent hover:bg-transparent\",\n isAnimating ? \"animate-bounce\" : \"\",\n multiSelectVariants({ variant }),\n )}\n style={{ animationDuration: `${animation}s` }}\n >\n {`+ ${selectedValues.length - maxCount} more`}\n <XCircle\n className=\"ml-2 h-4 w-4 cursor-pointer\"\n onClick={(event) => {\n event.stopPropagation();\n clearExtraOptions();\n }}\n />\n </Badge>\n )}\n </div>\n <div className=\"flex items-center justify-between\">\n <XIcon\n className=\"text-muted-foreground mx-2 h-4 cursor-pointer\"\n onClick={(event) => {\n event.stopPropagation();\n handleClear();\n }}\n />\n <Separator orientation=\"vertical\" className=\"flex h-full min-h-6\" />\n <ChevronDown className=\"text-muted-foreground mx-2 h-4 cursor-pointer\" />\n </div>\n </div>\n ) : (\n <div className=\"mx-auto flex w-full items-center justify-between\">\n <span className=\"text-muted-foreground mx-3 text-sm\">{placeholder}</span>\n <ChevronDown className=\"text-muted-foreground mx-2 h-4 cursor-pointer\" />\n </div>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\" onEscapeKeyDown={() => setIsPopoverOpen(false)}>\n <Command>\n <CommandInput\n autoFocus\n placeholder=\"Search...\"\n onKeyDown={handleInputKeyDown}\n onValueChange={onSearchChange}\n />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup>\n <CommandItem key=\"all\" onSelect={toggleAll} className=\"cursor-pointer\">\n <div\n className={cn(\n \"border-primary mr-2 flex h-4 w-4 items-center justify-center rounded-sm border\",\n selectedValues.length === options.length\n ? \"bg-primary text-primary-foreground\"\n : \"opacity-50 [&_svg]:invisible\",\n )}\n >\n <CheckIcon className=\"h-4 w-4\" />\n </div>\n <span>(Select All)</span>\n </CommandItem>\n {options.map((option) => {\n const isSelected = selectedValues.includes(option.value);\n return (\n <CommandItem\n key={option.value}\n onSelect={() => toggleOption(option.value)}\n className=\"cursor-pointer\"\n >\n <div\n className={cn(\n \"border-primary mr-2 flex h-4 w-4 items-center justify-center rounded-sm border\",\n isSelected ? \"bg-primary text-primary-foreground\" : \"opacity-50 [&_svg]:invisible\",\n )}\n >\n <CheckIcon className=\"h-4 w-4\" />\n </div>\n {option.icon && <option.icon className=\"text-muted-foreground mr-2 h-4 w-4\" />}\n <span>{option.label}</span>\n </CommandItem>\n );\n })}\n </CommandGroup>\n <CommandSeparator />\n <CommandGroup>\n <div className=\"flex items-center justify-between\">\n {selectedValues.length > 0 && (\n <>\n <CommandItem onSelect={handleClear} className=\"flex-1 cursor-pointer justify-center\">\n Clear\n </CommandItem>\n <Separator orientation=\"vertical\" className=\"flex h-full min-h-6\" />\n </>\n )}\n <CommandItem\n onSelect={() => setIsPopoverOpen(false)}\n className=\"max-w-full flex-1 cursor-pointer justify-center\"\n >\n Close\n </CommandItem>\n </div>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n {animation > 0 && selectedValues.length > 0 && (\n <WandSparkles\n className={cn(\n \"text-foreground bg-background my-2 h-3 w-3 cursor-pointer\",\n isAnimating ? \"\" : \"text-muted-foreground\",\n )}\n onClick={() => setIsAnimating(!isAnimating)}\n />\n )}\n </Popover>\n );\n },\n);\n\nMultiSelect.displayName = \"MultiSelect\";\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { CommonDeleter } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { useI18nRouter, usePageUrlGenerator } from \"../../../../hooks\";\nimport { Action } from \"../../../../permissions\";\nimport { getRoleId } from \"../../../../roles\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype UserDeleterProps = {\n user: UserInterface;\n companyId?: string;\n onDeleted?: () => void;\n};\n\nfunction UserDeleterInternal({ user, onDeleted, companyId }: UserDeleterProps) {\n const { currentUser, company } = useCurrentUserContext<UserInterface>();\n const generateUrl = usePageUrlGenerator();\n const router = useI18nRouter();\n const t = useTranslations();\n\n let cId;\n if (currentUser?.roles.find((role) => role.id === getRoleId().Administrator) && companyId) {\n cId = companyId;\n } else {\n if (!company) return;\n cId = company.id;\n }\n\n return (\n <CommonDeleter\n type={`users`}\n deleteFunction={() =>\n UserService.delete({ userId: user.id, companyId: cId }).then(() =>\n onDeleted ? onDeleted() : router.push(generateUrl({ page: Modules.User })),\n )\n }\n />\n );\n}\n\nexport function UserDeleter(props: UserDeleterProps) {\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n if (!hasPermissionToModule({ module: Modules.User, action: Action.Delete, data: props.user })) return null;\n\n return <UserDeleterInternal {...props} />;\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { v4 } from \"uuid\";\nimport { z } from \"zod\";\nimport {\n CommonEditorButtons,\n CommonEditorHeader,\n CommonEditorTrigger,\n errorToast,\n FormCheckbox,\n FormInput,\n FormPassword,\n FormRoles,\n FormTextarea,\n} from \"../../../../components\";\nimport { useCompanyContext } from \"../../../../contexts\";\nimport { Modules } from \"../../../../core\";\nimport { useI18nRouter, usePageUrlGenerator } from \"../../../../hooks\";\nimport { Action } from \"../../../../permissions\";\nimport { getRoleId } from \"../../../../roles\";\nimport { Dialog, DialogContent, DialogTrigger, Form } from \"../../../../shadcnui\";\nimport { CompanyInterface } from \"../../../company\";\nimport { RoleInterface } from \"../../../role\";\nimport { S3Interface } from \"../../../s3\";\nimport { RoleService } from \"../../../role/data/role.service\";\nimport { S3Service } from \"../../../s3/data/s3.service\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInput, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\nimport { UserAvatarEditor } from \"./UserAvatarEditor\";\nimport { UserDeleter } from \"./UserDeleter\";\n\ntype UserEditorProps = {\n user?: UserInterface;\n propagateChanges?: (user: UserInterface) => void;\n adminCreated?: boolean;\n trigger?: React.ReactNode;\n onRevalidate?: (path: string) => Promise<void>;\n};\n\nfunction UserEditorInternal({ user, propagateChanges, adminCreated, trigger, onRevalidate }: UserEditorProps) {\n const {\n company: userCompany,\n hasPermissionToModule,\n hasRole,\n currentUser,\n setUser,\n } = useCurrentUserContext<UserInterface>();\n const { company: companyFromContext } = useCompanyContext();\n const generateUrl = usePageUrlGenerator();\n const router = useI18nRouter();\n const [open, setOpen] = useState<boolean>(false);\n const [roles, setRoles] = useState<RoleInterface[]>([]);\n const [file, setFile] = useState<File | null>(null);\n const [contentType, setContentType] = useState<string | null>(null);\n const t = useTranslations();\n const [resetImage, setResetImage] = useState<boolean>(false);\n const [company, setCompany] = useState<CompanyInterface | null>(companyFromContext || userCompany);\n\n useEffect(() => {\n if (!companyFromContext && userCompany) setCompany(userCompany);\n }, [company]);\n\n const formSchema = z.object({\n id: z.uuidv4(),\n name: z.string().min(1, { message: t(`foundations.user.fields.name.error`) }),\n email: z.string().min(1, { message: t(`generic.fields.email.error`) }),\n password: z.string().optional(),\n title: z.string().optional(),\n bio: z.string().optional(),\n phone: z.string().optional(),\n roleIds: z.array(z.string()).optional(),\n sendInvitationEmail: z.boolean().optional(),\n avatar: z.string().optional(),\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n id: user?.id || v4(),\n name: user?.name || \"\",\n title: user?.title || \"\",\n bio: user?.bio || \"\",\n email: user?.email || \"\",\n phone: user?.phone || \"\",\n password: \"\",\n roleIds: user?.roles.map((role: RoleInterface) => role.id) || [],\n sendInvitationEmail: false,\n avatar: user?.avatarUrl || \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n if (!user) {\n try {\n const existingUser = await UserService.findByEmail({ email: values.email });\n if (existingUser) {\n form.setError(\"email\", {\n type: \"manual\",\n message: t(`foundations.user.errors.email_exists`),\n });\n errorToast({ title: t(`foundations.user.errors.email_exists`), error: \"\" });\n return;\n }\n } catch (error) {\n // User does not exist, proceed\n }\n }\n\n if (values.avatar && contentType) {\n const s3: S3Interface = await S3Service.getPreSignedUrl({\n key: values.avatar,\n contentType: contentType,\n isPublic: true,\n });\n\n await fetch(s3.url, {\n method: \"PUT\",\n headers: s3.headers,\n body: file,\n });\n }\n\n const payload: UserInput = {\n id: values.id,\n email: values.email,\n name: values.name,\n title: values.title,\n bio: values.bio,\n phone: values.phone,\n password: values.password,\n avatar: resetImage ? undefined : values.avatar,\n roleIds: values.roleIds,\n sendInvitationEmail: values.sendInvitationEmail,\n companyId: company!.id,\n adminCreated: adminCreated,\n };\n\n try {\n const updatedUser = user\n ? ((await UserService.update(payload)) as UserInterface)\n : ((await UserService.create(payload)) as UserInterface);\n\n if (currentUser?.id === updatedUser.id) setUser(updatedUser);\n\n if (onRevalidate) {\n await onRevalidate(generateUrl({ page: Modules.User, id: updatedUser.id, language: `[locale]` }));\n }\n if (propagateChanges) {\n propagateChanges(updatedUser);\n setOpen(false);\n } else {\n router.push(generateUrl({ page: Modules.User, id: updatedUser.id }));\n }\n } catch (error) {\n errorToast({ title: user ? t(`generic.errors.update`) : t(`generic.errors.create`), error });\n }\n };\n\n useEffect(() => {\n async function fetchRoles() {\n const roles = await RoleService.findAllRoles({});\n\n const availableRoles = roles.filter(\n (role: RoleInterface) =>\n role.id !== getRoleId().Administrator &&\n (role.requiredFeature === undefined ||\n company?.features.some((feature) => feature.id === role.requiredFeature?.id)),\n );\n\n setRoles(availableRoles);\n }\n\n if (\n open &&\n (company || currentUser?.roles.find((role: RoleInterface) => role.id === getRoleId().Administrator)) &&\n roles.length === 0\n )\n fetchRoles();\n }, [company, open]);\n\n useEffect(() => {\n if (file && company) {\n const id = form.getValues(\"id\");\n const fileType = file.type;\n let extension = \"\";\n\n switch (fileType) {\n default:\n extension = file.type.split(\"/\").pop() ?? \"\";\n break;\n }\n\n const timestamp = new Date().toISOString().replace(/[-:T]/g, \"\").split(\".\")[0];\n\n const fileUrl = `companies/${company.id}/users/${id}/${id}.${timestamp}.${extension}`;\n form.setValue(\"avatar\", fileUrl);\n\n setContentType(fileType);\n } else {\n setContentType(null);\n }\n }, [file]);\n\n const canChangeRoles =\n !(currentUser?.id === user?.id && hasRole(getRoleId().Administrator)) &&\n (hasPermissionToModule({ module: Modules.User, action: Action.Update }) || hasRole(getRoleId().Administrator));\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n {trigger ? <DialogTrigger asChild>{trigger}</DialogTrigger> : <CommonEditorTrigger isEdit={!!user} />}\n <DialogContent\n className={`flex max-h-[70vh] ${canChangeRoles ? `max-w-[90vw]` : `max-w-3xl`} min-h-3xl max-h-[90vh] flex-col overflow-y-auto`}\n >\n <CommonEditorHeader type={t(`types.users`, { count: 1 })} name={user?.name} />\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className={`flex w-full flex-col gap-y-4`}>\n <div className={`flex flex-row gap-x-4`}>\n <div className={`flex w-40 flex-col justify-start gap-y-2`}>\n <UserAvatarEditor\n user={user}\n file={file}\n setFile={setFile}\n resetImage={resetImage}\n setResetImage={setResetImage}\n />\n </div>\n <div className={`flex w-full flex-col justify-start`}>\n <FormInput\n form={form}\n id=\"name\"\n name={t(`foundations.user.fields.name.label`)}\n placeholder={t(`foundations.user.fields.name.placeholder`)}\n />\n <FormInput\n form={form}\n id=\"email\"\n name={t(`generic.fields.email.label`)}\n placeholder={t(`generic.fields.email.placeholder`)}\n />\n <FormInput\n form={form}\n id=\"phone\"\n name={t(`foundations.user.fields.phone.label`)}\n placeholder={t(`foundations.user.fields.phone.placeholder`)}\n />\n <FormPassword\n form={form}\n id=\"password\"\n name={t(`foundations.user.fields.password.label`)}\n placeholder={t(`foundations.user.fields.password.placeholder`)}\n />\n <FormInput\n form={form}\n id=\"title\"\n name={t(`foundations.user.fields.title.label`)}\n placeholder={t(`foundations.user.fields.title.placeholder`)}\n />\n <FormTextarea\n form={form}\n id=\"bio\"\n name={t(`foundations.user.fields.bio.label`)}\n placeholder={t(`foundations.user.fields.bio.placeholder`)}\n className=\"min-h-40\"\n />\n </div>\n {canChangeRoles && (\n <div className=\"flex w-1/3 flex-col\">\n {canChangeRoles && (\n <FormRoles form={form} id=\"roleIds\" name={t(`types.roles`, { count: 2 })} roles={roles} />\n )}\n {!user && (\n <div className=\"flex flex-col gap-y-4\">\n <div className=\"text-sm font-semibold\">{t(`foundations.user.send_activation_email`)}</div>\n <FormCheckbox\n form={form}\n id=\"sendInvitationEmail\"\n name={t(`foundations.user.send_activation_email`)}\n />\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"flex justify-end gap-x-4\">\n {user && currentUser?.roles.find((role: RoleInterface) => role.id === getRoleId().Administrator) && (\n <UserDeleter\n companyId={user.company?.id}\n user={user}\n onDeleted={() => {\n setOpen(false);\n if (propagateChanges) propagateChanges(user);\n }}\n />\n )}\n <CommonEditorButtons form={form} setOpen={setOpen} isEdit={!!user} />\n </div>\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport function UserEditor(props: UserEditorProps) {\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n if (\n !hasPermissionToModule({\n module: Modules.User,\n action: props.user ? Action.Update : Action.Create,\n data: props.user,\n })\n )\n return null;\n\n return <UserEditorInternal {...props} />;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useWatch } from \"react-hook-form\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever, useDebounce } from \"../../../../hooks\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n MultiSelect,\n} from \"../../../../shadcnui\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\n// Type for user objects in the form\ntype UserSelectType = {\n id: string;\n name: string;\n avatar?: string;\n};\n\ntype UserMultiSelectProps = {\n id: string;\n form: any;\n currentUser?: UserInterface;\n label?: string;\n placeholder?: string;\n onChange?: (users?: UserInterface[]) => void;\n maxCount?: number;\n isRequired?: boolean;\n};\n\nfunction UserAvatarIcon({ className, url, name }: { className?: string; url?: string; name?: string }) {\n return (\n <Avatar className={`${className || \"h-4 w-4\"}`}>\n <AvatarImage src={url} />\n <AvatarFallback>\n {name\n ? name\n .split(\" \")\n .map((n: string) => n.charAt(0).toUpperCase())\n .join(\"\")\n : \"U\"}\n </AvatarFallback>\n </Avatar>\n );\n}\n\nexport function UserMultiSelect({\n id,\n form,\n currentUser,\n label,\n placeholder,\n onChange,\n maxCount = 3,\n isRequired = false,\n}: UserMultiSelectProps) {\n const { company } = useCurrentUserContext<UserInterface>();\n\n const searchTermRef = useRef<string>(\"\");\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n const [isSearching, setIsSearching] = useState<boolean>(false);\n const [userOptions, setUserOptions] = useState<any[]>([]);\n\n // Get the current selected users from the form\n const selectedUsers: UserSelectType[] = useWatch({ control: form.control, name: id }) || [];\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n ready: !!company,\n retriever: (params) => {\n return UserService.findAllUsers(params);\n },\n retrieverParams: { companyId: company?.id },\n module: Modules.User,\n }) as DataListRetriever<UserInterface>;\n\n useEffect(() => {\n if (company) data.setReady(true);\n }, [company]);\n\n const search = useCallback(\n async (searchedTerm: string) => {\n try {\n if (searchedTerm === searchTermRef.current) return;\n setIsSearching(true);\n searchTermRef.current = searchedTerm;\n await data.search(searchedTerm);\n } finally {\n setIsSearching(false);\n }\n },\n [searchTermRef, data],\n );\n\n const updateSearchTerm = useDebounce(search, 500);\n\n useEffect(() => {\n setIsSearching(true);\n updateSearchTerm(searchTerm);\n }, [updateSearchTerm, searchTerm]);\n\n // Update userOptions when data changes or when initial selected users are available\n useEffect(() => {\n if (data.data && data.data.length > 0) {\n const users = data.data as UserInterface[];\n const filteredUsers = users.filter((user) => user.id !== currentUser?.id);\n\n const options = filteredUsers.map((user) => ({\n label: user.name,\n value: user.id,\n icon: ({ className }: { className?: string }) => (\n <UserAvatarIcon className={className} url={user.avatar} name={user.name} />\n ),\n userData: user,\n }));\n\n setUserOptions(options);\n }\n }, [data.data, currentUser]);\n\n // Add options for any already selected users that aren't in search results\n useEffect(() => {\n if (selectedUsers.length > 0) {\n // Create a map of existing option IDs for quick lookup\n const existingOptionIds = new Set(userOptions.map((option) => option.value));\n\n // Find selected users that don't have an option yet\n const missingOptions = selectedUsers\n .filter((user) => !existingOptionIds.has(user.id))\n .map((user) => ({\n label: user.name,\n value: user.id,\n icon: ({ className }: { className?: string }) => (\n <UserAvatarIcon className={className} url={user.avatar} name={user.name} />\n ),\n userData: user,\n }));\n\n // Add missing options if there are any\n if (missingOptions.length > 0) {\n setUserOptions((prev) => [...prev, ...missingOptions]);\n }\n }\n }, [selectedUsers, userOptions]);\n\n const handleValueChange = (selectedIds: string[]) => {\n // Map selected IDs to user objects for the form\n const updatedSelectedUsers = selectedIds.map((id) => {\n // First check if user is already in the selected users (preserve existing data)\n const existingUser = selectedUsers.find((user) => user.id === id);\n if (existingUser) {\n return existingUser;\n }\n\n // Otherwise, get user data from the options\n const option = userOptions.find((option) => option.value === id);\n if (option?.userData) {\n return {\n id: option.userData.id,\n name: option.userData.name,\n avatar: option.userData.avatar,\n };\n }\n\n // Fallback to just the ID if no data is available\n return { id, name: id };\n });\n\n form.setValue(id, updatedSelectedUsers);\n\n if (onChange) {\n const fullSelectedUsers = selectedIds\n .map((id) => userOptions.find((option) => option.value === id)?.userData)\n .filter(Boolean) as UserInterface[];\n onChange(fullSelectedUsers);\n }\n };\n\n // Extract just the IDs for the MultiSelect component\n const selectedUserIds = selectedUsers.map((user: UserSelectType) => user.id);\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${label ? \"mb-5\" : \"mb-1\"}`}>\n {label && (\n <FormLabel className=\"flex items-center\">\n {label}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <MultiSelect\n options={userOptions}\n onValueChange={handleValueChange}\n defaultValue={selectedUserIds}\n placeholder={placeholder}\n maxCount={maxCount}\n animation={0}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { UserCheckIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useState } from \"react\";\nimport { errorToast } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { Action } from \"../../../../permissions\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"../../../../shadcnui\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype UserReactivatorProps = {\n user: UserInterface;\n propagateChanges: (user: UserInterface) => void;\n};\n\nfunction UserReactivatorInterface({ user, propagateChanges }: UserReactivatorProps) {\n const [open, setOpen] = useState<boolean>(false);\n const t = useTranslations();\n\n const reactivateUser = async () => {\n try {\n const updatedUser = (await UserService.reactivate({ userId: user.id })) as UserInterface;\n\n setOpen(false);\n propagateChanges(updatedUser);\n } catch (error) {\n errorToast({ title: t(`generic.errors.error`), error: error });\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogTrigger asChild>\n <Button size=\"sm\">\n <UserCheckIcon className=\"mr-3 h-3.5 w-3.5\" />\n {t(`foundations.user.buttons.reactivate`)}\n </Button>\n </DialogTrigger>\n <DialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>\n <DialogHeader>\n <DialogTitle>{t(`foundations.user.reactivate.title`)}</DialogTitle>\n <DialogDescription>{t(`foundations.user.reactivate.subtitle`)}</DialogDescription>\n </DialogHeader>\n {t(`foundations.user.reactivate.description`, { name: user.name })}\n <div className=\"flex justify-end\">\n <Button className=\"mr-2\" variant={\"outline\"} type={`button`} onClick={() => setOpen(false)}>\n {t(`generic.buttons.cancel`)}\n </Button>\n <Button\n type=\"submit\"\n onClick={(e) => {\n e.preventDefault();\n reactivateUser();\n }}\n >\n {t(`foundations.user.buttons.reactivate`)}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport function UserReactivator(props: UserReactivatorProps) {\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n if (!hasPermissionToModule({ module: Modules.User, action: Action.Update, data: props.user })) return null;\n\n return <UserReactivatorInterface {...props} />;\n}\n","\"use client\";\n\nimport { MailIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { errorToast } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { Action } from \"../../../../permissions\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../../../shadcnui\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype UserResentInvitationEmailProps = {\n user: UserInterface;\n};\n\nfunction UserResentInvitationEmailInternal({ user }: UserResentInvitationEmailProps) {\n const [open, setOpen] = useState<boolean>(false);\n const t = useTranslations();\n\n const sendInvitationEmail = async () => {\n try {\n await UserService.sendInvitation({ userId: user.id, companyId: user.company!.id });\n\n setOpen(false);\n toast.message(t(`foundations.user.resend_activation.email_sent`), {\n description: t(`foundations.user.resend_activation.email_sent_description`, { email: user.email }),\n });\n } catch (error) {\n errorToast({ title: t(`generic.errors.error`), error: error });\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <Tooltip>\n <TooltipTrigger asChild>\n <DialogTrigger asChild>\n <Button size=\"sm\" variant={`ghost`} className=\"text-muted-foreground\">\n <MailIcon />\n </Button>\n </DialogTrigger>\n </TooltipTrigger>\n <TooltipContent>{t(`foundations.user.buttons.resend_activation`)}</TooltipContent>\n </Tooltip>\n <DialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>\n <DialogHeader>\n <DialogTitle>{t(`foundations.user.resend_activation.title`)}</DialogTitle>\n <DialogDescription>{t(`foundations.user.resend_activation.subtitle`)}</DialogDescription>\n </DialogHeader>\n {t(`foundations.user.resend_activation.description`, { email: user.email })}\n <div className=\"flex justify-end\">\n <Button className=\"mr-2\" variant={\"outline\"} type={`button`} onClick={() => setOpen(false)}>\n {t(`generic.buttons.cancel`)}\n </Button>\n <Button\n type=\"submit\"\n onClick={(e) => {\n e.preventDefault();\n sendInvitationEmail();\n }}\n >\n {t(`foundations.user.buttons.resend_activation`)}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport function UserResentInvitationEmail(props: UserResentInvitationEmailProps) {\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n if (!hasPermissionToModule({ module: Modules.User, action: Action.Update, data: props.user })) return null;\n\n return <UserResentInvitationEmailInternal {...props} />;\n}\n","\"use client\";\n\nimport { CircleX, RefreshCwIcon, SearchIcon, XIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever, useDebounce } from \"../../../../hooks\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n Command,\n CommandItem,\n CommandList,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\nimport { UserAvatar } from \"../widgets\";\n\ntype UserSelectorProps = {\n id: string;\n form: any;\n label?: string;\n placeholder?: string;\n onChange?: (user?: UserInterface) => void;\n isRequired?: boolean;\n};\n\nexport function UserSelector({ id, form, label, placeholder, onChange, isRequired = false }: UserSelectorProps) {\n const t = useTranslations();\n\n const [open, setOpen] = useState<boolean>(false);\n\n const searchTermRef = useRef<string>(\"\");\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n\n const [isSearching, setIsSearching] = useState<boolean>(false);\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n retriever: (params) => {\n return UserService.findMany(params);\n },\n retrieverParams: {},\n module: Modules.User,\n });\n\n const search = useCallback(\n async (searchedTerm: string) => {\n try {\n if (searchedTerm === searchTermRef.current) return;\n setIsSearching(true);\n searchTermRef.current = searchedTerm;\n await data.search(searchedTerm);\n } finally {\n setIsSearching(false);\n }\n },\n [searchTermRef, data],\n );\n\n const updateSearchTerm = useDebounce(search, 500);\n\n useEffect(() => {\n setIsSearching(true);\n updateSearchTerm(searchTerm);\n }, [updateSearchTerm, searchTerm]);\n\n const setUser = (user?: UserInterface) => {\n if (onChange) onChange(user);\n if (!user) {\n form.setValue(id, undefined);\n setOpen(false);\n return;\n }\n\n form.setValue(id, { id: user.id, name: user.name, avatar: user.avatar });\n setOpen(false);\n\n setTimeout(() => {\n setOpen(false);\n }, 0);\n };\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${label ? \"mb-5\" : \"mb-1\"}`}>\n {label && (\n <FormLabel className=\"flex items-center\">\n {label}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <Popover open={open} onOpenChange={setOpen} modal={true}>\n <div className=\"flex w-full flex-row items-center justify-between\">\n <PopoverTrigger className=\"w-full\">\n <div className=\"flex w-full flex-row items-center justify-start rounded-md\">\n {field.value ? (\n <>\n <div className=\"flex w-full flex-row items-center justify-start rounded-md border p-2\">\n <div className=\"*:ring-border *:ring-1\">\n <Avatar className={`mr-2 h-6 w-6`}>\n <AvatarImage src={field.value?.avatar} />\n <AvatarFallback>\n {field.value?.name\n ? field.value?.name.split(\" \").map((name: string) => name.charAt(0).toUpperCase())\n : \"X\"}\n </AvatarFallback>\n </Avatar>\n </div>\n <span className=\"\">{field.value?.name ?? \"\"}</span>\n </div>\n </>\n ) : (\n <div className=\"text-muted-foreground mr-7 flex h-10 w-full flex-row items-center justify-start rounded-md border p-2 text-sm\">\n {placeholder ?? t(`generic.search.placeholder`, { type: t(`types.users`, { count: 1 }) })}\n </div>\n )}\n </div>\n </PopoverTrigger>\n {field.value && (\n <CircleX\n className=\"text-muted hover:text-destructive ml-2 h-6 w-6 cursor-pointer\"\n onClick={() => setUser()}\n />\n )}\n </div>\n <PopoverContent>\n <Command shouldFilter={false}>\n <div className=\"relative mb-2 w-full\">\n <SearchIcon className=\"text-muted-foreground absolute top-2.5 left-2.5 h-4 w-4\" />\n <Input\n placeholder={t(`generic.search.placeholder`, { type: t(`types.users`, { count: 1 }) })}\n type=\"text\"\n className=\"w-full pr-8 pl-8\"\n onChange={(e) => setSearchTerm(e.target.value)}\n value={searchTerm}\n />\n {isSearching ? (\n <RefreshCwIcon className=\"text-muted-foreground absolute top-2.5 right-2.5 h-4 w-4 animate-spin\" />\n ) : searchTermRef.current ? (\n <XIcon\n className={`absolute top-2.5 right-2.5 h-4 w-4 ${searchTermRef.current ? \"cursor-pointer\" : \"text-muted-foreground\"}`}\n onClick={() => {\n setSearchTerm(\"\");\n search(\"\");\n }}\n />\n ) : (\n <></>\n )}\n </div>\n <CommandList>\n {data.data &&\n data.data.length > 0 &&\n (data.data as UserInterface[]).map((user: UserInterface) => (\n <CommandItem className=\"cursor-pointer\" key={user.id} onSelect={() => setUser(user)}>\n <UserAvatar user={user} className={`mr-2 h-4 w-4`} />\n <span className=\"\">{user.name}</span>\n </CommandItem>\n ))}\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n Link,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../../../shadcnui\";\nimport { cn } from \"../../../../utils\";\nimport { UserInterface } from \"../../data\";\n\ntype UserAvatarProps = {\n user: UserInterface;\n className?: string;\n showFull?: boolean;\n showLink?: boolean;\n};\n\nexport function UserAvatar({ user, className, showFull, showLink }: UserAvatarProps) {\n const generateUrl = usePageUrlGenerator();\n\n const getInitial = (param?: string) => {\n if (!param) return \"\";\n return param[0].toUpperCase();\n };\n\n const getInitials = (name: string) => {\n const words = name.split(\" \");\n const initials =\n words.length > 1 ? getInitial(words[0][0]) + getInitial(words[words.length - 1][0]) : getInitial(words[0][0]);\n\n return initials ?? \"\";\n };\n\n const getAvatar = () => {\n return (\n <div className=\"*:ring-border *:ring-1\">\n <Avatar className={`h-6 w-6 ${className}`}>\n <AvatarImage className=\"object-cover\" src={user?.avatar} />\n <AvatarFallback>{getInitials(user.name)}</AvatarFallback>\n </Avatar>\n </div>\n );\n };\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n {showLink === false ? (\n // If showLink is explicitly false, never show a link\n showFull ? (\n <div className={cn(`mb-2 flex w-full flex-row items-center justify-start gap-x-2 text-sm`, className)}>\n {getAvatar()}\n {user.name}\n </div>\n ) : (\n getAvatar()\n )\n ) : showFull ? (\n <Link\n href={generateUrl({ page: Modules.User, id: user.id })}\n className={cn(`mb-2 flex w-full flex-row items-center justify-start gap-x-2 text-sm`, className)}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex w-full flex-row items-center gap-x-2\">\n {getAvatar()}\n {user.name}\n </div>\n </Link>\n ) : showLink ? (\n <Link href={generateUrl({ page: Modules.User, id: user.id })} className={className}>\n {getAvatar()}\n </Link>\n ) : (\n getAvatar()\n )}\n </TooltipTrigger>\n <TooltipContent>{user.name}</TooltipContent>\n </Tooltip>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { useUserContext } from \"../../contexts\";\nimport { UserDetails } from \"../details\";\n\nexport function UserContainer() {\n const { user } = useUserContext();\n if (!user) return null;\n\n const t = useTranslations();\n\n return (\n <div className=\"flex w-full gap-x-4\">\n <div className=\"w-2xl flex h-[calc(100vh-theme(spacing.20))] flex-col justify-between border-r pr-4\">\n <div className=\"flex h-full overflow-y-auto\">\n <UserDetails user={user} />\n </div>\n </div>\n <div className=\"flex w-full flex-col gap-y-4\"></div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { ReactElement } from \"react\";\nimport { AttributeElement, ContentTitle } from \"../../../../components\";\nimport { useSharedContext } from \"../../../../contexts\";\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { Badge, Link } from \"../../../../shadcnui\";\nimport { RoleInterface } from \"../../../role\";\nimport { UserInterface } from \"../../data\";\n\ntype UserDetailsProps = {\n user: UserInterface;\n};\n\nexport function UserDetails({ user }: UserDetailsProps) {\n const generateUrl = usePageUrlGenerator();\n const t = useTranslations();\n const { title } = useSharedContext();\n\n let roles: ReactElement<any> = <></>;\n\n if (user.roles && user.roles.length > 0) {\n roles = (\n <div className=\"mb-4 w-full\">\n <div className=\"flex flex-wrap gap-2\">\n {user.roles.map((role: RoleInterface, index: number) => (\n <Link key={role.id} href={generateUrl({ page: Modules.Role, id: role.id })}>\n <Badge className=\"mr-2\" variant={`default`}>\n {t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) })}\n </Badge>\n </Link>\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex w-full flex-col gap-y-2\">\n {user.avatar && (\n <div className=\"relative aspect-auto w-full max-w-md overflow-hidden rounded-lg\">\n <Image\n src={user.avatar}\n alt={user.name}\n width={800}\n height={600}\n className=\"h-auto w-full rounded-lg object-contain\"\n />\n </div>\n )}\n <ContentTitle type={title.type} element={title.element} functions={title.functions} />\n {user.isDeleted ? (\n <div>\n <Badge variant=\"destructive\">{t(`foundations.user.errors.deleted`)}</Badge>\n </div>\n ) : (\n <>\n {!user.isActivated && (\n <div>\n <Badge variant=\"destructive\">{t(`foundations.user.errors.inactive`)}</Badge>\n </div>\n )}\n </>\n )}\n {roles}\n <AttributeElement inline={true} title={t(`foundations.user.fields.title.label`)} value={user.title} />\n <AttributeElement inline={true} title={t(`generic.fields.email.label`)} value={user.email} />\n <AttributeElement inline={false} title={t(`foundations.user.fields.bio.label`)} value={user.bio} />\n </div>\n );\n}\n","\"use client\";\n\nimport { Card, CardContent } from \"../../../../shadcnui\";\nimport { useCurrentUserContext, useUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\nimport { UserAvatar } from \"../widgets\";\n\nexport function UserIndexDetails() {\n const { user } = useUserContext();\n const { currentUser } = useCurrentUserContext<UserInterface>();\n if (!user || !currentUser) return null;\n\n return (\n <div className=\"flex w-full flex-row gap-x-4\">\n <Card className=\"min-h-96 w-96 flex-shrink-0 self-start p-2\">\n <CardContent className=\"flex h-full flex-col gap-y-4 p-2\">\n <div className=\"flex w-full justify-start gap-x-4\">\n {user.avatar && <UserAvatar user={user} className=\"h-40 w-40\" />}\n <div className=\"flex flex-col justify-start gap-y-2\">\n <div className=\"text-primary text-2xl font-semibold\">{user.name}</div>\n <div className=\"text-muted-foreground text-xs\">{user.bio ?? \"\"}</div>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n","\"use client\";\n\nimport { PageContentContainer } from \"../../../../components\";\nimport { useUserContext } from \"../../contexts\";\nimport { UserIndexDetails } from \"../details\";\n\nexport function UserIndexContainer() {\n const { user } = useUserContext();\n if (!user) return null;\n\n return <PageContentContainer details={<UserIndexDetails />} />;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { CompanyUsersList, Tab, TabsContainer } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { Action } from \"../../../../permissions\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../data\";\n\nfunction UsersListContainerInternal() {\n const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();\n const t = useTranslations();\n\n if (!hasPermissionToModule({ module: Modules.User, action: Action.Delete })) return <CompanyUsersList />;\n\n const tabs: Tab[] = [\n {\n label: t(`types.users`, { count: 2 }),\n content: <CompanyUsersList />,\n modules: [Modules.Company],\n action: Action.Read,\n },\n {\n label: t(`foundations.user.deleted`),\n content: <CompanyUsersList isDeleted={true} />,\n modules: [Modules.Company],\n action: Action.Update,\n },\n ];\n\n return <TabsContainer tabs={tabs} />;\n}\n\nexport function UsersListContainer() {\n return <UsersListContainerInternal />;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { useCompanyContext } from \"../../../../contexts\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { CompanyInterface } from \"../../../company\";\nimport { UserFields, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\nimport { UserEditor } from \"../forms\";\n\ntype AdminUsersListProps = {\n company: CompanyInterface;\n};\n\nfunction AdminUsersListInternal({ company }: AdminUsersListProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n retriever: (params) => UserService.findManyForAmin(params),\n retrieverParams: { companyId: company.id },\n module: Modules.User,\n });\n\n return (\n <ContentListTable\n title={t(`types.users`, { count: 2 })}\n data={data}\n fields={[UserFields.name, UserFields.email, UserFields.createdAt]}\n tableGeneratorType={Modules.User}\n functions={<UserEditor propagateChanges={data.refresh} adminCreated />}\n />\n );\n}\n\nexport function AdminUsersList() {\n const { company } = useCompanyContext();\n if (!company) return null;\n\n return <AdminUsersListInternal company={company} />;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ReactNode, useEffect } from \"react\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserFields, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\nimport { UserEditor } from \"../forms\";\n\ntype CompanyUsersListProps = {\n isDeleted?: boolean;\n};\n\nexport function CompanyUsersList({ isDeleted }: CompanyUsersListProps) {\n const { company } = useCurrentUserContext<UserInterface>();\n const t = useTranslations();\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n ready: !!company,\n retriever: (params) => UserService.findAllUsers(params),\n retrieverParams: { companyId: company?.id, isDeleted: isDeleted },\n module: Modules.User,\n }) as DataListRetriever<UserInterface>;\n\n useEffect(() => {\n if (company) data.setReady(true);\n }, [company]);\n\n const functions: ReactNode[] = [\n isDeleted ? undefined : <UserEditor key=\"create-user\" propagateChanges={data.refresh} />,\n ];\n\n return (\n <ContentListTable\n data={data}\n fields={[UserFields.name, UserFields.email]}\n tableGeneratorType={Modules.User}\n functions={functions}\n title={t(`types.users`, { count: 2 })}\n />\n );\n}\n","\"use client\";\n\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { Link } from \"../../../../shadcnui\";\nimport { ContentInterface } from \"../../../content\";\nimport { UserInterface } from \"../../data\";\nimport { UserAvatar } from \"../widgets\";\n\ntype ContributorsListProps = {\n content: ContentInterface;\n};\n\nexport function ContributorsList({ content }: ContributorsListProps) {\n const generateUrl = usePageUrlGenerator();\n\n return (\n <div className=\"flex flex-row items-center\">\n <Link\n key={content.author.id}\n href={generateUrl({ page: Modules.User, id: content.author.id })}\n onClick={(e) => e.stopPropagation()}\n >\n <UserAvatar user={content.author} className=\"mr-1 h-6 w-6\" />\n </Link>\n <div className=\"flex flex-row-reverse justify-end -space-x-1 space-x-reverse\">\n {content.editors\n .filter((editor: UserInterface) => editor.id !== content.author.id)\n .map((editor: UserInterface) => (\n <Link\n key={editor.id}\n href={generateUrl({ page: Modules.User, id: editor.id })}\n onClick={(e) => e.stopPropagation()}\n >\n <UserAvatar user={editor} className=\"h-5 w-5\" />\n </Link>\n ))}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { UserFields, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype RelevantUsersListProps = {\n id: string;\n};\n\nexport function RelevantUsersList({ id }: RelevantUsersListProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n module: Modules.User,\n retriever: (params) => UserService.findRelevant(params),\n retrieverParams: { id: id },\n }) as DataListRetriever<UserInterface>;\n\n return (\n <ContentListTable\n data={data}\n fields={[UserFields.name, UserFields.email, UserFields.relevance]}\n tableGeneratorType={Modules.User}\n title={t(`generic.relevant_users`)}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { RoleInterface } from \"../../../role\";\nimport { UserFields, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype RoleUsersListProps = {\n role: RoleInterface;\n};\n\nexport function RoleUsersList({ role }: RoleUsersListProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n retriever: (params) => UserService.findAllUsersByRole(params),\n retrieverParams: { roleId: role.id },\n module: Modules.User,\n }) as DataListRetriever<UserInterface>;\n\n return (\n <ContentListTable\n data={data}\n fields={[UserFields.name, UserFields.email]}\n tableGeneratorType={Modules.User}\n title={t(`types.users`, { count: 2 })}\n />\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { DataListRetriever } from \"../../../../hooks\";\nimport { CommandItem } from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../data\";\nimport { UserAvatar } from \"../widgets\";\n\ntype UserListInAddProps = {\n data: DataListRetriever<UserInterface>;\n existingUsers: UserInterface[] | null;\n setSelectedUser: (user: UserInterface) => void;\n setLevelOpen?: (open: boolean) => void;\n};\n\nexport function UserListInAdd({ data, existingUsers, setSelectedUser, setLevelOpen }: UserListInAddProps) {\n return (\n <>\n {data.data !== undefined &&\n (data.data as UserInterface[])\n .filter(\n (user: UserInterface) =>\n existingUsers && !existingUsers.find((existingUser: UserInterface) => existingUser.id === user.id),\n )\n .map((user: UserInterface) => {\n return (\n <React.Fragment key={user.id}>\n <CommandItem\n className=\"cursor-pointer\"\n key={user.id}\n onClick={(e) => {\n setSelectedUser(user);\n setLevelOpen?.(true);\n }}\n onSelect={(e) => {\n setSelectedUser(user);\n setLevelOpen?.(true);\n }}\n >\n <div className=\"flex w-full flex-row items-center justify-between px-4 py-1\">\n <UserAvatar user={user} />\n <div className=\"ml-5 flex w-full flex-col\">\n <div className=\"text-sm font-medium\">{user.name}</div>\n <div className=\"text-xs font-normal\">{user.email}</div>\n </div>\n </div>\n </CommandItem>\n </React.Fragment>\n );\n })}\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ReactElement } from \"react\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever } from \"../../../../hooks\";\nimport { UserFields, UserInterface } from \"../../data\";\n\ntype UsersListProps = {\n data: DataListRetriever<UserInterface>;\n optionComponents?: ReactElement<any>[];\n removeFunction?: (user: UserInterface) => Promise<void>;\n hideOptions?: boolean;\n showRelevance?: boolean;\n restrictToJoinRequests?: boolean;\n};\n\nexport function UsersList({ data, optionComponents, removeFunction, hideOptions, showRelevance }: UsersListProps) {\n const t = useTranslations();\n\n return (\n <ContentListTable\n data={data}\n fields={[UserFields.name, UserFields.email]}\n tableGeneratorType={Modules.User}\n title={t(`types.users`, { count: 2 })}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { UserFields, UserInterface } from \"../../data\";\nimport { UserService } from \"../../data/user.service\";\n\ntype UsersListByContentIdsProps = {\n contentIds: string[];\n};\n\nexport function UsersListByContentIds({ contentIds }: UsersListByContentIdsProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<UserInterface> = useDataListRetriever({\n module: Modules.User,\n retriever: (params) => UserService.findManyByContentIds(params),\n retrieverParams: { contentIds: contentIds },\n });\n\n return (\n <ContentListTable\n data={data}\n fields={[UserFields.name, UserFields.email]}\n tableGeneratorType={Modules.User}\n title={t(`generic.relevant_users`)}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { ContentTitle } from \"../../../../components\";\nimport { useSharedContext } from \"../../../../contexts\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { useCompanyContext } from \"../../contexts/CompanyContext\";\n\nexport function CompanyDetails() {\n const t = useTranslations();\n const { title } = useSharedContext();\n const generateUrl = usePageUrlGenerator();\n\n const { company } = useCompanyContext();\n if (!company) return null;\n\n return (\n <div className=\"flex w-full flex-col gap-y-2\">\n <ContentTitle type={title.type} element={title.element} functions={title.functions} />\n {company.logo && (\n <Image src={company.logo} alt={company.name} width={150} height={150} className=\"mb-4 rounded-md\" />\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { getRoleId } from \"../../../../roles\";\nimport { UserInterface } from \"../../../user\";\nimport { AdminUsersList } from \"../../../user/components\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { useCompanyContext } from \"../../contexts/CompanyContext\";\nimport { CompanyDetails } from \"../details/CompanyDetails\";\n\nfunction AdminCompanyContainerInternal() {\n const { company } = useCompanyContext();\n const { hasRole } = useCurrentUserContext<UserInterface>();\n\n if (!company || !hasRole(getRoleId().Administrator)) return null;\n\n return (\n <>\n <CompanyDetails />\n <AdminUsersList />\n </>\n );\n}\n\nexport function AdminCompanyContainer() {\n return <AdminCompanyContainerInternal />;\n}\n","\"use client\";\n\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { CompanyProvider } from \"../../contexts/CompanyContext\";\nimport { CompanyDetails } from \"../details/CompanyDetails\";\n\nexport function CompanyContainer() {\n const { currentUser } = useCurrentUserContext<UserInterface>();\n if (!currentUser) return null;\n\n return (\n <CompanyProvider dehydratedCompany={currentUser.company}>\n <CompanyDetails />\n </CompanyProvider>\n );\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Settings2Icon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport z from \"zod\";\nimport { CommonEditorButtons, errorToast } from \"../../../../components\";\nimport { getRoleId } from \"../../../../roles\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n Form,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { UserService } from \"../../../user/data/user.service\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { CompanyInput, CompanyInterface } from \"../../data\";\nimport { CompanyService } from \"../../data/company.service\";\nimport { CompanyConfigurationSecurityForm } from \"./CompanyConfigurationSecurityForm\";\n\ntype CompanyConfigurationEditorProps = {\n company: CompanyInterface;\n};\n\nfunction CompanyConfigurationEditorInternal({ company }: CompanyConfigurationEditorProps) {\n const [open, setOpen] = useState<boolean>(false);\n const t = useTranslations();\n const { setUser } = useCurrentUserContext<UserInterface>();\n\n const defaultValues = useMemo(() => {\n return {\n isManagedKnowledge: company.configurations?.isManagedKnowledge ?? false,\n allowPublicBot: company.configurations?.allowPublicBot ?? false,\n };\n }, [company.configurations]);\n\n const close = () => {\n setOpen(false);\n form.reset();\n };\n\n const formSchema = z.object({\n isManagedKnowledge: z.boolean().optional(),\n allowPublicBot: z.boolean().optional(),\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: defaultValues,\n shouldUnregister: false,\n });\n\n useEffect(() => {\n if (open) {\n form.reset({\n isManagedKnowledge: company.configurations?.isManagedKnowledge ?? false,\n allowPublicBot: company.configurations?.allowPublicBot ?? false,\n });\n }\n }, [company, open]);\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values) => {\n const payload: CompanyInput = {\n id: company.id,\n configurations: {\n isManagedKnowledge: values.isManagedKnowledge ?? false,\n allowPublicBot: values.allowPublicBot ?? false,\n },\n };\n\n try {\n await CompanyService.updateConfigurations(payload);\n\n // Refresh user data to update localStorage with new company configurations\n const fullUser = await UserService.findFullUser();\n if (fullUser) {\n setUser(fullUser);\n }\n\n toast.message(\"Configurations Updated\", {\n description: `The system configurations have been updated successfully.`,\n });\n close();\n } catch (error) {\n errorToast({\n title: t(`generic.errors.update`),\n error,\n });\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogTrigger asChild>\n <Button size=\"sm\" variant={`ghost`} className=\"cursor-pointer\">\n <Settings2Icon className=\"h-3.5 w-3.5\" />\n </Button>\n </DialogTrigger>\n <DialogContent className={`flex max-h-[70vh] max-w-4xl flex-col overflow-y-auto`}>\n <DialogHeader>\n <DialogTitle>{t(`types.configurations`, { count: 2 })}</DialogTitle>\n <DialogDescription className=\"text-destructive\">\n {t(`features.configuration.warning_description`)}\n </DialogDescription>\n </DialogHeader>\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className={`flex w-full flex-col gap-y-4`}>\n <div className={`flex flex-row gap-x-4`}>\n <div className={`flex w-full flex-col justify-start gap-y-4`}>\n <Tabs defaultValue={process.env.NEXT_PUBLIC_PRIVATE_INSTALLATION ? \"security\" : \"ai\"}>\n <TabsList>\n <TabsTrigger value=\"security\">Privacy & Security</TabsTrigger>\n </TabsList>\n <TabsContent value=\"features\">\n <div className=\"space-y-4\">\n <p className=\"text-muted-foreground text-sm\">\n Feature configuration will be implemented in future updates.\n </p>\n </div>\n </TabsContent>\n <TabsContent value=\"security\">\n <CompanyConfigurationSecurityForm form={form} />\n </TabsContent>\n </Tabs>\n </div>\n </div>\n <CommonEditorButtons form={form} setOpen={setOpen} isEdit={true} />\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport function CompanyConfigurationEditor(props: CompanyConfigurationEditorProps) {\n const { hasRole } = useCurrentUserContext<UserInterface>();\n\n if (hasRole(getRoleId().Administrator)) return <CompanyConfigurationEditorInternal {...props} />;\n\n return <CompanyConfigurationEditorInternal {...props} />;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { UseFormReturn } from \"react-hook-form\";\nimport { Checkbox, FormControl, FormField, FormItem, FormLabel, FormMessage, Input } from \"../../../../shadcnui\";\n\ntype SecurityConfigurationFormProps = {\n form: UseFormReturn<any>;\n};\n\ntype Fields = {\n fields: string[];\n defaults: Record<string, any>;\n};\n\nconst providerConfig: Fields = {\n fields: [\"isManagedKnowledge\", \"allowPublicBot\"],\n defaults: {},\n};\n\nexport function CompanyConfigurationSecurityForm({ form }: SecurityConfigurationFormProps) {\n const t = useTranslations();\n\n const renderProviderFields = () => {\n const config = providerConfig;\n if (!config) return null;\n\n return config.fields.map((currentField) => {\n const isRequired = currentField === \"\";\n\n let label = \"\";\n let placeholder = \"\";\n let type = \"text\";\n\n switch (currentField) {\n case \"isManagedKnowledge\":\n label = \"Limit Require structured knowledge management\";\n placeholder =\n \"Enforce single-nesting expertises, require expertise associations to content, and enable knowledge manager roles for better long-term organization.\";\n type = \"checkbox\";\n break;\n case \"allowPublicBot\":\n label = \"Allow Public Bot\";\n placeholder = \"Enable this to allow the public to access public information.\";\n type = \"checkbox\";\n break;\n }\n\n return (\n <FormField\n key={currentField}\n control={form.control}\n name={currentField}\n render={({ field: formField }) =>\n type === \"checkbox\" ? (\n <FormItem className=\"flex items-start space-x-4\">\n <FormControl>\n <Checkbox\n id={currentField}\n checked={formField.value}\n onCheckedChange={(checked) => {\n return checked ? formField.onChange(true) : formField.onChange(false);\n }}\n />\n </FormControl>\n <div className=\"grid gap-2\">\n <FormLabel htmlFor={currentField}>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </FormLabel>\n <p className=\"text-muted-foreground text-sm\">{placeholder}</p>\n </div>\n <FormLabel></FormLabel>\n <FormMessage />\n </FormItem>\n ) : (\n <FormItem>\n <FormLabel>\n {label} {isRequired && <span className=\"text-destructive\">*</span>}\n </FormLabel>\n <FormControl>\n <Input type={type} placeholder={placeholder} {...formField} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )\n }\n />\n );\n });\n };\n\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-4 border-t pt-4\">{renderProviderFields()}</div>\n </div>\n );\n}\n","\"use client\";\n\nimport { LoaderCircleIcon, Trash2Icon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useState } from \"react\";\nimport { errorToast } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { useI18nRouter } from \"../../../../i18n\";\nimport { Action } from \"../../../../permissions\";\nimport { getRoleId } from \"../../../../roles\";\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n Button,\n Input,\n Label,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { CompanyInterface } from \"../../data\";\nimport { CompanyService } from \"../../data/company.service\";\n\ntype CompanyDeleterProps = {\n company: CompanyInterface;\n};\n\nfunction CompanyDeleterInternal({ company }: CompanyDeleterProps) {\n const t = useTranslations();\n const router = useI18nRouter();\n const [open, setOpen] = useState<boolean>(false);\n const [isDeleting, setIsDeleting] = useState<boolean>(false);\n const [companyName, setCompanyName] = useState<string>(\"\");\n\n const handleDelete = async () => {\n setIsDeleting(true);\n try {\n await CompanyService.delete({ companyId: company.id });\n router.push(\"/\");\n } catch (error) {\n errorToast({ title: t(`generic.errors.delete`), error: error });\n }\n setIsDeleting(false);\n };\n\n return (\n <AlertDialog open={open} onOpenChange={setOpen}>\n <AlertDialogTrigger asChild>\n <Button size=\"sm\" variant={\"destructive\"}>\n <Trash2Icon className=\"mr-3 h-3.5 w-3.5\" />\n {t(`generic.buttons.delete`)}\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>\n <AlertDialogHeader>\n <AlertDialogTitle>{t(`generic.delete.title`, { type: t(`types.companies`, { count: 1 }) })}</AlertDialogTitle>\n <AlertDialogDescription>\n {t(`generic.delete.subtitle`, { type: t(`types.companies`, { count: 1 }) })}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <div className=\"text-destructive p-4 text-sm\">\n {t(`generic.delete.description`, { type: t(`types.companies`, { count: 1 }) })}\n </div>\n <div className=\"flex w-full flex-col gap-y-2\">\n <div>{t(`generic.delete.confirmation`, { type: t(`types.companies`, { count: 1 }) })}</div>\n <div className=\"flex w-full flex-col\">\n <Label className=\"flex items-center\">\n {t(`foundations.company.fields.name.label`)}\n <span className=\"text-destructive ml-2 font-semibold\">*</span>\n </Label>\n <Input\n className={`w-full`}\n placeholder={t(`foundations.company.fields.name.placeholder`)}\n onChange={(e) => setCompanyName(e.target.value)}\n />\n </div>\n </div>\n <div className=\"flex justify-end\">\n <Button\n className=\"mr-2\"\n variant={\"outline\"}\n type={`button`}\n onClick={() => setOpen(false)}\n disabled={isDeleting}\n >\n {t(`generic.buttons.cancel`)}\n </Button>\n <Button\n type=\"submit\"\n onClick={(e) => {\n e.preventDefault();\n handleDelete();\n }}\n variant={\"destructive\"}\n disabled={company.name !== companyName || isDeleting}\n >\n {isDeleting ? (\n <>\n {t(`generic.buttons.is_deleting`)}\n <LoaderCircleIcon className=\"animate-spin-slow h-5 w-5\" />\n </>\n ) : (\n t(`generic.buttons.delete`)\n )}\n </Button>\n </div>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n\nexport function CompanyDeleter({ company }: CompanyDeleterProps) {\n const { hasPermissionToModule, hasRole } = useCurrentUserContext<UserInterface>();\n\n if (!hasRole(getRoleId().Administrator) && !hasPermissionToModule({ module: Modules.Company, action: Action.Delete }))\n return null;\n\n return <CompanyDeleterInternal company={company} />;\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { setCookie } from \"cookies-next\";\nimport { UploadIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { DropzoneOptions } from \"react-dropzone\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { v4 } from \"uuid\";\nimport { z } from \"zod\";\nimport {\n CommonEditorButtons,\n CommonEditorHeader,\n CommonEditorTrigger,\n errorToast,\n FileInput,\n FileUploader,\n FormFeatures,\n FormInput,\n} from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { useI18nRouter } from \"../../../../i18n\";\nimport { getRoleId } from \"../../../../roles\";\nimport { Dialog, DialogContent, Form, ScrollArea } from \"../../../../shadcnui\";\nimport { FeatureInterface } from \"../../../feature\";\nimport { S3Interface } from \"../../../s3\";\nimport { FeatureService } from \"../../../feature/data/feature.service\";\nimport { S3Service } from \"../../../s3/data/s3.service\";\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { CompanyInput, CompanyInterface } from \"../../data\";\nimport { CompanyService } from \"../../data/company.service\";\n\ntype CompanyEditorProps = {\n company?: CompanyInterface;\n propagateChanges?: (company: CompanyInterface) => void;\n onRevalidate?: (path: string) => Promise<void>;\n};\n\nfunction CompanyEditorInternal({ company, propagateChanges, onRevalidate }: CompanyEditorProps) {\n const { hasRole } = useCurrentUserContext<UserInterface>();\n const router = useI18nRouter();\n const [open, setOpen] = useState<boolean>(false);\n const [features, setFeatures] = useState<FeatureInterface[]>([]);\n const [file, setFile] = useState<File | null>(null);\n const [files, setFiles] = useState<File[] | null>(null);\n const [contentType, setContentType] = useState<string | null>(null);\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n\n const formSchema = z.object({\n id: z.uuidv4(),\n name: z.string().min(1, {\n message: t(`foundations.company.fields.name.error`),\n }),\n featureIds: z.array(z.string()).optional(),\n moduleIds: z.array(z.string()).optional(),\n logo: z.string().optional(),\n });\n\n const form = useForm({\n resolver: zodResolver(formSchema),\n defaultValues: {\n id: company?.id || v4(),\n name: company?.name || \"\",\n featureIds: company?.features.map((feature) => feature.id) || [],\n moduleIds: company?.modules.map((module) => module.id) || [],\n logo: company?.logo || \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n if (values.logo && contentType) {\n const s3: S3Interface = await S3Service.getPreSignedUrl({\n key: values.logo,\n contentType: contentType,\n isPublic: true,\n });\n\n await fetch(s3.url, {\n method: \"PUT\",\n headers: s3.headers,\n body: file,\n });\n }\n\n const payload: CompanyInput = {\n id: company?.id ?? v4(),\n name: values.name,\n logo: files && contentType ? values.logo : undefined,\n featureIds: values.featureIds,\n moduleIds: values.moduleIds,\n };\n\n try {\n const updatedCompany = company ? await CompanyService.update(payload) : await CompanyService.create(payload);\n\n if (onRevalidate) {\n await onRevalidate(generateUrl({ page: Modules.Company, id: updatedCompany.id, language: `[locale]` }));\n }\n if (company && propagateChanges) {\n setCookie(\"reloadData\", \"true\", { path: \"/\" });\n propagateChanges(updatedCompany);\n setOpen(false);\n } else {\n router.push(`/administration/companies/${updatedCompany.id}`);\n }\n } catch (error) {\n errorToast({\n title: company ? t(`generic.errors.update`) : t(`generic.errors.create`),\n error,\n });\n }\n };\n\n useEffect(() => {\n async function fetchFeatures() {\n const allfeatures = await FeatureService.findMany({});\n if (hasRole(getRoleId().Administrator)) {\n setFeatures(allfeatures);\n } else {\n setFeatures(allfeatures.filter((feature) => feature.isProduction));\n }\n }\n if (\n open &&\n features.length === 0 &&\n (hasRole(getRoleId().Administrator) ||\n (hasRole(getRoleId().CompanyAdministrator) &&\n process.env.NEXT_PUBLIC_PRIVATE_INSTALLATION?.toLowerCase() === \"true\"))\n )\n fetchFeatures();\n }, [open, features]);\n\n useEffect(() => {\n if (file && company) {\n const id = form.getValues(\"id\");\n const fileType = file.type;\n let extension = \"\";\n\n switch (fileType) {\n default:\n extension = file.type.split(\"/\").pop() ?? \"\";\n break;\n }\n\n const timestamp = new Date().toISOString().replace(/[-:T]/g, \"\").split(\".\")[0];\n\n const fileUrl = `companies/${form.getValues(\"id\")}/companies/${id}/${id}.${timestamp}.${extension}`;\n form.setValue(\"logo\", fileUrl);\n\n setContentType(fileType);\n } else {\n setContentType(null);\n }\n }, [file]);\n\n useEffect(() => {\n if (files && files.length > 0) {\n setFile(files[0]);\n }\n }, [files]);\n\n const dropzone = {\n multiple: false,\n maxSize: 100 * 1024 * 1024,\n preventDropOnDocument: false,\n accept: {\n \"application/images\": [\".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".svg\"],\n },\n } satisfies DropzoneOptions;\n\n const canAccessFeatures =\n hasRole(getRoleId().Administrator) ||\n (hasRole(getRoleId().CompanyAdministrator) &&\n process.env.NEXT_PUBLIC_PRIVATE_INSTALLATION?.toLowerCase() === \"true\");\n\n const isAdministrator = hasRole(getRoleId().Administrator);\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <CommonEditorTrigger isEdit={!!company} />\n <DialogContent\n className={`flex max-h-[70vh] w-full ${isAdministrator || canAccessFeatures ? `max-w-5xl` : `max-w-4xl`} flex-col overflow-y-auto`}\n >\n <CommonEditorHeader type={t(`types.companies`, { count: 1 })} name={company?.name} />\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className={`flex w-full flex-col gap-y-4`}>\n <div className=\"flex w-full items-start justify-between gap-x-4\">\n <div className={`flex w-96 flex-col justify-start gap-y-4`}>\n <FileUploader value={files} onValueChange={setFiles} dropzoneOptions={dropzone} className=\"w-full p-4\">\n <FileInput className=\"text-neutral-300 outline-dashed\">\n <div className=\"flex w-full flex-col items-center justify-center pt-3 pb-4\">\n <div className=\"flex w-full flex-col items-center justify-center pt-3 pb-4\">\n {file || company?.logo ? (\n <Image\n src={file ? URL.createObjectURL(file) : company?.logo || \"\"}\n alt=\"Company Logo\"\n width={200}\n height={200}\n />\n ) : (\n <>\n <UploadIcon className=\"my-4 h-8 w-8\" />\n <p className=\"mb-1 flex w-full text-center text-sm\">\n {t(`foundations.company.click_drag_logo`)}\n </p>\n </>\n )}\n </div>\n </div>\n </FileInput>\n </FileUploader>\n </div>\n <div className={`flex w-full flex-col justify-start gap-y-4`}>\n <FormInput\n form={form}\n id=\"name\"\n name={t(`foundations.company.fields.name.label`)}\n placeholder={t(`foundations.company.fields.name.placeholder`)}\n />\n </div>\n {canAccessFeatures && (\n <div className={`flex w-96 flex-col justify-start gap-y-4`}>\n <ScrollArea className=\"h-max\">\n <FormFeatures\n form={form}\n name={t(`foundations.company.features_and_modules`)}\n features={features}\n />\n </ScrollArea>\n </div>\n )}\n </div>\n <CommonEditorButtons form={form} setOpen={setOpen} isEdit={!!company} />\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n}\n\nexport function CompanyEditor(props: CompanyEditorProps) {\n return <CompanyEditorInternal {...props} />;\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { deleteCookie } from \"cookies-next\";\nimport { ClipboardIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport z from \"zod\";\nimport { errorToast, FormInput, FormTextarea } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { useI18nRouter, usePageUrlGenerator } from \"../../../../hooks\";\nimport { getRoleId } from \"../../../../roles\";\nimport {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n Form,\n Input,\n Label,\n Link,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { UserService } from \"../../../user/data/user.service\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { CompanyInput } from \"../../data\";\nimport { CompanyService } from \"../../data/company.service\";\n\ntype TokenPayload = {\n userId: string;\n companyId?: string;\n licenseExpirationDate?: Date;\n roles: string[];\n features: string[];\n modules: {\n id: string;\n permissions: {\n create: boolean | string;\n read: boolean | string;\n update: boolean | string;\n delete: boolean | string;\n };\n }[];\n};\n\ntype CompanyLicenseProps = {\n onRevalidate?: (path: string) => Promise<void>;\n onUpdateToken?: (token: TokenPayload) => Promise<void>;\n};\n\nexport default function CompanyLicense({ onRevalidate, onUpdateToken }: CompanyLicenseProps = {}) {\n const { currentUser, setUser, hasRole } = useCurrentUserContext<UserInterface>();\n\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n const router = useI18nRouter();\n\n const copyToClipboard = (text: string) => {\n navigator.clipboard.writeText(text);\n toast(\"Copied to clipboard\");\n };\n\n const formSchema = z.object({\n license: z.string().min(1, {\n message: `License is required`,\n }),\n privateKey: z.string().min(1, {\n message: `Private key is required`,\n }),\n });\n\n const defaultValues = {\n license:\n \"09001678dca2f4a6d2d32bb984811278:3e93a432f6130579e543a511346c0d2c6ca7a97d49c7ff2d3e789ca7c7c8d79b864fd3406c8315e72aa5febf6232776dfaea51d72168ddcdd34a59ea1a05b3b3dd60ac3af6c3934203d19ea68642293aa5b79f012633b4ba2e4a474e9ceed6b6cda13d8dedc8e60ece61886843ee6edc1af6d2da5e07945033295507df6f87994f8347b5759b446aa20b1185d7b5c54c67509ae280e729913d0e68e95b5f090b0577a8a735f24fb7c1df8f6586886d840af4a43f9dc74d5d1f291058a45ace759176fa19fe5e164f5d8307981e8bcd166f346e97b676dd0242d1c30ec4fe744f22621fae603b1caaac25f198d2b29be0e0f2afc81a40edeb20242345e2feac8666027d0c30aa8dadbca742dd68ade46602545979f473b344021d27921553d5b284fd96a717b74573ca7e693723876357013e3c0d07a35d270a0e32654d2c244220e2492380279aa34a4744d145b89d06a8abef49cc2ef0dd0171e0eefcf16724decf53e545d10d9bfd8e0c4b03ca720b0fc63d8a20ca2c71d74cb0cf7e547637dbcc8d27257414b5b0b40eabe9eb53a4b5f61ca2250d5933a13565f785a89fc5e3e3c468acbeddf14627aa4109f32af641fc96513e52edc21849e81331cafc900ea85f58927d583aafe5a959af69ce5c967d0cd5d9050cf6601a615e8e3ccf32e6a04227f1f228d94f9bd24073c7b0ec2550f4efc69bddde745144dcb279864fb3e7e7d57d1e96d0701b55f0d6f3bd688880e4a78adb0974cba278cd34bc02753e8a736a4b3a4e48afdf206b9330fee4e29a3c28dec8457e0f44adc10735c1d1992b798e0dd710053ce98ff38b6ff59004079a5face769950401b49fdc13e4cd3324d7df2cf0f40593f51c117debbafd\",\n privateKey:\n \"-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCKDXrjEXBcYx6p\\nChtixITGiFqZeaurD3n2SeJl8QuniKlbl7ytC71gS9BzIG5Q/ENhAE41qa7FaHdN\\nHLQ2anfAjS/wd/41wx9ilvQeN/IcDb5Dx3Qd07OMLdrgDvkhlUPSvt7Y5/yft1IX\\nS8NaDrKoO4zjpVB9SeLYGyFXmfP0ciJ97AkWDfXp3l2WjwwxEQByo5uXOMzpEZla\\nkqBFy7kkO3c/SJWqnuXbXrUVr7AjZ9zMCPP/NbvvOkGzovrOYHN5WO9Rg7m+wIFK\\n+gTL2e3RnyjUUSoX5/NMZO9oyDNEaaWgIv6LOG72A2Xq55gpNQihjltZWd/o+xFb\\nIRZzbmllAgMBAAECggEABrrvgcBo5OgkJ4OJoEAKZQ9is1a+KsG/ZWVmtyeQNOOx\\ntfhox1rqKZaom+Q53JLfygvUxEL4dUFJh6Xdl0WLfwSjEKsY5pATqJ/JWOvLTtjQ\\nrMc9fvLCLxRRNlkkhiGbw9twS8zLgRHT27Ti2jIbPZ5hmPuHOARxHa386yNjREh1\\n14Vlhk+dvhmqtYt11AKWuU8nHuf92wCCetATUg/pfNQ1itf6XDlygUZTl4GkoJg/\\nVrt1MnsrTKcGzP+gvpNH0aOuUbgtUWtBIKaSuGgY6lMMny6AApeJ+kXZR8cyPVSi\\nYm/185AcxQDlPunoyl3QzvV41zJUccoMI576wFTUQQKBgQC8QQtNXjfcQvYDeVv8\\ntWKAxgk+OE6/3ntLkbYxPw2H5IOikhb5OjNirzUzRs4CKjnGhx0zDzCi4TV2xwZf\\nwDHpd9VEhEXmKBJe43RCQs0vb1jwz4ttRk9eoz1Oa4cNij3yH5F4oNu5ZnOSZWi/\\n1c4mIsGjjTWzeOkJ6J+fCc6ztQKBgQC7u53nuvMubVhNW3FyuHaXuE+nUlNaw2gc\\n9mhm17DY+MBf2YqdJOCY1B44WMIZe3k/75qXrZEYG4ikdlAGzrh7q3/8GMKCxk8P\\n5y+YeKODdURM1SsUoOqAzga7s2vFxnChtWxk3KfXCzjKUoX/9zWX/zfIAl9VsVVC\\nhrARyffM8QKBgC6pIJgIpmfd4QRzbC1y9/tbGqdlZX+BMaZFc5c5Pa1VIpuFAlS7\\n7EiljNYs0psOxEtE6iPhu/hjQdEy+414IebwYNgewQSPIh6K2iIiVKFRRAZMKw7m\\nwn1+kI+Db3IXtcrxsCjqFgwaLMM4h4IlCHfDXaOgOJNHgNuH4SiWUbmRAoGAUGD4\\nLuugi1RN5nEslc3dGQDVOfLJtabMwPnPoZjgI0X+OAvQiY/sigLoHYADOx3ewD06\\nl468/PFtA92UThXcbzbyyWFghtWZrFlzy3h7qiFfaPYsR9zOCvAredpMXpWkS9h9\\n3IGNa0lmu1mx/fI+hCHGJGC/qNUQiDda04MCEkECgYAxDhQW7sRox+7Pn0TsRotN\\nTv6AJggyTjBaF45fVy+28sn53f/9HE++Rxn8W5xQl+hEOywT95OcWB9b4CiZsp1P\\nZyjkByeUuraVM1DoFh66UdXUvC2FECdyz4N3JyKHvV82GdrTPsQLVPCsGfzkj7V8\\nX+iuQoeEbUvwnnrg3pbClQ==\\n-----END PRIVATE KEY-----\\n\",\n };\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: defaultValues,\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n if (!currentUser || !currentUser.company) {\n errorToast({\n title: t(\"generic.errors.error\"),\n error: new Error(\"User or company not found\"),\n });\n return;\n }\n\n const payload: CompanyInput = {\n id: currentUser.company.id,\n license: values.license,\n privateKey: values.privateKey,\n };\n\n try {\n const updatedLicense = await CompanyService.activateLicense(payload);\n\n const fullUser = await UserService.findFullUser();\n\n if (fullUser) {\n setUser(fullUser);\n const token = {\n userId: fullUser.id,\n companyId: fullUser.company?.id,\n licenseExpirationDate: fullUser.company?.licenseExpirationDate,\n roles: fullUser.roles.map((role) => role.id),\n features: fullUser.company?.features?.map((feature) => feature.id) ?? [],\n modules: fullUser.modules.map((module) => {\n return { id: module.id, permissions: module.permissions };\n }),\n };\n\n if (onUpdateToken) {\n await onUpdateToken(token);\n }\n deleteCookie(\"reloadData\");\n }\n\n if (onRevalidate) {\n await onRevalidate(generateUrl({ page: Modules.Company, id: updatedLicense.id, language: `[locale]` }));\n }\n router.push(generateUrl({ page: \"/\" }));\n } catch (error) {\n errorToast({\n title: t(`generic.errors.update`),\n error,\n });\n }\n };\n\n if (!currentUser || !currentUser.company) return null;\n\n return (\n <Form {...form}>\n <form\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"relative flex min-h-screen w-full flex-col items-center justify-center\"\n >\n <div className=\"absolute top-4 left-4 z-0\">\n <Image src={`/logo.webp`} className=\"object-contain p-4\" height={300} width={300} alt={\"Logo\"} priority />\n </div>\n <Card className=\"z-10 w-3xl\">\n {hasRole(getRoleId().CompanyAdministrator) ? (\n <>\n <CardHeader>\n <CardTitle>Company License Required</CardTitle>\n <CardDescription className={`flex w-full flex-col`}>\n <div>You need to activate your license to use Phlow.</div>\n <div>\n <span>To obtain your license, please visit</span>\n <Link href=\"https://phlow.com\" target=\"_blank\" className={`text-primary`}>\n our website (https://phlow.com)\n </Link>\n <span>, register for an account and follow the instructions provided.</span>\n </div>\n <div>You will be required to provide the installation identifier provided below.</div>\n <div>\n Once you have activated your license, please paste your license and private key in the fields below.\n </div>\n </CardDescription>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-y-4\">\n <div>\n <Label>Installation Identifier</Label>\n <div className=\"flex items-center\">\n <Input disabled value={currentUser.company.id} />\n <ClipboardIcon\n className=\"text-muted-foreground ml-2 cursor-pointer\"\n onClick={() => copyToClipboard(currentUser!.company!.id)}\n />\n </div>\n </div>\n <div>\n <FormInput form={form} id=\"license\" name={\"license\"} placeholder=\"Enter your license\" />\n </div>\n <div>\n <FormTextarea name=\"Private Key\" form={form} id=\"privateKey\" placeholder=\"Enter your private key\" />\n </div>\n </CardContent>\n <CardFooter className=\"flex justify-end\">\n <Button type=\"submit\">Activate License</Button>\n </CardFooter>\n </>\n ) : (\n <>\n <CardHeader>\n <CardTitle>Company License Required</CardTitle>\n <CardDescription className={`flex w-full flex-col`}>\n The company license is either missing or expired.\n </CardDescription>\n </CardHeader>\n <CardContent>Please contact your system administrator to resolve this issue.</CardContent>\n </>\n )}\n </Card>\n </form>\n </Form>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ReactNode } from \"react\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { CompanyFields, CompanyInterface } from \"../../data\";\nimport { CompanyService } from \"../../data/company.service\";\nimport { CompanyEditor } from \"../forms/CompanyEditor\";\n\nexport function CompaniesList() {\n const t = useTranslations();\n\n const data: DataListRetriever<CompanyInterface> = useDataListRetriever({\n retriever: (params) => CompanyService.findMany(params),\n retrieverParams: {},\n module: Modules.Company,\n });\n\n const functions: ReactNode[] = [<CompanyEditor key=\"create-account\" />];\n\n return (\n <ContentListTable\n data={data}\n fields={[CompanyFields.name, CompanyFields.createdAt]}\n tableGeneratorType={Modules.Company}\n functions={functions}\n title={t(`types.companies`, { count: 2 })}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport React, { createContext, ReactElement, useCallback, useContext, useState } from \"react\";\nimport { SharedProvider } from \"../../../contexts\";\nimport { Modules } from \"../../../core\";\nimport { useI18nRouter } from \"../../../i18n\";\nimport { BreadcrumbItemData } from \"../../../interfaces\";\nimport { NotificationMenuItem, NotificationToast } from \"../components/notifications/Notification\";\nimport { NotificationInterface } from \"../data\";\nimport { NotificationService } from \"../data/notification.service\";\n\ninterface NotificationContextType {\n notifications: NotificationInterface[];\n setNotifications: (notifications: NotificationInterface[]) => void;\n addNotification: (notification: NotificationInterface) => void;\n addSocketNotifications: (socketNotifications: NotificationInterface[]) => void;\n loadNotifications: () => Promise<void>;\n generateNotification: (notification: NotificationInterface, closePopover: () => void) => ReactElement<any>;\n generateToastNotification: (\n notification: NotificationInterface,\n t: any,\n generateUrl: any,\n ) => {\n title: string;\n description: string | ReactElement<any>;\n action?: {\n label: string;\n onClick: () => void;\n };\n };\n markNotificationsAsRead: (ids: string[]) => Promise<void>;\n isLoading: boolean;\n error: string | null;\n lastLoaded: number;\n shouldRefresh: boolean;\n}\n\nconst NotificationContext = createContext<NotificationContextType | undefined>(undefined);\n\ntype NotificationContextProviderProps = {\n children: React.ReactNode;\n};\n\nexport const NotificationContextProvider = ({ children }: NotificationContextProviderProps) => {\n const t = useTranslations();\n const router = useI18nRouter();\n\n const [notifications, setNotifications] = useState<NotificationInterface[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [lastLoaded, setLastLoaded] = useState(0);\n\n // Calculate shouldRefresh (5 minute cache)\n const shouldRefresh = Date.now() - lastLoaded > 5 * 60 * 1000;\n\n const addNotification = useCallback((notification: NotificationInterface) => {\n setNotifications((prev) => {\n // Check if notification already exists to prevent duplicates\n const exists = prev.some((n) => n.id === notification.id);\n if (exists) return prev;\n return [notification, ...prev];\n });\n }, []);\n\n const addSocketNotifications = useCallback((socketNotifications: NotificationInterface[]) => {\n setNotifications((prev) => {\n const newNotifications = socketNotifications.filter(\n (newNotif) => !prev.some((existingNotif) => existingNotif.id === newNotif.id),\n );\n return [...prev, ...newNotifications];\n });\n }, []);\n\n const loadNotifications = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n const fetchedNotifications = await NotificationService.findMany({});\n setNotifications(fetchedNotifications);\n setLastLoaded(Date.now());\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Failed to load notifications\";\n setError(errorMessage);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const markNotificationsAsRead = useCallback(async (ids: string[]) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const data: any = {\n data: ids.map((id: string) => ({\n type: Modules.Notification.name,\n id: id,\n attributes: {\n isRead: true,\n },\n meta: {},\n relationships: {},\n })),\n };\n\n await NotificationService.markAsRead({ data: data });\n const allNotifications = await NotificationService.findMany({});\n setNotifications(allNotifications);\n setLastLoaded(Date.now());\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Failed to mark notifications as read\";\n setError(errorMessage);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const generateToastNotification = (\n notification: NotificationInterface,\n t: any,\n generateUrl: any,\n ): {\n title: string;\n description: string | ReactElement<any>;\n action?: {\n label: string;\n onClick: () => void;\n };\n } => {\n return NotificationToast(notification, t, generateUrl, router);\n };\n\n const generateNotification = (notification: NotificationInterface, closePopover: () => void) => {\n return <NotificationMenuItem notification={notification} closePopover={closePopover} />;\n };\n\n const breadcrumb = () => {\n const response: BreadcrumbItemData[] = [];\n\n response.push({\n name: t(`types.notifications`, { count: 2 }),\n });\n\n return response;\n };\n\n const title = () => {\n const response: any = {\n type: t(`types.notifications`, { count: 2 }),\n };\n\n return response;\n };\n\n return (\n <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>\n <NotificationContext.Provider\n value={{\n notifications,\n setNotifications,\n addNotification,\n addSocketNotifications,\n loadNotifications,\n generateNotification,\n generateToastNotification,\n markNotificationsAsRead,\n isLoading,\n error,\n lastLoaded,\n shouldRefresh,\n }}\n >\n {children}\n </NotificationContext.Provider>\n </SharedProvider>\n );\n};\n\nexport const useNotificationContext = (): NotificationContextType => {\n const context = useContext(NotificationContext);\n if (context === undefined) {\n throw new Error(`Notification.messages.errors.use_context`);\n }\n return context;\n};\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ReactElement, useEffect, useState } from \"react\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { Link } from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { UserAvatar } from \"../../../user/components\";\nimport { NotificationInterface } from \"../../data\";\n\ntype TaskCommentedOnProps = {\n notification: NotificationInterface;\n closePopover: () => void;\n};\n\nexport const generateNotificationData = (params: {\n notification: NotificationInterface;\n generateUrl: any;\n}): { title: string; actor?: UserInterface; url?: string; taskId?: string } => {\n const response: any = {};\n\n response.actor = params.notification.actor;\n\n return response;\n};\n\nexport function NotificationToast(\n notification: NotificationInterface,\n t: any,\n generateUrl: any,\n reouter: any,\n): {\n title: string;\n description: string | ReactElement<any>;\n action?: {\n label: string;\n onClick: () => void;\n };\n} {\n const data = generateNotificationData({ notification: notification, generateUrl: generateUrl });\n\n return {\n title: t(`foundations.notification.${notification.notificationType}.title`),\n description: (\n <div className={`flex w-full flex-row items-center p-2`}>\n {data.actor ? (\n <div className=\"flex w-12 max-w-12 px-2\">\n <UserAvatar user={data.actor} className=\"h-8 w-8\" />\n </div>\n ) : (\n <div className=\"flex w-14 max-w-14 px-2\"></div>\n )}\n <div className=\"flex w-full flex-col\">\n <p className=\"text-sm\">\n {t.rich(`foundations.notification.${notification.notificationType}.description`, {\n strong: (chunks: any) => <strong>{chunks}</strong>,\n actor: data.actor?.name ?? \"\",\n title: data.title,\n })}\n </p>\n <div className=\"text-muted-foreground mt-1 w-full text-xs\">\n {new Date(notification.createdAt).toLocaleString()}\n </div>\n </div>\n </div>\n ),\n action: data.url\n ? {\n label: t(`foundations.notification.${notification.notificationType}.buttons.action`),\n onClick: () => {\n reouter.push(data.url!);\n },\n }\n : undefined,\n };\n}\n\nexport function NotificationMenuItem({ notification, closePopover }: TaskCommentedOnProps) {\n const generateUrl = usePageUrlGenerator();\n const [isRead, setIsRead] = useState<boolean>(false);\n const t = useTranslations();\n\n useEffect(() => {\n setIsRead(notification.isRead);\n }, []);\n\n const data = generateNotificationData({ notification: notification, generateUrl: generateUrl });\n\n const response = (\n <div className={`flex w-full flex-row p-2 ${isRead ? \"\" : \"bg-muted\"} items-center`}>\n {data.actor ? (\n <div className=\"flex w-12 max-w-12 px-2\">\n <UserAvatar user={data.actor} className=\"h-8 w-8\" />\n </div>\n ) : (\n <div className=\"flex w-14 max-w-14 px-2\"></div>\n )}\n <div className=\"flex w-full flex-col\">\n <p className=\"text-sm\">\n {t.rich(`foundations.notification.${notification.notificationType}.description` as any, {\n strong: (chunks: any) => <strong>{chunks}</strong>,\n actor: data.actor?.name ?? \"\",\n title: data.title,\n })}\n </p>\n <div className=\"text-muted-foreground mt-1 w-full text-xs\">\n {new Date(notification.createdAt).toLocaleString()}\n </div>\n </div>\n </div>\n );\n\n if (!data.url) return response;\n\n return (\n <Link href={data.url} onClick={closePopover}>\n {response}\n </Link>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { createContext, ReactNode, useContext, useState } from \"react\";\nimport { SharedProvider } from \"../../../contexts\";\nimport { JsonApiHydratedDataInterface, Modules, rehydrate } from \"../../../core\";\nimport { usePageUrlGenerator } from \"../../../hooks\";\nimport { BreadcrumbItemData } from \"../../../interfaces\";\nimport { RoleInterface } from \"../data\";\n\ninterface RoleContextType {\n role: RoleInterface | undefined;\n setRole: (value: RoleInterface | undefined) => void;\n}\n\nconst RoleContext = createContext<RoleContextType | undefined>(undefined);\n\ntype RoleProviderProps = {\n children: ReactNode;\n dehydratedRole?: JsonApiHydratedDataInterface;\n};\n\nexport const RoleProvider = ({ children, dehydratedRole }: RoleProviderProps) => {\n const generateUrl = usePageUrlGenerator();\n const t = useTranslations();\n\n const [role, setRole] = useState<RoleInterface | undefined>(\n dehydratedRole ? rehydrate<RoleInterface>(Modules.Role, dehydratedRole) : undefined,\n );\n\n const breadcrumb = () => {\n const response: BreadcrumbItemData[] = [];\n\n response.push({\n name: t(`types.roles`, { count: 2 }),\n href: generateUrl({ page: Modules.Role }),\n });\n\n if (role)\n response.push({\n name: role.name,\n href: generateUrl({ page: Modules.Role, id: role.id }),\n });\n\n return response;\n };\n\n const title = () => {\n const response: any = {\n type: t(`types.roles`, { count: role ? 1 : 2 }),\n };\n\n const functions: ReactNode[] = [];\n\n if (role) {\n response.element = role.name;\n }\n\n if (functions.length > 0) response.functions = functions;\n\n return response;\n };\n\n return (\n <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>\n <RoleContext.Provider\n value={{\n role: role,\n setRole: setRole,\n }}\n >\n {children}\n </RoleContext.Provider>\n </SharedProvider>\n );\n};\n\nexport const useRoleContext = (): RoleContextType => {\n const context = useContext(RoleContext);\n if (context === undefined) {\n throw new Error(\"useRoleContext must be used within a RoleProvider\");\n }\n return context;\n};\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\n\nimport { createContext, ReactNode, useContext } from \"react\";\nimport { UserInterface } from \"../features/user/data\";\nimport { useCurrentUserContext } from \"../features/user/contexts\";\nimport { BreadcrumbItemData } from \"../interfaces\";\nimport { SharedProvider } from \"./SharedContext\";\n\ninterface CommonContextType {}\n\nconst CommonContext = createContext<CommonContextType | undefined>(undefined);\n\ntype CommonProviderProps = {\n children: ReactNode;\n};\n\nexport const CommonProvider = ({ children }: CommonProviderProps) => {\n const { company } = useCurrentUserContext<UserInterface>();\n const t = useTranslations();\n\n const breadcrumb = () => {\n const response: BreadcrumbItemData[] = [];\n\n return response;\n };\n\n const title = () => {\n const response: any = {\n type: t(`generic.title`),\n };\n\n if (company) response.element = company.name;\n\n return response;\n };\n\n return (\n <SharedProvider value={{ breadcrumbs: breadcrumb(), title: title() }}>\n <CommonContext.Provider value={{}}>{children}</CommonContext.Provider>\n </SharedProvider>\n );\n};\n\nexport const useCommonContext = (): CommonContextType => {\n const context = useContext(CommonContext);\n if (context === undefined) {\n throw new Error(\"useCommonContext must be used within a CommonProvider\");\n }\n return context;\n};\n","\"use client\";\n\nimport { createContext, ReactNode, useContext } from \"react\";\nimport { BreadcrumbItemData } from \"../interfaces\";\n\nconst SharedContext = createContext<{\n breadcrumbs: BreadcrumbItemData[];\n title: {\n type: string | string[];\n element?: string;\n functions?: ReactNode;\n };\n} | null>(null);\n\ninterface SharedProviderProps {\n children: ReactNode;\n value: {\n breadcrumbs: BreadcrumbItemData[];\n title: {\n type: string;\n element?: string;\n functions?: ReactNode;\n };\n };\n}\n\nexport const SharedProvider = ({ children, value }: SharedProviderProps) => {\n return <SharedContext.Provider value={value}>{children}</SharedContext.Provider>;\n};\n\nexport const useSharedContext = () => {\n const context = useContext(SharedContext);\n if (!context) {\n throw new Error(\"useSharedContext must be used within a SharedProvider\");\n }\n return context;\n};\n","\"use client\";\n\nimport React, { createContext, useContext } from \"react\";\nimport { NotificationInterface } from \"../features/notification/data\";\nimport { useSocket } from \"../hooks\";\n\ninterface SocketContextProps {\n socket: ReturnType<typeof useSocket>[\"socket\"];\n isConnected: boolean;\n messages: any[];\n socketNotifications: NotificationInterface[];\n sendMessage: (event: string, data: any) => void;\n removeMessage: (index: number) => void;\n removeSocketNotification: (index: number) => void;\n clearMessages: () => void;\n clearSocketNotifications: () => void;\n}\n\nconst defaultContextValue: SocketContextProps = {\n socket: null,\n isConnected: false,\n messages: [],\n socketNotifications: [],\n sendMessage: () => {},\n removeMessage: () => {},\n removeSocketNotification: () => {},\n clearMessages: () => {},\n clearSocketNotifications: () => {},\n};\n\nexport const SocketContext = createContext<SocketContextProps>(defaultContextValue);\n\ninterface SocketProviderProps {\n token?: string;\n children: React.ReactNode;\n}\n\nexport const SocketProvider: React.FC<SocketProviderProps> = ({ token, children }) => {\n const socketHookData = token ? useSocket({ token }) : null;\n\n const sendMessage = (event: string, data: any) => {\n const currentSocket = socketHookData ? socketHookData.socket : defaultContextValue.socket;\n const currentIsConnected = socketHookData ? socketHookData.isConnected : defaultContextValue.isConnected;\n\n if (currentSocket && currentIsConnected) {\n currentSocket.emit(event, data);\n }\n };\n\n const value: SocketContextProps = {\n ...defaultContextValue,\n ...(socketHookData || {}),\n sendMessage: sendMessage,\n };\n\n return <SocketContext.Provider value={value}>{children}</SocketContext.Provider>;\n};\n\nexport const useSocketContext = () => {\n const context = useContext(SocketContext);\n if (!context) {\n throw new Error(\"useSocketContext must be used within a SocketProvider\");\n }\n return context;\n};\n","import { atomWithStorage } from \"jotai/utils\";\n\nexport interface RecentPage {\n url: string;\n title: string;\n moduleType: string;\n timestamp: number;\n}\n\nexport const recentPagesAtom = atomWithStorage<RecentPage[]>(\"recentPages\", []);\n","\"use client\";\n\nimport { useAtom } from \"jotai\";\nimport { usePathname } from \"next/navigation\";\nimport { useEffect } from \"react\";\nimport { RecentPage, recentPagesAtom } from \"../atoms\";\nimport { getTrackablePages } from \"../client/config\";\n\n// Routes to exclude from tracking\nconst EXCLUDED_ROUTES = [\"/\", \"/login\", \"/register\", \"/forgot-password\", \"/reset-password\", \"/activate\"];\n\nexport function usePageTracker() {\n const pathname = usePathname();\n const [_recentPages, setRecentPages] = useAtom(recentPagesAtom);\n\n useEffect(() => {\n if (!pathname) return;\n\n // Exclude certain routes\n if (EXCLUDED_ROUTES.some((route) => pathname === route || pathname.endsWith(route))) {\n return;\n }\n\n // Extract page information from pathname (already locale-free from next-intl)\n const pathParts = pathname.split(\"/\").filter(Boolean);\n\n if (pathParts.length === 0) return;\n\n // Try to find the module based on the route\n const moduleName = pathParts[0];\n const entityId = pathParts.length > 1 ? pathParts[1] : null;\n\n // Only track pages with entity IDs (detail pages)\n if (!entityId) return;\n\n // Find the module from configured trackable pages\n const trackablePages = getTrackablePages();\n const foundModule = trackablePages.find((mod) => mod.pageUrl === `/${moduleName}`);\n\n if (!foundModule) return;\n\n // Only use base path (module/id), ignoring any sub-paths\n const baseUrl = `/${moduleName}/${entityId}`;\n\n let pageTitle = foundModule.name;\n if (typeof document !== \"undefined\") {\n const titleParts = document.title.split(\"]\");\n if (titleParts[1]) {\n const cleanTitle = titleParts[1].split(\"|\")[0]?.trim();\n pageTitle = cleanTitle || foundModule.name;\n }\n }\n\n const newPage: RecentPage = {\n url: baseUrl,\n title: pageTitle,\n moduleType: foundModule.name,\n timestamp: Date.now(),\n };\n\n setRecentPages((prev) => {\n // Remove if already exists (to move to top)\n const filtered = prev.filter((page) => page.url !== newPage.url);\n\n // Add to beginning and limit to 10\n return [newPage, ...filtered].slice(0, 10);\n });\n }, [pathname, setRecentPages]);\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useCurrentUserContext } from \"../contexts\";\nimport { UserInterface } from \"../features/user/data\";\nimport { PushService } from \"../features/push/data/push.service\";\nimport { getRoleId } from \"../roles\";\nimport { getAppUrl } from \"../client/config\";\n\nfunction urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = window.atob(base64);\n const outputArray = new Uint8Array(rawData.length);\n for (let i = 0; i < rawData.length; i++) {\n outputArray[i] = rawData.charCodeAt(i);\n }\n return outputArray;\n}\n\nexport default function usePushNotifications(): void {\n const { currentUser, hasRole } = useCurrentUserContext<UserInterface>();\n\n useEffect(() => {\n const register = async () => {\n if (\"serviceWorker\" in navigator && \"PushManager\" in window) {\n try {\n // Check if we've already processed push notifications for this user in this session\n const sessionKey = `push_registered_${currentUser?.id}`;\n const lastRegisteredSubscription = sessionStorage.getItem(sessionKey);\n\n const registration = await navigator.serviceWorker.register(`${getAppUrl()}/sw.js`);\n\n // Check current permission status first\n let permission = Notification.permission;\n\n // Only request permission if it's not already determined\n if (permission === \"default\") {\n permission = await Notification.requestPermission();\n }\n\n if (permission !== \"granted\") {\n return; // User denied permission, this is not an error\n }\n\n const vapidPublicKey = (process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY || \"\").trim();\n const convertedKey = urlBase64ToUint8Array(vapidPublicKey);\n\n await navigator.serviceWorker.ready;\n\n let subscription = await registration.pushManager.getSubscription();\n if (!subscription) {\n const appServerKey = new Uint8Array(Array.from(convertedKey));\n\n subscription = await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: appServerKey,\n });\n }\n\n const plainSubscription = {\n endpoint: subscription.endpoint,\n keys: subscription.toJSON().keys,\n };\n\n // Create a simple hash to detect subscription changes\n const subscriptionHash = btoa(JSON.stringify(plainSubscription));\n\n // Only call the API if subscription has changed or this is the first registration\n if (lastRegisteredSubscription !== subscriptionHash) {\n await PushService.register({ data: plainSubscription });\n // Store the current subscription hash to avoid duplicate registrations\n sessionStorage.setItem(sessionKey, subscriptionHash);\n }\n } catch (error) {\n console.error(\"Error during service worker registration or push subscription:\", error);\n }\n }\n };\n\n if (currentUser && !hasRole(getRoleId().Administrator)) register();\n }, [currentUser]);\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport io from \"socket.io-client\";\nimport { Modules, rehydrate } from \"../core\";\nimport { NotificationInterface } from \"../features/notification/data\";\n\ntype Socket = ReturnType<typeof io>;\n\ninterface UseSocketOptions {\n token: string;\n}\n\ninterface SocketLike {\n emit: (event: string, ...args: any[]) => void;\n on: (event: string, callback: (...args: any[]) => void) => void;\n off: (event: string, callback?: (...args: any[]) => void) => void;\n connected: boolean;\n}\n\ninterface UseSocketReturn {\n socket: SocketLike | null;\n isConnected: boolean;\n messages: any[];\n socketNotifications: NotificationInterface[];\n sendMessage: (event: string, data: any) => void;\n removeMessage: (index: number) => void;\n removeSocketNotification: (index: number) => void;\n clearMessages: () => void;\n clearSocketNotifications: () => void;\n}\n\nexport function useSocket({ token }: UseSocketOptions): UseSocketReturn {\n const _errorCount = useRef(0);\n const shouldConnect = useRef(true);\n const _hookInstanceId = useRef(Math.random().toString(36).substring(2, 11));\n\n const [socket, setSocket] = useState<Socket | null>(null);\n const [isConnected, setIsConnected] = useState<boolean>(false);\n const [messages, setMessages] = useState<any[]>([]);\n const [socketNotifications, setSocketNotifications] = useState<NotificationInterface[]>([]);\n\n const socketRef = useRef<Socket | null>(null);\n\n useEffect(() => {\n if (!token) return;\n\n const globalSocketKey = `__socket_${process.env.NEXT_PUBLIC_API_URL?.replace(/[^a-zA-Z0-9]/g, \"_\")}`;\n\n if (typeof window !== \"undefined\") {\n const _allSocketKeys = Object.keys(window).filter((key) => key.startsWith(\"__socket_\"));\n\n const existingSocket = (window as any)[globalSocketKey];\n if (existingSocket) {\n if (existingSocket.connected) {\n // CRITICAL: Clear existing listeners to prevent accumulation\n existingSocket.removeAllListeners();\n\n socketRef.current = existingSocket;\n setSocket(existingSocket);\n setIsConnected(existingSocket.connected);\n } else {\n existingSocket.disconnect();\n delete (window as any)[globalSocketKey];\n }\n }\n }\n\n let currentSocket: any;\n const isReusing = socketRef.current && socketRef.current.connected;\n\n if (isReusing) {\n currentSocket = socketRef.current;\n } else {\n // React StrictMode protection: Prevent double-mounting issues\n if (!shouldConnect.current) {\n return;\n }\n shouldConnect.current = false;\n\n try {\n currentSocket = io(process.env.NEXT_PUBLIC_API_URL as string, {\n auth: { token },\n transports: [\"websocket\"],\n timeout: 20000,\n });\n\n if (typeof window !== \"undefined\") {\n if (currentSocket.id && currentSocket.id !== \"undefined\") {\n (window as any)[globalSocketKey] = currentSocket;\n }\n }\n\n socketRef.current = currentSocket;\n setSocket(currentSocket);\n } catch {\n return () => {}; // Return empty cleanup function on error\n }\n }\n\n const handleConnect = () => {\n setIsConnected(true);\n };\n\n const handleDisconnect = () => {\n setIsConnected(false);\n };\n\n const handleMessage = (data: any) => {\n setMessages((prevMessages) => {\n const newMessages = [...prevMessages, data];\n return newMessages;\n });\n };\n\n const handleNotification = (data: any) => {\n const notification = rehydrate(Modules.Notification, data) as NotificationInterface;\n if (notification) {\n setSocketNotifications((prev) => {\n const newNotifications = [...prev, notification];\n return newNotifications;\n });\n }\n };\n\n // Attach event listeners\n if (currentSocket) {\n currentSocket.on(\"connect\", handleConnect);\n currentSocket.on(\"disconnect\", handleDisconnect);\n currentSocket.on(\"message\", handleMessage);\n currentSocket.on(\"notification\", handleNotification);\n }\n\n return () => {\n shouldConnect.current = true;\n\n // In development, preserve socket in window for HMR but remove listeners\n if (currentSocket) {\n if (process.env.NODE_ENV === \"development\") {\n currentSocket.off(\"connect\", handleConnect);\n currentSocket.off(\"disconnect\", handleDisconnect);\n currentSocket.off(\"message\", handleMessage);\n currentSocket.off(\"notification\", handleNotification);\n } else {\n currentSocket.off(\"connect\", handleConnect);\n currentSocket.off(\"disconnect\", handleDisconnect);\n currentSocket.off(\"message\", handleMessage);\n currentSocket.off(\"notification\", handleNotification);\n\n currentSocket.disconnect();\n\n if (typeof window !== \"undefined\") {\n delete (window as any)[globalSocketKey];\n }\n }\n }\n };\n }, [token]);\n\n const sendMessage = (event: string, data: any) => {\n if (socketRef.current && isConnected) {\n socketRef.current.emit(event, data);\n }\n };\n\n const removeMessage = (index: number) => {\n setMessages((prevMessages) => {\n const newMessages = [...prevMessages];\n newMessages.splice(index, 1);\n return newMessages;\n });\n };\n\n const removeSocketNotification = (index: number) => {\n setSocketNotifications((prevNotifications) => {\n const newNotifications = [...prevNotifications];\n newNotifications.splice(index, 1);\n return newNotifications;\n });\n };\n\n const clearMessages = () => {\n setMessages([]);\n };\n\n const clearSocketNotifications = () => {\n setSocketNotifications([]);\n };\n\n return {\n socket,\n isConnected,\n messages,\n socketNotifications,\n sendMessage,\n removeMessage,\n removeSocketNotification,\n clearMessages,\n clearSocketNotifications,\n };\n}\n","\"use client\";\n\nimport { ReactNode, useEffect, useState } from \"react\";\nimport { cn } from \"../../utils\";\n\ntype TitleProps = {\n type?: string | string[];\n element?: string;\n functions?: ReactNode;\n className?: string;\n};\n\nexport function ContentTitle({ type, element, functions, className }: TitleProps) {\n const [clientFunctions, setClientFunctions] = useState<ReactNode>(null);\n const [isClient, setIsClient] = useState(false);\n\n // Defer function rendering to client-side only to prevent hydration mismatches\n // caused by Radix UI's dynamic ID generation in Dialog/AlertDialog components\n useEffect(() => {\n setIsClient(true);\n setClientFunctions(functions);\n }, [functions]);\n\n if (!element) return null;\n\n return (\n <div className={cn(`mb-4 flex w-full flex-col`, className)}>\n {(type || isClient) && (\n <div className=\"flex flex-row items-center justify-between gap-x-4\">\n {type && <div className={`text-muted-foreground text-xl font-light`}>{type}</div>}\n {isClient && clientFunctions && (\n <div className=\"flex flex-row items-center justify-start\">{clientFunctions}</div>\n )}\n </div>\n )}\n <div className={`text-primary w-full text-3xl font-semibold`}>{element}</div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useSharedContext } from \"../../contexts/SharedContext\";\nimport { SidebarTrigger } from \"../../shadcnui\";\nimport { BreadcrumbNavigation } from \"./Breadcrumb\";\n\ntype HeaderProps = {\n children?: React.ReactNode;\n};\n\nexport function Header({ children }: HeaderProps) {\n const { breadcrumbs } = useSharedContext();\n\n return (\n <header className={`sticky top-0 z-10 flex h-12 flex-col items-center justify-start gap-x-4 border-b`}>\n <div className=\"bg-sidebar flex h-12 w-full flex-row items-center justify-between pl-2 pr-4\">\n <SidebarTrigger aria-label=\"Toggle sidebar\" />\n <div className=\"flex w-full flex-row items-center justify-start\">\n <BreadcrumbNavigation items={breadcrumbs} />\n </div>\n <div className=\"flex w-64 flex-row items-center justify-end gap-x-4 whitespace-nowrap\">\n {children ? children : null}\n </div>\n </div>\n </header>\n );\n}\n","\"use client\";\n\nimport { MoonIcon, SunIcon } from \"lucide-react\";\nimport { useTheme } from \"next-themes\";\nimport { Switch } from \"../../shadcnui\";\n\nexport function ModeToggleSwitch() {\n const { theme, setTheme } = useTheme();\n\n const handleToggle = () => {\n setTheme(theme === \"light\" ? \"dark\" : \"light\");\n };\n\n return (\n <div className=\"flex items-center\">\n <Switch checked={theme === \"dark\"} onCheckedChange={handleToggle} className=\"relative\">\n {theme === \"dark\" ? (\n <MoonIcon className=\"text-primary-foreground h-4 w-4\" />\n ) : (\n <SunIcon className=\"text-primary h-4 w-4\" />\n )}\n </Switch>\n </div>\n );\n}\n","\"use client\";\n\nimport { ChevronDownIcon, ChevronRightIcon } from \"lucide-react\";\nimport { ReactNode, useEffect, useState } from \"react\";\nimport { v4 } from \"uuid\";\n\ntype PageSectionProps = {\n children: ReactNode;\n title?: string;\n options?: ReactNode[];\n open?: boolean;\n small?: boolean;\n onToggle?: (isOpen: boolean) => void;\n};\n\nexport function PageSection({ children, title, options, open, small, onToggle }: PageSectionProps) {\n const [isOpen, setIsOpen] = useState<boolean>(open ?? true);\n const [shouldRender, setShouldRender] = useState<boolean>(open ?? true);\n\n useEffect(() => {\n if (onToggle) {\n onToggle(isOpen);\n }\n }, [isOpen]);\n\n const toggleOpen = () => setIsOpen(!isOpen);\n\n useEffect(() => {\n if (isOpen) {\n setShouldRender(true);\n } else {\n const timer = setTimeout(() => setShouldRender(false), 300);\n return () => clearTimeout(timer);\n }\n }, [isOpen]);\n\n return (\n <section\n id={title ? title.toLowerCase().replaceAll(\" \", \"\") : v4()}\n className={`${isOpen ? \"mb-4\" : \"my-0\"} flex w-full scroll-mt-40 flex-col`}\n >\n {title && (\n <div\n className={`${isOpen ? \"mb-4\" : \"mb-0\"} flex w-full justify-between border-b ${small ? `border-muted` : `border-primary`} pb-1`}\n >\n <div className=\"flex w-full cursor-pointer items-center justify-start gap-x-2\" onClick={toggleOpen}>\n {isOpen ? (\n <ChevronDownIcon className={`text-primary h-4 w-4`} />\n ) : (\n <ChevronRightIcon className=\"text-primary h-4 w-4\" />\n )}\n <h2 className={`flex w-full ${small === true ? `text-sm` : `text-lg`} text-primary font-semibold`}>\n {title}\n </h2>\n </div>\n {options && <div className=\"flex gap-2\">{options}</div>}\n </div>\n )}\n <div className={`overflow-hidden transition-all duration-300 ${isOpen ? \"\" : \"max-h-0\"}`}>\n {shouldRender && children}\n </div>\n </section>\n );\n}\n","\"use client\";\n\nimport { useAtomValue } from \"jotai\";\nimport { HistoryIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { recentPagesAtom } from \"../../atoms\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Link,\n useSidebar,\n} from \"../../shadcnui\";\n\nexport function RecentPagesNavigator() {\n const recentPages = useAtomValue(recentPagesAtom);\n const t = useTranslations();\n const { state } = useSidebar();\n\n if (recentPages.length === 0) {\n return null;\n }\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <div className=\"flex w-full cursor-pointer items-center gap-2\">\n {state === \"collapsed\" ? <HistoryIcon className=\"h-4 w-4\" /> : <span>{t(`generic.recent_pages`)}</span>}\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-96\">\n <DropdownMenuLabel>{t(`generic.recent_pages`)}</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {recentPages.map((page, index) => (\n <DropdownMenuItem key={`${page.url}-${index}`} asChild>\n <Link href={page.url} className=\"flex items-center gap-2\">\n <div className=\"flex flex-col\">\n <div className=\"truncate text-sm\">{page.title}</div>\n <div className=\"text-muted-foreground text-xs font-normal\">\n {t(`types.${page.moduleType}`, { count: 1 })}\n </div>\n </div>\n </Link>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","\"use client\";\n\nimport { cn } from \"../../utils\";\nimport { Header } from \"../navigations\";\n\ntype PageContainerProps = { children: React.ReactNode; testId?: string; className?: string };\n\nexport function PageContainer({ children, testId, className }: PageContainerProps) {\n return (\n <div className={`flex h-full w-full flex-col`} data-testid={testId}>\n <Header />\n <main className={cn(`flex w-full flex-1 flex-col gap-y-4 pt-4 pl-4 pr-4`, className)}>{children}</main>\n </div>\n );\n}\n","\"use client\";\n\nimport { ChevronDown, ChevronUp } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useRef, useState } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\n\ntype ReactMarkdownContainerProps = {\n content: string;\n collapsible?: boolean;\n initialLines?: number;\n size?: \"small\" | \"normal\";\n};\n\nexport function ReactMarkdownContainer({\n content,\n collapsible = false,\n initialLines = 4,\n size = \"normal\",\n}: ReactMarkdownContainerProps) {\n const t = useTranslations(\"generic.buttons\");\n const [isExpanded, setIsExpanded] = useState(false);\n const [showExpandButton, setShowExpandButton] = useState(false);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (collapsible && contentRef.current && !isExpanded) {\n // Check if content exceeds the clamped height\n const isOverflowing = contentRef.current.scrollHeight > contentRef.current.clientHeight;\n setShowExpandButton(isOverflowing);\n }\n }, [collapsible, content, isExpanded]);\n\n const handleToggle = () => {\n setIsExpanded(!isExpanded);\n };\n\n const clampStyle =\n collapsible && !isExpanded\n ? {\n display: \"-webkit-box\",\n WebkitLineClamp: initialLines,\n WebkitBoxOrient: \"vertical\" as const,\n overflow: \"hidden\",\n }\n : {};\n\n return (\n <div className=\"flex flex-col\">\n <div className=\"relative\">\n <div ref={contentRef} style={clampStyle} className=\"transition-all duration-300 ease-in-out\">\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n p: ({ children }) => <p className={size === \"small\" ? \"text-xs\" : \"\"}>{children}</p>,\n li: ({ children }) => <li className={size === \"small\" ? \"text-xs\" : \"\"}>{children}</li>,\n table: ({ children }) => <table className=\"w-full table-auto border-collapse border\">{children}</table>,\n th: ({ children }) => (\n <th className={`border px-4 py-2 text-left ${size === \"small\" ? \"px-2 py-1 text-xs\" : \"\"}`}>\n {children}\n </th>\n ),\n td: ({ children }) => (\n <td className={`border px-4 py-2 ${size === \"small\" ? \"px-2 py-1 text-xs\" : \"\"}`}>{children}</td>\n ),\n tr: ({ children }) => <tr className=\"even:bg-gray-50\">{children}</tr>,\n ul: ({ children }) => <ul className={`list-disc ${size === \"small\" ? \"pl-3\" : \"pl-4\"}`}>{children}</ul>,\n ol: ({ children }) => (\n <ol className={`list-decimal ${size === \"small\" ? \"pl-3\" : \"pl-4\"}`}>{children}</ol>\n ),\n h1: ({ children }) => (\n <h1 className={size === \"small\" ? \"my-1 mt-2 text-sm font-bold\" : \"my-2 mt-4 text-3xl font-medium\"}>\n {children}\n </h1>\n ),\n h2: ({ children }) => (\n <h2\n className={size === \"small\" ? \"my-1 mt-2 text-sm font-semibold\" : \"my-2 mt-4 text-2xl font-semibold\"}\n >\n {children}\n </h2>\n ),\n h3: ({ children }) => (\n <h3 className={size === \"small\" ? \"my-1 mt-2 text-sm font-medium\" : \"my-2 mt-4 text-xl font-semibold\"}>\n {children}\n </h3>\n ),\n h4: ({ children }) => (\n <h4 className={size === \"small\" ? \"my-1 mt-2 text-sm font-medium\" : \"my-2 mt-4 text-lg font-semibold\"}>\n {children}\n </h4>\n ),\n }}\n >\n {content}\n </ReactMarkdown>\n </div>\n\n {collapsible && !isExpanded && showExpandButton && (\n <div className=\"pointer-events-none absolute right-0 bottom-0 left-0 h-12 bg-gradient-to-t from-white to-transparent\" />\n )}\n </div>\n\n {collapsible && showExpandButton && (\n <div className=\"mt-2 flex justify-end\">\n <button\n onClick={handleToggle}\n className=\"flex items-center gap-1 rounded-md px-3 py-1.5 text-sm text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900\"\n aria-label={isExpanded ? t(\"show_less\") : t(\"show_more\")}\n >\n <span>{isExpanded ? t(\"show_less\") : t(\"show_more\")}</span>\n {isExpanded ? <ChevronUp className=\"h-4 w-4\" /> : <ChevronDown className=\"h-4 w-4\" />}\n </button>\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useCurrentUserContext } from \"../../contexts\";\nimport { UserInterface } from \"../../features/user/data\";\nimport { Action, ModuleWithPermissions } from \"../../permissions\";\nimport { ScrollArea, Tabs, TabsContent, TabsList, TabsTrigger } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\nexport type Tab = {\n label: string;\n contentLabel?: React.ReactNode;\n content: React.ReactNode;\n modules?: ModuleWithPermissions[];\n action?: Action;\n};\n\ntype TabsContainerProps = {\n tabs: Tab[];\n defaultTab?: string;\n tabsListClassName?: string;\n tabsTriggerClassName?: string;\n scrollAreaClassName?: string;\n style?: \"navigation\";\n additionalComponent?: React.ReactNode;\n};\n\nexport function TabsContainer({\n tabs,\n defaultTab,\n tabsListClassName,\n tabsTriggerClassName,\n scrollAreaClassName,\n style,\n additionalComponent,\n}: TabsContainerProps) {\n const { hasPermissionToModules } = useCurrentUserContext<UserInterface>();\n\n const validTabs = tabs.filter((tab) =>\n tab.modules && tab.action ? hasPermissionToModules({ modules: tab.modules, action: tab.action }) : true,\n );\n\n if (validTabs.length === 0) return null;\n\n const defaultValue = defaultTab ?? tabs[0].label;\n\n if (validTabs.length === 1) {\n return validTabs[0].content;\n }\n\n return (\n <Tabs defaultValue={defaultValue} className=\"w-full\">\n <div className=\"flex w-full items-center justify-between\">\n <TabsList\n className={cn(\n `${style ? `my-4 flex w-full justify-start rounded-none border-b bg-transparent pb-0` : ``}`,\n tabsListClassName,\n )}\n >\n {validTabs.map((tab) => (\n <TabsTrigger\n key={tab.label}\n value={tab.label}\n className={cn(\n `${style ? `text-muted-foreground border-accent data-[state=active]:text-foreground hover:text-foreground cursor-pointer rounded-none bg-transparent pb-2 text-sm font-light hover:border-0 data-[state=active]:border-b data-[state=active]:font-medium data-[state=active]:shadow-none` : `text-primary text-xs`}`,\n tabsTriggerClassName,\n )}\n >\n {tab.contentLabel ?? tab.label}\n </TabsTrigger>\n ))}\n </TabsList>\n {additionalComponent && additionalComponent}\n </div>\n {scrollAreaClassName ? (\n <ScrollArea className={scrollAreaClassName}>\n {validTabs.map((tab) => (\n <TabsContent key={tab.label} value={tab.label}>\n {tab.content}\n </TabsContent>\n ))}\n </ScrollArea>\n ) : (\n <>\n {validTabs.map((tab) => (\n <TabsContent key={tab.label} value={tab.label}>\n {tab.content}\n </TabsContent>\n ))}\n </>\n )}\n </Tabs>\n );\n}\n","\"use client\";\n\nimport { ReactElement } from \"react\";\nimport { cn } from \"../../utils\";\n\ntype AttributeElementProps = {\n inline?: boolean;\n title?: string | ReactElement<any>;\n value?: string | ReactElement<any>;\n className?: string;\n};\n\nexport function AttributeElement({ inline, title, value, className }: AttributeElementProps) {\n return (\n <div className={cn(`flex ${inline === true ? \"flex-row\" : \"flex-col\"} my-1 justify-start`, className)}>\n {title && <div className={`${inline === true ? \"min-w-48 pr-4\" : \"w-full\"} text-sm font-semibold`}>{title}</div>}\n {value && <div className=\"flex w-full flex-col text-sm\">{value}</div>}\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentInterface } from \"../../features/content/data\";\nimport { ContributorsList } from \"../../features/user/components\";\n\ntype AllowedUsersDetailsProps = {\n showTitle?: boolean;\n content: ContentInterface;\n};\n\nexport function AllowedUsersDetails({ showTitle, content }: AllowedUsersDetailsProps) {\n const t = useTranslations();\n\n return (\n <div className=\"mb-2 flex w-full flex-col gap-y-2\">\n {showTitle && <h3 className=\"text-xs font-semibold\">{t(\"generic.permissions\")}</h3>}\n <div className=\"flex w-full items-center justify-start gap-x-4\">\n <ContributorsList content={content} />\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport dynamic from \"next/dynamic\";\nimport React from \"react\";\nimport { BlockNoteEditorProps } from \"./BlockNoteEditor\";\n\nconst BlockNoteEditor = dynamic(() => import(\"./BlockNoteEditor\"), {\n ssr: false,\n});\n\nexport const BlockNoteEditorContainer = React.memo(function EditorContainer(props: BlockNoteEditorProps) {\n return <BlockNoteEditor {...props} />;\n});\n","\"use client\";\n\nimport Image from \"next/image\";\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from \"../../shadcnui\";\n\nexport function ErrorDetails({ title, message, code }: { title?: string; message: string; code: number }) {\n if (code === 403)\n return (\n <div className=\"w-xl max-w-xl\">\n <Card className=\"w-full\">\n <CardHeader>\n <CardTitle className=\"text-foreground flex flex-col items-center gap-y-4 pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {/* <div>{code}</div> */}\n <div>Unauthorised</div>\n </CardTitle>\n <CardDescription className=\"text-center text-lg\">\n We are sorry, but you are not allowed to access this content.\n </CardDescription>\n </CardHeader>\n <CardContent></CardContent>\n </Card>\n </div>\n );\n\n return (\n <div className=\"w-xl max-w-xl\">\n <Card className=\"w-full\">\n <CardHeader>\n <CardTitle className=\"text-foreground flex flex-col items-center gap-y-4 pb-10 text-center text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n <div>{code}</div>\n <div>{title}</div>\n </CardTitle>\n <CardDescription className=\"text-center text-lg\">{message}</CardDescription>\n </CardHeader>\n <CardContent></CardContent>\n </Card>\n </div>\n );\n}\n","// import { toast } from \"@/hooks/use-toast\";\n\nimport { toast } from \"sonner\";\n\nexport function errorToast(params: { title?: string; error: any }) {\n toast.error(params?.title ?? \"Error\", {\n description: params.error instanceof Error ? params.error.message : String(params.error),\n });\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ReactNode, useCallback, useEffect, useRef, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { DataListRetriever, useDebounce } from \"../../hooks\";\nimport {\n Button,\n Command,\n CommandDialog,\n CommandEmpty,\n CommandInput,\n CommandList,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from \"../../shadcnui\";\n\ntype CommonAssociationTriggerProps = {\n sourceType: string;\n destinationType: string;\n hasDestination?: boolean;\n onTrigger: () => void;\n};\n\nexport function CommonAssociationTrigger({\n sourceType,\n destinationType,\n hasDestination,\n onTrigger,\n}: CommonAssociationTriggerProps) {\n const t = useTranslations();\n\n if (hasDestination)\n return (\n <div className=\"hover:text-accent cursor-pointer\" onClick={onTrigger}>\n Join\n </div>\n );\n\n return (\n <Button variant={`outline`} size={`sm`} onClick={onTrigger}>\n {t(`generic.association.label`, {\n source: sourceType,\n destination: destinationType,\n })}\n </Button>\n );\n}\n\ntype CommonAssociationCommandDialogProps = {\n show: boolean;\n setShow: (show: boolean) => void;\n data: DataListRetriever<any>;\n source: string;\n destination: string;\n destinationName: string;\n children: ReactNode;\n};\n\nexport function CommonAssociationCommandDialog({\n show,\n setShow,\n data,\n source,\n destination,\n destinationName,\n children,\n}: CommonAssociationCommandDialogProps) {\n const t = useTranslations();\n\n const searchTermRef = useRef<string>(\"\");\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n\n const refreshList = useCallback(\n async (searchedTerm: string) => {\n if (searchedTerm === searchTermRef.current) return;\n searchTermRef.current = searchedTerm;\n await data.search(searchedTerm);\n },\n [searchTerm, data],\n );\n\n const updateSearchTerm = useDebounce(refreshList, 500);\n\n useEffect(() => {\n if (show) updateSearchTerm(searchTerm);\n }, [show, searchTerm]);\n\n return (\n <CommandDialog open={show} onOpenChange={setShow}>\n <DialogHeader className=\"flex flex-col items-start p-4 pb-0\">\n <DialogTitle>\n {t(`generic.association.label`, {\n source: source,\n destination: destination,\n })}\n </DialogTitle>\n <DialogDescription>\n {t(`generic.association.description`, {\n source: source,\n destination: destination,\n destination_name: destinationName,\n })}\n </DialogDescription>\n </DialogHeader>\n <Command shouldFilter={false} className=\"p-4\">\n <CommandInput\n placeholder={t(`generic.search.placeholder`, { type: source })}\n value={searchTerm}\n onValueChange={setSearchTerm}\n />\n <CommandList className=\"mt-3 h-auto max-h-96 min-h-96 max-w-full overflow-y-auto overflow-x-hidden\">\n <CommandEmpty>{t(`generic.search.no_results`, { type: source })}</CommandEmpty>\n {children}\n </CommandList>\n </Command>\n </CommandDialog>\n );\n}\n\nexport const triggerAssociationToast = (params: {\n t: any;\n source: string;\n destination: string;\n source_name: string;\n destination_name: string;\n level?: string;\n}) => {\n if (params.level) {\n toast.message(\n params.t(`generic.association.label`, {\n source: params.source,\n destination: params.destination,\n }),\n {\n description: params.t(`generic.association.success_level`, {\n source: params.source,\n destination: params.destination,\n source_name: params.source_name,\n destination_name: params.destination_name,\n level: params.level,\n }),\n },\n );\n } else {\n toast.message(\n params.t(`generic.association.label`, {\n source: params.source,\n destination: params.destination,\n }),\n {\n description: params.t(`generic.association.success`, {\n source: params.source,\n destination: params.destination,\n source_name: params.source_name,\n destination_name: params.destination_name,\n }),\n },\n );\n }\n};\n","\"use client\";\n\nimport { LoaderCircleIcon, Trash2Icon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useI18nRouter, useI18nTranslations } from \"../../i18n\";\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n Button,\n} from \"../../shadcnui\";\nimport { errorToast } from \"../errors\";\n\ntype CommonDeleterProps = {\n type: string;\n deleteFunction: () => Promise<void>;\n redirectTo?: string;\n forceShow?: boolean;\n};\n\nexport function CommonDeleter({ deleteFunction, redirectTo, type, forceShow }: CommonDeleterProps) {\n const t = useI18nTranslations();\n const router = useI18nRouter();\n const [open, setOpen] = useState<boolean>(forceShow || false);\n const [isDeleting, setIsDeleting] = useState<boolean>(false);\n\n const handleDelete = async () => {\n setIsDeleting(true);\n try {\n await deleteFunction();\n\n setOpen(false);\n if (redirectTo) router.push(redirectTo);\n } catch (error) {\n errorToast({ title: t(`generic.errors.delete`), error: error });\n }\n setIsDeleting(false);\n };\n\n return (\n <AlertDialog open={open} onOpenChange={setOpen}>\n {forceShow ? null : (\n <AlertDialogTrigger asChild>\n <Button size=\"sm\" variant={\"ghost\"} className=\"text-muted-foreground hover:text-destructive\">\n <Trash2Icon />\n </Button>\n </AlertDialogTrigger>\n )}\n <AlertDialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>\n <AlertDialogHeader>\n <AlertDialogTitle>{t(`generic.delete.title`, { type: t(`types.${type}`, { count: 1 }) })}</AlertDialogTitle>\n <AlertDialogDescription>\n {t(`generic.delete.subtitle`, { type: t(`types.${type}`, { count: 1 }) })}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <div className=\"text-destructive p-4 text-sm\">\n {t(`generic.delete.description`, { type: t(`types.${type}`, { count: 1 }) })}\n </div>\n <div className=\"flex justify-end\">\n <Button\n className=\"mr-2\"\n variant={\"outline\"}\n type={`button`}\n onClick={() => setOpen(false)}\n disabled={isDeleting}\n >\n {t(`generic.buttons.cancel`)}\n </Button>\n <Button\n type=\"submit\"\n onClick={(e) => {\n e.preventDefault();\n handleDelete();\n }}\n variant={\"destructive\"}\n disabled={isDeleting}\n >\n {isDeleting ? (\n <>\n {t(`generic.buttons.is_deleting`)}\n <LoaderCircleIcon className=\"animate-spin-slow h-5 w-5\" />\n </>\n ) : (\n t(`generic.buttons.delete`)\n )}\n </Button>\n </div>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n","import { useTranslations } from \"next-intl\";\nimport { Button } from \"../../shadcnui\";\n\ntype CommonEditorButtonsProps = {\n isEdit: boolean;\n form: any;\n disabled?: boolean;\n setOpen: (open: boolean) => void;\n};\nexport function CommonEditorButtons({ isEdit, form, disabled, setOpen }: CommonEditorButtonsProps) {\n const t = useTranslations();\n\n return (\n <div className=\"flex justify-end\">\n <Button\n className=\"mr-2\"\n variant={\"outline\"}\n type={`button`}\n onClick={() => setOpen(false)}\n data-testid={`modal-button-cancel`}\n >\n {t(`generic.buttons.cancel`)}\n </Button>\n\n <Button type=\"submit\" disabled={form.formState.isSubmitting || disabled} data-testid={`modal-button-create`}>\n {isEdit ? t(`generic.buttons.confirm_update`) : t(`generic.buttons.confirm_create`)}\n </Button>\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { DialogDescription, DialogHeader, DialogTitle } from \"../../shadcnui\";\n\ntype CommonEditorHeaderProps = {\n type: string;\n name?: string;\n};\n\nexport function CommonEditorHeader({ type, name }: CommonEditorHeaderProps) {\n const t = useTranslations();\n\n return (\n <DialogHeader>\n <DialogTitle>\n {name\n ? t(`generic.edit.update.title`, {\n type: type,\n })\n : t(`generic.edit.create.title`, { type: type })}\n </DialogTitle>\n <DialogDescription>\n {name\n ? t(`generic.edit.update.description`, {\n type: type,\n name: name,\n })\n : t(`generic.edit.create.description`, {\n type: type,\n })}\n </DialogDescription>\n </DialogHeader>\n );\n}\n","\"use client\";\n\nimport { PencilIcon } from \"lucide-react\";\n\nimport { useTranslations } from \"next-intl\";\nimport { Button, DialogTrigger } from \"../../shadcnui\";\n\ntype CommonEditorTriggerProps = { isEdit: boolean; edit?: string; create?: string };\n\nexport function CommonEditorTrigger({ isEdit, edit, create }: CommonEditorTriggerProps) {\n const t = useTranslations();\n\n return (\n <DialogTrigger asChild>\n {isEdit ? (\n <Button size=\"sm\" variant={`ghost`} className=\"text-muted-foreground\">\n <PencilIcon />\n </Button>\n ) : (\n <Button size=\"sm\" variant={`outline`}>\n {create ? create : t(`generic.buttons.create`)}\n </Button>\n )}\n </DialogTrigger>\n );\n}\n","\"use client\";\n\nimport { isValid, parse } from \"date-fns\";\nimport { Calendar as CalendarIcon, CircleXIcon } from \"lucide-react\";\nimport { ReactNode, useMemo, useState } from \"react\";\nimport { useI18nDateFnsLocale, useI18nLocale } from \"../../i18n\";\nimport {\n Calendar,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\ntype DatePickerPopoverProps = {\n children: ReactNode;\n value?: Date;\n onSelect: (date?: Date) => void;\n minDate?: Date;\n align?: \"start\" | \"center\" | \"end\";\n className?: string;\n};\n\nexport const DatePickerPopover = ({\n children,\n value,\n onSelect,\n minDate,\n align = \"start\",\n className,\n}: DatePickerPopoverProps) => {\n const locale = useI18nLocale();\n const dateFnsLocale = useI18nDateFnsLocale();\n const [isOpen, setIsOpen] = useState(false);\n const [displayMonth, setDisplayMonth] = useState<Date>(() => value || new Date());\n\n // Locale-aware date formatter\n const dateFormatter = useMemo(\n () => new Intl.DateTimeFormat(locale, { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" }),\n [locale],\n );\n\n // Format date for display\n const formatDate = (date: Date): string => dateFormatter.format(date);\n\n // Get placeholder based on locale format\n const datePlaceholder = useMemo(() => {\n const parts = dateFormatter.formatToParts(new Date(2000, 0, 1));\n return parts\n .map((part) => {\n if (part.type === \"day\") return \"dd\";\n if (part.type === \"month\") return \"mm\";\n if (part.type === \"year\") return \"yyyy\";\n return part.value;\n })\n .join(\"\");\n }, [dateFormatter]);\n\n // Get date-fns format string from locale\n const dateFormatPattern = useMemo(() => {\n const parts = dateFormatter.formatToParts(new Date(2000, 0, 1));\n return parts\n .map((part) => {\n if (part.type === \"day\") return \"dd\";\n if (part.type === \"month\") return \"MM\";\n if (part.type === \"year\") return \"yyyy\";\n return part.value;\n })\n .join(\"\");\n }, [dateFormatter]);\n\n const [inputValue, setInputValue] = useState<string>(() => (value ? formatDate(value) : \"\"));\n\n // Generate year options (1900 to current year + 10)\n const currentYear = new Date().getFullYear();\n const yearOptions = Array.from({ length: currentYear - 1900 + 11 }, (_, i) => 1900 + i);\n\n // Generate month names dynamically based on current locale\n const monthNames = useMemo(() => {\n const formatter = new Intl.DateTimeFormat(locale, { month: \"long\" });\n return Array.from({ length: 12 }, (_, i) => {\n const monthName = formatter.format(new Date(2000, i, 1));\n return monthName.charAt(0).toUpperCase() + monthName.slice(1);\n });\n }, [locale]);\n\n // Handle text input change\n const handleInputChange = (inputValue: string) => {\n setInputValue(inputValue);\n\n // Try to parse the date using locale format\n const parsedDate = parse(inputValue, dateFormatPattern, new Date());\n\n if (isValid(parsedDate)) {\n onSelect(parsedDate);\n setDisplayMonth(parsedDate);\n } else if (inputValue === \"\") {\n onSelect(undefined);\n }\n };\n\n // Handle calendar selection\n const handleCalendarSelect = (selectedDate: Date | undefined) => {\n onSelect(selectedDate);\n if (selectedDate) {\n setInputValue(formatDate(selectedDate));\n setDisplayMonth(selectedDate);\n } else {\n setInputValue(\"\");\n }\n setIsOpen(false);\n };\n\n // Handle clear button\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation();\n onSelect(undefined);\n setInputValue(\"\");\n };\n\n return (\n <Popover open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent className={cn(\"w-auto p-0\", className)} align={align} onClick={(e) => e.stopPropagation()}>\n <div className=\"p-3\">\n {/* Manual Input */}\n <div className=\"relative mb-3\">\n <Input\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value)}\n placeholder={datePlaceholder}\n className=\"pr-16\"\n onClick={(e) => e.stopPropagation()}\n />\n <div className=\"absolute right-1 top-1/2 flex -translate-y-1/2 items-center space-x-1\">\n <button\n type=\"button\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md hover:bg-muted\"\n onClick={(e) => e.stopPropagation()}\n >\n <CalendarIcon className=\"h-4 w-4 opacity-50\" />\n </button>\n {value && (\n <button\n type=\"button\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md hover:bg-muted\"\n onClick={handleClear}\n >\n <CircleXIcon className=\"h-4 w-4 opacity-50 hover:opacity-100\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Year and Month Selectors */}\n <div className=\"mb-3 flex gap-2\">\n <Select\n value={displayMonth.getMonth().toString()}\n onValueChange={(value) => {\n const newMonth = parseInt(value);\n const newDate = new Date(displayMonth.getFullYear(), newMonth, 1);\n setDisplayMonth(newDate);\n }}\n >\n <SelectTrigger className=\"w-[130px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {monthNames.map((month, index) => (\n <SelectItem key={index} value={index.toString()}>\n {month}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <Select\n value={displayMonth.getFullYear().toString()}\n onValueChange={(value) => {\n const newYear = parseInt(value);\n const newDate = new Date(newYear, displayMonth.getMonth(), 1);\n setDisplayMonth(newDate);\n }}\n >\n <SelectTrigger className=\"w-[80px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {yearOptions.reverse().map((year) => (\n <SelectItem key={year} value={year.toString()}>\n {year}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Calendar */}\n <Calendar\n mode=\"single\"\n selected={value}\n onSelect={handleCalendarSelect}\n disabled={(date) => (minDate && date < minDate ? true : false)}\n locale={dateFnsLocale}\n weekStartsOn={1}\n month={displayMonth}\n onMonthChange={setDisplayMonth}\n />\n </div>\n </PopoverContent>\n </Popover>\n );\n};\n","\"use client\";\n\nimport { format } from \"date-fns\";\nimport { CalendarIcon } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { DateRange } from \"react-day-picker\";\nimport { Button, Calendar, Popover, PopoverContent, PopoverTrigger } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\ntype DateRangeSelectorProps = {\n onDateChange: (date?: DateRange) => void;\n avoidSettingDates?: boolean;\n showPreviousMonth?: boolean;\n};\n\nexport function DateRangeSelector({ onDateChange, avoidSettingDates, showPreviousMonth }: DateRangeSelectorProps) {\n const [date, setDate] = useState<DateRange | undefined>(\n avoidSettingDates\n ? undefined\n : {\n from: new Date(new Date().getFullYear(), new Date().getMonth(), 1),\n to: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0),\n },\n );\n\n const [open, setOpen] = useState(false);\n\n const [prevRange, setPrevRange] = useState<DateRange | undefined>(date);\n useEffect(() => {\n if (\n date?.from &&\n date?.to &&\n date.to > date.from &&\n (prevRange?.from?.getTime() !== date.from.getTime() || prevRange?.to?.getTime() !== date.to.getTime())\n ) {\n onDateChange(date);\n setPrevRange(date);\n setOpen(false);\n }\n }, [date, prevRange, onDateChange]);\n\n // Custom handler to reset end date if a new start date is picked\n const handleSelect = (range: DateRange | undefined) => {\n if (!range) {\n setDate(undefined);\n return;\n }\n // If a new start date is picked, reset end date\n if (range.from && (!date?.from || range.from.getTime() !== date.from.getTime())) {\n setDate({ from: range.from, to: undefined });\n } else {\n setDate(range);\n }\n };\n\n return (\n <div className={cn(\"grid gap-2\")}>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n id=\"date\"\n variant={\"outline\"}\n className={cn(\"w-[300px] justify-start text-left font-normal\", !date && \"text-muted-foreground\")}\n >\n <CalendarIcon />\n {date?.from ? (\n date.to ? (\n <>\n {format(date.from, \"LLL dd, y\")} - {format(date.to, \"LLL dd, y\")}\n </>\n ) : (\n format(date.from, \"LLL dd, y\")\n )\n ) : (\n <span>Pick a date</span>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\n <div className=\"flex flex-col gap-2 p-2\">\n <Calendar\n mode=\"range\"\n defaultMonth={\n date?.from ??\n (showPreviousMonth ? new Date(new Date().getFullYear(), new Date().getMonth() - 1, 1) : undefined)\n }\n selected={date}\n onSelect={handleSelect}\n numberOfMonths={2}\n />\n <Button\n variant=\"secondary\"\n type=\"button\"\n onClick={() => {\n setDate(undefined);\n setPrevRange(undefined);\n onDateChange(undefined);\n setOpen(false);\n }}\n className=\"cursor-pointer\"\n disabled={!date}\n >\n Clear\n </Button>\n </div>\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n","\"use client\";\n\nimport { Trash2 as RemoveIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport {\n createContext,\n Dispatch,\n forwardRef,\n SetStateAction,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { DropzoneOptions, DropzoneState, FileRejection, useDropzone } from \"react-dropzone\";\nimport { toast } from \"sonner\";\nimport { buttonVariants, Input } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\ntype DirectionOptions = \"rtl\" | \"ltr\" | undefined;\n\ntype FileUploaderContextType = {\n dropzoneState: DropzoneState;\n isLOF: boolean;\n isFileTooBig: boolean;\n removeFileFromSet: (index: number) => void;\n activeIndex: number;\n setActiveIndex: Dispatch<SetStateAction<number>>;\n orientation: \"horizontal\" | \"vertical\";\n direction: DirectionOptions;\n};\n\nconst FileUploaderContext = createContext<FileUploaderContextType | null>(null);\n\nexport const useFileUpload = () => {\n const context = useContext(FileUploaderContext);\n if (!context) {\n throw new Error(\"useFileUpload must be used within a FileUploaderProvider\");\n }\n return context;\n};\n\ntype FileUploaderProps = {\n value: File[] | null;\n reSelect?: boolean;\n onValueChange: (value: File[] | null) => void;\n dropzoneOptions: DropzoneOptions;\n orientation?: \"horizontal\" | \"vertical\";\n};\n\nexport const FileUploader = forwardRef<HTMLDivElement, FileUploaderProps & React.HTMLAttributes<HTMLDivElement>>(\n (\n { className, dropzoneOptions, value, onValueChange, reSelect, orientation = \"vertical\", children, dir, ...props },\n ref,\n ) => {\n const [isFileTooBig, setIsFileTooBig] = useState(false);\n const [isLOF, setIsLOF] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const { maxFiles = 1, maxSize = 4 * 1024 * 1024, multiple = true } = dropzoneOptions;\n const t = useTranslations();\n\n const reSelectAll = maxFiles === 1 ? true : reSelect;\n const direction: DirectionOptions = dir === \"rtl\" ? \"rtl\" : \"ltr\";\n\n const removeFileFromSet = useCallback(\n (i: number) => {\n if (!value) return;\n const newFiles = value.filter((_, index) => index !== i);\n onValueChange(newFiles);\n },\n [value, onValueChange],\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (!value) return;\n\n const moveNext = () => {\n const nextIndex = activeIndex + 1;\n setActiveIndex(nextIndex > value.length - 1 ? 0 : nextIndex);\n };\n\n const movePrev = () => {\n const nextIndex = activeIndex - 1;\n setActiveIndex(nextIndex < 0 ? value.length - 1 : nextIndex);\n };\n\n const prevKey = orientation === \"horizontal\" ? (direction === \"ltr\" ? \"ArrowLeft\" : \"ArrowRight\") : \"ArrowUp\";\n\n const nextKey = orientation === \"horizontal\" ? (direction === \"ltr\" ? \"ArrowRight\" : \"ArrowLeft\") : \"ArrowDown\";\n\n if (e.key === nextKey) {\n moveNext();\n } else if (e.key === prevKey) {\n movePrev();\n } else if (e.key === \"Enter\" || e.key === \"Space\") {\n if (activeIndex === -1) {\n dropzoneState.inputRef.current?.click();\n }\n } else if (e.key === \"Delete\" || e.key === \"Backspace\") {\n if (activeIndex !== -1) {\n removeFileFromSet(activeIndex);\n if (value.length - 1 === 0) {\n setActiveIndex(-1);\n return;\n }\n movePrev();\n }\n } else if (e.key === \"Escape\") {\n setActiveIndex(-1);\n }\n },\n [value, activeIndex, removeFileFromSet],\n );\n\n const onDrop = useCallback(\n (acceptedFiles: File[], rejectedFiles: FileRejection[]) => {\n const files = acceptedFiles;\n\n if (!files) {\n toast.error(t(\"generic.errors.file\"), {\n description: t(\"generic.errors.file_large\"),\n });\n return;\n }\n\n const newValues: File[] = value ? [...value] : [];\n\n if (reSelectAll) {\n newValues.splice(0, newValues.length);\n }\n\n files.forEach((file) => {\n if (newValues.length < maxFiles) {\n newValues.push(file);\n }\n });\n\n onValueChange(newValues);\n\n if (rejectedFiles.length > 0) {\n for (let i = 0; i < rejectedFiles.length; i++) {\n if (rejectedFiles[i].errors[0]?.code === \"file-too-large\") {\n toast.error(t(\"generic.errors.file\"), {\n description: t(`generic.errors.file_max`, { size: maxSize / 1024 / 1024 }),\n });\n break;\n }\n if (rejectedFiles[i].errors[0]?.message) {\n toast.error(t(`generic.errors.file`), {\n description: rejectedFiles[i].errors[0].message,\n });\n break;\n }\n }\n }\n },\n [reSelectAll, value],\n );\n\n useEffect(() => {\n if (!value) return;\n if (value.length === maxFiles) {\n // setIsLOF(true);\n return;\n }\n setIsLOF(false);\n }, [value, maxFiles]);\n\n const opts = dropzoneOptions ? dropzoneOptions : { maxFiles, maxSize, multiple };\n\n const dropzoneState = useDropzone({\n ...opts,\n onDrop,\n onDropRejected: () => setIsFileTooBig(true),\n onDropAccepted: () => setIsFileTooBig(false),\n });\n\n const { isDragActive } = dropzoneState; // Correctly get isDragActive\n\n return (\n <FileUploaderContext.Provider\n value={{\n dropzoneState,\n isLOF,\n isFileTooBig,\n removeFileFromSet,\n activeIndex,\n setActiveIndex,\n orientation,\n direction,\n }}\n >\n <div\n ref={ref}\n tabIndex={0}\n onKeyDownCapture={handleKeyDown}\n className={cn(\n \"grid w-full overflow-hidden focus:outline-none\",\n className, // Original className from props\n {\n \"gap-2\": value && value.length > 0,\n \"bg-muted border-primary border-dashed\": isDragActive, // Apply drag-active styles to the main FileUploader div\n },\n )}\n dir={dir}\n {...props}\n >\n {children}\n </div>\n </FileUploaderContext.Provider>\n );\n },\n);\n\nFileUploader.displayName = \"FileUploader\";\n\nexport const FileUploaderContent = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ children, className, ...props }, ref) => {\n const { orientation } = useFileUpload();\n const containerRef = useRef<HTMLDivElement>(null);\n\n return (\n <div className={cn(\"w-full px-1\")} ref={containerRef} aria-description=\"content file holder\">\n <div\n {...props}\n ref={ref}\n className={cn(\n \"flex gap-1 rounded-xl\",\n orientation === \"horizontal\" ? \"flex-raw flex-wrap\" : \"flex-col\",\n className,\n )}\n >\n {children}\n </div>\n </div>\n );\n },\n);\n\nFileUploaderContent.displayName = \"FileUploaderContent\";\n\nexport const FileUploaderItem = forwardRef<HTMLDivElement, { index: number } & React.HTMLAttributes<HTMLDivElement>>(\n ({ className, index, children, ...props }, ref) => {\n const { removeFileFromSet, activeIndex, direction } = useFileUpload();\n const isSelected = index === activeIndex;\n const t = useTranslations();\n\n return (\n <div\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"ghost\" }),\n \"relative h-6 cursor-pointer justify-between p-1\",\n className,\n isSelected ? \"bg-muted\" : \"\",\n )}\n {...props}\n >\n <div className=\"flex h-full w-full items-center gap-1.5 leading-none font-medium tracking-tight\">\n {children}\n </div>\n <button\n type=\"button\"\n className={cn(\"absolute\", direction === \"rtl\" ? \"top-1 left-1\" : \"top-1 right-1\")}\n onClick={() => removeFileFromSet(index)}\n >\n <span className=\"sr-only\">{t(`generic.remove_item`, { index: index })}</span>\n <RemoveIcon className=\"hover:stroke-destructive h-4 w-4 duration-200 ease-in-out\" />\n </button>\n </div>\n );\n },\n);\n\nFileUploaderItem.displayName = \"FileUploaderItem\";\n\nexport const FileInput = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, children, ...props }, ref) => {\n const { dropzoneState, isFileTooBig, isLOF } = useFileUpload();\n const rootProps = isLOF ? {} : dropzoneState.getRootProps();\n // Get isDragActive from the context for FileInput as well, to ensure it can react if needed, or to simplify its own styling.\n const { isDragActive: parentIsDragActive } = dropzoneState;\n\n return (\n <div\n ref={ref}\n {...props}\n className={cn(`relative w-full ${isLOF ? \"cursor-not-allowed opacity-50\" : \"cursor-pointer\"}`, className)}\n >\n <div\n className={cn(\n \"w-full rounded-lg duration-300 ease-in-out\",\n // Simpler border logic: if parent is drag-active, it controls the border.\n // Otherwise, FileInput can show its own accept/reject/default border.\n {\n \"border-green-500\": dropzoneState.isDragAccept && !parentIsDragActive,\n \"border-red-500\": (dropzoneState.isDragReject || isFileTooBig) && !parentIsDragActive,\n \"border-gray-300\":\n !dropzoneState.isDragAccept && !dropzoneState.isDragReject && !isFileTooBig && !parentIsDragActive,\n },\n // className from props should be last to allow overrides if necessary\n className,\n )}\n {...rootProps}\n >\n {children}\n </div>\n <Input\n ref={dropzoneState.inputRef}\n disabled={isLOF}\n {...dropzoneState.getInputProps()}\n className={`${isLOF ? \"cursor-not-allowed\" : \"\"}`}\n />\n </div>\n );\n },\n);\n\nFileInput.displayName = \"FileInput\";\n","\"use client\";\n\nimport {\n Checkbox,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../shadcnui\";\n\ntype FormCheckboxProps = {\n form: any;\n id: string;\n name: string;\n labelBefore?: boolean;\n description?: string;\n isRequired?: boolean;\n};\n\nexport function FormCheckbox({ form, id, name, labelBefore, description, isRequired }: FormCheckboxProps) {\n const simpleLabel = () => {\n return (\n <FormLabel htmlFor={id} className={`font-normal ${labelBefore ? \"\" : \"ml-3\"}`}>\n {name}\n </FormLabel>\n );\n };\n\n const label = () => {\n if (description) return simpleLabel();\n else\n return (\n <Tooltip>\n <TooltipTrigger asChild>{simpleLabel()}</TooltipTrigger>\n <TooltipContent>{description}</TooltipContent>\n </Tooltip>\n );\n };\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n <FormControl>\n <div className=\"flex gap-x-4\">\n {labelBefore && label()}\n {labelBefore && isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n <Checkbox id={id} defaultChecked={field.value} onCheckedChange={field.onChange} />\n {!labelBefore && label()}\n {!labelBefore && isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { ReactElement } from \"react\";\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage } from \"../../shadcnui\";\n\nexport function FormContainerGeneric({\n form,\n id,\n name,\n children,\n isRequired = false,\n}: {\n form: any;\n id: string;\n name?: string;\n children: ReactElement<any>;\n isRequired?: boolean;\n}) {\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && (\n <FormLabel className=\"flex items-center\">\n <span>{name}</span>\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>{children}</FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { isValid, parse } from \"date-fns\";\nimport { Calendar as CalendarIcon, CircleXIcon } from \"lucide-react\";\nimport { useMemo, useState } from \"react\";\nimport { useI18nDateFnsLocale, useI18nLocale } from \"../../i18n\";\nimport {\n Calendar,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\n\nexport function FormDate({\n form,\n id,\n name,\n minDate,\n onChange,\n isRequired = false,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n minDate?: Date;\n onChange?: (date?: Date) => Promise<void>;\n isRequired?: boolean;\n}) {\n const locale = useI18nLocale();\n const dateFnsLocale = useI18nDateFnsLocale();\n const [open, setOpen] = useState<boolean>(false);\n const [displayMonth, setDisplayMonth] = useState<Date>(() => {\n const currentValue = form.getValues(id);\n return currentValue || new Date();\n });\n\n // Locale-aware date formatter\n const dateFormatter = useMemo(\n () => new Intl.DateTimeFormat(locale, { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" }),\n [locale],\n );\n\n // Format date for display\n const formatDate = (date: Date): string => dateFormatter.format(date);\n\n // Get placeholder based on locale format\n const datePlaceholder = useMemo(() => {\n const parts = dateFormatter.formatToParts(new Date(2000, 0, 1));\n return parts\n .map((part) => {\n if (part.type === \"day\") return \"dd\";\n if (part.type === \"month\") return \"mm\";\n if (part.type === \"year\") return \"yyyy\";\n return part.value;\n })\n .join(\"\");\n }, [dateFormatter]);\n\n // Get date-fns format string from locale\n const dateFormatPattern = useMemo(() => {\n const parts = dateFormatter.formatToParts(new Date(2000, 0, 1));\n return parts\n .map((part) => {\n if (part.type === \"day\") return \"dd\";\n if (part.type === \"month\") return \"MM\";\n if (part.type === \"year\") return \"yyyy\";\n return part.value;\n })\n .join(\"\");\n }, [dateFormatter]);\n\n const [inputValue, setInputValue] = useState<string>(() => {\n const currentValue = form.getValues(id);\n return currentValue ? formatDate(currentValue) : \"\";\n });\n\n // Generate year options (1900 to current year)\n const currentYear = new Date().getFullYear();\n const yearOptions = Array.from({ length: currentYear - 1900 + 1 }, (_, i) => 1900 + i);\n\n // Generate month names dynamically based on current locale\n const monthNames = useMemo(() => {\n const formatter = new Intl.DateTimeFormat(locale, { month: \"long\" });\n return Array.from({ length: 12 }, (_, i) => {\n const monthName = formatter.format(new Date(2000, i, 1));\n return monthName.charAt(0).toUpperCase() + monthName.slice(1);\n });\n }, [locale]);\n\n // Handle text input change\n const handleInputChange = (value: string, field: any) => {\n setInputValue(value);\n\n // Try to parse the date using locale format\n const parsedDate = parse(value, dateFormatPattern, new Date());\n\n if (isValid(parsedDate)) {\n field.onChange(parsedDate);\n setDisplayMonth(parsedDate);\n if (onChange) onChange(parsedDate);\n } else if (value === \"\") {\n field.onChange(undefined);\n if (onChange) onChange(undefined);\n }\n };\n\n // Handle calendar selection\n const handleCalendarSelect = (selectedDate: Date | undefined, field: any) => {\n field.onChange(selectedDate);\n if (selectedDate) {\n setInputValue(formatDate(selectedDate));\n setDisplayMonth(selectedDate);\n } else {\n setInputValue(\"\");\n }\n if (onChange) onChange(selectedDate);\n };\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"} w-full`}>\n {name && (\n <FormLabel className=\"dlex items-center\">\n {name} {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <div className=\"relative\">\n <Popover open={open} onOpenChange={setOpen} modal={true}>\n <div className=\"relative\">\n <Input\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value, field)}\n placeholder={datePlaceholder}\n className=\"pr-16\"\n />\n <div className=\"absolute right-1 top-1/2 flex -translate-y-1/2 items-center space-x-1\">\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"hover:bg-muted flex h-8 w-8 items-center justify-center rounded-md\"\n >\n <CalendarIcon className=\"h-4 w-4 opacity-50\" />\n </button>\n </PopoverTrigger>\n {field.value && (\n <button\n type=\"button\"\n className=\"hover:bg-muted flex h-8 w-8 items-center justify-center rounded-md\"\n onClick={() => {\n field.onChange(undefined);\n setInputValue(\"\");\n if (onChange) onChange(undefined);\n }}\n >\n <CircleXIcon className=\"h-4 w-4 opacity-50 hover:opacity-100\" />\n </button>\n )}\n </div>\n </div>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\n <div className=\"p-3\">\n {/* Year and Month Selectors */}\n <div className=\"mb-3 flex gap-2\">\n <Select\n value={displayMonth.getMonth().toString()}\n onValueChange={(value) => {\n const newMonth = parseInt(value);\n const newDate = new Date(displayMonth.getFullYear(), newMonth, 1);\n setDisplayMonth(newDate);\n }}\n >\n <SelectTrigger className=\"w-[130px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {monthNames.map((month, index) => (\n <SelectItem key={index} value={index.toString()}>\n {month}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n <Select\n value={displayMonth.getFullYear().toString()}\n onValueChange={(value) => {\n const newYear = parseInt(value);\n const newDate = new Date(newYear, displayMonth.getMonth(), 1);\n setDisplayMonth(newDate);\n }}\n >\n <SelectTrigger className=\"w-[80px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {yearOptions.reverse().map((year) => (\n <SelectItem key={year} value={year.toString()}>\n {year}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Calendar */}\n <Calendar\n mode=\"single\"\n selected={field.value}\n onSelect={(e) => {\n handleCalendarSelect(e, field);\n setOpen(false);\n }}\n disabled={(date) => (minDate && date < minDate ? true : false)}\n locale={dateFnsLocale}\n weekStartsOn={1}\n month={displayMonth}\n onMonthChange={setDisplayMonth}\n />\n </div>\n </PopoverContent>\n </Popover>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { Calendar as CalendarIcon, CircleXIcon } from \"lucide-react\";\nimport { useMemo, useState } from \"react\";\nimport { useI18nDateFnsLocale, useI18nLocale, useI18nTranslations } from \"../../i18n\";\nimport {\n Button,\n Calendar,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Label,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\nexport function FormDateTime({\n form,\n id,\n name,\n minDate,\n onChange,\n allowEmpty,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n minDate?: Date;\n onChange?: (date?: Date) => Promise<void>;\n allowEmpty?: boolean;\n}) {\n const [open, setOpen] = useState<boolean>(false);\n const t = useI18nTranslations();\n const locale = useI18nLocale();\n const dateFnsLocale = useI18nDateFnsLocale();\n\n // Locale-aware date-time formatter\n const dateTimeFormatter = useMemo(\n () =>\n new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n }),\n [locale],\n );\n\n // Format date-time for display\n const formatDateTime = (date: Date): string => dateTimeFormatter.format(date);\n\n const [selectedHours, setSelectedHours] = useState<number>(new Date().getHours());\n const [selectedMinutes, setSelectedMinutes] = useState<number>(roundToNearestFiveMinutes(new Date().getMinutes()));\n\n const hoursOptions = Array.from({ length: 24 }, (_, i) => {\n const hour = i;\n return {\n value: hour,\n label: hour.toString().padStart(2, \"0\"),\n };\n });\n\n const minutesOptions = Array.from({ length: 12 }, (_, i) => {\n const minute = i * 5;\n return {\n value: minute,\n label: minute.toString().padStart(2, \"0\"),\n };\n });\n\n function roundToNearestFiveMinutes(minutes: number): number {\n return (Math.round(minutes / 5) * 5) % 60;\n }\n\n const handleTimeChange = (hours: number, minutes: number) => {\n const currentDate = form.getValues(id);\n if (currentDate) {\n const updatedDate = new Date(currentDate);\n updatedDate.setHours(hours);\n updatedDate.setMinutes(minutes);\n form.setValue(id, updatedDate);\n if (onChange) onChange(updatedDate);\n }\n };\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"} w-full`}>\n {name && <FormLabel>{name}</FormLabel>}\n <FormControl>\n <div className=\"relative flex flex-row\">\n <Popover open={open} onOpenChange={setOpen} modal={true}>\n <div className=\"flex w-full flex-row items-center justify-between\">\n <PopoverTrigger asChild>\n <FormControl>\n <Button\n variant={\"outline\"}\n className={cn(\"w-full pl-3 text-left font-normal\", !field.value && \"text-muted-foreground\")}\n >\n {field.value ? formatDateTime(field.value) : <span>{t(`generic.pick_date_time`)}</span>}\n <CalendarIcon className=\"ml-auto h-4 w-4 opacity-50\" />\n </Button>\n </FormControl>\n </PopoverTrigger>\n {field.value && allowEmpty !== false && (\n <CircleXIcon\n className=\"text-muted hover:text-destructive ml-2 h-6 w-6 cursor-pointer\"\n onClick={() => {\n if (onChange) onChange(undefined);\n form.setValue(id, \"\");\n }}\n />\n )}\n </div>\n <PopoverContent className=\"w-auto p-4\" align=\"start\">\n <div className=\"flex flex-col space-y-4\">\n <Calendar\n mode=\"single\"\n selected={field.value}\n onSelect={(date) => {\n if (date) {\n // Preserve the current time when selecting a new date\n const newDate = new Date(date);\n if (field.value) {\n const currentDate = new Date(field.value);\n newDate.setHours(currentDate.getHours(), currentDate.getMinutes());\n } else {\n newDate.setHours(selectedHours, selectedMinutes);\n }\n form.setValue(id, newDate);\n if (onChange) onChange(newDate);\n\n // Update time state values\n setSelectedHours(newDate.getHours());\n setSelectedMinutes(roundToNearestFiveMinutes(newDate.getMinutes()));\n }\n }}\n disabled={(date) => (minDate && date < minDate ? true : false)}\n locale={dateFnsLocale}\n />\n <div className=\"flex flex-row items-end justify-center space-x-4\">\n <div className=\"flex flex-col space-y-2\">\n <Label htmlFor=\"hours-select\">{t(`generic.hours`)}</Label>\n <Select\n value={String(field.value ? new Date(field.value).getHours() : selectedHours)}\n onValueChange={(value) => {\n const hours = parseInt(value);\n setSelectedHours(hours);\n handleTimeChange(\n hours,\n field.value\n ? roundToNearestFiveMinutes(new Date(field.value).getMinutes())\n : selectedMinutes,\n );\n }}\n >\n <SelectTrigger id=\"hours-select\" className=\"w-[70px]\">\n <SelectValue placeholder=\"Hour\" />\n </SelectTrigger>\n <SelectContent>\n {hoursOptions.map((option) => (\n <SelectItem key={option.value} value={String(option.value)}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"mb-[9px] text-xl\">:</div>\n <div className=\"flex flex-col space-y-2\">\n <Label htmlFor=\"minutes-select\">{t(`generic.minutes`)}</Label>\n <Select\n value={String(\n field.value\n ? roundToNearestFiveMinutes(new Date(field.value).getMinutes())\n : selectedMinutes,\n )}\n onValueChange={(value) => {\n const minutes = parseInt(value);\n setSelectedMinutes(minutes);\n handleTimeChange(field.value ? new Date(field.value).getHours() : selectedHours, minutes);\n }}\n >\n <SelectTrigger id=\"minutes-select\" className=\"w-[70px]\">\n <SelectValue placeholder=\"Min\" />\n </SelectTrigger>\n <SelectContent>\n {minutesOptions.map((option) => (\n <SelectItem key={option.value} value={String(option.value)}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <Button\n className=\"mt-2\"\n onClick={() => {\n setOpen(false);\n }}\n >\n {t(`generic.buttons.select_date`)}\n </Button>\n </div>\n </PopoverContent>\n </Popover>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport React from \"react\";\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, Input } from \"../../shadcnui\";\n\nexport function FormInput({\n form,\n id,\n name,\n placeholder,\n type,\n onBlur,\n disabled,\n onKeyDown,\n autoFocus,\n onChange,\n testId,\n isRequired = false,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n type?: \"text\" | \"number\" | \"currency\" | \"password\" | \"link\";\n onBlur?: () => Promise<void>;\n disabled?: boolean;\n onKeyDown?: (event: React.KeyboardEvent) => void;\n autoFocus?: boolean;\n onChange?: (value: string | number) => Promise<void>;\n testId?: string;\n isRequired?: boolean;\n}) {\n const t = useTranslations();\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => {\n const handleBlur = async (e: React.FocusEvent<HTMLInputElement>) => {\n let value = e.target.value;\n\n if (type === \"link\" && value) {\n if (!/^https?:\\/\\//i.test(value)) {\n value = \"https://\" + value;\n field.onChange(value);\n }\n try {\n new URL(value);\n form.clearErrors(id);\n } catch (error) {\n form.setError(id, {\n type: \"validate\",\n message: t(`generic.errors.valid_url`),\n });\n }\n }\n\n if (onBlur) await onBlur();\n field.onBlur();\n };\n\n return (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && (\n <FormLabel className=\"flex items-center\">\n {name}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <div className=\"relative\">\n {type === \"currency\" && (\n <span className=\"text-muted-foreground absolute top-0 left-0 pt-2 pl-3\">€</span>\n )}\n <Input\n data-testid={testId}\n {...field}\n autoFocus={autoFocus === true}\n type={\n type === \"number\" || type === \"currency\" ? \"number\" : type === \"password\" ? \"password\" : \"text\"\n }\n className={`w-full ${type === \"number\" || type === \"currency\" ? \"text-end\" : \"\"}`}\n disabled={disabled === true || form.formState.isSubmitting}\n placeholder={placeholder || \"\"}\n onBlur={handleBlur}\n onKeyDown={onKeyDown}\n onChange={(e) => {\n if (type === \"number\" || type === \"currency\") {\n const value = e.target.value.replace(/[^0-9]/g, \"\");\n field.onChange(+value);\n if (onChange) onChange(+value);\n } else {\n field.onChange(e.target.value);\n if (onChange) onChange(e.target.value);\n }\n }}\n />\n </div>\n </FormControl>\n <FormMessage data-testid={testId ? `${testId}-error` : undefined} />\n </FormItem>\n );\n }}\n />\n </div>\n );\n}\n","import * as React from \"react\";\n\nimport { EyeIcon, EyeOffIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { Button, Input } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\nexport interface PasswordInputProps extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>(({ className, type, ...props }, ref) => {\n const [showPassword, setShowPassword] = React.useState(false);\n const disabled = props.value === \"\" || props.value === undefined || props.disabled;\n const t = useTranslations();\n\n return (\n <div className=\"relative\">\n <Input type={showPassword ? \"text\" : \"password\"} className={cn(\"\", className)} ref={ref} {...props} />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent\"\n onClick={() => setShowPassword((prev) => !prev)}\n disabled={disabled}\n >\n {showPassword && !disabled ? (\n <EyeIcon className=\"h-4 w-4\" aria-hidden=\"true\" />\n ) : (\n <EyeOffIcon className=\"h-4 w-4\" aria-hidden=\"true\" />\n )}\n <span className=\"sr-only\">{showPassword ? t(`generic.hide_password`) : t(`generic.show_password`)}</span>\n </Button>\n\n <style>{`\n\t\t\t\t\t.hide-password-toggle::-ms-reveal,\n\t\t\t\t\t.hide-password-toggle::-ms-clear {\n\t\t\t\t\t\tvisibility: hidden;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\tdisplay: none;\n\t\t\t\t\t}\n\t\t\t\t`}</style>\n </div>\n );\n});\nPasswordInput.displayName = \"PasswordInput\";\n\nexport { PasswordInput };\n","\"use client\";\n\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage } from \"../../shadcnui\";\nimport { PasswordInput } from \"./PasswordInput\";\n\nexport function FormPassword({\n form,\n id,\n name,\n placeholder,\n onBlur,\n disabled,\n testId,\n isRequired,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n onBlur?: () => Promise<void>;\n disabled?: boolean;\n testId?: string;\n isRequired?: boolean;\n}) {\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && (\n <FormLabel>\n {name}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <PasswordInput\n {...field}\n className={`w-full`}\n disabled={disabled === true || form.formState.isSubmitting}\n placeholder={placeholder ? placeholder : \"\"}\n onBlur={onBlur}\n data-testid={testId}\n />\n </FormControl>\n <FormMessage data-testid={testId ? `${testId}-error` : undefined} />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, Input } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\n/**\n * FormPlaceAutocomplete component integrates Google Places API (New)\n * to provide address suggestions as the user types.\n *\n * Prerequisites:\n * 1. Set NEXT_PUBLIC_GOOGLE_MAPS_API_KEY environment variable\n * 2. Enable Places API (New) in Google Cloud Console\n * 3. Configure API key restrictions as needed\n *\n * Note: This uses the new Places API via REST calls, not the legacy JavaScript API\n */\n\ninterface PlaceSuggestion {\n place_id: string;\n description: string;\n structured_formatting: {\n main_text: string;\n secondary_text: string;\n };\n}\n\ninterface PlaceAutocompleteProps {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n disabled?: boolean;\n testId?: string;\n isRequired?: boolean;\n onPlaceSelect?: (place: PlaceSuggestion) => void;\n className?: string;\n /**\n * Optional array of place types to include in search results.\n * When not specified, defaults to address types: [\"street_address\", \"premise\", \"subpremise\"]\n * For cities, use: [\"locality\", \"administrative_area_level_3\"]\n * For regions, use: [\"administrative_area_level_1\", \"administrative_area_level_2\"]\n */\n includeTypes?: string[];\n}\n\nexport function FormPlaceAutocomplete({\n form,\n id,\n name,\n placeholder,\n disabled,\n testId,\n isRequired = false,\n onPlaceSelect,\n className,\n includeTypes,\n}: PlaceAutocompleteProps) {\n const [inputValue, setInputValue] = useState(\"\");\n const [suggestions, setSuggestions] = useState<PlaceSuggestion[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [loadError, setLoadError] = useState(false);\n const [apiKey, setApiKey] = useState<string | null>(null);\n const debounceRef = useRef<NodeJS.Timeout | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Initialize API key\n useEffect(() => {\n const key = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY;\n\n if (!key) {\n console.error(\"Google Maps API key not found. Please set NEXT_PUBLIC_GOOGLE_MAPS_API_KEY environment variable.\");\n setLoadError(true);\n return;\n }\n\n setApiKey(key);\n }, []);\n\n // Update input value when form value changes\n useEffect(() => {\n const formValue = form.getValues(id);\n if (formValue !== inputValue) {\n setInputValue(formValue || \"\");\n }\n }, [form.watch(id), id, inputValue]);\n\n // Fetch place suggestions from Google Places API (New)\n const fetchSuggestions = async (input: string) => {\n if (!apiKey) return;\n\n try {\n setIsLoading(true);\n\n // Using the new Places API autocomplete endpoint\n const response = await fetch(`https://places.googleapis.com/v1/places:autocomplete`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Goog-Api-Key\": apiKey,\n },\n body: JSON.stringify({\n input: input,\n includedPrimaryTypes: includeTypes || [\"street_address\", \"premise\", \"subpremise\"],\n languageCode: \"en\",\n }),\n });\n\n if (!response.ok) {\n throw new Error(`Places API error: ${response.status}`);\n }\n\n const data = await response.json();\n\n if (data.suggestions) {\n const formattedSuggestions: PlaceSuggestion[] = data.suggestions.map((suggestion: any) => ({\n place_id: suggestion.placePrediction?.placeId || \"\",\n description: suggestion.placePrediction?.text?.text || \"\",\n structured_formatting: {\n main_text: suggestion.placePrediction?.structuredFormat?.mainText?.text || \"\",\n secondary_text: suggestion.placePrediction?.structuredFormat?.secondaryText?.text || \"\",\n },\n }));\n\n setSuggestions(formattedSuggestions);\n setShowSuggestions(true);\n } else {\n setSuggestions([]);\n }\n } catch (error) {\n console.error(\"Error fetching place suggestions:\", error);\n setSuggestions([]);\n } finally {\n setIsLoading(false);\n }\n };\n\n // Handle input changes with debouncing\n const handleInputChange = (value: string) => {\n setInputValue(value);\n form.setValue(id, value);\n\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n\n if (value.length > 2 && apiKey) {\n debounceRef.current = setTimeout(() => {\n fetchSuggestions(value);\n }, 300);\n } else {\n setSuggestions([]);\n setShowSuggestions(false);\n setIsLoading(false);\n }\n };\n\n // Handle suggestion selection\n const handleSuggestionSelect = (suggestion: PlaceSuggestion) => {\n setInputValue(suggestion.description);\n form.setValue(id, suggestion.description);\n setShowSuggestions(false);\n setSuggestions([]);\n\n if (onPlaceSelect) {\n onPlaceSelect(suggestion);\n }\n };\n\n // Close suggestions when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setShowSuggestions(false);\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, []);\n\n // Cleanup debounce on unmount\n useEffect(() => {\n return () => {\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n };\n }, []);\n\n // Fallback to regular input if API key is not available\n if (loadError) {\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && (\n <FormLabel className=\"flex items-center\">\n {name}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <Input\n {...field}\n placeholder={placeholder}\n disabled={disabled}\n data-testid={testId}\n className={cn(\"w-full\", className)}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n }\n\n return (\n <div className=\"flex w-full flex-col\" ref={containerRef}>\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && (\n <FormLabel className=\"flex items-center\">\n {name}\n {isRequired && <span className=\"text-destructive ml-2 font-semibold\">*</span>}\n </FormLabel>\n )}\n <FormControl>\n <div className=\"relative\">\n <Input\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value)}\n onBlur={field.onBlur}\n onFocus={() => {\n if (suggestions.length > 0) {\n setShowSuggestions(true);\n }\n }}\n placeholder={placeholder}\n disabled={disabled || !apiKey}\n data-testid={testId}\n className={cn(\"w-full\", className)}\n />\n\n {/* Loading indicator */}\n {isLoading && (\n <div className=\"absolute right-3 top-1/2 -translate-y-1/2\">\n <div className=\"border-primary h-4 w-4 animate-spin rounded-full border-2 border-t-transparent\"></div>\n </div>\n )}\n\n {/* Suggestions dropdown */}\n {showSuggestions && suggestions.length > 0 && (\n <div className=\"bg-background absolute left-0 right-0 top-full z-50 mt-1 max-h-60 overflow-auto rounded-md border shadow-lg\">\n {suggestions.map((suggestion, index) => (\n <div\n key={suggestion.place_id || index}\n className=\"hover:bg-muted cursor-pointer px-3 py-2 text-sm\"\n onClick={() => handleSuggestionSelect(suggestion)}\n >\n <div className=\"font-medium\">{suggestion.structured_formatting?.main_text}</div>\n <div className=\"text-muted-foreground\">{suggestion.structured_formatting?.secondary_text}</div>\n </div>\n ))}\n </div>\n )}\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport {\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\n\nexport function FormSelect({\n form,\n id,\n name,\n placeholder,\n disabled,\n values,\n onChange,\n useRows,\n testId,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n disabled?: boolean;\n values: { id: string; text: string }[];\n onChange?: (value: string) => void;\n useRows?: boolean;\n testId?: string;\n}) {\n return (\n <div className={`flex w-full flex-col`}>\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`flex w-full ${useRows ? `flex-row items-center justify-between gap-x-4` : `flex-col`}`}>\n {name && <FormLabel className={`${useRows ? `min-w-28` : ``}`}>{name}</FormLabel>}\n <Select\n onValueChange={(e) => {\n field.onChange(e);\n if (onChange) onChange(e);\n }}\n defaultValue={field.value}\n data-testid={testId}\n >\n <FormControl className=\"w-full\">\n <SelectTrigger>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n </FormControl>\n <SelectContent>\n {values.map((type: { id: string; text: string }) => (\n <SelectItem key={type.id} value={type.id}>\n {type.text}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { useWatch } from \"react-hook-form\";\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, Slider } from \"../../shadcnui\";\n\nexport function FormSlider({\n form,\n id,\n name,\n disabled,\n showPercentage,\n}: {\n form: any;\n id: string;\n name?: string;\n placeholder?: string;\n disabled?: boolean;\n showPercentage?: boolean;\n}) {\n const value = useWatch({ control: form.control, name: id });\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n {name && <FormLabel>{name}</FormLabel>}\n <FormControl>\n <div>\n {showPercentage && (\n <div className=\"text-muted-foreground mb-2 flex w-full justify-center text-xs\">{`${value}%`}</div>\n )}\n <Slider\n onValueChange={(value: number[]) => form.setValue(id, value[0])}\n value={[value]}\n max={100}\n step={5}\n disabled={disabled === true || form.formState.isSubmitting}\n />\n {/* </div> */}\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, Switch } from \"../../shadcnui\";\n\nexport function FormSwitch({ form, id, name, disabled }: { form: any; id: string; name?: string; disabled?: boolean }) {\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n <FormControl>\n <div className=\"flex flex-row gap-x-4\">\n <Switch checked={field.value} onCheckedChange={field.onChange} />\n {name && <FormLabel>{name}</FormLabel>}\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { FormControl, FormField, FormItem, FormLabel, FormMessage, Textarea } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\n\nexport function FormTextarea({\n form,\n id,\n name,\n className,\n placeholder,\n testId,\n}: {\n form: any;\n id: string;\n name: string;\n placeholder?: string;\n className?: string;\n testId?: string;\n}) {\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className=\"mb-5\">\n <FormLabel>{name}</FormLabel>\n <FormControl>\n <Textarea\n {...field}\n className={cn(\"min-h-96 w-full\", className)}\n disabled={form.formState.isSubmitting}\n placeholder={placeholder}\n data-testid={testId}\n />\n </FormControl>\n <FormMessage data-testid={testId ? `${testId}-error` : undefined} />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { FileIcon, FileImageIcon, FileSpreadsheetIcon, FileTextIcon, UploadIcon, XIcon } from \"lucide-react\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { DropzoneOptions } from \"react-dropzone\";\nimport { cn } from \"../../utils\";\nimport { FileInput, FileUploader } from \"./FileUploader\";\n\ntype MultiFileUploaderProps = {\n files: File[];\n setFiles: (files: File[]) => void;\n};\n\nconst dropzone = {\n multiple: false,\n maxSize: 100 * 1024 * 1024,\n preventDropOnDocument: false,\n accept: {\n \"application/images\": [\".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".svg\", \".docx\", \".xslx\", \".pdf\", \".txt\", \".md\"],\n },\n} satisfies DropzoneOptions;\n\nexport default function MultiFileUploader({ files, setFiles }: MultiFileUploaderProps) {\n const uploadFiles = (newFiles: File[] | null) => {\n if (!newFiles) return;\n\n setFiles([...files, ...newFiles]);\n };\n\n const handleRemoveFile = (indexToRemove: number) => {\n setFiles(files.filter((_, index) => index !== indexToRemove));\n };\n\n return (\n <div className=\"grid w-full grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6\">\n <FileUploader\n value={files}\n onValueChange={uploadFiles}\n dropzoneOptions={dropzone}\n className=\"text-muted-foreground hover:text-primary relative aspect-square h-full cursor-pointer overflow-hidden rounded-lg border\"\n >\n <FileInput className={cn(\"text-muted-foreground flex h-full w-full flex-col items-center justify-center\")}>\n <UploadIcon className=\"my-4 h-8 w-8\" />\n </FileInput>\n </FileUploader>\n {files.map((file, index) => (\n <FilePreviewItem key={file.name + \"-\" + index} file={file} onRemoveClick={() => handleRemoveFile(index)} />\n ))}\n </div>\n );\n}\n\nconst FilePreviewItem = ({ file, onRemoveClick }: { file: File; onRemoveClick: () => void }) => {\n const [objectUrl, setObjectUrl] = useState<string | null>(null);\n\n useEffect(() => {\n if (file.type.startsWith(\"image/\")) {\n const url = URL.createObjectURL(file);\n setObjectUrl(url);\n return () => URL.revokeObjectURL(url);\n }\n setObjectUrl(null);\n }, [file]);\n\n const getFileIcon = () => {\n const extension = file.name.split(\".\").pop()?.toLowerCase();\n if (file.type.startsWith(\"image/\")) {\n return <FileImageIcon className=\"text-muted h-10 w-10 sm:h-12 sm:w-12\" />;\n }\n if (file.type === \"application/pdf\") {\n return <FileTextIcon className=\"text-destructive h-10 w-10 sm:h-12 sm:w-12\" />;\n }\n if (file.type.includes(\"wordprocessingml\") || extension === \"docx\" || extension === \"doc\") {\n return <FileTextIcon className=\"text-primary h-10 w-10 sm:h-12 sm:w-12\" />;\n }\n if (file.type.includes(\"spreadsheetml\") || extension === \"xlsx\" || extension === \"xls\") {\n return <FileSpreadsheetIcon className=\"text-secondary h-10 w-10 sm:h-12 sm:w-12\" />;\n }\n if (file.type.startsWith(\"text/\")) {\n return <FileTextIcon className=\"h-10 w-10 sm:h-12 sm:w-12\" />;\n }\n return <FileIcon className=\"text-muted h-10 w-10 sm:h-12 sm:w-12\" />;\n };\n\n return (\n <div className=\"text-muted-foreground group relative aspect-square h-full overflow-hidden rounded-lg border\">\n <button\n onClick={onRemoveClick}\n className=\"absolute top-1.5 right-1.5 z-20 rounded-full bg-black/60 p-1 text-white opacity-0 transition-all duration-200 ease-in-out group-hover:opacity-100 hover:bg-red-600 focus:outline-none\"\n aria-label=\"Remove file\"\n >\n <XIcon className=\"h-3.5 w-3.5\" />\n </button>\n {objectUrl ? (\n <Image src={objectUrl} alt={file.name} className=\"h-full w-full object-cover\" width={200} height={200} />\n ) : (\n <div className=\"bg-muted/30 flex h-full w-full flex-col items-center justify-center p-2\">\n {getFileIcon()}\n <span className=\"text-foreground/80 mt-2 w-full truncate px-1 text-center text-[10px] sm:text-xs\">\n {file.name}\n </span>\n </div>\n )}\n </div>\n );\n};\n","\"use client\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n Checkbox,\n FormLabel,\n FormMessage,\n} from \"../../../../shadcnui\";\nimport { ModuleInterface } from \"../../../module\";\nimport { FeatureInterface } from \"../../data\";\n\ntype FormFeaturesProps = {\n form: any;\n name?: string;\n features: FeatureInterface[];\n featureField?: string;\n moduleField?: string;\n};\n\nexport function FormFeatures({\n form,\n name,\n features,\n featureField = \"featureIds\",\n moduleField = \"moduleIds\",\n}: FormFeaturesProps) {\n const selectedFeatures: string[] = form.watch(featureField);\n const selectedModules: string[] = form.watch(moduleField);\n\n const toggleFeature = (feature: FeatureInterface, checked: boolean) => {\n let newFeatureIds = [...selectedFeatures];\n let newModuleIds = [...selectedModules];\n\n if (checked) {\n if (!newFeatureIds.includes(feature.id)) {\n newFeatureIds.push(feature.id);\n }\n feature.modules.forEach((module) => {\n if (!newModuleIds.includes(module.id)) {\n newModuleIds.push(module.id);\n }\n });\n } else {\n newFeatureIds = newFeatureIds.filter((id) => id !== feature.id);\n feature.modules.forEach((module) => {\n newModuleIds = newModuleIds.filter((id) => id !== module.id);\n });\n }\n form.setValue(featureField, newFeatureIds);\n form.setValue(moduleField, newModuleIds);\n };\n\n const toggleModule = (feature: FeatureInterface, module: ModuleInterface, checked: boolean) => {\n const modulesForFeature = feature.modules.map((m) => m.id);\n let newModuleIds = [...selectedModules];\n\n if (checked) {\n if (!selectedFeatures.includes(feature.id)) {\n newModuleIds = newModuleIds.filter((id) => !modulesForFeature.includes(id));\n newModuleIds.push(module.id);\n form.setValue(featureField, [...selectedFeatures, feature.id]);\n } else {\n if (!newModuleIds.includes(module.id)) {\n newModuleIds.push(module.id);\n }\n }\n } else {\n newModuleIds = newModuleIds.filter((id) => id !== module.id);\n const remaining = feature.modules.filter((m) => newModuleIds.includes(m.id));\n if (remaining.length === 0) {\n form.setValue(\n featureField,\n selectedFeatures.filter((id) => id !== feature.id),\n );\n }\n }\n form.setValue(moduleField, newModuleIds);\n };\n\n const isFeatureChecked = (feature: FeatureInterface) =>\n selectedFeatures.includes(feature.id) || feature.modules.every((module) => selectedModules.includes(module.id));\n\n return (\n <div className=\"flex w-full flex-col\">\n {name && <h2 className=\"mb-5 font-semibold\">{name}</h2>}\n {features.map((feature) => (\n <Accordion\n key={feature.id}\n type=\"single\"\n collapsible\n // className={`w-full p-0 ${feature.modules.filter((module) => !module.isCore).length === 0 ? \"border-t\" : \"\"}`}\n className={`w-full p-0`}\n >\n <AccordionItem value={feature.id} className=\"p-0\">\n <div\n className={`flex items-center justify-between p-0 ${feature.modules.filter((module) => !module.isCore).length === 0 ? \"py-4\" : \"\"}`}\n >\n <div className=\"flex items-center\" onClick={(e) => e.stopPropagation()}>\n <Checkbox\n id={feature.id}\n checked={isFeatureChecked(feature)}\n onCheckedChange={(val) => {\n toggleFeature(feature, val === true);\n }}\n />\n <FormLabel htmlFor={feature.id} className=\"ml-3 cursor-pointer font-normal\">\n {feature.name}\n </FormLabel>\n </div>\n {feature.modules.filter((module) => !module.isCore).length > 0 && (\n <AccordionTrigger asChild>\n <div className=\"w-full\"></div>\n </AccordionTrigger>\n )}\n </div>\n {feature.modules.filter((module) => !module.isCore).length > 0 && (\n <AccordionContent className=\"pl-6\">\n {feature.modules\n .filter((module) => !module.isCore)\n .sort((a: ModuleInterface, b: ModuleInterface) => a.name.localeCompare(b.name))\n .map((module: ModuleInterface) => (\n <div\n key={module.id}\n className=\"flex items-center border-t py-2\"\n onClick={(e) => e.stopPropagation()}\n >\n <Checkbox\n id={module.id}\n checked={selectedModules.includes(module.id)}\n onCheckedChange={(val) => {\n toggleModule(feature, module, val === true);\n }}\n />\n <FormLabel htmlFor={module.id} className=\"ml-3 cursor-pointer font-normal\">\n {module.name}\n </FormLabel>\n </div>\n ))}\n </AccordionContent>\n )}\n </AccordionItem>\n </Accordion>\n ))}\n <FormMessage />\n </div>\n );\n}\n","\"use client\";\n\nimport { ReactNode, useEffect, useRef, useState } from \"react\";\nimport { useUrlRewriter } from \"../../hooks/url.rewriter\";\nimport { ModuleWithPermissions } from \"../../permissions\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"../../shadcnui\";\n\nexport type PageContainerItems = {\n title: string;\n content: ReactNode;\n};\n\ntype PageContainerContentDetailsProps = {\n items: PageContainerItems[];\n section?: string;\n module: ModuleWithPermissions;\n id: string;\n};\n\nexport function PageContainerContentDetails({ items, section, module, id }: PageContainerContentDetailsProps) {\n const rewriteUrl = useUrlRewriter();\n const [isScrolled, setIsScrolled] = useState<boolean>(false);\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n // Use IntersectionObserver to detect when content scrolls past the TabsList\n useEffect(() => {\n const sentinel = sentinelRef.current;\n if (!sentinel) return;\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n // When sentinel is not visible (scrolled past), show border\n setIsScrolled(!entry.isIntersecting);\n },\n {\n threshold: 0,\n rootMargin: \"0px\",\n },\n );\n\n observer.observe(sentinel);\n\n return () => {\n observer.disconnect();\n };\n }, []);\n\n return (\n <Tabs\n defaultValue={section || items[0].title}\n onValueChange={(a) => rewriteUrl({ page: module, id: id, childPage: a })}\n >\n {/* Sentinel element - invisible, used to detect scroll position */}\n <div ref={sentinelRef} className=\"h-0\" />\n\n {/* Sticky TabsList with conditional border */}\n <div className={`bg-background sticky top-0 z-10 mb-2 pb-2 transition-shadow ${isScrolled ? \"border-b\" : \"\"}`}>\n <TabsList>\n {items.map((item) => (\n <TabsTrigger key={item.title} value={item.title}>\n {item.title}\n </TabsTrigger>\n ))}\n </TabsList>\n </div>\n\n <div className=\"pr-4\">\n {items.map((item) => (\n <TabsContent key={item.title} value={item.title}>\n {item.content}\n </TabsContent>\n ))}\n </div>\n </Tabs>\n );\n}\n","\"use client\";\n\nimport { ReactNode } from \"react\";\nimport { ResizableHandle, ResizablePanel, ResizablePanelGroup } from \"../../shadcnui\";\n\ntype PageContentContainerProps = {\n details: ReactNode;\n footer?: ReactNode;\n content?: ReactNode;\n};\n\nexport function PageContentContainer({ details, footer, content }: PageContentContainerProps) {\n return (\n <div className=\"flex h-[calc(100vh-(--spacing(16)))] w-full\">\n <ResizablePanelGroup direction=\"horizontal\" className=\"items-stretch\" autoSaveId=\"page-content-layout\">\n <ResizablePanel id=\"left-panel\" defaultSize={32} minSize={20} maxSize={40}>\n <div className=\"@container flex h-full flex-col pr-4\">\n <div className=\"flex-1 overflow-y-auto\">{details}</div>\n\n {/* Sticky footer - always visible at bottom */}\n {footer && <div className=\"flex flex-col gap-y-2 pt-2 pb-2\">{footer}</div>}\n </div>\n </ResizablePanel>\n <ResizableHandle withHandle />\n <ResizablePanel id=\"right-panel\" className=\"pl-4\">\n <div className=\"h-full overflow-y-auto\">{content}</div>\n </ResizablePanel>\n </ResizablePanelGroup>\n </div>\n );\n}\n","import { ColumnDef } from \"@tanstack/react-table\";\nimport React from \"react\";\n\nexport const cellComponent = (params: {\n id: string;\n name: string;\n title: string;\n component: React.ReactNode;\n}): ColumnDef<any> => {\n return {\n id: params.name,\n accessorKey: params.name,\n header: params.title,\n cell: ({ row }) => params.component,\n enableSorting: false,\n enableHiding: false,\n };\n};\n","import { ColumnDef } from \"@tanstack/react-table\";\n\nexport const cellDate = (params: { name: string; title: string }): ColumnDef<any> => {\n return {\n id: params.name,\n accessorKey: params.name,\n header: params.title,\n cell: ({ row }) => (\n <span className=\"text-muted-foreground text-xs\">\n {row.getValue<Date>(params.name).toLocaleDateString(\"en\", { dateStyle: \"medium\" })}\n </span>\n ),\n enableSorting: false,\n enableHiding: false,\n };\n};\n","import { ColumnDef } from \"@tanstack/react-table\";\nimport { Checkbox } from \"../../../shadcnui\";\n\nexport const cellId = (params: {\n name: string;\n checkedIds?: string[];\n toggleId?: (id: string) => void;\n}): ColumnDef<any> => {\n return {\n id: params.name,\n accessorKey: params.name,\n header: \"\",\n cell: ({ row }) =>\n params.toggleId ? (\n <Checkbox\n checked={params.checkedIds?.includes(row.getValue(params.name)) || false}\n onCheckedChange={(value) => {\n row.toggleSelected(!!value);\n params.toggleId?.(row.getValue(params.name));\n }}\n aria-label=\"Select row\"\n />\n ) : null,\n enableSorting: false,\n enableHiding: true,\n };\n};\n","import { ColumnDef } from \"@tanstack/react-table\";\nimport { Link } from \"../../../shadcnui\";\n\nexport const cellLink = <T,>(params: {\n id: string;\n name: string;\n title: string;\n generateUrl: (id: string) => string;\n}): ColumnDef<T> => {\n return {\n id: params.name,\n accessorKey: params.name,\n header: params.title,\n cell: ({ row }) => <Link href={params.generateUrl(row.getValue(params.id))}>{row.getValue(params.name)}</Link>,\n enableSorting: false,\n enableHiding: false,\n };\n};\n","import { ColumnDef } from \"@tanstack/react-table\";\nimport { Link } from \"../../../shadcnui\";\n\nexport const cellUrl = (params: { name: string; title: string }): ColumnDef<any> => {\n return {\n id: params.name,\n accessorKey: params.name,\n header: params.title,\n cell: ({ row }) => <Link href={row.getValue(params.name)}>{row.getValue(params.name)}</Link>,\n enableSorting: false,\n enableHiding: false,\n };\n};\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\n\nexport type CacheProfile = \"seconds\" | \"minutes\" | \"hours\" | \"days\" | \"weeks\" | \"max\" | \"default\";\n\nexport interface JsonApiConfig {\n /**\n * The base URL for API requests (e.g., https://api.example.com)\n */\n apiUrl: string;\n\n /**\n * Custom token getter function. If not provided, will use default cookie-based token retrieval.\n */\n tokenGetter?: () => Promise<string | undefined>;\n\n /**\n * Custom language getter function. If not provided, will use browser locale or next-intl.\n */\n languageGetter?: () => Promise<string>;\n\n /**\n * Default headers to include in all requests\n */\n defaultHeaders?: Record<string, string>;\n\n /**\n * Global error handler for failed requests (client-side only)\n */\n onError?: (status: number, message: string) => void;\n\n /**\n * Cache configuration\n */\n cacheConfig?: {\n defaultProfile: CacheProfile;\n };\n\n /**\n * Function to bootstrap the data class registry.\n * Will be called automatically when needed.\n */\n bootstrapper?: () => void;\n}\n\nconst JsonApiContext = createContext<JsonApiConfig | null>(null);\n\nexport function useJsonApiConfig(): JsonApiConfig {\n const config = useContext(JsonApiContext);\n if (!config) {\n throw new Error(\"useJsonApiConfig must be used within a JsonApiProvider\");\n }\n return config;\n}\n\nexport function useJsonApiConfigOptional(): JsonApiConfig | null {\n return useContext(JsonApiContext);\n}\n\nexport { JsonApiContext };\n","\"use client\";\n\nimport React, { useEffect, useMemo } from \"react\";\nimport { JsonApiConfig, JsonApiContext } from \"./JsonApiContext\";\n\nexport interface JsonApiProviderProps {\n config: JsonApiConfig;\n children: React.ReactNode;\n}\n\nexport function JsonApiProvider({ config, children }: JsonApiProviderProps) {\n // Run bootstrapper on mount if provided\n useEffect(() => {\n if (config.bootstrapper) {\n config.bootstrapper();\n }\n }, [config.bootstrapper]);\n\n // Memoize config to prevent unnecessary re-renders\n const memoizedConfig = useMemo(() => config, [config]);\n\n return (\n <JsonApiContext.Provider value={memoizedConfig}>\n {children}\n </JsonApiContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport { ApiDataInterface } from \"../../core/interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../../core/interfaces/ApiRequestDataTypeInterface\";\nimport { ApiResponseInterface } from \"../../core/interfaces/ApiResponseInterface\";\n\nexport interface UseJsonApiGetOptions {\n /**\n * Whether to enable the query. If false, the query won't run.\n */\n enabled?: boolean;\n /**\n * Dependencies that trigger a refetch when changed.\n */\n deps?: any[];\n}\n\nexport interface UseJsonApiGetResult<T> {\n /**\n * The fetched data, or null if not yet fetched.\n */\n data: T | null;\n /**\n * Whether the query is currently loading.\n */\n loading: boolean;\n /**\n * Error message if the query failed.\n */\n error: string | null;\n /**\n * The full API response (includes raw data, pagination, etc.)\n */\n response: ApiResponseInterface | null;\n /**\n * Function to manually refetch the data.\n */\n refetch: () => Promise<void>;\n /**\n * Whether there is a next page available.\n */\n hasNextPage: boolean;\n /**\n * Whether there is a previous page available.\n */\n hasPreviousPage: boolean;\n /**\n * Function to fetch the next page.\n */\n fetchNextPage: () => Promise<void>;\n /**\n * Function to fetch the previous page.\n */\n fetchPreviousPage: () => Promise<void>;\n}\n\n/**\n * Hook for fetching data from a JSON:API endpoint.\n *\n * @example\n * ```tsx\n * const { data, loading, error, refetch } = useJsonApiGet<Article>({\n * classKey: Modules.Article,\n * endpoint: `/articles/${id}`,\n * });\n *\n * if (loading) return <Loading />;\n * if (error) return <Error message={error} />;\n * return <ArticleView article={data} />;\n * ```\n */\nexport function useJsonApiGet<T extends ApiDataInterface>(params: {\n classKey: ApiRequestDataTypeInterface;\n endpoint: string;\n companyId?: string;\n options?: UseJsonApiGetOptions;\n}): UseJsonApiGetResult<T> {\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [response, setResponse] = useState<ApiResponseInterface | null>(null);\n const isMounted = useRef(true);\n\n const fetchData = useCallback(async () => {\n if (params.options?.enabled === false) return;\n\n setLoading(true);\n setError(null);\n\n try {\n const { JsonApiGet } = await import(\"../../unified/JsonApiRequest\");\n const language = navigator.language.split(\"-\")[0] || \"en\";\n\n const apiResponse = await JsonApiGet({\n classKey: params.classKey,\n endpoint: params.endpoint,\n companyId: params.companyId,\n language,\n });\n\n if (!isMounted.current) return;\n\n setResponse(apiResponse);\n\n if (apiResponse.ok) {\n setData(apiResponse.data as T);\n } else {\n setError(apiResponse.error);\n }\n } catch (err) {\n if (!isMounted.current) return;\n setError(err instanceof Error ? err.message : \"Unknown error\");\n } finally {\n if (isMounted.current) {\n setLoading(false);\n }\n }\n }, [params.classKey, params.endpoint, params.companyId, params.options?.enabled]);\n\n const fetchNextPage = useCallback(async () => {\n if (!response?.nextPage) return;\n\n setLoading(true);\n try {\n const nextResponse = await response.nextPage();\n if (!isMounted.current) return;\n\n setResponse(nextResponse);\n if (nextResponse.ok) {\n setData(nextResponse.data as T);\n } else {\n setError(nextResponse.error);\n }\n } catch (err) {\n if (!isMounted.current) return;\n setError(err instanceof Error ? err.message : \"Unknown error\");\n } finally {\n if (isMounted.current) {\n setLoading(false);\n }\n }\n }, [response]);\n\n const fetchPreviousPage = useCallback(async () => {\n if (!response?.prevPage) return;\n\n setLoading(true);\n try {\n const prevResponse = await response.prevPage();\n if (!isMounted.current) return;\n\n setResponse(prevResponse);\n if (prevResponse.ok) {\n setData(prevResponse.data as T);\n } else {\n setError(prevResponse.error);\n }\n } catch (err) {\n if (!isMounted.current) return;\n setError(err instanceof Error ? err.message : \"Unknown error\");\n } finally {\n if (isMounted.current) {\n setLoading(false);\n }\n }\n }, [response]);\n\n useEffect(() => {\n isMounted.current = true;\n fetchData();\n return () => {\n isMounted.current = false;\n };\n }, [fetchData, ...(params.options?.deps || [])]);\n\n return {\n data,\n loading,\n error,\n response,\n refetch: fetchData,\n hasNextPage: !!response?.next,\n hasPreviousPage: !!response?.prev,\n fetchNextPage,\n fetchPreviousPage,\n };\n}\n","\"use client\";\n\nimport { useState, useCallback } from \"react\";\nimport { ApiDataInterface } from \"../../core/interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../../core/interfaces/ApiRequestDataTypeInterface\";\nimport { ApiResponseInterface } from \"../../core/interfaces/ApiResponseInterface\";\n\nexport type MutationMethod = \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\nexport interface UseJsonApiMutationResult<T> {\n /**\n * The result data from the mutation, or null if not yet executed.\n */\n data: T | null;\n /**\n * Whether the mutation is currently in progress.\n */\n loading: boolean;\n /**\n * Error message if the mutation failed.\n */\n error: string | null;\n /**\n * The full API response.\n */\n response: ApiResponseInterface | null;\n /**\n * Execute the mutation.\n */\n mutate: (params: MutationParams) => Promise<T | null>;\n /**\n * Reset the mutation state.\n */\n reset: () => void;\n}\n\nexport interface MutationParams {\n /**\n * The endpoint to call.\n */\n endpoint: string;\n /**\n * The request body.\n */\n body?: any;\n /**\n * Files to upload.\n */\n files?: { [key: string]: File | Blob } | File | Blob;\n /**\n * Company ID for multi-tenant requests.\n */\n companyId?: string;\n /**\n * Override the default JSON:API body creation.\n */\n overridesJsonApiCreation?: boolean;\n /**\n * Response type if different from the request type.\n */\n responseType?: ApiRequestDataTypeInterface;\n}\n\n/**\n * Hook for making mutations (POST, PUT, PATCH, DELETE) to a JSON:API endpoint.\n *\n * @example\n * ```tsx\n * const { mutate, loading, error } = useJsonApiMutation<Article>({\n * method: \"POST\",\n * classKey: Modules.Article,\n * });\n *\n * const handleSubmit = async (data: ArticleInput) => {\n * const result = await mutate({\n * endpoint: \"/articles\",\n * body: data,\n * });\n * if (result) {\n * // Success!\n * }\n * };\n * ```\n */\nexport function useJsonApiMutation<T extends ApiDataInterface>(config: {\n method: MutationMethod;\n classKey: ApiRequestDataTypeInterface;\n onSuccess?: (data: T) => void;\n onError?: (error: string) => void;\n}): UseJsonApiMutationResult<T> {\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [response, setResponse] = useState<ApiResponseInterface | null>(null);\n\n const reset = useCallback(() => {\n setData(null);\n setLoading(false);\n setError(null);\n setResponse(null);\n }, []);\n\n const mutate = useCallback(\n async (params: MutationParams): Promise<T | null> => {\n setLoading(true);\n setError(null);\n\n try {\n const { JsonApiPost, JsonApiPut, JsonApiPatch, JsonApiDelete } = await import(\"../../unified/JsonApiRequest\");\n const language = navigator.language.split(\"-\")[0] || \"en\";\n\n let apiResponse: ApiResponseInterface;\n\n switch (config.method) {\n case \"POST\":\n apiResponse = await JsonApiPost({\n classKey: config.classKey,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.body,\n overridesJsonApiCreation: params.overridesJsonApiCreation,\n files: params.files,\n language,\n responseType: params.responseType,\n });\n break;\n case \"PUT\":\n apiResponse = await JsonApiPut({\n classKey: config.classKey,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.body,\n files: params.files,\n language,\n responseType: params.responseType,\n });\n break;\n case \"PATCH\":\n apiResponse = await JsonApiPatch({\n classKey: config.classKey,\n endpoint: params.endpoint,\n companyId: params.companyId,\n body: params.body,\n overridesJsonApiCreation: params.overridesJsonApiCreation,\n files: params.files,\n language,\n responseType: params.responseType,\n });\n break;\n case \"DELETE\":\n apiResponse = await JsonApiDelete({\n classKey: config.classKey,\n endpoint: params.endpoint,\n companyId: params.companyId,\n language,\n responseType: params.responseType,\n });\n break;\n }\n\n setResponse(apiResponse);\n\n if (apiResponse.ok) {\n const resultData = apiResponse.data as T;\n setData(resultData);\n config.onSuccess?.(resultData);\n return resultData;\n } else {\n setError(apiResponse.error);\n config.onError?.(apiResponse.error);\n return null;\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n config.onError?.(errorMessage);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [config],\n );\n\n return {\n data,\n loading,\n error,\n response,\n mutate,\n reset,\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { ApiDataInterface } from \"../../core/interfaces/ApiDataInterface\";\nimport { ApiRequestDataTypeInterface } from \"../../core/interfaces/ApiRequestDataTypeInterface\";\nimport { JsonApiHydratedDataInterface } from \"../../core/interfaces/JsonApiHydratedDataInterface\";\nimport { RehydrationFactory } from \"../../core/factories/RehydrationFactory\";\n\n/**\n * Hook to rehydrate server-passed data into typed objects.\n * Use this when passing data from server components to client components.\n *\n * @example\n * ```tsx\n * // In server component\n * const article = await ArticleService.findOne(id);\n * return <ArticleDetails data={article.dehydrate()} />;\n *\n * // In client component\n * function ArticleDetails({ data }: { data: JsonApiHydratedDataInterface }) {\n * const article = useRehydration<Article>(Modules.Article, data);\n * return <div>{article.title}</div>;\n * }\n * ```\n */\nexport function useRehydration<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface | null | undefined,\n): T | null {\n return useMemo(() => {\n if (!data) return null;\n return RehydrationFactory.rehydrate<T>(classKey, data);\n }, [classKey, data]);\n}\n\n/**\n * Hook to rehydrate a list of server-passed data into typed objects.\n */\nexport function useRehydrationList<T extends ApiDataInterface>(\n classKey: ApiRequestDataTypeInterface,\n data: JsonApiHydratedDataInterface[] | null | undefined,\n): T[] {\n return useMemo(() => {\n if (!data || data.length === 0) return [];\n return RehydrationFactory.rehydrateList<T>(classKey, data);\n }, [classKey, data]);\n}\n","\"use client\";\n\nimport { ColumnDef, Row } from \"@tanstack/react-table\";\nimport { useTranslations } from \"next-intl\";\nimport { useMemo } from \"react\";\nimport { cellDate, cellId } from \"../../../components\";\nimport { Modules } from \"../../../core\";\nimport { TableContent, usePageUrlGenerator, UseTableStructureHook } from \"../../../hooks\";\nimport { getRoleId } from \"../../../roles\";\nimport { Link } from \"../../../shadcnui\";\nimport { UserInterface } from \"../../user\";\nimport { useCurrentUserContext } from \"../../user/contexts\";\nimport { CompanyFields, CompanyInterface } from \"../data\";\n\nexport const useCompanyTableStructure: UseTableStructureHook<CompanyInterface, CompanyFields> = (params) => {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n const { hasRole } = useCurrentUserContext<UserInterface>();\n\n // Memoize tableData to prevent infinite re-renders\n const tableData = useMemo(() => {\n return params.data.map((company: CompanyInterface) => {\n const entry: TableContent<CompanyInterface> = {\n jsonApiData: company,\n };\n entry[CompanyFields.companyId] = company.id;\n params.fields.forEach((field) => {\n entry[field] = company[field as keyof CompanyInterface];\n });\n return entry;\n });\n }, [params.data, params.fields]);\n\n const fieldColumnMap: Partial<Record<CompanyFields, () => any>> = {\n [CompanyFields.companyId]: () =>\n cellId({\n name: \"companyId\",\n checkedIds: params.checkedIds,\n toggleId: params.toggleId,\n }),\n [CompanyFields.name]: () => ({\n id: \"name\",\n accessorKey: \"name\",\n header: t(`foundations.user.fields.name.label`),\n cell: ({ row }: { row: Row<TableContent<CompanyInterface>> }) => {\n const company = row.original.jsonApiData as CompanyInterface;\n return (\n <Link\n href={\n hasRole(getRoleId().Administrator)\n ? generateUrl({\n page: \"/administration\",\n id: Modules.Company.pageUrl?.substring(1),\n childPage: company.id,\n })\n : generateUrl({ page: Modules.Company, id: company.id })\n }\n >\n {row.getValue(\"name\")}\n </Link>\n );\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [CompanyFields.createdAt]: () =>\n cellDate({\n name: \"createdAt\",\n title: t(`generic.date.create`),\n }),\n };\n\n // Memoize columns to prevent infinite re-renders\n const columns = useMemo(() => {\n return params.fields.map((field) => fieldColumnMap[field]?.()).filter((col) => col !== undefined) as ColumnDef<\n TableContent<CompanyInterface>\n >[];\n }, [params.fields, fieldColumnMap, t, generateUrl, hasRole]);\n\n // Memoize the return object to prevent infinite re-renders\n return useMemo(() => ({ data: tableData, columns: columns }), [tableData, columns]);\n};\n","\"use client\";\n\nimport { ColumnDef, Row } from \"@tanstack/react-table\";\nimport { useTranslations } from \"next-intl\";\nimport { useMemo } from \"react\";\nimport { cellDate, cellId } from \"../../../components\";\nimport { Modules } from \"../../../core\";\nimport { TableContent, usePageUrlGenerator, UseTableStructureHook } from \"../../../hooks\";\nimport { Link } from \"../../../shadcnui\";\nimport { RoleFields, RoleInterface } from \"../data\";\n\nexport const useRoleTableStructure: UseTableStructureHook<RoleInterface, RoleFields> = (params) => {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n\n // Memoize tableData to prevent infinite re-renders\n const tableData = useMemo(() => {\n return params.data.map((role: RoleInterface) => {\n const entry: TableContent<RoleInterface> = {\n jsonApiData: role,\n };\n entry[RoleFields.roleId] = role.id;\n params.fields.forEach((field) => {\n entry[field] = role[field as keyof RoleInterface];\n });\n return entry;\n });\n }, [params.data, params.fields]);\n\n const fieldColumnMap: Partial<Record<RoleFields, () => any>> = {\n [RoleFields.roleId]: () =>\n cellId({\n name: \"roleId\",\n checkedIds: params.checkedIds,\n toggleId: params.toggleId,\n }),\n [RoleFields.name]: () => ({\n id: \"name\",\n accessorKey: \"name\",\n header: t(`foundations.role.fields.name.label`),\n cell: ({ row }: { row: Row<TableContent<RoleInterface>> }) => {\n const role = row.original.jsonApiData as RoleInterface;\n return <Link href={generateUrl({ page: Modules.Role, id: role.id })}>{row.getValue(\"name\")}</Link>;\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [RoleFields.description]: () => ({\n id: \"description\",\n accessorKey: \"description\",\n header: t(`foundations.role.fields.description.label`),\n cell: ({ row }: { row: Row<TableContent<RoleInterface>> }) => <>{row.getValue(\"description\")}</>,\n enableSorting: false,\n enableHiding: false,\n }),\n [RoleFields.createdAt]: () =>\n cellDate({\n name: \"createdAt\",\n title: t(`generic.date.create`),\n }),\n };\n\n // Memoize columns to prevent infinite re-renders\n const columns = useMemo(() => {\n return params.fields.map((field) => fieldColumnMap[field]?.()).filter((col) => col !== undefined) as ColumnDef<\n TableContent<RoleInterface>\n >[];\n }, [params.fields, fieldColumnMap, t, generateUrl]);\n\n // Memoize the return object to prevent infinite re-renders\n return useMemo(() => ({ data: tableData, columns: columns }), [tableData, columns]);\n};\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useDebounce } from \"../../../hooks/useDebounce\";\nimport { UserInterface } from \"../data\";\nimport { UserService } from \"../data/user.service\";\n\nexport const useUserSearch = () => {\n const [users, setUsers] = useState<UserInterface[]>([]);\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [isLoading, setIsLoading] = useState(false);\n const searchQueryRef = useRef(\"\");\n\n const loadUsers = useCallback(\n async (search: string) => {\n try {\n if (search === searchQueryRef.current && users.length > 0) return;\n setIsLoading(true);\n searchQueryRef.current = search;\n const fetchedUsers = await UserService.findMany({ search, fetchAll: true });\n setUsers(fetchedUsers);\n } catch (error) {\n console.error(\"Failed to load users:\", error);\n } finally {\n setIsLoading(false);\n }\n },\n [users.length],\n );\n\n const debouncedLoadUsers = useDebounce(loadUsers, 500);\n\n useEffect(() => {\n if (searchQuery !== searchQueryRef.current) {\n setIsLoading(true);\n debouncedLoadUsers(searchQuery);\n }\n }, [searchQuery, debouncedLoadUsers]);\n\n const clearSearch = () => {\n setSearchQuery(\"\");\n searchQueryRef.current = \"\";\n };\n\n return {\n users,\n searchQuery,\n setSearchQuery,\n isLoading,\n loadUsers,\n clearSearch,\n searchQueryRef,\n };\n};\n","\"use client\";\n\nimport { ColumnDef, Row } from \"@tanstack/react-table\";\nimport { useTranslations } from \"next-intl\";\nimport { useMemo } from \"react\";\nimport { cellDate, cellId, UserAvatar } from \"../../../components\";\nimport { Modules } from \"../../../core\";\nimport { TableContent, UseTableStructureHook } from \"../../../hooks/types\";\nimport { usePageUrlGenerator } from \"../../../hooks/usePageUrlGenerator\";\nimport { Link } from \"../../../shadcnui\";\nimport { cn } from \"../../../utils\";\nimport { UserFields, UserInterface } from \"../data\";\n\nexport const useUserTableStructure: UseTableStructureHook<UserInterface, UserFields> = (params) => {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n\n // Memoize tableData to prevent infinite re-renders\n const tableData = useMemo(() => {\n return params.data.map((user: UserInterface) => {\n const entry: TableContent<UserInterface> = {\n jsonApiData: user,\n };\n entry[UserFields.userId] = user.id;\n params.fields.forEach((field) => {\n entry[field] = user[field as keyof UserInterface];\n });\n return entry;\n });\n }, [params.data, params.fields]);\n\n const fieldColumnMap: Partial<Record<UserFields, () => any>> = {\n [UserFields.userId]: () =>\n cellId({\n name: \"userId\",\n checkedIds: params.checkedIds,\n toggleId: params.toggleId,\n }),\n [UserFields.name]: () => ({\n id: \"name\",\n accessorKey: \"name\",\n header: t(`foundations.user.fields.name.label`),\n cell: ({ row }: { row: Row<TableContent<UserInterface>> }) => {\n const user = row.original.jsonApiData as UserInterface;\n return (\n <Link\n href={generateUrl({ page: Modules.User, id: user.id })}\n className={cn(\n `flex items-center justify-start gap-2`,\n user.isDeleted || !user.isActivated ? \"text-muted-foreground italic\" : \"\",\n )}\n >\n <UserAvatar user={user} />\n {user.name}\n {user.isDeleted ? ` - ${t(\"foundations.user.errors.deleted\")}` : \"\"}\n {!user.isActivated ? ` - ${t(\"foundations.user.errors.inactive\")}` : \"\"}\n </Link>\n );\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [UserFields.email]: () => ({\n id: \"email\",\n accessorKey: \"email\",\n header: t(`generic.fields.email.label`),\n cell: ({ row }: { row: Row<TableContent<UserInterface>> }) => <>{row.getValue(\"email\")}</>,\n enableSorting: false,\n enableHiding: false,\n }),\n [UserFields.relevance]: () => ({\n id: \"relevance\",\n accessorKey: \"relevance\",\n header: t(`generic.relevance`),\n cell: ({ row }: { row: TableContent<UserInterface> }) => {\n const user: UserInterface = row.original.jsonApiData;\n\n if (!user.relevance) return <></>;\n\n const response = `${user.relevance.toFixed(0)}%`;\n\n return (\n <div className=\"relative flex h-5 w-20 items-center justify-center overflow-hidden rounded border text-center\">\n <div\n className={`bg-accent absolute top-0 left-0 h-full opacity-${Math.round(user.relevance)}`}\n style={{ width: `${user.relevance}%` }}\n ></div>\n <span\n className={`relative text-xs ${user.relevance < 40 ? \"text-muted-foreground\" : \"text-accent-foreground font-semibold\"}`}\n >\n {response}\n </span>\n </div>\n );\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [UserFields.createdAt]: () =>\n cellDate({\n name: \"createdAt\",\n title: t(`generic.date.create`),\n }),\n };\n\n // Memoize columns to prevent infinite re-renders\n const columns = useMemo(() => {\n return params.fields.map((field) => fieldColumnMap[field]?.()).filter((col) => col !== undefined) as ColumnDef<\n TableContent<UserInterface>\n >[];\n }, [params.fields, fieldColumnMap, t, generateUrl]);\n\n // Memoize the return object to prevent infinite re-renders\n return useMemo(() => ({ data: tableData, columns: columns }), [tableData, columns]);\n};\n","\"use client\";\n\nimport { ColumnDef } from \"@tanstack/react-table\";\nimport { useTranslations } from \"next-intl\";\nimport { useMemo } from \"react\";\nimport { cellDate, cellId, ContributorsList } from \"../../../components\";\nimport { Modules } from \"../../../core\";\nimport { TableContent, usePageUrlGenerator, UseTableStructureHook } from \"../../../hooks\";\nimport { Link, Tooltip, TooltipContent, TooltipTrigger } from \"../../../shadcnui\";\nimport { getIconByModule } from \"../../../utils\";\nimport { ContentFields, ContentInterface } from \"../data\";\n\nexport const useContentTableStructure = <U extends string = ContentFields>(\n params: Parameters<UseTableStructureHook<ContentInterface, U>>[0],\n): ReturnType<UseTableStructureHook<ContentInterface, U>> => {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n\n const tableData = useMemo(() => {\n return params.data.map((content: ContentInterface) => {\n const entry: TableContent<ContentInterface> = {\n jsonApiData: content,\n };\n entry[ContentFields.contentId] = content.id;\n params.fields.forEach((field) => {\n entry[field as string] = content[field as keyof ContentInterface];\n });\n return entry;\n });\n }, [params.data, params.fields]);\n\n const fieldColumnMap: Partial<Record<string, () => any>> = {\n [ContentFields.contentId]: () =>\n cellId({\n name: \"contentId\",\n checkedIds: params.checkedIds,\n toggleId: params.toggleId,\n }),\n [ContentFields.name]: () => ({\n id: \"name\",\n accessorKey: \"name\",\n header: t(`foundations.content.fields.name.label`),\n cell: ({ row }: { row: TableContent<ContentInterface> }) => {\n const content: ContentInterface = row.original.jsonApiData;\n\n const contentModule = content.contentType ? Modules.findByModelName(content.contentType) : undefined;\n const link = contentModule ? generateUrl({ page: contentModule, id: content.id }) : \"#\";\n\n return (\n <Tooltip>\n <TooltipTrigger className=\"flex items-center justify-start space-x-2\">\n <>\n {contentModule && getIconByModule({ module: contentModule, className: \"h-4 w-4\" })}\n <Link href={link}>{content.name}</Link>\n </>\n </TooltipTrigger>\n <TooltipContent>{content.tldr}</TooltipContent>\n </Tooltip>\n );\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [ContentFields.relevance]: () => ({\n id: \"relevance\",\n accessorKey: \"relevance\",\n header: t(`generic.relevance`),\n cell: ({ row }: { row: TableContent<ContentInterface> }) => {\n const content: ContentInterface = row.original.jsonApiData;\n\n if (!content.relevance) return <></>;\n\n const response = `${content.relevance.toFixed(0)}%`;\n\n return (\n <div className=\"relative flex h-5 w-20 items-center justify-center overflow-hidden rounded border text-center\">\n <div\n className={`bg-accent absolute top-0 left-0 h-full opacity-${Math.round(content.relevance)}`}\n style={{ width: `${content.relevance}%` }}\n ></div>\n <span\n className={`relative text-xs ${content.relevance < 40 ? \"text-muted-foreground\" : \"text-accent-foreground font-semibold\"}`}\n >\n {response}\n </span>\n </div>\n );\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [ContentFields.authors]: () => ({\n id: \"authors\",\n accessorKey: \"authors\",\n header: t(`generic.relationships.author.label`),\n cell: ({ row }: { row: TableContent<ContentInterface> }) => {\n const content: ContentInterface = row.original.jsonApiData;\n return <ContributorsList content={content} />;\n },\n enableSorting: false,\n enableHiding: false,\n }),\n [ContentFields.createdAt]: () =>\n cellDate({\n name: \"createdAt\",\n title: t(`generic.date.create`),\n }),\n [ContentFields.updatedAt]: () =>\n cellDate({\n name: \"updatedAt\",\n title: t(`generic.date.update`),\n }),\n };\n\n const columns = useMemo(() => {\n return params.fields\n .map((field) => {\n // First check local fieldColumnMap\n const localHandler = fieldColumnMap[field];\n if (localHandler) return localHandler();\n\n // Fallback to customCells from context\n const customHandler = params.context?.customCells?.[field];\n if (customHandler) return customHandler({ t });\n\n return undefined;\n })\n .filter((col) => col !== undefined) as ColumnDef<TableContent<ContentInterface>>[];\n }, [params.fields, fieldColumnMap, t, generateUrl, params.context?.customCells]);\n\n return useMemo(() => ({ data: tableData, columns: columns }), [tableData, columns]);\n};\n","\"use client\";\n\n// Context and Provider\nexport * from \"./context\";\n\n// Client-side hooks\nexport * from \"./hooks\";\n\n// Client-side request utilities\nexport * from \"./request\";\nexport * from \"./token\";\nexport * from \"./JsonApiClient\";\nexport * from \"./config\";\n\n// All hooks (merged from /hooks entry point)\nexport * from \"../hooks\";\n\n// Table generator registration (must be in client-only context)\nimport { useCompanyTableStructure } from \"../features/company/hooks\";\nimport { useRoleTableStructure } from \"../features/role/hooks\";\nimport { useUserTableStructure } from \"../features/user/hooks\";\nimport { registerTableGenerator } from \"../hooks\";\n\nexport * from \"../features/content/hooks\";\nexport * from \"../features/role/hooks\";\nexport * from \"../features/user/hooks\";\n\nregisterTableGenerator(\"roles\", useRoleTableStructure);\nregisterTableGenerator(\"users\", useUserTableStructure);\nregisterTableGenerator(\"companies\", useCompanyTableStructure);\n// Note: Content registration moved to app-level to support app-specific cellTopic\n","\"use client\";\nimport \"../../client\";\n\nimport { flexRender, getCoreRowModel, useReactTable } from \"@tanstack/react-table\";\n\nimport { CaretLeftIcon, CaretRightIcon } from \"@radix-ui/react-icons\";\nimport { ReactNode, memo, useMemo } from \"react\";\nimport { DataListRetriever, useTableGenerator } from \"../../hooks\";\nimport { ModuleWithPermissions } from \"../../permissions\";\nimport { Button, Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from \"../../shadcnui\";\nimport { ContentTableSearch } from \"./ContentTableSearch\";\n\nconst EMPTY_ARRAY: any[] = [];\n\nexport type GenerateTableStructureParams = {\n data: any[];\n toggleValueToFormIdsId: (id: string, name: string) => void;\n isSelected: (id: string) => boolean;\n};\n\ntype ContentListTableProps = {\n title?: string;\n data: DataListRetriever<any>;\n tableGenerator?: never;\n tableGeneratorType: ModuleWithPermissions;\n fields: any[];\n checkedIds?: string[];\n toggleId?: (id: string) => void;\n functions?: ReactNode;\n filters?: ReactNode;\n allowSearch?: boolean;\n context?: Record<string, any>;\n};\n\nexport const ContentListTable = memo(function ContentListTable(props: ContentListTableProps) {\n const { data, fields, checkedIds, toggleId, allowSearch, filters } = props;\n\n const { data: tableData, columns: tableColumns } = useTableGenerator(props.tableGeneratorType, {\n data: data?.data ?? EMPTY_ARRAY,\n fields: fields,\n checkedIds: checkedIds,\n toggleId: toggleId,\n dataRetriever: data,\n context: props.context,\n });\n\n const columnVisibility = useMemo(\n () =>\n fields.reduce(\n (acc, columnId) => {\n acc[columnId] = true;\n return acc;\n },\n {} as Record<string, boolean>,\n ),\n [fields],\n );\n\n const table = useReactTable({\n data: tableData,\n columns: tableColumns,\n getCoreRowModel: getCoreRowModel(),\n initialState: {\n columnVisibility,\n },\n });\n\n // if (!data.isLoaded || !data.data) {\n // return <ContentListTableLoader />;\n // }\n\n const rowModel = tableData ? table.getRowModel() : null;\n const showFooter = !!(props.functions || data.next || data.previous);\n\n return (\n <div className=\"flex w-full flex-col\">\n <div className=\"overflow-hidden rounded-md border\">\n <Table>\n <TableHeader className=\"bg-muted font-semibold\">\n {props.title && (\n <TableRow>\n <TableHead className=\"bg-card text-primary p-4 text-left font-bold\" colSpan={tableColumns.length}>\n <div className=\"flex w-full items-center justify-between gap-x-2\">\n <div className=\"w-full\">{props.title}</div>\n {(props.functions || props.filters || allowSearch) && (\n <>\n {props.functions}\n {props.filters}\n <ContentTableSearch data={data} />\n </>\n )}\n </div>\n </TableHead>\n </TableRow>\n )}\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map((header) => {\n return (\n <TableHead key={header.id}>\n {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}\n </TableHead>\n );\n })}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n {rowModel && rowModel.rows?.length ? (\n rowModel.rows.map((row) => (\n <TableRow key={row.id}>\n {row.getVisibleCells().map((cell) => (\n <TableCell key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCell>\n ))}\n </TableRow>\n ))\n ) : (\n <TableRow>\n <TableCell colSpan={tableColumns.length} className=\"h-24 text-center\">\n No results.\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n {showFooter && (\n <TableFooter>\n <TableRow>\n <TableCell colSpan={tableColumns.length} className=\"bg-card py-4 text-right\">\n <div className=\"flex items-center justify-end space-x-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.preventDefault();\n data.previous?.(true);\n }}\n disabled={!data.previous}\n >\n <CaretLeftIcon className=\"h-4 w-4\" />\n </Button>\n {data.pageInfo && (\n <span className=\"text-muted-foreground text-xs\">\n {data.pageInfo.startItem}-{data.pageInfo.endItem}\n </span>\n )}\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.preventDefault();\n data.next?.(true);\n }}\n disabled={!data.next}\n >\n <CaretRightIcon className=\"h-4 w-4\" />\n </Button>\n </div>\n </TableCell>\n </TableRow>\n </TableFooter>\n )}\n </Table>\n </div>\n </div>\n );\n});\n","\"use client\";\n\nimport { RefreshCw, Search, X } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { DataListRetriever, useDebounce } from \"../../hooks\";\nimport { Input } from \"../../shadcnui\";\n\ntype ContentTableSearchProps = {\n data: DataListRetriever<any>;\n};\n\nexport function ContentTableSearch({ data }: ContentTableSearchProps) {\n const t = useTranslations();\n const searchTermRef = useRef<string>(\"\");\n const inputRef = useRef<HTMLInputElement>(null);\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n const [isFocused, setIsFocused] = useState<boolean>(false);\n const [isSearching, setIsSearching] = useState<boolean>(false);\n\n const isExpanded = isFocused || searchTerm.length > 0;\n\n const search = useCallback(\n async (searchedTerm: string) => {\n try {\n if (searchedTerm === searchTermRef.current) return;\n searchTermRef.current = searchedTerm;\n\n await data.search(searchedTerm);\n } finally {\n setIsSearching(false);\n }\n },\n [searchTermRef, data],\n );\n\n const updateSearchTerm = useDebounce(search, 500);\n\n useEffect(() => {\n setIsSearching(true);\n updateSearchTerm(searchTerm);\n }, [updateSearchTerm, searchTerm]);\n\n const handleSearchIconClick = () => {\n if (!isExpanded) {\n setIsFocused(true);\n // Small delay to ensure the input is rendered before focusing\n setTimeout(() => inputRef.current?.focus(), 50);\n }\n };\n\n const handleBlur = () => {\n // Auto-collapse only if search is empty\n if (searchTerm.length === 0) {\n setIsFocused(false);\n }\n };\n\n const handleClear = () => {\n setSearchTerm(\"\");\n search(\"\");\n setIsFocused(false);\n };\n\n return (\n <div\n className={`relative flex h-6 items-center text-xs font-normal transition-all duration-300 ease-in-out ${\n isExpanded ? \"w-64\" : \"w-6\"\n }`}\n >\n <Search\n className={`absolute top-1 left-1 h-4 w-4 transition-colors ${\n isExpanded ? \"text-muted-foreground\" : \"text-muted-foreground hover:text-foreground cursor-pointer\"\n }`}\n onClick={handleSearchIconClick}\n />\n {isExpanded && (\n <Input\n ref={inputRef}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n handleClear();\n }\n }}\n onFocus={() => setIsFocused(true)}\n onBlur={handleBlur}\n placeholder={t(`generic.search.placeholder_global`)}\n type=\"text\"\n className=\"border-border/50 focus-visible:border-border h-10 w-full pr-8 pl-8 text-xs shadow-none focus-visible:ring-0\"\n onChange={(e) => setSearchTerm(e.target.value)}\n value={searchTerm}\n />\n )}\n {isExpanded && isSearching && (\n <RefreshCw className=\"text-muted-foreground absolute top-1 right-1 h-4 w-4 animate-spin\" />\n )}\n {isExpanded && !isSearching && searchTermRef.current && (\n <X\n className=\"text-muted-foreground hover:text-foreground absolute top-1 right-1 h-4 w-4 cursor-pointer\"\n onClick={handleClear}\n />\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport Image from \"next/image\";\nimport { Card } from \"../../../../shadcnui\";\nimport { AuthContextProvider, useAuthContext } from \"../../contexts\";\nimport { AuthComponent } from \"../../enums\";\n\ntype AuthContainerProps = {\n componentType: AuthComponent;\n params?: { code?: string };\n};\n\nexport function AuthContainer({ componentType, params }: AuthContainerProps) {\n return (\n <AuthContextProvider initialComponentType={componentType} initialParams={params}>\n <InnerAuthContainer />\n </AuthContextProvider>\n );\n}\n\nfunction InnerAuthContainer() {\n const { activeComponent } = useAuthContext();\n\n if (activeComponent === null)\n return (\n <div className=\"max-w-sm\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} className=\"animate-spin-slow\" priority />\n </div>\n );\n\n return <Card className=\"w-full max-w-md\">{activeComponent}</Card>;\n}\n","\"use client\";\n\nimport { createContext, ReactElement, useContext, useMemo, useState } from \"react\";\nimport {\n AcceptInvitation,\n ActivateAccount,\n ForgotPassword,\n LandingComponent,\n Login,\n ResetPassword,\n} from \"../components\";\nimport Register from \"../components/forms/Register\";\nimport { AuthComponent } from \"../enums\";\n\ninterface AuthContextType {\n activeComponent: ReactElement<any> | null;\n setComponentType: (componentType: AuthComponent) => void;\n setParams: (params?: { code?: string }) => void;\n params?: { code?: string };\n}\n\nconst AuthContext = createContext<AuthContextType | undefined>(undefined);\n\nexport const AuthContextProvider = ({\n children,\n initialComponentType,\n initialParams,\n}: {\n children: React.ReactNode;\n initialComponentType?: AuthComponent;\n initialParams?: { code?: string };\n}) => {\n const [componentType, setComponentType] = useState<AuthComponent | undefined>(initialComponentType);\n const [params, setParams] = useState<{ code?: string } | undefined>(initialParams);\n\n const activeComponent = useMemo(() => {\n if (componentType === undefined) return null;\n\n switch (componentType) {\n case AuthComponent.Login:\n return <Login />;\n case AuthComponent.Register:\n return <Register />;\n case AuthComponent.ForgotPassword:\n return <ForgotPassword />;\n case AuthComponent.ActivateAccount:\n return <ActivateAccount />;\n case AuthComponent.ResetPassword:\n return <ResetPassword />;\n case AuthComponent.AcceptInvitation:\n return <AcceptInvitation />;\n default:\n return <LandingComponent />;\n }\n }, [componentType]);\n\n return (\n <AuthContext.Provider\n value={{\n activeComponent,\n setComponentType,\n setParams,\n params,\n }}\n >\n {children}\n </AuthContext.Provider>\n );\n};\n\nexport const useAuthContext = (): AuthContextType => {\n const context = useContext(AuthContext);\n if (context === undefined) {\n throw new Error(\"useAuthContext must be used within a AuthComponentProvider\");\n }\n return context;\n};\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { v4 } from \"uuid\";\nimport { z } from \"zod\";\nimport { errorToast, FormInput, FormPassword } from \"../../../../components\";\nimport {\n Button,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n Form,\n Link,\n} from \"../../../../shadcnui\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport default function Register() {\n const t = useTranslations();\n const { setComponentType } = useAuthContext();\n\n const [showConfirmation, setShowConfirmation] = useState<boolean>(false);\n\n const formSchema = z.object({\n company: z.string().min(1, {\n message: t(`generic.errors.missing_company_name`),\n }),\n name: z.string().min(1, {\n message: t(\"generic.errors.missing_name\"),\n }),\n email: z.string().email({\n message: t(`generic.errors.invalid_email`),\n }),\n password: z\n .string()\n .min(8, t(`foundations.auth.errors.password_too_short`))\n .regex(/^(?=.*[0-9])(?=.*[^a-zA-Z0-9]).*$/, {\n message: t(`foundations.auth.errors.password_invalid_format`),\n }),\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n company: \"\",\n name: \"\",\n email: \"\",\n password: \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n try {\n const payload = {\n id: v4(),\n companyName: values.company,\n name: values.name,\n email: values.email,\n password: values.password,\n };\n\n await AuthService.register(payload);\n setShowConfirmation(true);\n } catch (e) {\n errorToast({ error: e });\n }\n };\n\n return (\n <>\n <CardHeader>\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(`foundations.auth.register`)}\n </CardTitle>\n <CardDescription className=\"text-sm\">\n {showConfirmation ? <> </> : <>{t(`foundations.auth.register_description`)}</>}\n </CardDescription>\n </CardHeader>\n {showConfirmation ? (\n <CardContent>\n <CardDescription className=\"text-center text-xl\">\n {t(\"foundations.auth.register_confirmation\")}\n </CardDescription>\n </CardContent>\n ) : (\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <CardContent>\n <FormInput\n isRequired\n form={form}\n id=\"company\"\n name={t(`foundations.company.fields.name.label`)}\n placeholder={t(`foundations.company.fields.name.placeholder`)}\n />\n <FormInput\n isRequired\n form={form}\n id=\"name\"\n name={t(`foundations.user.fields.name.label`)}\n placeholder={t(`foundations.user.fields.name.placeholder`)}\n />\n <FormInput\n isRequired\n form={form}\n id=\"email\"\n name={t(`generic.fields.email.label`)}\n placeholder={t(`generic.fields.email.placeholder`)}\n />\n <FormPassword\n isRequired\n form={form}\n id=\"password\"\n name={t(`foundations.user.fields.password.label`)}\n placeholder={t(`foundations.user.fields.password.placeholder`)}\n />\n <Button className=\"mt-4 w-full\" type={\"submit\"}>\n {t(`foundations.auth.buttons.register`)}\n </Button>\n </CardContent>\n <CardFooter className=\"flex w-full flex-row justify-between\">\n <Link\n href=\"#\"\n className=\"flex w-full justify-start\"\n onClick={() => setComponentType(AuthComponent.Login)}\n >\n {t(`foundations.auth.buttons.login`)}\n </Link>\n <Link\n href=\"#\"\n className=\"flex w-full justify-end\"\n onClick={() => setComponentType(AuthComponent.ForgotPassword)}\n >\n {t(`foundations.auth.buttons.forgot_password`)}\n </Link>\n </CardFooter>\n </form>\n </Form>\n )}\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { isDiscordConfigured, isInternalAuthConfigured } from \"../../../../discord\";\nimport { Button, CardDescription, CardFooter, CardHeader, CardTitle, Link } from \"../../../../shadcnui\";\nimport { getApiUrl } from \"../../../../client/config\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function LandingComponent() {\n const t = useTranslations();\n\n const { setComponentType } = useAuthContext();\n\n return (\n <>\n <CardHeader className=\"mb-4\" data-testid=\"page-pre-login-container\">\n <CardTitle className=\"text-primary flex flex-col items-center gap-y-8 pb-8 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(`generic.title`)}\n </CardTitle>\n <CardDescription className=\"flex w-full justify-center text-center text-sm\">\n {t(`generic.description`)}\n </CardDescription>\n </CardHeader>\n <CardFooter className=\"mt-4 flex w-full flex-col justify-between gap-y-4\">\n {isInternalAuthConfigured() && (\n <>\n <Link\n href=\"#\"\n className=\"flex w-full justify-start\"\n onClick={() => setComponentType(AuthComponent.Register)}\n >\n <Button className=\"w-full\" variant={`default`}>\n {t(`foundations.auth.buttons.register`)}\n </Button>\n </Link>\n <Link href=\"#\" className=\"flex w-full justify-end\" onClick={() => setComponentType(AuthComponent.Login)}>\n <Button className=\"w-full\" variant={`outline`} data-testid=\"page-login-button-initial-login\">\n {t(`foundations.auth.buttons.login`)}\n </Button>\n </Link>\n </>\n )}\n {isDiscordConfigured() && (\n <Link href={`${getApiUrl()}auth/discord`} className=\"flex w-full justify-end\">\n <Button className=\"w-full\" variant={`outline`} data-testid=\"page-login-button-initial-login\">\n Login with Discord\n </Button>\n </Link>\n )}\n </CardFooter>\n </>\n );\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\nimport { errorToast, FormPassword } from \"../../../../components\";\nimport { Button, CardContent, CardDescription, CardHeader, CardTitle, Form } from \"../../../../shadcnui\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function AcceptInvitation() {\n const { setComponentType, params, setParams } = useAuthContext();\n const [showConfirmation, setShowConfirmation] = useState<boolean>(false);\n const [error, setError] = useState<string | undefined>(undefined);\n const t = useTranslations();\n\n useEffect(() => {\n async function validateCode(code: string) {\n try {\n const payload: any = {\n code: code,\n };\n\n await AuthService.validateCode(payload);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n errorToast({ title: t(`generic.errors.error`), error: e });\n }\n }\n\n if (params && params.code) {\n validateCode(params.code);\n } else {\n setError(t(`foundations.auth.errors.invalid_invitation_code`));\n }\n }, []);\n\n const formSchema = z\n .object({\n password: z.string().min(1, {\n message: t(`foundations.user.fields.password.error`),\n }),\n passwordRetype: z.string().min(1, {\n message: t(\"foundations.auth.errors.password_retype_required\"),\n }),\n })\n .refine((data) => data.password === data.passwordRetype, {\n message: t(\"foundations.auth.fields.retype_password.error_not_match\"),\n path: [\"passwordRetype\"],\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n password: \"\",\n passwordRetype: \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n try {\n if (!params?.code) return;\n\n const payload = {\n code: params?.code,\n password: values.password,\n };\n\n await AuthService.acceptInvitation(payload);\n setShowConfirmation(true);\n\n toast.success(t(\"foundations.auth.account_activated\"), {\n description: t(\"foundations.auth.account_activated_description\"),\n });\n\n setTimeout(() => {\n setComponentType(AuthComponent.Login);\n setParams(undefined);\n }, 2000);\n } catch (e) {\n errorToast({ title: t(`generic.errors.error`), error });\n }\n };\n\n return (\n <>\n <CardHeader>\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(\"foundations.auth.accept_invitation\")}\n </CardTitle>\n <CardDescription className=\"text-center text-sm\">\n {error ? (\n <>{t(\"foundations.auth.errors.activating_account\")}</>\n ) : (\n <>{t(\"foundations.auth.select_password\")}</>\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {showConfirmation ? (\n <CardDescription className=\"text-center text-xl\">\n {t(\"foundations.auth.activation_description\")}\n </CardDescription>\n ) : error ? (\n <CardDescription className=\"text-center text-xl\">{error}</CardDescription>\n ) : (\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <FormPassword\n form={form}\n id=\"password\"\n name={t(`foundations.user.fields.password.label`)}\n placeholder={t(`foundations.user.fields.password.placeholder`)}\n />\n <FormPassword\n form={form}\n id=\"passwordRetype\"\n name={t(\"foundations.auth.fields.retype_password.label\")}\n placeholder={t(`foundations.auth.fields.retype_password.placeholder`)}\n />\n <Button className=\"mt-4 w-full\" type={\"submit\"}>\n {t(\"foundations.auth.accept_invitation\")}\n </Button>\n </form>\n </Form>\n )}\n </CardContent>\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { errorToast } from \"../../../../components\";\nimport { CardContent, CardDescription, CardHeader, CardTitle } from \"../../../../shadcnui\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function ActivateAccount() {\n const { setComponentType, params, setParams } = useAuthContext();\n const [showConfirmation, setShowConfirmation] = useState<boolean>(false);\n const [error, setError] = useState<string | undefined>(undefined);\n const t = useTranslations();\n\n useEffect(() => {\n async function ActivateAccount(code: string) {\n try {\n const payload = {\n activationCode: code,\n };\n\n await AuthService.activate(payload);\n setShowConfirmation(true);\n\n setParams(undefined);\n\n toast.success(t(\"foundations.auth.account_activated\"), {\n description: t(\"foundations.auth.account_activated_description\"),\n });\n\n setTimeout(() => {\n setComponentType(AuthComponent.Login);\n }, 2000);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n errorToast({ title: t(`generic.errors.error`), error: e });\n }\n }\n\n if (params && params.code) {\n ActivateAccount(params.code);\n } else {\n setError(t(`foundations.auth.errors.invalid_invitation_code`));\n }\n }, []);\n\n return (\n <>\n <CardHeader>\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(\"foundations.auth.accept_invitation\")}\n </CardTitle>\n <CardDescription className=\"text-center text-sm\">\n {error ? <>{t(\"foundations.auth.errors.activating_account\")}</> : <> </>}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <CardDescription className=\"text-center text-xl\">\n {showConfirmation ? (\n <>{t(\"foundations.auth.activation_description\")}</>\n ) : error ? (\n <>{error}</>\n ) : (\n <>{t(\"foundations.auth.activation_wait\")}</>\n )}\n </CardDescription>\n </CardContent>\n </>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { JsonApiHydratedDataInterface, Modules, rehydrate } from \"../../../../core\";\nimport { useI18nRouter } from \"../../../../i18n\";\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { AuthInterface } from \"../../data\";\nimport { AuthService } from \"../../data/auth.service\";\n\nexport function Cookies({ dehydratedAuth, page }: { dehydratedAuth: JsonApiHydratedDataInterface; page?: string }) {\n const { setUser } = useCurrentUserContext<UserInterface>();\n const router = useI18nRouter();\n const [hasSaved, setHasSaved] = useState(false);\n\n useEffect(() => {\n if (hasSaved) return;\n async function saveTokenOnServer() {\n await AuthService.saveToken({ dehydratedAuth });\n const auth: AuthInterface = rehydrate(Modules.Auth, dehydratedAuth) as AuthInterface;\n setUser(auth.user as UserInterface);\n setHasSaved(true);\n\n if (page) {\n if (page.startsWith(\"/\")) router.push(page ?? \"/\");\n window.location.href = page;\n }\n }\n saveTokenOnServer();\n }, [dehydratedAuth, setUser, hasSaved, router]);\n\n return null;\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { errorToast, FormInput } from \"../../../../components\";\nimport {\n Button,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n Form,\n Link,\n} from \"../../../../shadcnui\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function ForgotPassword() {\n const t = useTranslations();\n const { setComponentType } = useAuthContext();\n\n const [showConfirmation, setShowConfirmation] = useState<boolean>(false);\n\n const formSchema = z.object({\n email: z.string().email({\n message: t(`generic.errors.invalid_email`),\n }),\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n email: \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n try {\n const payload = {\n email: values.email,\n };\n\n await AuthService.initialiseForgotPassword(payload);\n setShowConfirmation(true);\n } catch (e) {\n errorToast({ error: e });\n }\n };\n\n return (\n <>\n <CardHeader data-testid=\"page-forgot-password-container\">\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(\"foundations.auth.forgot_password\")}\n </CardTitle>\n <CardDescription className=\"text-sm\">\n {showConfirmation ? <> </> : <>{t(`foundations.auth.add_email_to_reset`)}</>}\n </CardDescription>\n </CardHeader>\n {showConfirmation ? (\n <CardContent>\n <CardDescription className=\"text-center text-xl\">{t(`foundations.auth.reset_confirmation`)}</CardDescription>\n </CardContent>\n ) : (\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <CardContent>\n <FormInput\n form={form}\n id=\"email\"\n name={t(`generic.fields.email.label`)}\n placeholder={t(`generic.fields.email.placeholder`)}\n testId=\"form-forgot-password-input-email\"\n />\n <Button className=\"mt-4 w-full\" type={\"submit\"} data-testid=\"form-forgot-password-button-reset\">\n {t(`foundations.auth.buttons.reset_password`)}\n </Button>\n </CardContent>\n <CardFooter className=\"flex w-full flex-row justify-between\">\n {/* <Link\n href=\"#\"\n className=\"flex w-full justify-start\"\n onClick={() => setComponentType(AuthComponent.Register)}\n >\n {t(\"foundations.auth.buttons.register\")}\n </Link> */}\n <Link\n href=\"#\"\n className=\"flex w-full justify-end\"\n onClick={() => setComponentType(AuthComponent.Login)}\n data-testid=\"form-forgot-password-link-login\"\n >\n {t(`foundations.auth.buttons.login`)}\n </Link>\n </CardFooter>\n </form>\n </Form>\n )}\n </>\n );\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { errorToast, FormInput, FormPassword } from \"../../../../components\";\nimport { useI18nRouter, usePageUrlGenerator } from \"../../../../hooks\";\nimport {\n Button,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n Form,\n Link,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function Login() {\n const t = useTranslations();\n const { setUser } = useCurrentUserContext<UserInterface>();\n const { setComponentType } = useAuthContext();\n const generateUrl = usePageUrlGenerator();\n const router = useI18nRouter();\n\n const formSchema = z.object({\n email: z.string().email({\n message: t(`generic.errors.invalid_email`),\n }),\n password: z.string().min(3, { message: t(`foundations.auth.errors.password_too_short`) }),\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n email: \"\",\n password: \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n try {\n const user: UserInterface = (await AuthService.login({\n email: values.email,\n password: values.password,\n })) as UserInterface;\n\n setUser(user);\n router.replace(generateUrl({ page: `/` }));\n } catch (e) {\n errorToast({\n title: t(`generic.errors.error`),\n error: e,\n });\n }\n };\n\n return (\n <>\n <CardHeader data-testid=\"page-login-container\">\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(\"foundations.auth.login\")}\n </CardTitle>\n\n <CardDescription className=\"text-sm\">{t(`foundations.auth.login_description`)}</CardDescription>\n </CardHeader>\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <CardContent>\n <FormInput\n autoFocus\n form={form}\n id=\"email\"\n name={t(`generic.fields.email.label`)}\n placeholder={t(`generic.fields.email.placeholder`)}\n testId=\"form-login-input-email\"\n />\n <FormPassword\n form={form}\n id=\"password\"\n name={t(`foundations.user.fields.password.label`)}\n placeholder={t(`foundations.user.fields.password.placeholder`)}\n testId=\"form-login-input-password\"\n />\n <Button className=\"mt-4 w-full\" type={\"submit\"} data-testid=\"form-login-button-submit\">\n {t(`foundations.auth.login`)}\n </Button>\n </CardContent>\n <CardFooter className=\"flex w-full flex-row justify-between\">\n <Link\n href=\"#\"\n className=\"flex w-full justify-start\"\n onClick={() => setComponentType(AuthComponent.Register)}\n >\n {t(`foundations.auth.register`)}\n </Link>\n <Link\n href=\"#\"\n className=\"flex w-full justify-end\"\n onClick={() => setComponentType(AuthComponent.ForgotPassword)}\n data-testid=\"form-login-link-forgot-password\"\n >\n {t(`foundations.auth.forgot_password`)}\n </Link>\n </CardFooter>\n </form>\n </Form>\n </>\n );\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { AuthService } from \"../../data/auth.service\";\n\nexport function Logout() {\n const generateUrl = usePageUrlGenerator();\n\n useEffect(() => {\n const logOut = async () => {\n await AuthService.logout();\n window.location.href = generateUrl({ page: `/` });\n };\n logOut();\n }, []);\n\n return <></>;\n}\n","\"use client\";\n\nimport { deleteCookie, getCookie } from \"cookies-next\";\nimport { useEffect } from \"react\";\nimport { UserInterface } from \"../../../user\";\nimport { UserService } from \"../../../user/data/user.service\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { getTokenHandler } from \"../../config\";\n\nexport function RefreshUser() {\n const { setUser } = useCurrentUserContext<UserInterface>();\n\n const loadFullUser = async () => {\n const fullUser = await UserService.findFullUser();\n\n if (fullUser) {\n setUser(fullUser);\n const token = {\n userId: fullUser.id,\n companyId: fullUser.company?.id,\n licenseExpirationDate: fullUser.company?.licenseExpirationDate,\n roles: fullUser.roles.map((role) => role.id),\n features: fullUser.company?.features?.map((feature) => feature.id) ?? [],\n modules: fullUser.modules.map((module) => {\n return { id: module.id, permissions: module.permissions };\n }),\n };\n\n await getTokenHandler()?.updateToken(token);\n deleteCookie(\"reloadData\");\n }\n };\n\n useEffect(() => {\n const reloadData = getCookie(\"reloadData\");\n if (reloadData !== undefined) loadFullUser();\n }, []);\n\n return null;\n}\n","\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { useTranslations } from \"next-intl\";\nimport Image from \"next/image\";\nimport { useEffect, useState } from \"react\";\nimport { SubmitHandler, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\nimport { errorToast, FormPassword } from \"../../../../components\";\nimport { Button, CardContent, CardDescription, CardHeader, CardTitle, Form } from \"../../../../shadcnui\";\nimport { useAuthContext } from \"../../contexts\";\nimport { AuthService } from \"../../data/auth.service\";\nimport { AuthComponent } from \"../../enums\";\n\nexport function ResetPassword() {\n const { setComponentType, params, setParams } = useAuthContext();\n const [showConfirmation, setShowConfirmation] = useState<boolean>(false);\n const [error, setError] = useState<string | undefined>(undefined);\n const t = useTranslations();\n\n useEffect(() => {\n async function validateResetPasswordCode(code: string) {\n try {\n const payload: any = {\n code: code,\n };\n\n await AuthService.validateCode(payload);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n errorToast({ title: t(`generic.errors.error`), error: e });\n }\n }\n\n if (params && params.code) {\n validateResetPasswordCode(params.code);\n } else {\n setError(t(`foundations.auth.errors.invalid_password_reset_code`));\n }\n }, []);\n\n const formSchema = z\n .object({\n password: z.string().min(1, {\n message: t(`foundations.user.fields.password.error`),\n }),\n passwordRetype: z.string().min(1, {\n message: t(`foundations.auth.fields.retype_password.error`),\n }),\n })\n .refine((data) => data.password === data.passwordRetype, {\n message: t(`foundations.auth.fields.retype_password.error_not_match`),\n path: [\"passwordRetype\"],\n });\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n password: \"\",\n passwordRetype: \"\",\n },\n });\n\n const onSubmit: SubmitHandler<z.infer<typeof formSchema>> = async (values: z.infer<typeof formSchema>) => {\n try {\n if (!params?.code) return;\n\n const payload = {\n code: params?.code,\n password: values.password,\n };\n\n await AuthService.resetPassword(payload);\n setShowConfirmation(true);\n\n toast.success(t(`foundations.auth.reset_success`), {\n description: t(`foundations.auth.reset_success_description`),\n });\n\n setTimeout(() => {\n setComponentType(AuthComponent.Login);\n setParams(undefined);\n }, 2000);\n } catch (e) {\n errorToast({ title: t(`generic.errors.error`), error });\n }\n };\n\n return (\n <>\n <CardHeader>\n <CardTitle className=\"text-primary flex flex-col items-center pb-10 text-4xl\">\n <Image src=\"/logo.webp\" alt=\"Logo\" width={100} height={100} priority />\n {t(`foundations.auth.password_reset`)}\n </CardTitle>\n <CardDescription className=\"text-center text-sm\">\n {error ? (\n <>{t(`foundations.auth.errors.password_reset_error`)}</>\n ) : (\n <>{t(`foundations.auth.reset_password`)}</>\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {showConfirmation ? (\n <CardDescription className=\"text-center text-xl\">\n {t(`foundations.auth.reset_success_description`)}\n </CardDescription>\n ) : error ? (\n <CardDescription className=\"text-center text-xl\">{error}</CardDescription>\n ) : (\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)}>\n <FormPassword form={form} id=\"password\" name={\"Password\"} />\n <FormPassword form={form} id=\"passwordRetype\" name={\"Retype Password\"} />\n <Button className=\"mt-4 w-full\" type={\"submit\"}>\n {t(`foundations.auth.buttons.reset_password`)}\n </Button>\n </form>\n </Form>\n )}\n </CardContent>\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { Modules } from \"../../../../core\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport { HoverCard, HoverCardContent, HoverCardTrigger, Link } from \"../../../../shadcnui\";\nimport { getIconByModule } from \"../../../../utils\";\nimport { ContributorsList } from \"../../../user/components\";\nimport { ContentInterface } from \"../../data\";\n\ntype ContentsListProps = {\n contentList: ContentInterface[];\n};\n\nexport function ContentsList({ contentList }: ContentsListProps) {\n const t = useTranslations();\n\n return (\n <div className=\"flex min-h-0 w-full flex-col overflow-y-auto\">\n <h2 className=\"text-xl font-semibold\">{t(`foundations.content.news`)}</h2>\n <div className=\"flex flex-col\">\n {contentList.map((content) => (\n <ContentsListElement content={content} key={content.id} />\n ))}\n </div>\n </div>\n );\n}\n\ntype ContentsListElementProps = {\n content: ContentInterface;\n};\n\nfunction ContentsListElement({ content }: ContentsListElementProps) {\n const generateUrl = usePageUrlGenerator();\n\n const contentModule = content.contentType ? Modules.findByModelName(content.contentType) : undefined;\n const link = contentModule ? generateUrl({ page: contentModule, id: content.id }) : \"#\";\n\n return (\n <div className=\"hover:bg-muted flex w-full flex-col gap-y-2 border-b p-2 py-4\">\n <div className=\"flex w-full justify-between gap-x-2\">\n <HoverCard>\n <HoverCardTrigger asChild>\n <Link href={link} className=\"flex w-full items-center justify-start gap-2 font-semibold\">\n {contentModule && getIconByModule({ module: contentModule, className: \"h-4 w-4\" })}\n {content.name}\n </Link>\n </HoverCardTrigger>\n <HoverCardContent className=\"flex max-h-96 w-96 flex-col gap-y-4 overflow-y-auto\">\n <Link href={link} className=\"font-semibold\">\n {content.name}\n </Link>\n <div className=\"text-xs\">{content.abstract}</div>\n </HoverCardContent>\n </HoverCard>\n <ContributorsList content={content} />\n </div>\n {/* <div className=\"text-muted-foreground text-xs\">{content.tldr}</div>\n {content.topics.length > 0 && (\n <div className=\"flex w-full items-center justify-between\">\n <TopicBadgesList topics={content.topics} limit={1} />\n </div>\n )} */}\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { ContentFields, ContentInterface } from \"../../data\";\nimport { ContentService } from \"../../data/content.service\";\n\ntype ContentsListByIdProps = {\n contentIds: string[];\n};\n\nexport function ContentsListById({ contentIds }: ContentsListByIdProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<ContentInterface> = useDataListRetriever({\n module: Modules.Content,\n retriever: (params) => ContentService.findMany(params),\n retrieverParams: { contentIds: contentIds },\n });\n\n return (\n <ContentListTable\n data={data}\n fields={[ContentFields.name, ContentFields.authors, ContentFields.updatedAt]}\n tableGeneratorType={Modules.Content}\n title={t(`generic.relevant`)}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { ContentFields, ContentInterface } from \"../../data\";\nimport { ContentService } from \"../../data/content.service\";\n\ntype RelevantContentsListProps = {\n id: string;\n};\n\nexport function RelevantContentsList({ id }: RelevantContentsListProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<ContentInterface> = useDataListRetriever({\n module: Modules.Content,\n retriever: (params) => ContentService.findRelevant(params),\n retrieverParams: { id: id },\n });\n\n return (\n <ContentListTable\n data={data}\n fields={[ContentFields.name, ContentFields.authors, ContentFields.relevance, ContentFields.updatedAt]}\n tableGeneratorType={Modules.Content}\n title={t(`generic.relevant`)}\n />\n );\n}\n","\"use client\";\n\nimport React, { Component, ReactNode } from \"react\";\n\ninterface Props {\n children: ReactNode;\n fallback?: ReactNode;\n}\n\ninterface State {\n hasError: boolean;\n error?: Error;\n}\n\nexport class NotificationErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false };\n }\n\n static getDerivedStateFromError(error: Error): State {\n // Update state so the next render will show the fallback UI\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n console.error(\"🚨 [NotificationErrorBoundary] Caught error:\", error, errorInfo);\n }\n\n render() {\n if (this.state.hasError) {\n return (\n this.props.fallback || (\n <div className=\"flex items-center justify-center p-4 text-center\">\n <div className=\"text-muted-foreground text-sm\">\n <p>Something went wrong with notifications.</p>\n <button\n onClick={() => this.setState({ hasError: false })}\n className=\"text-primary mt-2 underline hover:no-underline\"\n >\n Try again\n </button>\n </div>\n </div>\n )\n );\n }\n\n return this.props.children;\n }\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { Tab, TabsContainer } from \"../../../../components\";\nimport { useNotificationContext } from \"../../contexts/NotificationContext\";\nimport { NotificationErrorBoundary } from \"../common\";\nimport { NotificationsList } from \"../lists/NotificationsList\";\n\nfunction NotificationsListContainerContent() {\n const t = useTranslations();\n const { notifications, isLoading, error } = useNotificationContext();\n\n if (error) {\n return (\n <div className=\"flex items-center justify-center p-8 text-center\">\n <div className=\"text-destructive text-sm\">\n <p>Error loading notifications: {error}</p>\n <p className=\"text-muted-foreground mt-2\">Please try refreshing the page.</p>\n </div>\n </div>\n );\n }\n\n const tabs: Tab[] = [\n {\n label: t(`foundations.notification.inbox`),\n content: <NotificationsList archived={false} />,\n },\n {\n label: t(`foundations.notification.archived`),\n content: <NotificationsList archived={true} />,\n },\n ];\n\n return <TabsContainer tabs={tabs} />;\n}\n\nexport function NotificationsListContainer() {\n return (\n <NotificationErrorBoundary>\n <NotificationsListContainerContent />\n </NotificationErrorBoundary>\n );\n}\n","\"use client\";\n\nimport { ArchiveIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever, usePageUrlGenerator } from \"../../../../hooks\";\nimport {\n Button,\n Card,\n CardContent,\n Link,\n Skeleton,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../../../shadcnui\";\nimport { UserAvatar } from \"../../../user/components\";\nimport { NotificationInterface } from \"../../data\";\nimport { NotificationService } from \"../../data/notification.service\";\nimport { generateNotificationData } from \"../notifications/Notification\";\n\ntype NotificationsListProps = {\n archived: boolean;\n};\n\nexport function NotificationsList({ archived }: NotificationsListProps) {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n\n const data: DataListRetriever<NotificationInterface> = useDataListRetriever({\n retriever: (params) => NotificationService.findMany(params),\n retrieverParams: { isArchived: archived },\n module: Modules.Notification,\n });\n\n const archiveNotification = async (notification: NotificationInterface) => {\n await NotificationService.archive({ id: notification.id });\n data.removeElement(notification);\n };\n\n const LoadingSkeleton = () => (\n <div className=\"space-y-4\">\n {Array.from({ length: 3 }).map((_, i) => (\n <Card key={i}>\n <CardContent className=\"p-2\">\n <div className=\"flex w-full flex-row items-center\">\n <Skeleton className=\"mr-4 h-8 w-8 rounded-full\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n <Skeleton className=\"h-8 w-20\" />\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n );\n\n return (\n <div className=\"space-y-4\">\n {data.isLoaded ? (\n (data.data as NotificationInterface[])?.map((notification: NotificationInterface) => {\n const notificationData = generateNotificationData({ notification: notification, generateUrl: generateUrl });\n\n return (\n <Card key={notification.id}>\n <CardContent className=\"p-0\">\n <div className={`flex w-full flex-row items-center p-2`}>\n {notificationData.actor ? (\n <div className=\"flex w-12 max-w-12 px-2\">\n <Link href={generateUrl({ page: Modules.User, id: notificationData.actor.id })}>\n <UserAvatar user={notificationData.actor} className=\"h-8 w-8\" />\n </Link>\n </div>\n ) : (\n <div className=\"flex w-14 max-w-14 px-2\"></div>\n )}\n <div className=\"flex w-full flex-col\">\n <p className=\"text-sm\">\n {t.rich(`foundations.notification.${notification.notificationType}.description` as any, {\n strong: (chunks: any) => <strong>{chunks}</strong>,\n actor: notificationData.actor?.name ?? \"\",\n title: notificationData.title,\n })}\n </p>\n <div className=\"text-muted-foreground mt-1 w-full text-xs\">\n {new Date(notification.createdAt).toLocaleString()}\n </div>\n </div>\n <div className=\"flex flex-row items-center\">\n {notificationData.url ? (\n <Link href={notificationData.url}>\n <Button variant={`outline`} size={`sm`} onClick={(e) => e.stopPropagation()}>\n {t(`foundations.notification.${notification.notificationType}.buttons.action` as any)}\n </Button>\n </Link>\n ) : (\n <></>\n )}\n {!archived && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant={`link`}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n archiveNotification(notification);\n }}\n className=\"text-muted-foreground hover:text-destructive ml-2\"\n >\n <ArchiveIcon className=\"h-4 w-4 cursor-pointer\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>{t(`foundations.notification.buttons.archive`)}</TooltipContent>\n </Tooltip>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n );\n })\n ) : (\n <LoadingSkeleton />\n )}\n </div>\n );\n}\n","import { BellIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { Fragment, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { useSocketContext } from \"../../../../contexts\";\nimport { usePageUrlGenerator } from \"../../../../hooks\";\nimport {\n Card,\n CardHeader,\n CardTitle,\n Popover,\n PopoverContent,\n PopoverTrigger,\n ScrollArea,\n Separator,\n SidebarMenuButton,\n} from \"../../../../shadcnui\";\nimport { useNotificationContext } from \"../../contexts/NotificationContext\";\nimport { NotificationInterface } from \"../../data\";\nimport { NotificationErrorBoundary } from \"../common\";\n\ninterface NotificationModalProps {\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n}\n\nfunction NotificationModalContent({ isOpen, setIsOpen }: NotificationModalProps) {\n const instanceId = useRef(Math.random().toString(36).substr(2, 9));\n const {\n notifications,\n addNotification,\n generateNotification,\n generateToastNotification,\n markNotificationsAsRead,\n isLoading,\n error,\n } = useNotificationContext();\n const { socketNotifications, removeSocketNotification, clearSocketNotifications } = useSocketContext();\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n const [newNotifications, setNewNotifications] = useState<boolean>(false);\n const preventAutoClose = useRef(false);\n\n const circuitBreakerRef = useRef({\n count: 0,\n resetTime: 0,\n isOpen: false,\n });\n\n const checkCircuitBreaker = useCallback(() => {\n const now = Date.now();\n const breaker = circuitBreakerRef.current;\n\n // Reset counter every 10 seconds\n if (now > breaker.resetTime) {\n breaker.count = 0;\n breaker.resetTime = now + 10000; // 10 seconds\n breaker.isOpen = false;\n }\n\n // Trip breaker if more than 20 notifications in 10 seconds\n breaker.count++;\n if (breaker.count > 20) {\n breaker.isOpen = true;\n return false;\n }\n\n return !breaker.isOpen;\n }, []);\n\n const { unreadCount, unreadIds } = useMemo(() => {\n const unreadNotifications = notifications.filter((notif) => !notif.isRead);\n return {\n unreadCount: unreadNotifications.length,\n unreadIds: unreadNotifications.map((notif) => notif.id),\n };\n }, [notifications]);\n\n useEffect(() => {\n setNewNotifications(unreadCount > 0);\n }, [unreadCount]);\n\n const processSocketNotificationsRef = useRef<NodeJS.Timeout | null>(null);\n\n const processSocketNotifications = useCallback(() => {\n if (socketNotifications.length === 0) {\n return;\n }\n\n if (!checkCircuitBreaker()) {\n clearSocketNotifications(); // Still clear to prevent memory leaks\n return;\n }\n\n const currentSocketNotifications = [...socketNotifications];\n clearSocketNotifications();\n\n // Process notifications in smaller batches to prevent UI freeze\n const batchSize = 3;\n const batches = [];\n for (let i = 0; i < currentSocketNotifications.length; i += batchSize) {\n batches.push(currentSocketNotifications.slice(i, i + batchSize));\n }\n\n batches.forEach((batch, batchIndex) => {\n setTimeout(() => {\n batch.forEach((notification) => {\n addNotification(notification);\n const toastNotification = generateToastNotification(notification, t, generateUrl);\n\n toast.message(toastNotification.title, {\n description: toastNotification.description,\n action: toastNotification.action,\n });\n });\n\n // Only set newNotifications on the last batch\n if (batchIndex === batches.length - 1) {\n setNewNotifications(true);\n }\n }, batchIndex * 100); // 100ms delay between batches\n });\n }, [\n socketNotifications,\n clearSocketNotifications,\n addNotification,\n generateToastNotification,\n t,\n generateUrl,\n checkCircuitBreaker,\n ]);\n\n // 🔗 SOCKET: Throttled processing with 300ms delay\n useEffect(() => {\n if (processSocketNotificationsRef.current) {\n clearTimeout(processSocketNotificationsRef.current);\n }\n\n processSocketNotificationsRef.current = setTimeout(() => {\n processSocketNotifications();\n }, 300); // 300ms throttle\n\n return () => {\n if (processSocketNotificationsRef.current) {\n clearTimeout(processSocketNotificationsRef.current);\n }\n };\n }, [processSocketNotifications]);\n\n const handleOpenChange = (newlyRequestedOpenState: boolean) => {\n if (!newlyRequestedOpenState && preventAutoClose.current) {\n return;\n }\n\n setIsOpen(newlyRequestedOpenState);\n\n if (newlyRequestedOpenState) {\n preventAutoClose.current = true;\n\n if (unreadIds.length > 0) {\n markNotificationsAsRead(unreadIds)\n .catch((error) => {\n console.error(\"❌ [NotificationModal] Failed to mark notifications as read:\", error);\n })\n .finally(() => {\n preventAutoClose.current = false;\n // Workaround: re-open if it was open before\n setIsOpen(true);\n });\n } else {\n preventAutoClose.current = false;\n }\n setNewNotifications(false);\n }\n };\n\n const unreadNotifications = newNotifications && unreadCount > 0;\n\n return (\n <Popover open={isOpen} onOpenChange={handleOpenChange} data-testid={`sidebar-notification button`}>\n <PopoverTrigger asChild>\n <SidebarMenuButton className=\"text-muted-foreground h-6\" disabled={isLoading}>\n <BellIcon\n className={`h-5 w-5 cursor-pointer ${unreadNotifications ? \"text-destructive\" : \"\"} ${isLoading ? \"animate-pulse\" : \"\"}`}\n />\n {t(`types.notifications`, { count: 2 })}\n </SidebarMenuButton>\n </PopoverTrigger>\n <PopoverContent className=\"relative left-10 w-80 border-0 p-0 shadow-none\">\n <Card>\n <CardHeader className=\"p-4\">\n <CardTitle>{t(`types.notifications`, { count: 2 })}</CardTitle>\n {isLoading && <div className=\"text-muted-foreground text-xs\">Loading...</div>}\n {error && <div className=\"text-destructive text-xs\">Error: {error}</div>}\n </CardHeader>\n <Separator />\n <ScrollArea className=\"h-96\">\n {notifications.length > 0 ? (\n notifications.map((notification: NotificationInterface) => (\n <Fragment key={notification.id}>{generateNotification(notification, () => setIsOpen(false))}</Fragment>\n ))\n ) : (\n <div className=\"p-4 text-center text-sm text-gray-500\">\n {t(`foundations.notification.empty`, { count: 2 })}\n </div>\n )}\n </ScrollArea>\n </Card>\n </PopoverContent>\n </Popover>\n );\n}\n\nexport function NotificationModal(props: NotificationModalProps) {\n return (\n <NotificationErrorBoundary>\n <NotificationModalContent {...props} />\n </NotificationErrorBoundary>\n );\n}\n","\"use client\";\n\nimport { ReactNode, type JSX } from \"react\";\nimport usePushNotifications from \"../../../../hooks/usePushNotifications\";\n\nexport function PushNotificationProvider({ children }: { children: ReactNode }): JSX.Element {\n usePushNotifications();\n return <>{children}</>;\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { AttributeElement } from \"../../../../components\";\nimport { Card, CardContent } from \"../../../../shadcnui\";\nimport { useRoleContext } from \"../../contexts\";\n\nexport function RoleDetails() {\n const { role } = useRoleContext();\n const t = useTranslations();\n\n if (!role) return null;\n\n return (\n <Card className=\"w-full\">\n <CardContent className=\"p-4\">\n <AttributeElement title={t(`foundations.role.fields.description.label`)} value={role.description} />\n </CardContent>\n </Card>\n );\n}\n","\"use client\";\n\nimport { RoleUsersList } from \"../../../user/components/lists/RoleUsersList\";\nimport { useRoleContext } from \"../../contexts\";\nimport { RoleDetails } from \"../details\";\n\nexport function RoleContainer() {\n const { role } = useRoleContext();\n\n if (!role) return null;\n\n return (\n <>\n <RoleDetails />\n <RoleUsersList role={role} />\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport {\n Checkbox,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\nimport { RoleInterface } from \"../../data\";\n\ntype FormRolesProps = {\n form: any;\n id: string;\n name: string;\n roles: RoleInterface[];\n};\n\nexport function FormRoles({ form, id, name, roles }: FormRolesProps) {\n const t = useTranslations();\n const { hasAccesToFeature } = useCurrentUserContext<UserInterface>();\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormField\n control={form.control}\n name={id}\n render={({ field }) => (\n <FormItem className={`${name ? \"mb-5\" : \"mb-1\"}`}>\n <FormControl>\n <div>\n <div className=\"text-sm font-semibold\">{name}</div>\n {roles\n .filter((role: RoleInterface) => role.isSelectable)\n .sort((a: RoleInterface, b: RoleInterface) => a.name.localeCompare(b.name))\n .map((role: RoleInterface) => {\n if (role.requiredFeature && !hasAccesToFeature(role.requiredFeature.id)) return null;\n\n return (\n <div key={role.id}>\n <Checkbox\n defaultChecked={(field.value as string[]).some((roleId: string) => roleId === role.id)}\n onCheckedChange={(checked) => {\n if (checked) {\n form.setValue(id, [...(field.value as string[]), role.id]);\n } else {\n form.setValue(\n id,\n (field.value as string[]).filter((roleId: string) => roleId !== role.id),\n );\n }\n }}\n />\n <Tooltip>\n <TooltipTrigger asChild>\n <FormLabel className=\"ml-3 font-normal\">\n {t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) })}\n </FormLabel>\n </TooltipTrigger>\n <TooltipContent>\n {t(`foundations.role.roles_descriptions`, { role: role.id.replaceAll(`-`, ``) })}\n </TooltipContent>\n </Tooltip>\n </div>\n );\n })}\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useState } from \"react\";\nimport { errorToast } from \"../../../../components\";\nimport { getRoleId } from \"../../../../roles\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { UserService } from \"../../../user/data/user.service\";\nimport { RoleInterface } from \"../../data\";\nimport { RoleService } from \"../../data/role.service\";\n\ntype RemoveUserFromRoleProps = {\n user: UserInterface;\n role: RoleInterface;\n refresh: () => Promise<void>;\n};\n\nexport function RemoveUserFromRole({ role, user, refresh }: RemoveUserFromRoleProps) {\n const [open, setOpen] = useState<boolean>(false);\n const [canRemove, setCanRemove] = useState<boolean>(false);\n const t = useTranslations();\n\n useEffect(() => {\n async function checkCompanyAdminDeletability(): Promise<void> {\n const roleUsers = await UserService.findAllUsersByRole({\n roleId: role.id,\n });\n\n if (roleUsers.length > 1) setCanRemove(true);\n }\n\n if (role.id !== getRoleId().CompanyAdministrator) {\n setCanRemove(true);\n return;\n }\n\n checkCompanyAdminDeletability();\n }, [role]);\n\n const remove = async () => {\n try {\n await RoleService.removeUserFromRole({\n roleId: role.id,\n userId: user.id,\n });\n\n setOpen(false);\n refresh();\n } catch (error) {\n errorToast({ title: t(`generic.errors.error`), error: error });\n }\n };\n\n const roleName = t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) });\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogTrigger\n onClick={(e) => {\n e.stopPropagation();\n e.preventDefault();\n setOpen(true);\n }}\n >\n <span className=\"hover:text-destructive cursor-pointer\">{t(`foundations.role.remove_user.title`)}</span>\n </DialogTrigger>\n <DialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>\n <DialogHeader>\n <DialogTitle>{t(`foundations.role.remove_user.title`)}</DialogTitle>\n <DialogDescription>\n {canRemove\n ? t(`foundations.role.remove_user.subtitle_allowed`)\n : t(`foundations.role.remove_user.subtitle_not_allowed`)}\n </DialogDescription>\n </DialogHeader>\n {canRemove ? (\n <>\n {t(`foundations.role.remove_user.description_allowed`, { role: roleName, user: user.name })}\n <div className=\"flex justify-end\">\n <Button className=\"mr-2\" variant={\"outline\"} type={`button`} onClick={() => setOpen(false)}>\n {t(`generic.buttons.cancel`)}\n </Button>\n <Button\n type=\"submit\"\n onClick={(e) => {\n e.preventDefault();\n remove();\n }}\n variant={\"destructive\"}\n >\n {t(`generic.buttons.confirm_delete`)}\n </Button>\n </div>\n </>\n ) : (\n <>{t(`foundations.role.remove_user.description_not_allowed`, { role: roleName, user: user.name })}</>\n )}\n </DialogContent>\n </Dialog>\n );\n}\n","\"use client\";\n\nimport { PlusCircle } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { useDebounce } from \"../../../../hooks\";\nimport {\n Button,\n Command,\n CommandDialog,\n CommandEmpty,\n CommandInput,\n CommandItem,\n CommandList,\n DialogDescription,\n DialogTitle,\n} from \"../../../../shadcnui\";\nimport { UserInterface } from \"../../../user\";\nimport { RoleInterface } from \"../../data\";\nimport { RoleService } from \"../../data/role.service\";\n\ntype UserRoleAddProps = {\n user: UserInterface;\n refresh: () => Promise<void>;\n};\n\nexport function UserRoleAdd({ user, refresh }: UserRoleAddProps) {\n const [open, setOpen] = useState<boolean>(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const [searchTerm, setSearchTerm] = useState<string>(\"\");\n const [roles, setRoles] = useState<RoleInterface[]>([]);\n const t = useTranslations();\n\n const addUserToRole = async (role: RoleInterface) => {\n await RoleService.addUserToRole({\n roleId: role.id,\n userId: user.id,\n });\n setRoles(roles.filter((u) => u.id !== role.id));\n\n toast.message(\n t(`generic.association.label`, {\n source: t(`types.roles`, { count: 1 }),\n destination: t(`types.users`, { count: 1 }),\n }),\n {\n description: t(`generic.association.success`, {\n source: t(`types.roles`, { count: 1 }),\n destination: t(`types.users`, { count: 1 }),\n source_name: role.name,\n destination_name: user.name,\n }),\n },\n );\n\n refresh();\n };\n\n const searchRoles = useCallback(\n async (term: string) => {\n setRoles(\n await RoleService.findAllRolesUserNotIn({\n search: term,\n userId: user.id,\n }),\n );\n },\n [searchTerm, user],\n );\n\n const updateSearchTerm = useDebounce(searchRoles, 500);\n\n useEffect(() => {\n if (open) updateSearchTerm(searchTerm);\n }, [open, searchTerm]);\n\n useEffect(() => {\n if (open) searchRoles(\"\");\n }, [open]);\n\n return (\n <>\n <Button size=\"sm\" onClick={() => setOpen(true)}>\n <PlusCircle className=\"mr-3 h-3.5 w-3.5\" />\n {t(`generic.association.label`, {\n source: t(`types.roles`, { count: 1 }),\n destination: t(`types.users`, { count: 1 }),\n })}\n </Button>\n <CommandDialog open={open} onOpenChange={setOpen}>\n <DialogTitle>\n {t(`generic.association.label`, {\n source: t(`types.roles`, { count: 1 }),\n destination: t(`types.users`, { count: 1 }),\n })}\n </DialogTitle>\n <DialogDescription>\n {t(`generic.association.description`, {\n source: t(`types.roles`, { count: 1 }),\n destination: t(`types.users`, { count: 1 }),\n destination_name: user.name,\n })}\n </DialogDescription>\n <Command shouldFilter={false}>\n <CommandInput\n placeholder={t(`generic.search.placeholder`, { type: t(`types.roles`, { count: 1 }) })}\n value={searchTerm}\n onValueChange={setSearchTerm}\n ref={inputRef}\n />\n <CommandList className=\"mt-3 h-auto max-h-96 min-h-96 max-w-full overflow-x-hidden overflow-y-auto\">\n <CommandEmpty>{t(`generic.search.no_results`, { type: t(`types.roles`, { count: 1 }) })}</CommandEmpty>\n {roles.map((role: RoleInterface) => (\n <CommandItem\n className=\"cursor-pointer\"\n key={role.id}\n onSelect={() => addUserToRole(role)}\n onClick={() => addUserToRole(role)}\n >\n {t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) })}\n </CommandItem>\n ))}\n </CommandList>\n </Command>\n </CommandDialog>\n </>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { RoleFields, RoleInterface } from \"../../data\";\nimport { RoleService } from \"../../data/role.service\";\nimport \"../../hooks/useRoleTableStructure\";\n\nexport function RolesList() {\n const t = useTranslations();\n\n const data: DataListRetriever<RoleInterface> = useDataListRetriever({\n retriever: (params) => RoleService.findAllRoles(params),\n retrieverParams: {},\n module: Modules.Role,\n });\n\n return (\n <ContentListTable\n data={data}\n fields={[RoleFields.name, RoleFields.description]}\n tableGeneratorType={Modules.Role}\n title={t(`types.roles`, { count: 2 })}\n />\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport { ContentListTable } from \"../../../../components\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever } from \"../../../../hooks\";\nimport { UserInterface } from \"../../../user\";\nimport { RoleFields, RoleInterface } from \"../../data\";\nimport { RoleService } from \"../../data/role.service\";\n\ntype UserRolesListProps = {\n user: UserInterface;\n};\n\nexport function UserRolesList({ user }: UserRolesListProps) {\n const t = useTranslations();\n\n const data: DataListRetriever<RoleInterface> = useDataListRetriever({\n retriever: (params) => RoleService.findAllRolesByUser(params),\n retrieverParams: { userId: user.id },\n module: Modules.Role,\n });\n\n return (\n <ContentListTable\n data={data}\n fields={[RoleFields.name, RoleFields.description]}\n tableGeneratorType={Modules.Role}\n title={t(`types.roles`, { count: 2 })}\n />\n );\n}\n"]}
|