@carlonicora/nextjs-jsonapi 1.29.0 → 1.29.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-YBVEOPV4.js → BlockNoteEditor-BEWKLGW3.js} +13 -13
- package/dist/{BlockNoteEditor-YBVEOPV4.js.map → BlockNoteEditor-BEWKLGW3.js.map} +1 -1
- package/dist/{BlockNoteEditor-ZM4YPXHO.mjs → BlockNoteEditor-GNFK7ZVR.mjs} +3 -3
- package/dist/billing/index.js +334 -333
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/index.mjs +8 -7
- package/dist/billing/index.mjs.map +1 -1
- package/dist/{chunk-UCD5CUE4.mjs → chunk-IJSB4FH6.mjs} +5 -5
- package/dist/{chunk-UCD5CUE4.mjs.map → chunk-IJSB4FH6.mjs.map} +1 -1
- package/dist/{chunk-DU64WMZD.mjs → chunk-NYNLJEPF.mjs} +4 -4
- package/dist/chunk-NYNLJEPF.mjs.map +1 -0
- package/dist/{chunk-J22NEVSK.js → chunk-UYBCHXXL.js} +4 -4
- package/dist/chunk-UYBCHXXL.js.map +1 -0
- package/dist/{chunk-3X7EEFMN.js → chunk-XU4MY6OG.js} +429 -429
- package/dist/{chunk-3X7EEFMN.js.map → chunk-XU4MY6OG.js.map} +1 -1
- 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 +3 -3
- package/dist/server/index.mjs +1 -1
- package/package.json +1 -1
- package/src/components/pages/PageContentContainer.tsx +2 -2
- package/src/core/abstracts/AbstractService.ts +2 -2
- package/src/features/billing/stripe-subscription/hooks/useSubscriptionWizard.ts +5 -4
- package/src/utils/blocknote-diff.util.ts +1 -1
- package/dist/chunk-DU64WMZD.mjs.map +0 -1
- package/dist/chunk-J22NEVSK.js.map +0 -1
- /package/dist/{BlockNoteEditor-ZM4YPXHO.mjs.map → BlockNoteEditor-GNFK7ZVR.mjs.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-3X7EEFMN.js","../src/contexts/HeaderChildrenContext.tsx","../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/contexts/SocketContext.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/input-group.tsx","../src/shadcnui/ui/input.tsx","../src/shadcnui/ui/textarea.tsx","../src/shadcnui/ui/context-menu.tsx","../src/shadcnui/ui/drawer.tsx","../src/shadcnui/ui/dropdown-menu.tsx","../src/shadcnui/ui/field.tsx","../src/shadcnui/ui/label.tsx","../src/shadcnui/ui/separator.tsx","../src/shadcnui/ui/form.tsx","../src/shadcnui/ui/hover-card.tsx","../src/shadcnui/ui/input-otp.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/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/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/components/forms/CommonAssociationForm.tsx","../src/components/forms/CommonDeleter.tsx","../src/components/errors/ErrorDetails.tsx","../src/components/errors/errorToast.ts","../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/FormFieldWrapper.tsx","../src/components/forms/FormCheckbox.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/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/details/TokenStatusIndicator.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/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/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/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/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/company/hooks/useSubscriptionStatus.ts","../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/features/oauth/hooks/useOAuthClients.ts","../src/features/oauth/atoms/oauth.atoms.ts","../src/features/oauth/hooks/useOAuthClient.ts","../src/features/oauth/hooks/useOAuthConsent.ts","../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","../src/features/oauth/components/OAuthRedirectUriInput.tsx","../src/features/oauth/components/OAuthScopeSelector.tsx","../src/features/oauth/components/OAuthClientSecretDisplay.tsx","../src/features/oauth/components/OAuthClientCard.tsx","../src/features/oauth/components/OAuthClientList.tsx","../src/features/oauth/components/OAuthClientForm.tsx","../src/features/oauth/components/OAuthClientDetail.tsx","../src/features/oauth/components/consent/OAuthConsentHeader.tsx","../src/features/oauth/components/consent/OAuthScopeList.tsx","../src/features/oauth/components/consent/OAuthConsentActions.tsx","../src/features/oauth/components/consent/OAuthConsentScreen.tsx"],"names":[],"mappings":"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AAAI,MAAA;AAAI,sBAAA;AAGT,MAAA;AAAI,IAAA;AAGR,EAAA;AAIR;AA/FgB;AtMozchB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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-3X7EEFMN.js","sourcesContent":[null,"\"use client\";\n\nimport { createContext, useContext, ReactNode } from \"react\";\n\ninterface HeaderChildrenContextType {\n headerChildren: ReactNode | null;\n}\n\nconst HeaderChildrenContext = createContext<HeaderChildrenContextType>({\n headerChildren: null,\n});\n\ninterface HeaderChildrenProviderProps {\n children: ReactNode;\n content: ReactNode;\n}\n\n/**\n * Provider to supply custom content to be rendered in the Header component.\n * Wrap your layout with this provider and pass the content you want in the header.\n */\nexport function HeaderChildrenProvider({ children, content }: HeaderChildrenProviderProps) {\n return <HeaderChildrenContext.Provider value={{ headerChildren: content }}>{children}</HeaderChildrenContext.Provider>;\n}\n\n/**\n * Hook to get the header children content from context.\n * Used internally by PageContainer to pass children to Header.\n */\nexport function useHeaderChildren(): ReactNode | null {\n const context = useContext(HeaderChildrenContext);\n return context.headerChildren;\n}\n","\"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: {\n page: ModuleWithPermissions | string;\n id?: string;\n childPage?: ModuleWithPermissions | string;\n childId?: string;\n }): void => {\n window.history.replaceState(\n null,\n \"\",\n generateUrl({\n page: params.page,\n id: params.id,\n childPage: params.childPage,\n childId: params.childId,\n language: locale,\n }),\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) return;\n\n // Prevent concurrent fetches (unless it's a pagination call)\n if (isFetchingRef.current && !fetchParams?.callNext && !fetchParams?.callPrevious) return;\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\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\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 if (thisRequestId === requestIdRef.current) {\n setIsLoaded(true);\n console.error(\"Error fetching data:\", error);\n }\n } finally {\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) {\n fetchData({ isRefresh: onlyNewRecords, callNext: true });\n }\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 setData(undefined); // Clear stale data immediately before fetching new data\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 { 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, useCallback, useContext, useEffect, useRef, useState } from \"react\";\nimport { Modules, rehydrate } from \"../../../core\";\nimport { Action, checkPermissions, ModuleWithPermissions } from \"../../../permissions\";\nimport { getRoleId } from \"../../../roles\";\nimport { CompanyInterface } from \"../../company/data/company.interface\";\nimport { FeatureInterface } from \"../../feature\";\nimport { RoleInterface } from \"../../role\";\nimport { UserInterface, UserService } from \"../data\";\nimport { useSocketContext } from \"../../../contexts/SocketContext\";\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 refreshUser: () => Promise<void>;\n isRefreshing: 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 // State for tracking refresh status\n const [isRefreshing, setIsRefreshing] = useState(false);\n\n // Function to refresh user data from the API\n const refreshUser = useCallback(async (): Promise<void> => {\n if (isRefreshing) return;\n\n setIsRefreshing(true);\n try {\n const fullUser = await UserService.findFullUser();\n if (fullUser) {\n setDehydratedUser(fullUser.dehydrate() as any);\n }\n } catch (error) {\n console.error(\"Failed to refresh user data:\", error);\n } finally {\n setIsRefreshing(false);\n }\n }, [isRefreshing, setDehydratedUser]);\n\n // WebSocket integration for real-time token updates\n const { socket, isConnected } = useSocketContext();\n\n // Use ref for stable refreshUser reference to avoid effect re-runs\n const refreshUserRef = useRef(refreshUser);\n refreshUserRef.current = refreshUser;\n\n // Track refresh in progress to prevent duplicate API calls\n const isRefreshingRef = useRef(false);\n\n // Listen for company:tokens_updated WebSocket events\n useEffect(() => {\n if (!socket || !isConnected || !currentUser?.company?.id) return;\n\n const handleTokensUpdated = (data: { companyId: string; type: string }) => {\n if (data.companyId === currentUser.company?.id && !isRefreshingRef.current) {\n isRefreshingRef.current = true;\n refreshUserRef.current().finally(() => {\n isRefreshingRef.current = false;\n });\n }\n };\n\n socket.on(\"company:tokens_updated\", handleTokensUpdated);\n\n return () => {\n socket.off(\"company:tokens_updated\", handleTokensUpdated);\n };\n }, [socket, isConnected, currentUser?.company?.id]);\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 refreshUser: refreshUser,\n isRefreshing: isRefreshing,\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 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","\"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 { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\"\n\nfunction Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n className={cn(\"overflow-hidden rounded-md border flex w-full flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\"data-open:bg-muted/50 not-last:border-b\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionPrimitive.Trigger.Props) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n \"**:data-[slot=accordion-trigger-icon]:text-muted-foreground gap-6 p-2 text-left text-xs/relaxed font-medium hover:underline **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 group/accordion-trigger relative flex flex-1 items-start justify-between border border-transparent transition-all outline-none disabled:pointer-events-none disabled:opacity-50\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronDownIcon data-slot=\"accordion-trigger-icon\" className=\"pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden\" />\n <ChevronUpIcon data-slot=\"accordion-trigger-icon\" className=\"pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: AccordionPrimitive.Panel.Props) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-content\"\n className=\"data-open:animate-accordion-down data-closed:animate-accordion-up px-2 text-xs/relaxed overflow-hidden\"\n {...props}\n >\n <div\n className={cn(\n \"pt-0 pb-4 [&_a]:hover:text-foreground h-(--accordion-panel-height) data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4\",\n className\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n )\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst alertVariants = cva(\"grid gap-0.5 rounded-lg border px-2 py-1.5 text-left text-xs/relaxed has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-1.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-3.5 w-full relative group/alert\", {\n variants: {\n variant: {\n default: \"bg-card text-card-foreground\",\n destructive: \"text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n})\n\nfunction Alert({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof alertVariants>) {\n return (\n <div\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-title\"\n className={cn(\n \"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDescription({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(\n \"text-muted-foreground text-xs/relaxed text-balance md:text-pretty [&_p:not(:last-child)]:mb-4 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-action\"\n className={cn(\"absolute top-1.5 right-2\", className)}\n {...props}\n />\n )\n}\n\nexport { Alert, AlertTitle, AlertDescription, AlertAction }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { AlertDialog as AlertDialogPrimitive } from \"@base-ui/react/alert-dialog\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\n\nfunction AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {\n return <AlertDialogPrimitive.Root data-slot=\"alert-dialog\" {...props} />\n}\n\nfunction AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {\n return (\n <AlertDialogPrimitive.Trigger data-slot=\"alert-dialog-trigger\" {...props} />\n )\n}\n\nfunction AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {\n return (\n <AlertDialogPrimitive.Portal data-slot=\"alert-dialog-portal\" {...props} />\n )\n}\n\nfunction AlertDialogOverlay({\n className,\n ...props\n}: AlertDialogPrimitive.Backdrop.Props) {\n return (\n <AlertDialogPrimitive.Backdrop\n data-slot=\"alert-dialog-overlay\"\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogContent({\n className,\n size = \"default\",\n ...props\n}: AlertDialogPrimitive.Popup.Props & {\n size?: \"default\" | \"sm\"\n}) {\n return (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Popup\n data-slot=\"alert-dialog-content\"\n data-size={size}\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-3 rounded-xl p-4 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-64 data-[size=default]:sm:max-w-sm group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 outline-none\",\n className\n )}\n {...props}\n />\n </AlertDialogPortal>\n )\n}\n\nfunction AlertDialogHeader({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-header\"\n className={cn(\"grid grid-rows-[auto_1fr] place-items-center gap-1 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogFooter({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogMedia({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-media\"\n className={cn(\"bg-muted mb-2 inline-flex size-8 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-4\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {\n return (\n <AlertDialogPrimitive.Title\n data-slot=\"alert-dialog-title\"\n className={cn(\"text-sm font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {\n return (\n <AlertDialogPrimitive.Description\n data-slot=\"alert-dialog-description\"\n className={cn(\"text-muted-foreground *:[a]:hover:text-foreground text-xs/relaxed text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: React.ComponentProps<typeof Button>) {\n return (\n <Button\n data-slot=\"alert-dialog-action\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogCancel({\n className,\n variant = \"outline\",\n size = \"default\",\n ...props\n}: AlertDialogPrimitive.Close.Props &\n Pick<React.ComponentProps<typeof Button>, \"variant\" | \"size\">) {\n return (\n <AlertDialogPrimitive.Close\n data-slot=\"alert-dialog-cancel\"\n className={cn(className)}\n render={<Button variant={variant} size={size} />}\n {...props}\n />\n )\n}\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogMedia,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n}\n","import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent bg-clip-padding text-xs/relaxed font-medium focus-visible:ring-[2px] aria-invalid:ring-[2px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline: \"border-border dark:bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground\",\n secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost: \"hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground\",\n destructive: \"bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-7 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n xs: \"h-5 gap-1 rounded-sm px-2 text-[0.625rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-2.5\",\n sm: \"h-6 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n lg: \"h-8 gap-1 px-2.5 text-xs/relaxed has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-4\",\n icon: \"size-7 [&_svg:not([class*='size-'])]:size-3.5\",\n \"icon-xs\": \"size-5 rounded-sm [&_svg:not([class*='size-'])]:size-2.5\",\n \"icon-sm\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-lg\": \"size-8 [&_svg:not([class*='size-'])]:size-4\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Avatar as AvatarPrimitive } from \"@base-ui/react/avatar\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Avatar({\n className,\n size = \"default\",\n ...props\n}: AvatarPrimitive.Root.Props & {\n size?: \"default\" | \"sm\" | \"lg\"\n}) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n data-size={size}\n className={cn(\n \"size-8 rounded-full after:rounded-full data-[size=lg]:size-10 data-[size=sm]:size-6 after:border-border group/avatar relative flex shrink-0 select-none after:absolute after:inset-0 after:border after:mix-blend-darken dark:after:mix-blend-lighten\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\n \"rounded-full aspect-square size-full object-cover\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: AvatarPrimitive.Fallback.Props) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"bg-muted text-muted-foreground rounded-full flex size-full items-center justify-center text-sm group-data-[size=sm]/avatar:text-xs\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarBadge({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"avatar-badge\"\n className={cn(\n \"bg-primary text-primary-foreground ring-background absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-blend-color ring-2 select-none\",\n \"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden\",\n \"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2\",\n \"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"avatar-group\"\n className={cn(\n \"*:data-[slot=avatar]:ring-background group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarGroupCount({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"avatar-group-count\"\n className={cn(\"bg-muted text-muted-foreground size-8 rounded-full text-xs/relaxed group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3 ring-background relative flex shrink-0 items-center justify-center ring-2\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Avatar,\n AvatarImage,\n AvatarFallback,\n AvatarGroup,\n AvatarGroupCount,\n AvatarBadge,\n}\n","import { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"h-5 gap-1 rounded-full border border-transparent px-2 py-0.5 text-[0.625rem] font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-2.5! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-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 transition-colors overflow-hidden group/badge\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n secondary: \"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80\",\n destructive: \"bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20\",\n outline: \"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground bg-input/20 dark:bg-input/30\",\n ghost: \"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant = \"default\",\n render,\n ...props\n}: useRender.ComponentProps<\"span\"> & VariantProps<typeof badgeVariants>) {\n return useRender({\n defaultTagName: \"span\",\n props: mergeProps<\"span\">(\n {\n className: cn(badgeVariants({ className, variant })),\n },\n props\n ),\n render,\n state: {\n slot: \"badge\",\n variant,\n },\n })\n}\n\nexport { Badge, badgeVariants }\n","import * as React from \"react\"\nimport { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronRightIcon, MoreHorizontalIcon } from \"lucide-react\"\n\nfunction Breadcrumb({ className, ...props }: React.ComponentProps<\"nav\">) {\n return (\n <nav\n aria-label=\"breadcrumb\"\n data-slot=\"breadcrumb\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbList({ className, ...props }: React.ComponentProps<\"ol\">) {\n return (\n <ol\n data-slot=\"breadcrumb-list\"\n className={cn(\n \"text-muted-foreground gap-1.5 text-xs/relaxed flex flex-wrap items-center break-words\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"breadcrumb-item\"\n className={cn(\"gap-1 inline-flex items-center\", className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbLink({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"a\">) {\n return useRender({\n defaultTagName: \"a\",\n props: mergeProps<\"a\">(\n {\n className: cn(\"hover:text-foreground transition-colors\", className),\n },\n props\n ),\n render,\n state: {\n slot: \"breadcrumb-link\",\n },\n })\n}\n\nfunction BreadcrumbPage({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"breadcrumb-page\"\n role=\"link\"\n aria-disabled=\"true\"\n aria-current=\"page\"\n className={cn(\"text-foreground font-normal\", className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"breadcrumb-separator\"\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"[&>svg]:size-3.5\", className)}\n {...props}\n >\n {children ?? (\n <ChevronRightIcon\n />\n )}\n </li>\n )\n}\n\nfunction BreadcrumbEllipsis({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"breadcrumb-ellipsis\"\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\n \"size-4 [&>svg]:size-3.5 flex items-center justify-center\",\n className\n )}\n {...props}\n >\n <MoreHorizontalIcon\n />\n <span className=\"sr-only\">More</span>\n </span>\n )\n}\n\nexport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport {\n DayPicker,\n getDefaultClassNames,\n type DayButton,\n} from \"react-day-picker\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button, buttonVariants } from \"@/components/ui/button\"\nimport { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from \"lucide-react\"\n\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n captionLayout = \"label\",\n buttonVariant = \"ghost\",\n formatters,\n components,\n ...props\n}: React.ComponentProps<typeof DayPicker> & {\n buttonVariant?: React.ComponentProps<typeof Button>[\"variant\"]\n}) {\n const defaultClassNames = getDefaultClassNames()\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\n \"p-3 [--cell-radius:var(--radius-md)] [--cell-size:--spacing(6)] bg-background group/calendar [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent\",\n String.raw`rtl:**:[.rdp-button\\_next>svg]:rotate-180`,\n String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\n className\n )}\n captionLayout={captionLayout}\n formatters={{\n formatMonthDropdown: (date) =>\n date.toLocaleString(\"default\", { month: \"short\" }),\n ...formatters,\n }}\n classNames={{\n root: cn(\"w-fit\", defaultClassNames.root),\n months: cn(\n \"flex gap-4 flex-col md:flex-row relative\",\n defaultClassNames.months\n ),\n month: cn(\"flex flex-col w-full gap-4\", defaultClassNames.month),\n nav: cn(\n \"flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between\",\n defaultClassNames.nav\n ),\n button_previous: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none\",\n defaultClassNames.button_previous\n ),\n button_next: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none\",\n defaultClassNames.button_next\n ),\n month_caption: cn(\n \"flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)\",\n defaultClassNames.month_caption\n ),\n dropdowns: cn(\n \"w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5\",\n defaultClassNames.dropdowns\n ),\n dropdown_root: cn(\n \"relative cn-calendar-dropdown-root rounded-(--cell-radius)\",\n defaultClassNames.dropdown_root\n ),\n dropdown: cn(\n \"absolute bg-popover inset-0 opacity-0\",\n defaultClassNames.dropdown\n ),\n caption_label: cn(\n \"select-none font-medium\",\n captionLayout === \"label\"\n ? \"text-sm\"\n : \"cn-calendar-caption-label rounded-(--cell-radius) flex items-center gap-1 text-sm [&>svg]:text-muted-foreground [&>svg]:size-3.5\",\n defaultClassNames.caption_label\n ),\n table: \"w-full border-collapse\",\n weekdays: cn(\"flex\", defaultClassNames.weekdays),\n weekday: cn(\n \"text-muted-foreground rounded-(--cell-radius) flex-1 font-normal text-[0.8rem] select-none\",\n defaultClassNames.weekday\n ),\n week: cn(\"flex w-full mt-2\", defaultClassNames.week),\n week_number_header: cn(\n \"select-none w-(--cell-size)\",\n defaultClassNames.week_number_header\n ),\n week_number: cn(\n \"text-[0.8rem] select-none text-muted-foreground\",\n defaultClassNames.week_number\n ),\n day: cn(\n \"relative w-full rounded-(--cell-radius) h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius) group/day aspect-square select-none\",\n props.showWeekNumber\n ? \"[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)\"\n : \"[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)\",\n defaultClassNames.day\n ),\n range_start: cn(\n \"rounded-l-(--cell-radius) bg-muted elative after:bg-muted after:absolute after:inset-y-0 after:w-4 after:right-0 -z-0 isolate\",\n defaultClassNames.range_start\n ),\n range_middle: cn(\"rounded-none\", defaultClassNames.range_middle),\n range_end: cn(\n \"rounded-r-(--cell-radius) bg-muted relative after:bg-muted after:absolute after:inset-y-0 after:w-4 after:left-0 -z-0 isolate\",\n defaultClassNames.range_end\n ),\n today: cn(\n \"bg-muted text-foreground rounded-(--cell-radius) data-[selected=true]:rounded-none\",\n defaultClassNames.today\n ),\n outside: cn(\n \"text-muted-foreground aria-selected:text-muted-foreground\",\n defaultClassNames.outside\n ),\n disabled: cn(\n \"text-muted-foreground opacity-50\",\n defaultClassNames.disabled\n ),\n hidden: cn(\"invisible\", defaultClassNames.hidden),\n ...classNames,\n }}\n components={{\n Root: ({ className, rootRef, ...props }) => {\n return (\n <div\n data-slot=\"calendar\"\n ref={rootRef}\n className={cn(className)}\n {...props}\n />\n )\n },\n Chevron: ({ className, orientation, ...props }) => {\n if (orientation === \"left\") {\n return (\n <ChevronLeftIcon className={cn(\"size-4\", className)} {...props} />\n )\n }\n\n if (orientation === \"right\") {\n return (\n <ChevronRightIcon className={cn(\"size-4\", className)} {...props} />\n )\n }\n\n return (\n <ChevronDownIcon className={cn(\"size-4\", className)} {...props} />\n )\n },\n DayButton: CalendarDayButton,\n WeekNumber: ({ children, ...props }) => {\n return (\n <td {...props}>\n <div className=\"flex size-(--cell-size) items-center justify-center text-center\">\n {children}\n </div>\n </td>\n )\n },\n ...components,\n }}\n {...props}\n />\n )\n}\n\nfunction CalendarDayButton({\n className,\n day,\n modifiers,\n ...props\n}: React.ComponentProps<typeof DayButton>) {\n const defaultClassNames = getDefaultClassNames()\n\n const ref = React.useRef<HTMLButtonElement>(null)\n React.useEffect(() => {\n if (modifiers.focused) ref.current?.focus()\n }, [modifiers.focused])\n\n return (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n data-day={day.date.toLocaleDateString()}\n data-selected-single={\n modifiers.selected &&\n !modifiers.range_start &&\n !modifiers.range_end &&\n !modifiers.range_middle\n }\n data-range-start={modifiers.range_start}\n data-range-end={modifiers.range_end}\n data-range-middle={modifiers.range_middle}\n className={cn(\n \"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-muted data-[range-middle=true]:text-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-foreground relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 border-0 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius) data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius) [&>span]:text-xs [&>span]:opacity-70\",\n defaultClassNames.day,\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Calendar, CalendarDayButton }\n","import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\"ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-lg py-4 text-xs/relaxed ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg group/card flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"gap-1 rounded-t-lg px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-muted-foreground text-xs/relaxed\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-4 group-data-[size=sm]/card:px-3\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"rounded-b-lg px-4 group-data-[size=sm]/card:px-3 [.border-t]:pt-4 group-data-[size=sm]/card:[.border-t]:pt-3 flex items-center\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-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\nfunction Carousel({\n orientation = \"horizontal\",\n opts,\n setApi,\n plugins,\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & CarouselProps) {\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) return\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) return\n setApi(api)\n }, [api, setApi])\n\n React.useEffect(() => {\n if (!api) return\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:\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n )\n}\n\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\n const { carouselRef, orientation } = useCarousel()\n\n return (\n <div\n ref={carouselRef}\n className=\"overflow-hidden\"\n data-slot=\"carousel-content\"\n >\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const { orientation } = useCarousel()\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n data-slot=\"carousel-item\"\n className={cn(\n \"min-w-0 shrink-0 grow-0 basis-full\",\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-previous\"\n variant={variant}\n size={size}\n className={cn(\n \"rounded-full absolute touch-manipulation\",\n orientation === \"horizontal\"\n ? \"top-1/2 -left-12 -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 <ChevronLeftIcon\n />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n )\n}\n\nfunction CarouselNext({\n className,\n variant = \"outline\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollNext, canScrollNext } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-next\"\n variant={variant}\n size={size}\n className={cn(\n \"rounded-full absolute touch-manipulation\",\n orientation === \"horizontal\"\n ? \"top-1/2 -right-12 -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 <ChevronRightIcon\n />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n )\n}\n\nexport {\n type CarouselApi,\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselPrevious,\n CarouselNext,\n useCarousel,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\n// Custom type for tooltip/legend payload items\ntype PayloadItem = {\n dataKey?: string | number\n name?: string\n value?: string | number\n type?: string\n color?: string\n payload?: Record<string, unknown> & { fill?: string }\n fill?: string\n}\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record<keyof typeof THEMES, string> }\n )\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<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"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>\n {children}\n </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(\n ([, config]) => config.theme || config.color\n )\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 =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n 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\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps<\"div\"> & {\n active?: boolean\n payload?: PayloadItem[]\n label?: string | number\n labelFormatter?: (label: unknown, payload: PayloadItem[]) => React.ReactNode\n formatter?: (value: unknown, name: string, item: PayloadItem, index: number, payload: unknown) => React.ReactNode\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n labelClassName?: string\n color?: string\n }) {\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 !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n <div className={cn(\"font-medium\", labelClassName)}>\n {labelFormatter(value, payload)}\n </div>\n )\n }\n\n if (!value) {\n return null\n }\n\n return <div className={cn(\"font-medium\", labelClassName)}>{value}</div>\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\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 gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs/relaxed shadow-xl grid min-w-[8rem] items-start\",\n className\n )}\n >\n {!nestLabel ? tooltipLabel : null}\n <div className=\"grid gap-1.5\">\n {payload\n .filter((item) => item.type !== \"none\")\n .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(\n \"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)\",\n {\n \"h-2.5 w-2.5\": indicator === \"dot\",\n \"w-1\": indicator === \"line\",\n \"w-0 border-[1.5px] border-dashed bg-transparent\":\n indicator === \"dashed\",\n \"my-0.5\": nestLabel && indicator === \"dashed\",\n }\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(\n \"flex flex-1 justify-between leading-none\",\n nestLabel ? \"items-end\" : \"items-center\"\n )}\n >\n <div className=\"grid gap-1.5\">\n {nestLabel ? tooltipLabel : null}\n <span className=\"text-muted-foreground\">\n {itemConfig?.label || item.name}\n </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\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n payload?: PayloadItem[]\n verticalAlign?: \"top\" | \"bottom\" | \"middle\"\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n <div\n className={cn(\n \"flex items-center justify-center gap-4\",\n verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\n className\n )}\n >\n {payload\n .filter((item) => item.type !== \"none\")\n .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(\n \"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3\"\n )}\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\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\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[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n","\"use client\"\n\nimport { Checkbox as CheckboxPrimitive } from \"@base-ui/react/checkbox\"\n\nimport { cn } from \"@/lib/utils\"\nimport { CheckIcon } from \"lucide-react\"\n\nfunction Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n \"border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-[4px] border transition-shadow group-has-disabled/field:opacity-50 focus-visible:ring-[2px] aria-invalid:ring-[2px] peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"[&>svg]:size-3.5 grid place-content-center text-current transition-none\"\n >\n <CheckIcon\n />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport { Checkbox }\n","\"use client\";\n\nimport { Collapsible as CollapsiblePrimitive } from \"@base-ui/react/collapsible\";\n\nfunction Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />;\n}\n\nfunction CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {\n return <CollapsiblePrimitive.Trigger data-slot=\"collapsible-trigger\" {...props} />;\n}\n\nfunction CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {\n return <CollapsiblePrimitive.Panel data-slot=\"collapsible-content\" {...props} />;\n}\n\nexport { Collapsible, CollapsibleContent, CollapsibleTrigger };\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Command as CommandPrimitive } from \"cmdk\"\n\nimport { cn } from \"@/lib/utils\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from \"@/components/ui/dialog\"\nimport {\n InputGroup,\n InputGroupAddon,\n} from \"@/components/ui/input-group\"\nimport { SearchIcon, CheckIcon } from \"lucide-react\"\n\nfunction Command({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive>) {\n return (\n <CommandPrimitive\n data-slot=\"command\"\n className={cn(\n \"bg-popover text-popover-foreground rounded-xl p-1 flex size-full flex-col overflow-hidden\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandDialog({\n title = \"Command Palette\",\n description = \"Search for a command to run...\",\n children,\n className,\n showCloseButton = false,\n ...props\n}: Omit<React.ComponentProps<typeof Dialog>, \"children\"> & {\n title?: string\n description?: string\n className?: string\n showCloseButton?: boolean\n children: React.ReactNode\n}) {\n return (\n <Dialog {...props}>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n <DialogContent\n className={cn(\"rounded-xl! p-0 overflow-hidden p-0\", className)}\n showCloseButton={showCloseButton}\n >\n {children}\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction CommandInput({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Input>) {\n return (\n <div data-slot=\"command-input-wrapper\" className=\"p-1 pb-0\">\n <InputGroup className=\"bg-input/20 dark:bg-input/30 h-8!\">\n <CommandPrimitive.Input\n data-slot=\"command-input\"\n className={cn(\n \"w-full text-xs/relaxed outline-hidden disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n <InputGroupAddon>\n <SearchIcon className=\"size-3.5 shrink-0 opacity-50\" />\n </InputGroupAddon>\n </InputGroup>\n </div>\n )\n}\n\nfunction CommandList({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.List>) {\n return (\n <CommandPrimitive.List\n data-slot=\"command-list\"\n className={cn(\n \"no-scrollbar max-h-72 scroll-py-1 outline-none overflow-x-hidden overflow-y-auto\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandEmpty({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n data-slot=\"command-empty\"\n className={cn(\"py-6 text-center text-xs/relaxed\", className)}\n {...props}\n />\n )\n}\n\nfunction CommandGroup({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n data-slot=\"command-group\"\n className={cn(\"text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CommandSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n data-slot=\"command-separator\"\n className={cn(\"bg-border/50 -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction CommandItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return (\n <CommandPrimitive.Item\n data-slot=\"command-item\"\n className={cn(\n \"data-selected:bg-muted data-selected:text-foreground data-selected:*:[svg]:text-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md px-2.5 py-1.5 text-xs/relaxed outline-hidden select-none [&_svg:not([class*='size-'])]:size-3.5 [[data-slot=dialog-content]_&]:rounded-md group/command-item data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n {children}\n <CheckIcon className=\"ml-auto opacity-0 group-has-[[data-slot=command-shortcut]]/command-item:hidden group-data-[checked=true]/command-item:opacity-100\" />\n </CommandPrimitive.Item>\n )\n}\n\nfunction CommandShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"command-shortcut\"\n className={cn(\"text-muted-foreground group-data-selected/command-item:text-foreground ml-auto text-[0.625rem] tracking-widest\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { XIcon } from \"lucide-react\"\n\nfunction Dialog({ ...props }: DialogPrimitive.Root.Props) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({ ...props }: DialogPrimitive.Close.Props) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: DialogPrimitive.Backdrop.Props) {\n return (\n <DialogPrimitive.Backdrop\n data-slot=\"dialog-overlay\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: DialogPrimitive.Popup.Props & {\n showCloseButton?: boolean\n}) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Popup\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid gap-4 rounded-xl p-4 text-xs/relaxed ring-1 duration-100 fixed top-1/2 left-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 outline-none\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-2 right-2\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon\n />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Popup>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"gap-1 flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({\n className,\n showCloseButton = false,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showCloseButton?: boolean\n}) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"gap-2 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close render={<Button variant=\"outline\" />}>\n Close\n </DialogPrimitive.Close>\n )}\n </div>\n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground *:[a]:hover:text-foreground text-xs/relaxed *:[a]:underline *:[a]:underline-offset-3\", className)}\n {...props}\n />\n )\n}\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 * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../utils/cn\"\nimport { Button } from \"./button\"\nimport { Input } from \"./input\"\nimport { Textarea } from \"./textarea\"\n\nfunction InputGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-group\"\n role=\"group\"\n className={cn(\n \"border-input bg-input/20 dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/30 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 h-7 rounded-md border transition-colors has-data-[align=block-end]:rounded-md has-data-[align=block-start]:rounded-md has-[[data-slot=input-group-control]:focus-visible]:ring-[2px] has-[[data-slot][aria-invalid=true]]:ring-[2px] has-[textarea]:rounded-md has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5 [[data-slot=combobox-content]_&]:focus-within:border-inherit [[data-slot=combobox-content]_&]:focus-within:ring-0 group/input-group relative flex w-full min-w-0 items-center outline-none has-[>textarea]:h-auto\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst inputGroupAddonVariants = cva(\n \"text-muted-foreground **:data-[slot=kbd]:bg-muted-foreground/10 h-auto gap-1 py-2 text-xs/relaxed font-medium group-data-[disabled=true]/input-group:opacity-50 **:data-[slot=kbd]:rounded-[calc(var(--radius-sm)-2px)] **:data-[slot=kbd]:px-1 **:data-[slot=kbd]:text-[0.625rem] [&>svg:not([class*='size-'])]:size-3.5 flex cursor-text items-center justify-center select-none\",\n {\n variants: {\n align: {\n \"inline-start\": \"pl-2 has-[>button]:ml-[-0.275rem] has-[>kbd]:ml-[-0.275rem] order-first\",\n \"inline-end\": \"pr-2 has-[>button]:mr-[-0.275rem] has-[>kbd]:mr-[-0.275rem] order-last\",\n \"block-start\":\n \"px-2 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2 order-first w-full justify-start\",\n \"block-end\":\n \"px-2 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2 order-last w-full justify-start\",\n },\n },\n defaultVariants: {\n align: \"inline-start\",\n },\n }\n)\n\nfunction InputGroupAddon({\n className,\n align = \"inline-start\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof inputGroupAddonVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"input-group-addon\"\n data-align={align}\n className={cn(inputGroupAddonVariants({ align }), className)}\n onClick={(e) => {\n if ((e.target as HTMLElement).closest(\"button\")) {\n return\n }\n e.currentTarget.parentElement?.querySelector(\"input\")?.focus()\n }}\n {...props}\n />\n )\n}\n\nconst inputGroupButtonVariants = cva(\n \"gap-2 rounded-md text-xs/relaxed shadow-none flex items-center\",\n {\n variants: {\n size: {\n xs: \"h-5 gap-1 rounded-[calc(var(--radius-sm)-2px)] px-1 [&>svg:not([class*='size-'])]:size-3\",\n sm: \"\",\n \"icon-xs\": \"size-6 p-0 has-[>svg]:p-0\",\n \"icon-sm\": \"size-8 p-0 has-[>svg]:p-0\",\n },\n },\n defaultVariants: {\n size: \"xs\",\n },\n }\n)\n\nfunction InputGroupButton({\n className,\n type = \"button\",\n variant = \"ghost\",\n size = \"xs\",\n ...props\n}: Omit<React.ComponentProps<typeof Button>, \"size\" | \"type\"> &\n VariantProps<typeof inputGroupButtonVariants> & {\n type?: \"button\" | \"submit\" | \"reset\"\n }) {\n return (\n <Button\n type={type}\n data-size={size}\n variant={variant}\n className={cn(inputGroupButtonVariants({ size }), className)}\n {...props}\n />\n )\n}\n\nfunction InputGroupText({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n className={cn(\n \"text-muted-foreground gap-2 text-xs/relaxed [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction InputGroupInput({\n className,\n ...props\n}: React.ComponentProps<\"input\">) {\n return (\n <Input\n data-slot=\"input-group-control\"\n className={cn(\"rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent flex-1\", className)}\n {...props}\n />\n )\n}\n\nfunction InputGroupTextarea({\n className,\n ...props\n}: React.ComponentProps<\"textarea\">) {\n return (\n <Textarea\n data-slot=\"input-group-control\"\n className={cn(\"rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent flex-1 resize-none\", className)}\n {...props}\n />\n )\n}\n\nexport {\n InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupText,\n InputGroupInput,\n InputGroupTextarea,\n}\n","import * as React from \"react\"\nimport { Input as InputPrimitive } from \"@base-ui/react/input\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <InputPrimitive\n type={type}\n data-slot=\"input\"\n className={cn(\n \"bg-input/20 dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 h-7 rounded-md border px-2 py-0.5 text-sm transition-colors file:h-6 file:text-xs/relaxed file:font-medium focus-visible:ring-[2px] aria-invalid:ring-[2px] md:text-xs/relaxed file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n","import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"border-input bg-input/20 dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 resize-none rounded-md border px-2 py-2 text-sm transition-colors focus-visible:ring-[2px] aria-invalid:ring-[2px] md:text-xs/relaxed placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Textarea }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { ContextMenu as ContextMenuPrimitive } from \"@base-ui/react/context-menu\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronRightIcon, CheckIcon } from \"lucide-react\"\n\nfunction ContextMenu({ ...props }: ContextMenuPrimitive.Root.Props) {\n return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />\n}\n\nfunction ContextMenuPortal({ ...props }: ContextMenuPrimitive.Portal.Props) {\n return (\n <ContextMenuPrimitive.Portal data-slot=\"context-menu-portal\" {...props} />\n )\n}\n\nfunction ContextMenuTrigger({\n className,\n ...props\n}: ContextMenuPrimitive.Trigger.Props) {\n return (\n <ContextMenuPrimitive.Trigger\n data-slot=\"context-menu-trigger\"\n className={cn(\"select-none\", className)}\n {...props}\n />\n )\n}\n\nfunction ContextMenuContent({\n className,\n align = \"start\",\n alignOffset = 4,\n side = \"right\",\n sideOffset = 0,\n ...props\n}: ContextMenuPrimitive.Popup.Props &\n Pick<\n ContextMenuPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Positioner\n className=\"isolate z-50 outline-none\"\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <ContextMenuPrimitive.Popup\n data-slot=\"context-menu-content\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 z-50 max-h-(--available-height) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none\", className )}\n {...props}\n />\n </ContextMenuPrimitive.Positioner>\n </ContextMenuPrimitive.Portal>\n )\n}\n\nfunction ContextMenuGroup({ ...props }: ContextMenuPrimitive.Group.Props) {\n return (\n <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />\n )\n}\n\nfunction ContextMenuLabel({\n className,\n inset,\n ...props\n}: ContextMenuPrimitive.GroupLabel.Props & {\n inset?: boolean\n}) {\n return (\n <ContextMenuPrimitive.GroupLabel\n data-slot=\"context-menu-label\"\n data-inset={inset}\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs data-[inset]:pl-8\", className)}\n {...props}\n />\n )\n}\n\nfunction ContextMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: ContextMenuPrimitive.Item.Props & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <ContextMenuPrimitive.Item\n data-slot=\"context-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed [&_svg:not([class*='size-'])]:size-3.5 group/context-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction ContextMenuSub({ ...props }: ContextMenuPrimitive.SubmenuRoot.Props) {\n return (\n <ContextMenuPrimitive.SubmenuRoot data-slot=\"context-menu-sub\" {...props} />\n )\n}\n\nfunction ContextMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: ContextMenuPrimitive.SubmenuTrigger.Props & {\n inset?: boolean\n}) {\n return (\n <ContextMenuPrimitive.SubmenuTrigger\n data-slot=\"context-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs [&_svg:not([class*='size-'])]:size-3.5 flex cursor-default items-center outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto\" />\n </ContextMenuPrimitive.SubmenuTrigger>\n )\n}\n\nfunction ContextMenuSubContent({\n ...props\n}: React.ComponentProps<typeof ContextMenuContent>) {\n return (\n <ContextMenuContent\n data-slot=\"context-menu-sub-content\"\n className=\"shadow-lg\"\n side=\"right\"\n {...props}\n />\n )\n}\n\nfunction ContextMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: ContextMenuPrimitive.CheckboxItem.Props) {\n return (\n <ContextMenuPrimitive.CheckboxItem\n data-slot=\"context-menu-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none\">\n <ContextMenuPrimitive.CheckboxItemIndicator>\n <CheckIcon\n />\n </ContextMenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n )\n}\n\nfunction ContextMenuRadioGroup({\n ...props\n}: ContextMenuPrimitive.RadioGroup.Props) {\n return (\n <ContextMenuPrimitive.RadioGroup\n data-slot=\"context-menu-radio-group\"\n {...props}\n />\n )\n}\n\nfunction ContextMenuRadioItem({\n className,\n children,\n ...props\n}: ContextMenuPrimitive.RadioItem.Props) {\n return (\n <ContextMenuPrimitive.RadioItem\n data-slot=\"context-menu-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none\">\n <ContextMenuPrimitive.RadioItemIndicator>\n <CheckIcon\n />\n </ContextMenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n )\n}\n\nfunction ContextMenuSeparator({\n className,\n ...props\n}: ContextMenuPrimitive.Separator.Props) {\n return (\n <ContextMenuPrimitive.Separator\n data-slot=\"context-menu-separator\"\n className={cn(\"bg-border/50 -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction ContextMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"context-menu-shortcut\"\n className={cn(\"text-muted-foreground group-focus/context-menu-item:text-accent-foreground ml-auto text-[0.625rem] tracking-widest\", className)}\n {...props}\n />\n )\n}\n\nexport {\n ContextMenu,\n ContextMenuTrigger,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuCheckboxItem,\n ContextMenuRadioItem,\n ContextMenuLabel,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuGroup,\n ContextMenuPortal,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuRadioGroup,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n return <DrawerPrimitive.Root data-slot=\"drawer\" {...props} />\n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\n return <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props} />\n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Close>) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Content>) {\n return (\n <DrawerPortal data-slot=\"drawer-portal\">\n <DrawerOverlay />\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n \"before:bg-background relative flex h-auto flex-col bg-transparent p-2 text-xs/relaxed before:absolute before:inset-2 before:-z-10 before:rounded-xl data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm group/drawer-content fixed z-50\",\n className\n )}\n {...props}\n >\n <div className=\"bg-muted mx-auto mt-4 hidden h-1.5 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block bg-muted mx-auto hidden shrink-0 group-data-[vaul-drawer-direction=bottom]/drawer-content:block\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n )\n}\n\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn(\"gap-1 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:text-left flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-footer\"\n className={cn(\"gap-2 p-4 mt-auto flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Title>) {\n return (\n <DrawerPrimitive.Title\n data-slot=\"drawer-title\"\n className={cn(\"text-foreground text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Description>) {\n return (\n <DrawerPrimitive.Description\n data-slot=\"drawer-description\"\n className={cn(\"text-muted-foreground text-xs/relaxed\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Drawer,\n DrawerPortal,\n DrawerOverlay,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronRightIcon, CheckIcon } from \"lucide-react\"\n\nfunction DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {\n return <MenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />\n}\n\nfunction DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\n}\n\nfunction DropdownMenuContent({\n align = \"start\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n className,\n ...props\n}: MenuPrimitive.Popup.Props &\n Pick<\n MenuPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner\n className=\"isolate z-50 outline-none\"\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <MenuPrimitive.Popup\n data-slot=\"dropdown-menu-content\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden\", className )}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {\n return <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: MenuPrimitive.GroupLabel.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.GroupLabel\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs data-[inset]:pl-8\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: MenuPrimitive.Item.Props & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <MenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed [&_svg:not([class*='size-'])]:size-3.5 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {\n return <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.SubmenuTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs [&_svg:not([class*='size-'])]:size-3.5 flex cursor-default items-center outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto\" />\n </MenuPrimitive.SubmenuTrigger>\n )\n}\n\nfunction DropdownMenuSubContent({\n align = \"start\",\n alignOffset = -3,\n side = \"right\",\n sideOffset = 0,\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuContent>) {\n return (\n <DropdownMenuContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 w-auto\", className)}\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: MenuPrimitive.CheckboxItem.Props) {\n return (\n <MenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none\"\n data-slot=\"dropdown-menu-checkbox-item-indicator\"\n >\n <MenuPrimitive.CheckboxItemIndicator>\n <CheckIcon\n />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n )\n}\n\nfunction DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {\n return (\n <MenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: MenuPrimitive.RadioItem.Props) {\n return (\n <MenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none\"\n data-slot=\"dropdown-menu-radio-item-indicator\"\n >\n <MenuPrimitive.RadioItemIndicator>\n <CheckIcon\n />\n </MenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n )\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: MenuPrimitive.Separator.Props) {\n return (\n <MenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"bg-border/50 -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\"text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-[0.625rem] tracking-widest\", className)}\n {...props}\n />\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n}\n","\"use client\"\n\nimport { useMemo } from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../utils/cn\"\nimport { Label } from \"./label\"\nimport { Separator } from \"./separator\"\n\nfunction FieldSet({ className, ...props }: React.ComponentProps<\"fieldset\">) {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn(\"gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction FieldLegend({\n className,\n variant = \"legend\",\n ...props\n}: React.ComponentProps<\"legend\"> & { variant?: \"legend\" | \"label\" }) {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(\"mb-2 font-medium data-[variant=label]:text-xs/relaxed data-[variant=legend]:text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction FieldGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n \"gap-4 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4 group/field-group @container/field-group flex w-full flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst fieldVariants = cva(\"data-[invalid=true]:text-destructive gap-2 group/field flex w-full\", {\n variants: {\n orientation: {\n vertical:\n \"flex-col [&>*]:w-full [&>.sr-only]:w-auto\",\n horizontal:\n \"flex-row items-center [&>[data-slot=field-label]]:flex-auto has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\",\n responsive:\n \"flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto @md/field-group:[&>[data-slot=field-label]]:flex-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\",\n },\n },\n defaultVariants: {\n orientation: \"vertical\",\n },\n})\n\nfunction Field({\n className,\n orientation = \"vertical\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof fieldVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"field\"\n data-orientation={orientation}\n className={cn(fieldVariants({ orientation }), className)}\n {...props}\n />\n )\n}\n\nfunction FieldContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-content\"\n className={cn(\n \"gap-0.5 group/field-content flex flex-1 flex-col leading-snug\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldLabel({\n className,\n ...props\n}: React.ComponentProps<typeof Label>) {\n return (\n <Label\n data-slot=\"field-label\"\n className={cn(\n \"has-data-checked:bg-primary/5 dark:has-data-checked:bg-primary/10 gap-2 group-data-[disabled=true]/field:opacity-50 has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-2 group/field-label peer/field-label flex w-fit leading-snug\",\n \"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-label\"\n className={cn(\n \"gap-2 text-xs/relaxed font-medium group-data-[disabled=true]/field:opacity-50 flex w-fit items-center leading-snug\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"field-description\"\n className={cn(\n \"text-muted-foreground text-left text-xs/relaxed [[data-variant=legend]+&]:-mt-1.5 leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance\",\n \"last:mt-0 nth-last-2:-mt-1\",\n \"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n children?: React.ReactNode\n}) {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn(\"-my-2 h-5 text-xs/relaxed group-data-[variant=outline]/field-group:-mb-2 relative\", className)}\n {...props}\n >\n <Separator className=\"absolute inset-0 top-1/2\" />\n {children && (\n <span\n className=\"text-muted-foreground px-2 bg-background relative mx-auto block w-fit\"\n data-slot=\"field-separator-content\"\n >\n {children}\n </span>\n )}\n </div>\n )\n}\n\nfunction FieldError({\n className,\n children,\n errors,\n ...props\n}: React.ComponentProps<\"div\"> & {\n errors?: Array<{ message?: string } | undefined>\n}) {\n const content = useMemo(() => {\n if (children) {\n return children\n }\n\n if (!errors?.length) {\n return null\n }\n\n const uniqueErrors = [\n ...new Map(errors.map((error) => [error?.message, error])).values(),\n ]\n\n if (uniqueErrors?.length == 1) {\n return uniqueErrors[0]?.message\n }\n\n return (\n <ul className=\"ml-4 flex list-disc flex-col gap-1\">\n {uniqueErrors.map(\n (error, index) =>\n error?.message && <li key={index}>{error.message}</li>\n )}\n </ul>\n )\n }, [children, errors])\n\n if (!content) {\n return null\n }\n\n return (\n <div\n role=\"alert\"\n data-slot=\"field-error\"\n className={cn(\"text-destructive text-xs/relaxed font-normal\", className)}\n {...props}\n >\n {content}\n </div>\n )\n}\n\nexport {\n Field,\n FieldLabel,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLegend,\n FieldSeparator,\n FieldSet,\n FieldContent,\n FieldTitle,\n}\n","\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Label({ className, ...props }: React.ComponentProps<\"label\">) {\n return (\n <label\n data-slot=\"label\"\n className={cn(\n \"gap-2 text-xs/relaxed leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Label }\n","\"use client\"\n\nimport { Separator as SeparatorPrimitive } from \"@base-ui/react/separator\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Separator({\n className,\n orientation = \"horizontal\",\n ...props\n}: SeparatorPrimitive.Props) {\n return (\n <SeparatorPrimitive\n data-slot=\"separator\"\n orientation={orientation}\n className={cn(\n \"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Separator }\n","\"use client\";\n\nimport { FormProvider } from \"react-hook-form\";\n\n/**\n * Form component is a wrapper around react-hook-form's FormProvider.\n * Use this to wrap your form and spread the form object into it.\n *\n * @example\n * const form = useForm<FormValues>();\n * return (\n * <Form {...form}>\n * <form onSubmit={form.handleSubmit(onSubmit)}>\n * <FormInput form={form} id=\"email\" name=\"Email\" />\n * </form>\n * </Form>\n * );\n */\nconst Form = FormProvider;\n\nexport { Form };\n","\"use client\"\n\nimport { PreviewCard as PreviewCardPrimitive } from \"@base-ui/react/preview-card\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction HoverCard({ ...props }: PreviewCardPrimitive.Root.Props) {\n return <PreviewCardPrimitive.Root data-slot=\"hover-card\" {...props} />\n}\n\nfunction HoverCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) {\n return (\n <PreviewCardPrimitive.Trigger data-slot=\"hover-card-trigger\" {...props} />\n )\n}\n\nfunction HoverCardContent({\n className,\n side = \"bottom\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 4,\n ...props\n}: PreviewCardPrimitive.Popup.Props &\n Pick<\n PreviewCardPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <PreviewCardPrimitive.Portal data-slot=\"hover-card-portal\">\n <PreviewCardPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <PreviewCardPrimitive.Popup\n data-slot=\"hover-card-content\"\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground w-72 rounded-lg p-2.5 text-xs/relaxed shadow-md ring-1 duration-100 z-50 origin-(--transform-origin) outline-hidden\",\n className\n )}\n {...props}\n />\n </PreviewCardPrimitive.Positioner>\n </PreviewCardPrimitive.Portal>\n )\n}\n\nexport { HoverCard, HoverCardTrigger, HoverCardContent }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { OTPInput, OTPInputContext } from \"input-otp\"\n\nimport { cn } from \"@/lib/utils\"\nimport { MinusIcon } from \"lucide-react\"\n\nfunction InputOTP({\n className,\n containerClassName,\n ...props\n}: React.ComponentProps<typeof OTPInput> & {\n containerClassName?: string\n}) {\n return (\n <OTPInput\n data-slot=\"input-otp\"\n containerClassName={cn(\n \"cn-input-otp flex items-center has-disabled:opacity-50\",\n containerClassName\n )}\n spellCheck={false}\n className={cn(\n \"disabled:cursor-not-allowed\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction InputOTPGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-otp-group\"\n className={cn(\"has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive rounded-md has-aria-invalid:ring-[2px] flex items-center\", className)}\n {...props}\n />\n )\n}\n\nfunction InputOTPSlot({\n index,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n index: number\n}) {\n const inputOTPContext = React.useContext(OTPInputContext)\n const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}\n\n return (\n <div\n data-slot=\"input-otp-slot\"\n data-active={isActive}\n className={cn(\n \"bg-input/20 dark:bg-input/30 border-input data-[active=true]:border-ring data-[active=true]:ring-ring/30 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive size-7 border-y border-r text-xs/relaxed transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:ring-[2px] relative flex items-center justify-center data-[active=true]:z-10\",\n className\n )}\n {...props}\n >\n {char}\n {hasFakeCaret && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"animate-caret-blink bg-foreground h-4 w-px duration-1000 bg-foreground h-4 w-px\" />\n </div>\n )}\n </div>\n )\n}\n\nfunction InputOTPSeparator({ ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-otp-separator\"\n className=\"[&_svg:not([class*='size-'])]:size-4 flex items-center\"\n role=\"separator\"\n {...props}\n >\n <MinusIcon\n />\n </div>\n )\n}\n\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }\n","import { NavigationMenu as NavigationMenuPrimitive } from \"@base-ui/react/navigation-menu\"\nimport { cva } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronDownIcon } from \"lucide-react\"\n\nfunction NavigationMenu({\n className,\n children,\n ...props\n}: NavigationMenuPrimitive.Root.Props) {\n return (\n <NavigationMenuPrimitive.Root\n data-slot=\"navigation-menu\"\n className={cn(\n \"max-w-max group/navigation-menu relative flex max-w-max flex-1 items-center justify-center\",\n className\n )}\n {...props}\n >\n {children}\n <NavigationMenuPositioner />\n </NavigationMenuPrimitive.Root>\n )\n}\n\nfunction NavigationMenuList({\n className,\n ...props\n}: NavigationMenuPrimitive.List.Props) {\n return (\n <NavigationMenuPrimitive.List\n data-slot=\"navigation-menu-list\"\n className={cn(\n \"gap-0 group flex flex-1 list-none items-center justify-center\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction NavigationMenuItem({\n className,\n ...props\n}: NavigationMenuPrimitive.Item.Props) {\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 \"bg-background hover:bg-muted focus:bg-muted data-open:hover:bg-muted data-open:focus:bg-muted data-open:bg-muted/50 focus-visible:ring-ring/30 data-popup-open:bg-muted/50 data-popup-open:hover:bg-muted rounded-md px-2.5 py-1.5 text-xs/relaxed font-medium transition-all focus-visible:ring-[2px] focus-visible:outline-1 disabled:opacity-50 group/navigation-menu-trigger inline-flex h-9 w-max items-center justify-center disabled:pointer-events-none outline-none\"\n)\n\nfunction NavigationMenuTrigger({\n className,\n children,\n ...props\n}: NavigationMenuPrimitive.Trigger.Props) {\n return (\n <NavigationMenuPrimitive.Trigger\n data-slot=\"navigation-menu-trigger\"\n className={cn(navigationMenuTriggerStyle(), \"group\", className)}\n {...props}\n >\n {children}{\" \"}\n <ChevronDownIcon className=\"relative top-[1px] ml-1 size-3 transition duration-300 group-data-open/navigation-menu-trigger:rotate-180 group-data-popup-open/navigation-menu-trigger:rotate-180\" aria-hidden=\"true\" />\n </NavigationMenuPrimitive.Trigger>\n )\n}\n\nfunction NavigationMenuContent({\n className,\n ...props\n}: NavigationMenuPrimitive.Content.Props) {\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 group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-open:animate-in group-data-[viewport=false]/navigation-menu:data-closed:animate-out group-data-[viewport=false]/navigation-menu:data-closed:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-open:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-open:fade-in-0 group-data-[viewport=false]/navigation-menu:data-closed:fade-out-0 group-data-[viewport=false]/navigation-menu:ring-foreground/10 p-1.5 ease-[cubic-bezier(0.22,1,0.36,1)] group-data-[viewport=false]/navigation-menu:rounded-xl group-data-[viewport=false]/navigation-menu:shadow-md group-data-[viewport=false]/navigation-menu:ring-1 group-data-[viewport=false]/navigation-menu:duration-300 h-full w-auto **: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 NavigationMenuPositioner({\n className,\n side = \"bottom\",\n sideOffset = 8,\n align = \"start\",\n alignOffset = 0,\n ...props\n}: NavigationMenuPrimitive.Positioner.Props) {\n return (\n <NavigationMenuPrimitive.Portal>\n <NavigationMenuPrimitive.Positioner\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n className={cn(\n \"transition-[top,left,right,bottom] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] data-[side=bottom]:before:top-[-10px] data-[side=bottom]:before:right-0 data-[side=bottom]:before:left-0 isolate z-50 h-[var(--positioner-height)] w-[var(--positioner-width)] max-w-[var(--available-width)] data-[instant]:transition-none\",\n className\n )}\n {...props}\n >\n <NavigationMenuPrimitive.Popup className=\"bg-popover text-popover-foreground ring-foreground/10 rounded-xl shadow ring-1 transition-all ease-[cubic-bezier(0.22,1,0.36,1)] outline-none data-[ending-style]:scale-90 data-[ending-style]:opacity-0 data-[ending-style]:duration-150 data-[starting-style]:scale-90 data-[starting-style]:opacity-0 xs:w-(--popup-width) relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin)\">\n <NavigationMenuPrimitive.Viewport className=\"relative size-full overflow-hidden\" />\n </NavigationMenuPrimitive.Popup>\n </NavigationMenuPrimitive.Positioner>\n </NavigationMenuPrimitive.Portal>\n )\n}\n\nfunction NavigationMenuLink({\n className,\n ...props\n}: NavigationMenuPrimitive.Link.Props) {\n return (\n <NavigationMenuPrimitive.Link\n data-slot=\"navigation-menu-link\"\n className={cn(\"data-[active=true]:focus:bg-muted data-[active=true]:hover:bg-muted data-[active=true]:bg-muted/50 focus-visible:ring-ring/30 hover:bg-muted focus:bg-muted flex items-center gap-1.5 rounded-lg p-2 text-xs/relaxed transition-all outline-none focus-visible:ring-[2px] focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4\", className)}\n {...props}\n />\n )\n}\n\nfunction NavigationMenuIndicator({\n className,\n ...props\n}: NavigationMenuPrimitive.Icon.Props) {\n return (\n <NavigationMenuPrimitive.Icon\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 rounded-tl-sm shadow-md relative top-[60%] h-2 w-2 rotate-45\" />\n </NavigationMenuPrimitive.Icon>\n )\n}\n\nexport {\n NavigationMenu,\n NavigationMenuContent,\n NavigationMenuIndicator,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n NavigationMenuTrigger,\n navigationMenuTriggerStyle,\n NavigationMenuPositioner,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Popover as PopoverPrimitive } from \"@base-ui/react/popover\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Popover({ ...props }: PopoverPrimitive.Root.Props) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\nfunction PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n ...props\n}: PopoverPrimitive.Popup.Props &\n Pick<\n PopoverPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <PopoverPrimitive.Popup\n data-slot=\"popover-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 flex flex-col gap-4 rounded-lg p-2.5 text-xs shadow-md ring-1 duration-100 z-50 w-72 origin-(--transform-origin) outline-hidden\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Positioner>\n </PopoverPrimitive.Portal>\n )\n}\n\nfunction PopoverHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\"flex flex-col gap-1 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {\n return (\n <PopoverPrimitive.Title\n data-slot=\"popover-title\"\n className={cn(\"text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverDescription({\n className,\n ...props\n}: PopoverPrimitive.Description.Props) {\n return (\n <PopoverPrimitive.Description\n data-slot=\"popover-description\"\n className={cn(\"text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Popover,\n PopoverContent,\n PopoverDescription,\n PopoverHeader,\n PopoverTitle,\n PopoverTrigger,\n}\n","\"use client\"\n\nimport { Progress as ProgressPrimitive } from \"@base-ui/react/progress\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Progress({\n className,\n children,\n value,\n ...props\n}: ProgressPrimitive.Root.Props) {\n return (\n <ProgressPrimitive.Root\n value={value}\n data-slot=\"progress\"\n className={cn(\"flex flex-wrap gap-3\", className)}\n {...props}\n >\n {children}\n <ProgressTrack>\n <ProgressIndicator />\n </ProgressTrack>\n </ProgressPrimitive.Root>\n )\n}\n\nfunction ProgressTrack({ className, ...props }: ProgressPrimitive.Track.Props) {\n return (\n <ProgressPrimitive.Track\n className={cn(\n \"bg-muted h-1 rounded-md relative flex w-full items-center overflow-x-hidden\",\n className\n )}\n data-slot=\"progress-track\"\n {...props}\n />\n )\n}\n\nfunction ProgressIndicator({\n className,\n ...props\n}: ProgressPrimitive.Indicator.Props) {\n return (\n <ProgressPrimitive.Indicator\n data-slot=\"progress-indicator\"\n className={cn(\"bg-primary h-full transition-all\", className)}\n {...props}\n />\n )\n}\n\nfunction ProgressLabel({ className, ...props }: ProgressPrimitive.Label.Props) {\n return (\n <ProgressPrimitive.Label\n className={cn(\"text-xs/relaxed font-medium\", className)}\n data-slot=\"progress-label\"\n {...props}\n />\n )\n}\n\nfunction ProgressValue({ className, ...props }: ProgressPrimitive.Value.Props) {\n return (\n <ProgressPrimitive.Value\n className={cn(\"text-muted-foreground ml-auto text-xs/relaxed tabular-nums\", className)}\n data-slot=\"progress-value\"\n {...props}\n />\n )\n}\n\nexport {\n Progress,\n ProgressTrack,\n ProgressIndicator,\n ProgressLabel,\n ProgressValue,\n}\n","\"use client\"\n\nimport { Radio as RadioPrimitive } from \"@base-ui/react/radio\"\nimport { RadioGroup as RadioGroupPrimitive } from \"@base-ui/react/radio-group\"\n\nimport { cn } from \"@/lib/utils\"\nimport { CircleIcon } from \"lucide-react\"\n\nfunction RadioGroup({ className, ...props }: RadioGroupPrimitive.Props) {\n return (\n <RadioGroupPrimitive\n data-slot=\"radio-group\"\n className={cn(\"grid gap-3 w-full\", className)}\n {...props}\n />\n )\n}\n\nfunction RadioGroupItem({ className, ...props }: RadioPrimitive.Root.Props) {\n return (\n <RadioPrimitive.Root\n data-slot=\"radio-group-item\"\n className={cn(\n \"border-input text-primary dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 data-checked:bg-primary data-checked:border-primary flex size-4 rounded-full transition-none focus-visible:ring-[2px] aria-invalid:ring-[2px] group/radio-group-item peer relative aspect-square shrink-0 border outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <RadioPrimitive.Indicator\n data-slot=\"radio-group-indicator\"\n className=\"group-aria-invalid/radio-group-item:text-destructive flex size-4 items-center justify-center text-white\"\n >\n <CircleIcon className=\"absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-current\" />\n </RadioPrimitive.Indicator>\n </RadioPrimitive.Root>\n )\n}\n\nexport { RadioGroup, RadioGroupItem }\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as ResizablePrimitive from \"react-resizable-panels\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction ResizablePanelGroup({\n className,\n ...props\n}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) {\n return (\n <ResizablePrimitive.PanelGroup\n data-slot=\"resizable-panel-group\"\n className={cn(\n \"flex h-full w-full data-[panel-group-direction=vertical]:flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction ResizablePanel({\n ...props\n}: 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-6 w-1 shrink-0 rounded-lg\" />\n )}\n </ResizablePrimitive.PanelResizeHandle>\n )\n}\n\nexport { ResizablePanelGroup, ResizablePanel, ResizableHandle }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { ScrollArea as ScrollAreaPrimitive } from \"@base-ui/react/scroll-area\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction ScrollArea({\n className,\n children,\n ...props\n}: ScrollAreaPrimitive.Root.Props) {\n return (\n <ScrollAreaPrimitive.Root\n data-slot=\"scroll-area\"\n className={cn(\"relative\", className)}\n {...props}\n >\n <ScrollAreaPrimitive.Viewport\n data-slot=\"scroll-area-viewport\"\n className=\"focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1\"\n >\n {children}\n </ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n )\n}\n\nfunction ScrollBar({\n className,\n orientation = \"vertical\",\n ...props\n}: ScrollAreaPrimitive.Scrollbar.Props) {\n return (\n <ScrollAreaPrimitive.Scrollbar\n data-slot=\"scroll-area-scrollbar\"\n data-orientation={orientation}\n orientation={orientation}\n className={cn(\n \"data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent flex touch-none p-px transition-colors select-none\",\n className\n )}\n {...props}\n >\n <ScrollAreaPrimitive.Thumb\n data-slot=\"scroll-area-thumb\"\n className=\"rounded-full bg-border relative flex-1\"\n />\n </ScrollAreaPrimitive.Scrollbar>\n )\n}\n\nexport { ScrollArea, ScrollBar }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronDownIcon, CheckIcon, ChevronUpIcon } from \"lucide-react\"\n\nconst Select = SelectPrimitive.Root\n\nfunction SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {\n return (\n <SelectPrimitive.Group\n data-slot=\"select-group\"\n className={cn(\"scroll-my-1 p-1\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {\n return (\n <SelectPrimitive.Value\n data-slot=\"select-value\"\n className={cn(\"flex flex-1 text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectTrigger({\n className,\n size = \"default\",\n children,\n ...props\n}: SelectPrimitive.Trigger.Props & {\n size?: \"sm\" | \"default\"\n}) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n \"border-input data-[placeholder]:text-muted-foreground bg-input/20 dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-1.5 rounded-md border px-2 py-1.5 text-xs/relaxed transition-colors focus-visible:ring-[2px] aria-invalid:ring-[2px] data-[size=default]:h-7 data-[size=sm]:h-6 *:data-[slot=select-value]:flex *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*='size-'])]:size-3.5 flex w-fit items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon\n render={\n <ChevronDownIcon className=\"text-muted-foreground size-3.5 pointer-events-none\" />\n }\n />\n </SelectPrimitive.Trigger>\n )\n}\n\nfunction SelectContent({\n className,\n children,\n side = \"bottom\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 0,\n alignItemWithTrigger = true,\n ...props\n}: SelectPrimitive.Popup.Props &\n Pick<\n SelectPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\" | \"alignItemWithTrigger\"\n >) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Positioner\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n alignItemWithTrigger={alignItemWithTrigger}\n className=\"isolate z-50\"\n >\n <SelectPrimitive.Popup\n data-slot=\"select-content\"\n className={cn(\"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 min-w-32 rounded-lg shadow-md ring-1 duration-100 relative isolate z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto\", className )}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.List>{children}</SelectPrimitive.List>\n <SelectScrollDownButton />\n </SelectPrimitive.Popup>\n </SelectPrimitive.Positioner>\n </SelectPrimitive.Portal>\n )\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: SelectPrimitive.GroupLabel.Props) {\n return (\n <SelectPrimitive.GroupLabel\n data-slot=\"select-label\"\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: SelectPrimitive.Item.Props) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed [&_svg:not([class*='size-'])]:size-3.5 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n <SelectPrimitive.ItemText className=\"flex flex-1 gap-2 shrink-0 whitespace-nowrap\">\n {children}\n </SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator\n render={<span className=\"pointer-events-none absolute right-2 flex items-center justify-center\" />}\n >\n <CheckIcon className=\"pointer-events-none\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n )\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: SelectPrimitive.Separator.Props) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\"bg-border/50 -mx-1 my-1 h-px pointer-events-none\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>) {\n return (\n <SelectPrimitive.ScrollUpArrow\n data-slot=\"select-scroll-up-button\"\n className={cn(\"bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-3.5 top-0 w-full\", className)}\n {...props}\n >\n <ChevronUpIcon\n />\n </SelectPrimitive.ScrollUpArrow>\n )\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>) {\n return (\n <SelectPrimitive.ScrollDownArrow\n data-slot=\"select-scroll-down-button\"\n className={cn(\"bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-3.5 bottom-0 w-full\", className)}\n {...props}\n >\n <ChevronDownIcon\n />\n </SelectPrimitive.ScrollDownArrow>\n )\n}\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 { Dialog as SheetPrimitive } from \"@base-ui/react/dialog\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { XIcon } from \"lucide-react\"\n\nfunction Sheet({ ...props }: SheetPrimitive.Root.Props) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />\n}\n\nfunction SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose({ ...props }: SheetPrimitive.Close.Props) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />\n}\n\nfunction SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {\n return (\n <SheetPrimitive.Backdrop\n data-slot=\"sheet-overlay\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-100 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n showCloseButton = true,\n ...props\n}: SheetPrimitive.Popup.Props & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n showCloseButton?: boolean\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Popup\n data-slot=\"sheet-content\"\n data-side={side}\n className={cn(\"bg-background data-open:animate-in data-closed:animate-out data-[side=right]:data-closed:slide-out-to-right-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=top]:data-closed:slide-out-to-top-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:fade-out-0 data-open:fade-in-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=bottom]:data-open:slide-in-from-bottom-10 fixed z-50 flex flex-col bg-clip-padding text-xs/relaxed shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm\", className)}\n {...props}\n >\n {children}\n {showCloseButton && (\n <SheetPrimitive.Close\n data-slot=\"sheet-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-4 right-4\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon\n />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n )}\n </SheetPrimitive.Popup>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"gap-1.5 p-6 flex flex-col\", 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(\"gap-2 p-6 mt-auto flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"text-foreground text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: SheetPrimitive.Description.Props) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-muted-foreground text-xs/relaxed\", 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 * as React from \"react\"\nimport { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { Input } from \"@/components/ui/input\"\nimport { Separator } from \"@/components/ui/separator\"\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n} from \"@/components/ui/sheet\"\nimport { Skeleton } from \"@/components/ui/skeleton\"\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\"\nimport { useIsMobile } from \"@/hooks/use-mobile\"\nimport { PanelLeftIcon } from \"lucide-react\"\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\"\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7\nconst SIDEBAR_WIDTH = \"16rem\"\nconst SIDEBAR_WIDTH_MOBILE = \"18rem\"\nconst SIDEBAR_WIDTH_ICON = \"3rem\"\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"b\"\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 (\n event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n (event.metaKey || event.ctrlKey)\n ) {\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 <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(\n \"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n </SidebarContext.Provider>\n )\n}\n\nfunction Sidebar({\n side = \"left\",\n variant = \"sidebar\",\n collapsible = \"offExamples\",\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n side?: \"left\" | \"right\"\n variant?: \"sidebar\" | \"floating\" | \"inset\"\n collapsible?: \"offExamples\" | \"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(\n \"bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col\",\n className\n )}\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 \"transition-[width] duration-200 ease-linear relative w-(--sidebar-width) bg-transparent\",\n \"group-data-[collapsible=offExamples]: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=offExamples]:left-[calc(var(--sidebar-width)*-1)]\"\n : \"right-0 group-data-[collapsible=offExamples]: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]:ring-sidebar-border group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 flex size-full flex-col\"\n >\n {children}\n </div>\n </div>\n </div>\n )\n}\n\nfunction SidebarTrigger({\n className,\n onClick,\n ...props\n}: 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-sm\"\n className={cn(className)}\n onClick={(event) => {\n onClick?.(event)\n toggleSidebar()\n }}\n {...props}\n >\n <PanelLeftIcon\n />\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=offExamples]:bg-sidebar group-data-[collapsible=offExamples]:translate-x-0 group-data-[collapsible=offExamples]:after:left-full\",\n \"[[data-side=left][data-collapsible=offExamples]_&]:-right-2\",\n \"[[data-side=right][data-collapsible=offExamples]_&]:-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 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 relative flex w-full flex-1 flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarInput({\n className,\n ...props\n}: React.ComponentProps<typeof Input>) {\n return (\n <Input\n data-slot=\"sidebar-input\"\n data-sidebar=\"input\"\n className={cn(\"bg-muted/20 dark:bg-muted/30 border-input h-8 w-full\", 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(\"gap-2 p-2 flex flex-col\", 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(\"gap-2 p-2 flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarSeparator({\n className,\n ...props\n}: 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 \"no-scrollbar gap-0 flex min-h-0 flex-1 flex-col 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(\n \"px-2 py-1 relative flex w-full min-w-0 flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarGroupLabel({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\"> & React.ComponentProps<\"div\">) {\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(\n {\n className: cn(\n \"text-sidebar-foreground/70 ring-sidebar-ring h-8 rounded-md px-2 text-xs transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 flex shrink-0 items-center outline-hidden [&>svg]:shrink-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-group-label\",\n sidebar: \"group-label\",\n },\n })\n}\n\nfunction SidebarGroupAction({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"button\"> & React.ComponentProps<\"button\">) {\n return useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\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 w-5 rounded-md p-0 focus-visible:ring-2 [&>svg]:size-4 flex aspect-square items-center justify-center outline-hidden transition-transform [&>svg]:shrink-0 after:absolute after:-inset-2 md:after:hidden group-data-[collapsible=icon]:hidden\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-group-action\",\n sidebar: \"group-action\",\n },\n })\n}\n\nfunction SidebarGroupContent({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-group-content\"\n data-sidebar=\"group-content\"\n className={cn(\"text-xs w-full\", 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(\"gap-px flex w-full min-w-0 flex-col\", 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 \"ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-[calc(var(--radius-sm)+2px)] p-2 text-left text-xs transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button 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 {\n variants: {\n variant: {\n default: \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n outline: \"bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]\",\n },\n size: {\n default: \"h-8 text-xs\",\n sm: \"h-7 text-xs\",\n lg: \"h-12 text-xs group-data-[collapsible=icon]:p-0!\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction SidebarMenuButton({\n render,\n isActive = false,\n variant = \"default\",\n size = \"default\",\n tooltip,\n className,\n ...props\n}: useRender.ComponentProps<\"button\"> &\n React.ComponentProps<\"button\"> & {\n isActive?: boolean\n tooltip?: string | React.ComponentProps<typeof TooltipContent>\n } & VariantProps<typeof sidebarMenuButtonVariants>) {\n const { isMobile, state } = useSidebar()\n const comp = useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\n className: cn(sidebarMenuButtonVariants({ variant, size }), className),\n },\n props\n ),\n render: !tooltip ? render : TooltipTrigger,\n state: {\n slot: \"sidebar-menu-button\",\n sidebar: \"menu-button\",\n size,\n active: isActive,\n },\n })\n\n if (!tooltip) {\n return comp\n }\n\n if (typeof tooltip === \"string\") {\n tooltip = {\n children: tooltip,\n }\n }\n\n return (\n <Tooltip>\n {comp}\n <TooltipContent\n side=\"right\"\n align=\"center\"\n hidden={state !== \"collapsed\" || isMobile}\n {...tooltip}\n />\n </Tooltip>\n )\n}\n\nfunction SidebarMenuAction({\n className,\n render,\n showOnHover = false,\n ...props\n}: useRender.ComponentProps<\"button\"> &\n React.ComponentProps<\"button\"> & {\n showOnHover?: boolean\n }) {\n return useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\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 aspect-square w-5 rounded-[calc(var(--radius-sm)-2px)] p-0 peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 focus-visible:ring-2 [&>svg]:size-4 flex items-center justify-center outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 md:after:hidden [&>svg]:shrink-0\",\n showOnHover &&\n \"peer-data-active/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-open:opacity-100 md:opacity-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-menu-action\",\n sidebar: \"menu-action\",\n },\n })\n}\n\nfunction SidebarMenuBadge({\n className,\n ...props\n}: 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 peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 rounded-[calc(var(--radius-sm)-2px)] px-1 text-xs font-medium peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 flex items-center justify-center tabular-nums select-none 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.useState(() => {\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(\"h-8 gap-2 rounded-md px-2 flex items-center\", className)}\n {...props}\n >\n {showIcon && (\n <Skeleton\n className=\"size-4 rounded-md\"\n data-sidebar=\"menu-skeleton-icon\"\n />\n )}\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(\"border-sidebar-border mx-3.5 translate-x-px gap-1 border-l px-2.5 py-0.5 group-data-[collapsible=icon]:hidden flex min-w-0 flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarMenuSubItem({\n className,\n ...props\n}: 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 render,\n size = \"md\",\n isActive = false,\n className,\n ...props\n}: useRender.ComponentProps<\"a\"> &\n React.ComponentProps<\"a\"> & {\n size?: \"sm\" | \"md\"\n isActive?: boolean\n }) {\n return useRender({\n defaultTagName: \"a\",\n props: mergeProps<\"a\">(\n {\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 data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground h-7 gap-2 rounded-md px-2 focus-visible:ring-2 data-[size=md]:text-xs data-[size=sm]:text-xs [&>svg]:size-4 flex min-w-0 -translate-x-px items-center overflow-hidden outline-hidden group-data-[collapsible=icon]:hidden disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:shrink-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-menu-sub-button\",\n sidebar: \"menu-sub-button\",\n size,\n active: isActive,\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 \"@/lib/utils\"\n\nfunction Skeleton({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"skeleton\"\n className={cn(\"bg-muted rounded-md animate-pulse\", className)}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n","\"use client\"\n\nimport { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction TooltipProvider({\n delay = 0,\n ...props\n}: TooltipPrimitive.Provider.Props) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delay={delay}\n {...props}\n />\n )\n}\n\nfunction Tooltip({ ...props }: TooltipPrimitive.Root.Props) {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n )\n}\n\nfunction TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />\n}\n\nfunction TooltipContent({\n className,\n side = \"top\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 0,\n children,\n ...props\n}: TooltipPrimitive.Popup.Props &\n Pick<\n TooltipPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <TooltipPrimitive.Popup\n data-slot=\"tooltip-content\"\n className={cn(\n \"data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-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 rounded-md px-3 py-1.5 text-xs **:data-[slot=kbd]:rounded-md bg-foreground text-background z-50 w-fit max-w-xs origin-(--transform-origin)\",\n className\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground z-50 data-[side=bottom]:top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5\" />\n </TooltipPrimitive.Popup>\n </TooltipPrimitive.Positioner>\n </TooltipPrimitive.Portal>\n )\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Slider as SliderPrimitive } from \"@base-ui/react/slider\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Slider({\n className,\n defaultValue,\n value,\n min = 0,\n max = 100,\n ...props\n}: SliderPrimitive.Root.Props) {\n const _values = React.useMemo(\n () =>\n Array.isArray(value)\n ? value\n : Array.isArray(defaultValue)\n ? defaultValue\n : [min, max],\n [value, defaultValue, min, max]\n )\n\n return (\n <SliderPrimitive.Root\n className=\"data-horizontal:w-full data-vertical:h-full\"\n data-slot=\"slider\"\n defaultValue={defaultValue}\n value={value}\n min={min}\n max={max}\n thumbAlignment=\"edge\"\n {...props}\n >\n <SliderPrimitive.Control\n className={cn(\n \"data-vertical:min-h-40 relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-vertical:h-full data-vertical:w-auto data-vertical:flex-col\",\n className\n )}\n >\n <SliderPrimitive.Track\n data-slot=\"slider-track\"\n className=\"bg-muted rounded-md data-horizontal:h-3 data-horizontal:w-full data-vertical:h-full data-vertical:w-3 relative overflow-hidden select-none\"\n >\n <SliderPrimitive.Indicator\n data-slot=\"slider-range\"\n className=\"bg-primary select-none data-horizontal:h-full data-vertical:w-full\"\n />\n </SliderPrimitive.Track>\n {Array.from({ length: _values.length }, (_, index) => (\n <SliderPrimitive.Thumb\n data-slot=\"slider-thumb\"\n key={index}\n className=\"border-primary ring-ring/30 size-4 rounded-md border bg-white shadow-sm transition-colors hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden block shrink-0 select-none disabled:pointer-events-none disabled:opacity-50\"\n />\n ))}\n </SliderPrimitive.Control>\n </SliderPrimitive.Root>\n )\n}\n\nexport { Slider }\n","\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, type ToasterProps } from \"sonner\"\nimport { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from \"lucide-react\"\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 icons={{\n success: (\n <CircleCheckIcon className=\"size-4\" />\n ),\n info: (\n <InfoIcon className=\"size-4\" />\n ),\n warning: (\n <TriangleAlertIcon className=\"size-4\" />\n ),\n error: (\n <OctagonXIcon className=\"size-4\" />\n ),\n loading: (\n <Loader2Icon className=\"size-4 animate-spin\" />\n ),\n }}\n style={\n {\n \"--normal-bg\": \"var(--popover)\",\n \"--normal-text\": \"var(--popover-foreground)\",\n \"--normal-border\": \"var(--border)\",\n \"--border-radius\": \"var(--radius)\",\n } as React.CSSProperties\n }\n toastOptions={{\n classNames: {\n toast: \"cn-toast\",\n },\n }}\n {...props}\n />\n )\n}\n\nexport { Toaster }\n","\"use client\"\n\nimport { Switch as SwitchPrimitive } from \"@base-ui/react/switch\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Switch({\n className,\n size = \"default\",\n children,\n ...props\n}: SwitchPrimitive.Root.Props & {\n size?: \"sm\" | \"default\"\n}) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-size={size}\n className={cn(\n \"data-checked:bg-primary data-unchecked:bg-input focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 dark:data-unchecked:bg-input/80 shrink-0 rounded-full border border-transparent focus-visible:ring-[2px] aria-invalid:ring-[2px] data-[size=default]:h-[16.6px] data-[size=default]:w-[28px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] peer group/switch relative inline-flex items-center transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n \"bg-background dark:data-unchecked:bg-foreground dark:data-checked:bg-primary-foreground rounded-full group-data-[size=default]/switch:size-3.5 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 pointer-events-none block ring-0 transition-transform\",\n children && \"flex items-center justify-center\"\n )}\n >\n {children}\n </SwitchPrimitive.Thumb>\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\n","\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Table({ className, ...props }: React.ComponentProps<\"table\">) {\n return (\n <div data-slot=\"table-container\" className=\"relative w-full overflow-x-auto\">\n <table\n data-slot=\"table\"\n className={cn(\"w-full caption-bottom text-xs\", className)}\n {...props}\n />\n </div>\n )\n}\n\nfunction TableHeader({ className, ...props }: React.ComponentProps<\"thead\">) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\"[&_tr]:border-b\", className)}\n {...props}\n />\n )\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<\"tbody\">) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<\"tfoot\">) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn(\"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<\"tr\">) {\n return (\n <tr\n data-slot=\"table-row\"\n className={cn(\"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors\", className)}\n {...props}\n />\n )\n}\n\nfunction TableHead({ className, ...props }: React.ComponentProps<\"th\">) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\"text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableCell({ className, ...props }: React.ComponentProps<\"td\">) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableCaption({\n className,\n ...props\n}: React.ComponentProps<\"caption\">) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn(\"text-muted-foreground mt-4 text-xs\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n","\"use client\"\n\nimport { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Tabs({\n className,\n orientation = \"horizontal\",\n ...props\n}: TabsPrimitive.Root.Props) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n data-orientation={orientation}\n className={cn(\n \"gap-2 group/tabs flex data-[orientation=horizontal]:flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst tabsListVariants = cva(\n \"rounded-lg p-[3px] group-data-horizontal/tabs:h-8 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col\",\n {\n variants: {\n variant: {\n default: \"bg-muted\",\n line: \"gap-1 bg-transparent\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction TabsList({\n className,\n variant = \"default\",\n ...props\n}: TabsPrimitive.List.Props & VariantProps<typeof tabsListVariants>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n data-variant={variant}\n className={cn(tabsListVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"tabs-trigger\"\n className={cn(\n \"gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-xs font-medium group-data-vertical/tabs:py-[calc(--spacing(1.25))] [&_svg:not([class*='size-'])]:size-3.5 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent\",\n \"data-active:bg-background dark:data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 data-active:text-foreground\",\n \"after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {\n return (\n <TabsPrimitive.Panel\n data-slot=\"tabs-content\"\n className={cn(\"text-xs/relaxed flex-1 outline-none\", className)}\n {...props}\n />\n )\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }\n","\"use client\"\n\nimport { Toggle as TogglePrimitive } from \"@base-ui/react/toggle\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst toggleVariants = cva(\n \"hover:text-foreground aria-pressed:bg-muted focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[state=on]:bg-muted gap-1 rounded-md text-xs font-medium transition-all [&_svg:not([class*='size-'])]:size-3.5 group/toggle hover:bg-muted inline-flex items-center justify-center whitespace-nowrap outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n outline: \"border-input hover:bg-muted border bg-transparent\",\n },\n size: {\n default: \"h-7 min-w-7 px-2\",\n sm: \"h-6 min-w-6 rounded-[min(var(--radius-md),8px)] px-1.5 text-[0.625rem] [&_svg:not([class*='size-'])]:size-3\",\n lg: \"h-8 min-w-8 px-2\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Toggle({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {\n return (\n <TogglePrimitive\n data-slot=\"toggle\"\n className={cn(toggleVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\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 * as React from \"react\";\nimport { getI18nLink } from \"../../i18n\";\nimport { cn } from \"../../utils/cn\";\n\n// Create our custom Link props interface\n// Note: We use 'any' for now since the actual Link is retrieved at runtime\nexport interface LinkProps {\n href: string;\n children: React.ReactNode;\n className?: string;\n [key: string]: any;\n}\n\nconst Link = React.forwardRef<HTMLAnchorElement, LinkProps>(({ className, href, children, ...props }, ref) => {\n // Get the configured next-intl Link component at runtime (after i18n is configured)\n const NextIntlLink = getI18nLink();\n return (\n <NextIntlLink prefetch={false} ref={ref} href={href} className={cn(`font-medium`, className)} {...props}>\n {children}\n </NextIntlLink>\n );\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 { cn } from \"../../utils/cn\";\nimport { Badge } from \"../ui/badge\";\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\";\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>, 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 * 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 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\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 </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\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\n key=\"all\"\n onSelect={toggleAll}\n className=\"cursor-pointer hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\n >\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 hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\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 hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\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/data/company.interface\";\nimport { RoleInterface } from \"../../../role\";\nimport { RoleService } from \"../../../role/data/role.service\";\nimport { S3Interface } from \"../../../s3\";\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>{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 { FormFieldWrapper } from \"../../../../components/forms\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever, useDebounce } from \"../../../../hooks\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\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 <FormFieldWrapper form={form} name={id} label={label} isRequired={isRequired}>\n {() => (\n <MultiSelect\n options={userOptions}\n onValueChange={handleValueChange}\n defaultValue={selectedUserIds}\n placeholder={placeholder}\n maxCount={maxCount}\n animation={0}\n />\n )}\n </FormFieldWrapper>\n </div>\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>\n <Button render={<div />} nativeButton={false} 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","\"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","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>\n {isEdit ? (\n <Button render={<div />} nativeButton={false} size=\"sm\" variant={`ghost`} className=\"text-muted-foreground\">\n <PencilIcon />\n </Button>\n ) : (\n <Button render={<div />} nativeButton={false} 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>{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 if (!value) return;\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 if (!value) return;\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>\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\";\n\nexport type { DropzoneOptions } 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 { ReactNode } from \"react\";\nimport {\n Controller,\n ControllerFieldState,\n ControllerRenderProps,\n FieldValues,\n Path,\n UseFormReturn,\n} from \"react-hook-form\";\nimport { Field, FieldDescription, FieldError, FieldLabel } from \"../../shadcnui\";\n\ntype FormFieldWrapperProps<T extends FieldValues> = {\n form: UseFormReturn<T>;\n name: Path<T>;\n label?: string;\n description?: string;\n isRequired?: boolean;\n orientation?: \"vertical\" | \"horizontal\" | \"responsive\";\n children: (field: ControllerRenderProps<T, Path<T>>, fieldState: ControllerFieldState) => ReactNode;\n testId?: string;\n};\n\nexport function FormFieldWrapper<T extends FieldValues>({\n form,\n name,\n label,\n description,\n isRequired,\n orientation = \"vertical\",\n children,\n testId,\n}: FormFieldWrapperProps<T>) {\n return (\n <Controller\n control={form.control}\n name={name}\n render={({ field, fieldState }) => (\n <Field orientation={orientation} data-invalid={!!fieldState.error} data-testid={testId}>\n {label && (\n <FieldLabel>\n {label}\n {isRequired && <span className=\"text-destructive ml-1 font-semibold\">*</span>}\n </FieldLabel>\n )}\n {children(field, fieldState)}\n {description && <FieldDescription>{description}</FieldDescription>}\n {fieldState.error && <FieldError>{fieldState.error.message}</FieldError>}\n </Field>\n )}\n />\n );\n}\n","\"use client\";\n\nimport {\n Checkbox,\n FieldLabel,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FieldLabel htmlFor={id} className={`font-normal ${labelBefore ? \"\" : \"ml-3\"}`}>\n {name}\n </FieldLabel>\n );\n };\n\n const label = () => {\n if (!description) return simpleLabel();\n else\n return (\n <Tooltip>\n <TooltipTrigger>{simpleLabel()}</TooltipTrigger>\n <TooltipContent>{description}</TooltipContent>\n </Tooltip>\n );\n };\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormFieldWrapper\n form={form}\n name={id}\n orientation=\"horizontal\"\n >\n {(field) => (\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 )}\n </FormFieldWrapper>\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 InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupInput,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n isRequired={isRequired}\n >\n {(field) => (\n <Popover open={open} onOpenChange={setOpen} modal={true}>\n <InputGroup>\n <InputGroupInput\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value, field)}\n placeholder={datePlaceholder}\n />\n <InputGroupAddon align=\"inline-end\">\n <PopoverTrigger render={<div />} nativeButton={false}>\n <InputGroupButton variant=\"ghost\" size=\"icon-xs\">\n <CalendarIcon className=\"h-4 w-4 opacity-50\" />\n </InputGroupButton>\n </PopoverTrigger>\n {field.value && (\n <InputGroupButton\n variant=\"ghost\"\n size=\"icon-xs\"\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 </InputGroupButton>\n )}\n </InputGroupAddon>\n </InputGroup>\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 if (!value) return;\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 if (!value) return;\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 )}\n </FormFieldWrapper>\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 Label,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n >\n {(field) => (\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\n render={\n <Button\n variant={\"outline\"}\n className={cn(\"w-full pl-3 text-left font-normal\", !field.value && \"text-muted-foreground\")}\n />\n }\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 </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 if (!value) return;\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 />\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 if (!value) return;\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 />\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 )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport React from \"react\";\nimport {\n Input,\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n InputGroupText,\n} from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n isRequired={isRequired}\n >\n {(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 const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\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 const inputProps = {\n ...field,\n autoFocus: autoFocus === true,\n type:\n type === \"number\" || type === \"currency\"\n ? \"number\"\n : type === \"password\"\n ? \"password\"\n : \"text\",\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,\n onChange: handleChange,\n \"data-testid\": testId,\n };\n\n // Use InputGroup for currency type to show Euro symbol\n if (type === \"currency\") {\n return (\n <InputGroup>\n <InputGroupAddon>\n <InputGroupText>{\"\\u20AC\"}</InputGroupText>\n </InputGroupAddon>\n <InputGroupInput {...inputProps} />\n </InputGroup>\n );\n }\n\n // Regular input for other types\n return <Input {...inputProps} />;\n }}\n </FormFieldWrapper>\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 { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n isRequired={isRequired}\n testId={testId}\n >\n {(field) => (\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 )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { Input } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper form={form} name={id} label={name} isRequired={isRequired}>\n {(field) => (\n <Input\n {...field}\n placeholder={placeholder}\n disabled={disabled}\n data-testid={testId}\n className={cn(\"w-full\", className)}\n />\n )}\n </FormFieldWrapper>\n </div>\n );\n }\n\n return (\n <div className=\"flex w-full flex-col\" ref={containerRef}>\n <FormFieldWrapper form={form} name={id} label={name} isRequired={isRequired}>\n {(field) => (\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 )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n orientation={useRows ? \"horizontal\" : \"vertical\"}\n testId={testId}\n >\n {(field) => (\n <Select\n onValueChange={(e) => {\n field.onChange(e);\n if (onChange) onChange(e);\n }}\n value={field.value}\n disabled={disabled}\n data-testid={testId}\n >\n <SelectTrigger className=\"w-full\">\n <SelectValue />\n </SelectTrigger>\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 )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport { useWatch } from \"react-hook-form\";\nimport { Slider } from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n >\n {() => (\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={(val) => {\n const newValue = Array.isArray(val) ? val[0] : val;\n form.setValue(id, newValue);\n }}\n value={[value]}\n max={100}\n step={5}\n disabled={disabled === true || form.formState.isSubmitting}\n />\n </div>\n )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport { FieldLabel, Switch } from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n orientation=\"horizontal\"\n >\n {(field) => (\n <div className=\"flex flex-row gap-x-4\">\n <Switch checked={field.value} onCheckedChange={field.onChange} disabled={disabled} />\n {name && <FieldLabel>{name}</FieldLabel>}\n </div>\n )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport { Textarea } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper form={form} name={id} label={name} testId={testId}>\n {(field) => (\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 )}\n </FormFieldWrapper>\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 { Checkbox, Label, ScrollArea } from \"../../../../shadcnui\";\nimport { FeatureInterface } from \"../../data\";\n\ntype FormFeaturesProps = {\n form: any;\n name?: string;\n features: FeatureInterface[];\n featureField?: string;\n};\n\nexport function FormFeatures({ form, name, features, featureField = \"featureIds\" }: FormFeaturesProps) {\n const selectedFeatures: string[] = form.watch(featureField);\n\n const toggleFeature = (feature: FeatureInterface, checked: boolean) => {\n let newFeatureIds = [...selectedFeatures];\n\n if (checked) {\n if (!newFeatureIds.includes(feature.id)) {\n newFeatureIds.push(feature.id);\n }\n } else {\n newFeatureIds = newFeatureIds.filter((id) => id !== feature.id);\n }\n form.setValue(featureField, newFeatureIds);\n };\n\n const isFeatureChecked = (feature: FeatureInterface) => selectedFeatures.includes(feature.id);\n\n return (\n <div className=\"flex w-full flex-col\">\n {name && <h2 className=\"mb-4 border-b text-lg font-semibold\">{name}</h2>}\n <ScrollArea className=\"h-[40vh]\">\n <div className=\"flex flex-col gap-y-2 pr-4\">\n {features\n .filter((feature) => !feature.isCore)\n .map((feature) => (\n <div key={feature.id} className=\"flex items-center\">\n <Checkbox\n id={feature.id}\n checked={isFeatureChecked(feature)}\n onCheckedChange={(val) => {\n toggleFeature(feature, val === true);\n }}\n />\n <Label htmlFor={feature.id} className=\"ml-3 cursor-pointer font-normal\">\n {feature.name}\n </Label>\n </div>\n ))}\n </div>\n </ScrollArea>\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>\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>\n <DialogTrigger>\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 { FormFieldWrapper } from \"../../../../components/forms\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n Command,\n CommandItem,\n CommandList,\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 <FormFieldWrapper\n form={form}\n name={id}\n label={label}\n isRequired={isRequired}\n >\n {(field) => (\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\n className=\"cursor-pointer hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\n key={user.id}\n onSelect={() => setUser(user)}\n >\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 )}\n </FormFieldWrapper>\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 showTooltip?: boolean;\n};\n\nexport function UserAvatar({ user, className, showFull, showLink, showTooltip = true }: 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 const content =\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: React.MouseEvent<HTMLAnchorElement>) => 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\n if (!showTooltip) {\n return content;\n }\n\n return (\n <Tooltip>\n <TooltipTrigger>{content}</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 module={Modules.User} 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/data/company.interface\";\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: React.MouseEvent<HTMLAnchorElement>) => 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: React.MouseEvent<HTMLAnchorElement>) => 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 hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\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 { Modules } from \"../../../../\";\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 module={Modules.Company} 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 { Battery, BatteryFull, BatteryLow, BatteryMedium, PlusCircle } from \"lucide-react\";\nimport Link from \"next/link\";\n\nimport { cn } from \"@/lib/utils\";\nimport { useTranslations } from \"next-intl\";\nimport { Button, Separator, Tooltip, TooltipContent, TooltipTrigger } from \"../../../../shadcnui\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\n\ninterface TokenStatusIndicatorProps {\n className?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n showExtraPages?: boolean;\n}\n\n/**\n * TokenStatusIndicator displays the current status of available monthly and extra pages\n * using battery icons to represent the percentage of monthly pages remaining.\n *\n * Battery levels:\n * - BatteryFull: >75% available\n * - BatteryMedium: 25-75% available\n * - BatteryLow: 5-25% available\n * - Battery (empty): <5% available\n */\nexport function TokenStatusIndicator({ className, size = \"md\", showExtraPages = true }: TokenStatusIndicatorProps) {\n const { company } = useCurrentUserContext();\n const t = useTranslations();\n\n // Don't render if no company data\n if (!company) return null;\n\n const monthlyTokens = company.monthlyTokens;\n const availableMonthlyTokens = company.availableMonthlyTokens;\n const availableExtraTokens = company.availableExtraTokens;\n\n // Calculate percentage of available monthly pages\n const percentage = monthlyTokens > 0 ? (availableMonthlyTokens / monthlyTokens) * 100 : 0;\n\n const sizeClasses = {\n sm: \"h-4 w-4\",\n md: \"h-5 w-5\",\n lg: \"h-6 w-6\",\n };\n\n const smallIconSizeClasses = {\n sm: \"h-3 w-3\",\n md: \"h-4 w-4\",\n lg: \"h-5 w-5\",\n };\n\n const textSizeClasses = {\n sm: \"text-xs\",\n md: \"text-sm\",\n lg: \"text-base\",\n };\n\n const iconSize = sizeClasses[size];\n const smallIconSize = smallIconSizeClasses[size];\n const textSize = textSizeClasses[size];\n\n const getBatteryIcon = () => {\n if (percentage > 75) {\n return <BatteryFull className={cn(iconSize, \"text-green-500\")} />;\n } else if (percentage >= 25) {\n return <BatteryMedium className={cn(iconSize, \"text-yellow-500\")} />;\n } else if (percentage >= 5) {\n return <BatteryLow className={cn(iconSize, \"text-orange-500\")} />;\n } else {\n return <Battery className={cn(iconSize, \"text-destructive\")} />;\n }\n };\n\n const getStatusColor = () => {\n if (percentage > 75) {\n return \"text-green-500\";\n } else if (percentage >= 25) {\n return \"text-yellow-500\";\n } else if (percentage >= 5) {\n return \"text-orange-500\";\n } else {\n return \"text-destructive\";\n }\n };\n\n const tooltipContent = (\n <div className=\"flex flex-col gap-2 p-1\">\n <div className=\"font-semibold text-sm\">{t(\"generic.tokens.status\", { defaultValue: \"Page Status\" })}</div>\n <div className=\"flex flex-col gap-1 text-xs\">\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-muted-foreground\">\n {t(\"generic.tokens.monthly\", { defaultValue: \"Monthly Pages\" })}:\n </span>\n <span className={cn(\"font-medium\", getStatusColor())}>\n {availableMonthlyTokens} / {monthlyTokens}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-muted-foreground\">{t(\"generic.tokens.available\", { defaultValue: \"Available\" })}:</span>\n <span className={cn(\"font-medium\", getStatusColor())}>{percentage.toFixed(0)}%</span>\n </div>\n <Link href=\"/settings/billing?action=subscribe\" className=\"w-full flex justify-end my-4\">\n <Button variant=\"outline\" size=\"sm\">\n {t(\"generic.tokens.upgrade_plan\", { defaultValue: \"Upgrade plan\" })}\n </Button>\n </Link>\n <Separator />\n <div className=\"flex items-center justify-between gap-4 pt-1 mt-1\">\n <span className=\"text-muted-foreground\">\n {t(\"generic.tokens.available_extra\", { defaultValue: \"Extra Pages\" })}:\n </span>\n <span className=\"font-medium text-blue-500\">{availableExtraTokens}</span>\n </div>\n <Link href=\"/settings/billing?action=subscribe\" className=\"w-full flex justify-end my-4\">\n <Button variant=\"outline\" size=\"sm\">\n {t(\"generic.tokens.purchase_extra\", { defaultValue: \"Purchase additional analysis\" })}\n </Button>\n </Link>\n </div>\n </div>\n );\n\n return (\n <Tooltip>\n <TooltipTrigger>\n <div\n className={cn(\"inline-flex items-center gap-1.5 cursor-default\", className)}\n aria-label={t(\"generic.tokens.status\", { defaultValue: \"Page Status\" })}\n >\n {getBatteryIcon()}\n <span className={cn(textSize, \"text-muted-foreground font-medium\")}>{availableMonthlyTokens}</span>\n {showExtraPages && availableExtraTokens > 0 && (\n <div className=\"inline-flex items-center gap-0.5\">\n <PlusCircle className={cn(smallIconSize, \"text-blue-500\")} />\n <span className={cn(textSize, \"text-blue-500 font-medium\")}>{availableExtraTokens}</span>\n </div>\n )}\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-xs\">\n {tooltipContent}\n </TooltipContent>\n </Tooltip>\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 { useCurrentUserContext } from \"../../../user/contexts\";\nimport { UserService } from \"../../../user/data/user.service\";\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>\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 { FormFieldWrapper } from \"../../../../components/forms\";\nimport { Checkbox, 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 <FormFieldWrapper\n key={currentField}\n form={form}\n name={currentField}\n label={label}\n description={type === \"checkbox\" ? placeholder : undefined}\n isRequired={isRequired}\n orientation={type === \"checkbox\" ? \"horizontal\" : \"vertical\"}\n >\n {(field) =>\n type === \"checkbox\" ? (\n <Checkbox\n id={currentField}\n checked={field.value}\n onCheckedChange={(checked) => {\n return checked ? field.onChange(true) : field.onChange(false);\n }}\n />\n ) : (\n <Input type={type} placeholder={placeholder} {...field} />\n )\n }\n </FormFieldWrapper>\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>\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 { FeatureService } from \"../../../feature/data/feature.service\";\nimport { S3Interface } from \"../../../s3\";\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.isCore));\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 { 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 // Use actionUrl from notification if available (for notifications without actor relationships)\n if (params.notification.actionUrl) {\n response.url = params.notification.actionUrl;\n }\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 message: notification.message ?? \"\",\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 message: notification.message ?? \"\",\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","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 { ModuleWithPermissions } from \"../../permissions\";\nimport { cn } from \"../../utils\";\n\ntype TitleProps = {\n type?: string | string[];\n element?: string;\n functions?: ReactNode;\n className?: string;\n module?: ModuleWithPermissions;\n};\n\nexport function ContentTitle({ module, 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 items-center justify-between gap-x-4 w-full`, className)}>\n <div className=\"flex flex-col w-full\">\n {type && (\n <div className={`text-muted-foreground text-xl font-light flex gap-x-2 items-center`}>\n {module && module.icon && <module.icon className=\"w-5 h-5 inline-block\" />}\n {type}\n </div>\n )}\n <div className={`text-primary w-full text-3xl font-semibold`}>{element}</div>\n </div>\n {isClient && clientFunctions && <div className=\"flex flex-row items-center justify-start\">{clientFunctions}</div>}\n </div>\n );\n}\n","\"use client\";\n\nimport { getRoleId } from \"@/roles\";\nimport { RefreshCwIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useSharedContext } from \"../../contexts/SharedContext\";\nimport { TokenStatusIndicator } from \"../../features/company/components/details\";\nimport { useCurrentUserContext } from \"../../features/user/contexts\";\nimport { Button, SidebarTrigger, Tooltip, TooltipContent, TooltipTrigger } from \"../../shadcnui\";\nimport { BreadcrumbNavigation } from \"./Breadcrumb\";\n\ntype HeaderProps = {\n children?: React.ReactNode;\n};\n\nexport function Header({ children }: HeaderProps) {\n const t = useTranslations();\n const { breadcrumbs } = useSharedContext();\n const { company, hasRole, refreshUser, isRefreshing } = useCurrentUserContext();\n const showTokenStatus = !hasRole(getRoleId().Administrator) && company;\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 <div className=\"flex flex-row items-center justify-end gap-x-4 whitespace-nowrap\">\n {showTokenStatus && (\n <div className=\"flex items-center gap-x-2\">\n <TokenStatusIndicator size=\"sm\" showExtraPages={true} />\n <Tooltip>\n <TooltipTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={() => refreshUser()}\n disabled={isRefreshing}\n aria-label={t(\"generic.refresh\", { defaultValue: \"Refresh\" })}\n />\n }\n >\n <RefreshCwIcon className={`h-3.5 w-3.5 ${isRefreshing ? \"animate-spin\" : \"\"}`} />\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">{t(\"generic.refresh\", { defaultValue: \"Refresh\" })}</TooltipContent>\n </Tooltip>\n </div>\n )}\n {children ? children : null}\n </div>\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>\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}`}>\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 { useHeaderChildren } from \"../../contexts/HeaderChildrenContext\";\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 const headerChildren = useHeaderChildren();\n\n return (\n <div className={`flex h-full w-full flex-col`} data-testid={testId}>\n <Header>{headerChildren}</Header>\n <main className={cn(`flex w-full flex-1 flex-col gap-y-4 pt-4 pl-4 pr-4 pb-20`, 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 { 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, useEffect, useState } from \"react\";\nimport { ResizableHandle, ResizablePanel, ResizablePanelGroup } from \"../../shadcnui\";\nimport { useIsMobile } from \"../../utils\";\n\ntype PageContentContainerProps = {\n header?: ReactNode;\n details?: ReactNode;\n footer?: ReactNode;\n content?: ReactNode;\n};\n\nexport function PageContentContainer({ header, details, footer, content }: PageContentContainerProps) {\n const [mounted, setMounted] = useState(false);\n const isMobile = useIsMobile();\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const isReady = mounted && isMobile !== undefined;\n\n if (!isReady) {\n return <div className=\"flex h-[calc(100vh-4rem)] w-full flex-col\" />;\n }\n\n return (\n <div className=\"flex h-[calc(100vh-4rem)] w-full flex-col transition-opacity duration-150 animate-in fade-in\">\n {header && <div className=\"mb-4 flex w-full shrink-0 border-b\">{header}</div>}\n <div className=\"min-h-0 flex-1\">\n {details || footer ? (\n <ResizablePanelGroup\n autoSaveId={`page-content-container-${isMobile ? \"mobile\" : \"desktop\"}`}\n direction={isMobile ? \"vertical\" : \"horizontal\"}\n className=\"h-full items-stretch\"\n >\n <ResizablePanel\n id=\"left-panel\"\n defaultSize={isMobile ? 10 : 32}\n minSize={isMobile ? 10 : 20}\n maxSize={isMobile ? 90 : 40}\n >\n <div className={`@container flex h-full flex-col ${isMobile ? \"pb-4\" : \"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={isMobile ? \"pt-4\" : \"pl-4\"}>\n <div className=\"h-full overflow-y-auto\">{content}</div>\n </ResizablePanel>\n </ResizablePanelGroup>\n ) : (\n <div className=\"h-full overflow-y-auto\">{content}</div>\n )}\n </div>\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 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 { useMemo } from \"react\";\nimport { useCurrentUserContext } from \"../../user/contexts/CurrentUserContext\";\n\nexport interface TrialSubscriptionStatus {\n status: \"loading\" | \"trial\" | \"active\" | \"expired\";\n trialEndsAt: Date | null;\n daysRemaining: number;\n isGracePeriod: boolean; // Last 3 days\n isBlocked: boolean;\n}\n\nconst TRIAL_DAYS = 14;\nconst GRACE_DAYS = 3;\n\nexport function useSubscriptionStatus(): TrialSubscriptionStatus {\n const { company, currentUser } = useCurrentUserContext();\n\n return useMemo(() => {\n // Still loading user data - don't block yet\n if (currentUser === null) {\n return {\n status: \"loading\",\n trialEndsAt: null,\n daysRemaining: 0,\n isGracePeriod: false,\n isBlocked: false,\n };\n }\n\n // No company after loading = blocked\n if (!company) {\n return {\n status: \"expired\",\n trialEndsAt: null,\n daysRemaining: 0,\n isGracePeriod: false,\n isBlocked: true,\n };\n }\n\n // Has active subscription = never blocked\n if (company.isActiveSubscription) {\n return {\n status: \"active\",\n trialEndsAt: null,\n daysRemaining: 0,\n isGracePeriod: false,\n isBlocked: false,\n };\n }\n\n // Calculate trial status from createdAt\n const createdAt = new Date(company.createdAt);\n const trialEndsAt = new Date(createdAt);\n trialEndsAt.setDate(trialEndsAt.getDate() + TRIAL_DAYS);\n\n const now = new Date();\n const msRemaining = trialEndsAt.getTime() - now.getTime();\n const daysRemaining = Math.ceil(msRemaining / (1000 * 60 * 60 * 24));\n\n return {\n status: daysRemaining > 0 ? \"trial\" : \"expired\",\n trialEndsAt,\n daysRemaining: Math.max(0, daysRemaining),\n isGracePeriod: daysRemaining > 0 && daysRemaining <= GRACE_DAYS,\n isBlocked: daysRemaining <= 0,\n };\n }, [company, currentUser]);\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\nimport { useAtom, useSetAtom } from \"jotai\";\nimport { useCallback, useEffect } from \"react\";\nimport {\n addOAuthClientAtom,\n oauthClientsAtom,\n oauthClientsErrorAtom,\n oauthClientsLoadingAtom,\n setNewClientSecretAtom,\n} from \"../atoms/oauth.atoms\";\nimport {\n OAuthClientCreateRequest,\n OAuthClientCreateResponse,\n OAuthClientInterface,\n} from \"../interfaces/oauth.interface\";\nimport { OAuthService } from \"../data/oauth.service\";\n\nexport interface UseOAuthClientsReturn {\n /** List of OAuth clients */\n clients: OAuthClientInterface[];\n /** Whether clients are being loaded */\n isLoading: boolean;\n /** Error from last operation */\n error: Error | null;\n /** Refetch clients from API */\n refetch: () => Promise<void>;\n /** Create a new OAuth client */\n createClient: (data: OAuthClientCreateRequest) => Promise<OAuthClientCreateResponse>;\n}\n\n/**\n * Hook for managing OAuth clients list\n *\n * @example\n * ```tsx\n * const { clients, isLoading, createClient } = useOAuthClients();\n *\n * const handleCreate = async (data) => {\n * const { client, clientSecret } = await createClient(data);\n * // clientSecret is shown only once!\n * };\n * ```\n */\nexport function useOAuthClients(): UseOAuthClientsReturn {\n const [clients, setClients] = useAtom(oauthClientsAtom);\n const [isLoading, setIsLoading] = useAtom(oauthClientsLoadingAtom);\n const [error, setError] = useAtom(oauthClientsErrorAtom);\n const addClient = useSetAtom(addOAuthClientAtom);\n const setNewClientSecret = useSetAtom(setNewClientSecretAtom);\n\n const fetchClients = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n const fetchedClients = await OAuthService.listClients();\n setClients(fetchedClients);\n } catch (err) {\n console.error(\"[useOAuthClients] Failed to fetch clients:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to fetch OAuth clients\"));\n } finally {\n setIsLoading(false);\n }\n }, [setClients, setIsLoading, setError]);\n\n // Fetch clients on mount\n useEffect(() => {\n fetchClients();\n }, [fetchClients]);\n\n const createClient = useCallback(\n async (data: OAuthClientCreateRequest): Promise<OAuthClientCreateResponse> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await OAuthService.createClient(data);\n\n // Add to local state\n addClient(result.client);\n\n // Store secret for one-time display\n if (result.clientSecret) {\n setNewClientSecret({\n clientId: result.client.clientId,\n secret: result.clientSecret,\n });\n }\n\n return result;\n } catch (err) {\n console.error(\"[useOAuthClients] Failed to create client:\", err);\n const error = err instanceof Error ? err : new Error(\"Failed to create OAuth client\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [addClient, setNewClientSecret, setIsLoading, setError],\n );\n\n return {\n clients,\n isLoading,\n error,\n refetch: fetchClients,\n createClient,\n };\n}\n","import { atom } from \"jotai\";\nimport { atomFamily } from \"jotai-family\";\nimport { OAuthClientInterface } from \"../interfaces/oauth.interface\";\n\n// ==========================================\n// OAUTH CLIENTS STATE\n// ==========================================\n\n/**\n * Primary store for OAuth clients\n * Populated by useOAuthClients hook\n */\nexport const oauthClientsAtom = atom<OAuthClientInterface[]>([]);\n\n/**\n * Loading state for OAuth clients list\n */\nexport const oauthClientsLoadingAtom = atom<boolean>(false);\n\n/**\n * Error state for OAuth client operations\n */\nexport const oauthClientsErrorAtom = atom<Error | null>(null);\n\n/**\n * Derived atom family for getting a single client by ID\n * Usage: const client = useAtomValue(oauthClientByIdAtom(clientId))\n *\n * @param clientId - The client ID (not the internal id, but the clientId field)\n * @returns The client if found, undefined otherwise\n */\nexport const oauthClientByIdAtom = atomFamily((clientId: string) =>\n atom((get) => {\n const clients = get(oauthClientsAtom);\n return clients.find((c) => c.clientId === clientId || c.id === clientId);\n }),\n);\n\n// ==========================================\n// ONE-TIME SECRET DISPLAY STATE\n// ==========================================\n\n/**\n * Stores the client secret for one-time display\n * Set after createClient or regenerateSecret, cleared after user acknowledges\n */\nexport const oauthNewClientSecretAtom = atom<string | null>(null);\n\n/**\n * The client ID associated with the new secret\n * Used to know which client the secret belongs to\n */\nexport const oauthNewClientIdAtom = atom<string | null>(null);\n\n// ==========================================\n// CONSENT FLOW STATE\n// ==========================================\n\n/**\n * Loading state for consent screen data fetch\n */\nexport const oauthConsentLoadingAtom = atom<boolean>(false);\n\n/**\n * Error state for consent flow\n */\nexport const oauthConsentErrorAtom = atom<Error | null>(null);\n\n// ==========================================\n// WRITE ATOMS (for actions)\n// ==========================================\n\n/**\n * Write atom to set a new client secret and associated client ID\n */\nexport const setNewClientSecretAtom = atom(null, (get, set, value: { clientId: string; secret: string } | null) => {\n if (value === null) {\n set(oauthNewClientSecretAtom, null);\n set(oauthNewClientIdAtom, null);\n } else {\n set(oauthNewClientSecretAtom, value.secret);\n set(oauthNewClientIdAtom, value.clientId);\n }\n});\n\n/**\n * Write atom to clear the new client secret (after user acknowledges)\n */\nexport const clearNewClientSecretAtom = atom(null, (get, set) => {\n set(oauthNewClientSecretAtom, null);\n set(oauthNewClientIdAtom, null);\n});\n\n/**\n * Write atom to update the clients list\n */\nexport const setOAuthClientsAtom = atom(null, (get, set, clients: OAuthClientInterface[]) => {\n set(oauthClientsAtom, clients);\n});\n\n/**\n * Write atom to add a client to the list\n */\nexport const addOAuthClientAtom = atom(null, (get, set, client: OAuthClientInterface) => {\n const clients = get(oauthClientsAtom);\n set(oauthClientsAtom, [...clients, client]);\n});\n\n/**\n * Write atom to update a client in the list\n */\nexport const updateOAuthClientAtom = atom(null, (get, set, updatedClient: OAuthClientInterface) => {\n const clients = get(oauthClientsAtom);\n const index = clients.findIndex((c) => c.id === updatedClient.id || c.clientId === updatedClient.clientId);\n if (index !== -1) {\n const newClients = [...clients];\n newClients[index] = updatedClient;\n set(oauthClientsAtom, newClients);\n }\n});\n\n/**\n * Write atom to remove a client from the list\n */\nexport const removeOAuthClientAtom = atom(null, (get, set, clientId: string) => {\n const clients = get(oauthClientsAtom);\n set(\n oauthClientsAtom,\n clients.filter((c) => c.id !== clientId && c.clientId !== clientId),\n );\n});\n","\"use client\";\n\nimport { useAtomValue, useSetAtom } from \"jotai\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport {\n oauthClientByIdAtom,\n removeOAuthClientAtom,\n setNewClientSecretAtom,\n updateOAuthClientAtom,\n} from \"../atoms/oauth.atoms\";\nimport { OAuthClientInput, OAuthClientInterface } from \"../interfaces/oauth.interface\";\nimport { OAuthService } from \"../data/oauth.service\";\n\nexport interface UseOAuthClientReturn {\n /** The OAuth client (from store or fetched) */\n client: OAuthClientInterface | null;\n /** Whether the client is being loaded */\n isLoading: boolean;\n /** Error from last operation */\n error: Error | null;\n /** Update the client */\n update: (data: Partial<OAuthClientInput>) => Promise<void>;\n /** Delete the client */\n deleteClient: () => Promise<void>;\n /** Regenerate the client secret */\n regenerateSecret: () => Promise<string>;\n /** Refetch client from API */\n refetch: () => Promise<void>;\n}\n\n/**\n * Hook for managing a single OAuth client\n *\n * @param clientId - The client ID to manage\n *\n * @example\n * ```tsx\n * const { client, update, deleteClient, regenerateSecret } = useOAuthClient(clientId);\n *\n * const handleRegenerate = async () => {\n * const newSecret = await regenerateSecret();\n * // newSecret is shown only once!\n * };\n * ```\n */\nexport function useOAuthClient(clientId: string): UseOAuthClientReturn {\n // Try to get from store first (populated by useOAuthClients)\n const storedClient = useAtomValue(oauthClientByIdAtom(clientId));\n const updateClientInStore = useSetAtom(updateOAuthClientAtom);\n const removeClientFromStore = useSetAtom(removeOAuthClientAtom);\n const setNewClientSecret = useSetAtom(setNewClientSecretAtom);\n\n // Local state for fetched client (if not in store)\n const [fetchedClient, setFetchedClient] = useState<OAuthClientInterface | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const client = storedClient || fetchedClient;\n\n const fetchClient = useCallback(async () => {\n if (!clientId) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const fetched = await OAuthService.getClient({ clientId });\n setFetchedClient(fetched);\n } catch (err) {\n console.error(\"[useOAuthClient] Failed to fetch client:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to fetch OAuth client\"));\n } finally {\n setIsLoading(false);\n }\n }, [clientId]);\n\n // Fetch if not in store\n useEffect(() => {\n if (!storedClient && clientId) {\n fetchClient();\n }\n }, [storedClient, clientId, fetchClient]);\n\n const update = useCallback(\n async (data: Partial<OAuthClientInput>): Promise<void> => {\n if (!clientId) throw new Error(\"No client ID\");\n\n setIsLoading(true);\n setError(null);\n\n try {\n const updated = await OAuthService.updateClient({ clientId, data });\n updateClientInStore(updated);\n setFetchedClient(updated);\n } catch (err) {\n console.error(\"[useOAuthClient] Failed to update client:\", err);\n const error = err instanceof Error ? err : new Error(\"Failed to update OAuth client\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [clientId, updateClientInStore],\n );\n\n const deleteClient = useCallback(async (): Promise<void> => {\n if (!clientId) throw new Error(\"No client ID\");\n\n setIsLoading(true);\n setError(null);\n\n try {\n await OAuthService.deleteClient({ clientId });\n removeClientFromStore(clientId);\n } catch (err) {\n console.error(\"[useOAuthClient] Failed to delete client:\", err);\n const error = err instanceof Error ? err : new Error(\"Failed to delete OAuth client\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, [clientId, removeClientFromStore]);\n\n const regenerateSecret = useCallback(async (): Promise<string> => {\n if (!clientId) throw new Error(\"No client ID\");\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await OAuthService.regenerateSecret({ clientId });\n\n // Store for one-time display\n setNewClientSecret({\n clientId,\n secret: result.clientSecret,\n });\n\n return result.clientSecret;\n } catch (err) {\n console.error(\"[useOAuthClient] Failed to regenerate secret:\", err);\n const error = err instanceof Error ? err : new Error(\"Failed to regenerate client secret\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, [clientId, setNewClientSecret]);\n\n return {\n client,\n isLoading,\n error,\n update,\n deleteClient,\n regenerateSecret,\n refetch: fetchClient,\n };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { OAuthConsentInfo, OAuthConsentRequest } from \"../interfaces/oauth.interface\";\nimport { OAuthService } from \"../data/oauth.service\";\n\nexport interface UseOAuthConsentReturn {\n /** Client and scope info for consent display */\n clientInfo: OAuthConsentInfo | null;\n /** Whether consent info is being loaded */\n isLoading: boolean;\n /** Error from consent flow */\n error: Error | null;\n /** Approve the authorization request */\n approve: () => Promise<void>;\n /** Deny the authorization request */\n deny: () => Promise<void>;\n /** Whether approve/deny is in progress */\n isSubmitting: boolean;\n}\n\n/**\n * Hook for managing the OAuth consent flow\n *\n * @param params - OAuth authorization parameters from URL\n *\n * @example\n * ```tsx\n * const { clientInfo, isLoading, approve, deny } = useOAuthConsent({\n * clientId: searchParams.client_id,\n * redirectUri: searchParams.redirect_uri,\n * scope: searchParams.scope,\n * state: searchParams.state,\n * });\n *\n * // Render consent screen with clientInfo\n * // On button click: approve() or deny()\n * ```\n */\nexport function useOAuthConsent(params: OAuthConsentRequest): UseOAuthConsentReturn {\n const [clientInfo, setClientInfo] = useState<OAuthConsentInfo | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n // Fetch client info on mount\n useEffect(() => {\n const fetchInfo = async () => {\n if (!params.clientId || !params.redirectUri || !params.scope) {\n setError(new Error(\"Missing required authorization parameters\"));\n setIsLoading(false);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const info = await OAuthService.getAuthorizationInfo(params);\n setClientInfo(info);\n } catch (err) {\n console.error(\"[useOAuthConsent] Failed to fetch authorization info:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to load authorization info\"));\n } finally {\n setIsLoading(false);\n }\n };\n\n fetchInfo();\n }, [\n params.clientId,\n params.redirectUri,\n params.scope,\n params.state,\n params.codeChallenge,\n params.codeChallengeMethod,\n ]);\n\n const approve = useCallback(async (): Promise<void> => {\n setIsSubmitting(true);\n setError(null);\n\n try {\n const result = await OAuthService.approveAuthorization(params);\n\n // Redirect to client with authorization code\n if (result.redirectUrl) {\n window.location.href = result.redirectUrl;\n }\n } catch (err) {\n console.error(\"[useOAuthConsent] Failed to approve authorization:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to approve authorization\"));\n setIsSubmitting(false);\n }\n // Note: Don't set isSubmitting to false on success - we're redirecting\n }, [params]);\n\n const deny = useCallback(async (): Promise<void> => {\n setIsSubmitting(true);\n setError(null);\n\n try {\n const result = await OAuthService.denyAuthorization(params);\n\n // Redirect to client with error\n if (result.redirectUrl) {\n window.location.href = result.redirectUrl;\n }\n } catch (err) {\n console.error(\"[useOAuthConsent] Failed to deny authorization:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to deny authorization\"));\n setIsSubmitting(false);\n }\n // Note: Don't set isSubmitting to false on success - we're redirecting\n }, [params]);\n\n return {\n clientInfo,\n isLoading,\n error,\n approve,\n deny,\n isSubmitting,\n };\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\";\nexport * from \"../features/oauth/hooks\";\nexport * from \"../features/company/hooks/useSubscriptionStatus\";\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 { ChevronLeft, ChevronRight } from \"lucide-react\";\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 <ChevronLeft 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 <ChevronRight 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 { isDiscordAuthEnabled, isInternalAuthEnabled, isRegistrationAllowed } from \"../../../../login\";\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 {isInternalAuthEnabled() && (\n <>\n {isRegistrationAllowed() && (\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 )}\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 {isDiscordAuthEnabled() && (\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 { getApiUrl } from \"../../../../client/config\";\nimport { errorToast, FormInput, FormPassword } from \"../../../../components\";\nimport { useI18nRouter, usePageUrlGenerator } from \"../../../../hooks\";\nimport { isDiscordAuthEnabled, isInternalAuthEnabled } from \"../../../../login\";\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 {isInternalAuthEnabled() && (\n <>\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 </>\n )}\n </CardContent>\n <CardFooter className=\"flex w-full flex-col gap-y-4 mt-4\">\n {isDiscordAuthEnabled() && (\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 <div 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 </div>\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 { useCurrentUserContext } from \"../../../user/contexts\";\nimport { UserService } from \"../../../user/data/user.service\";\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 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>\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>\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 loadNotifications,\n shouldRefresh,\n lastLoaded,\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 // Load notifications from API on mount if never loaded\n useEffect(() => {\n if (lastLoaded === 0) loadNotifications();\n }, [lastLoaded, loadNotifications]);\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 // Refresh notifications from API if cache is stale\n if (shouldRefresh) {\n loadNotifications();\n }\n\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>\n <SidebarMenuButton render={<div />} 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 { FormFieldWrapper } from \"../../../../components/forms\";\nimport {\n Checkbox,\n FieldLabel,\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 <FormFieldWrapper form={form} name={id} label={name}>\n {(field) => (\n <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>\n <FieldLabel className=\"ml-3 font-normal\">\n {t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) })}\n </FieldLabel>\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 )}\n </FormFieldWrapper>\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 hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\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","\"use client\";\n\nimport { useCallback } from \"react\";\nimport { Plus, Trash2 } from \"lucide-react\";\nimport { Button, Input, Label } from \"../../../shadcnui\";\n\nexport interface OAuthRedirectUriInputProps {\n /** Current array of redirect URIs */\n value: string[];\n /** Called when URIs change */\n onChange: (uris: string[]) => void;\n /** Error message to display */\n error?: string;\n /** Whether input is disabled */\n disabled?: boolean;\n /** Label text */\n label?: string;\n}\n\n/**\n * Validates a redirect URI\n * Allows: https://, http://localhost, custom schemes (myapp://)\n */\nfunction isValidRedirectUri(uri: string): boolean {\n if (!uri.trim()) return false;\n\n // Allow localhost for development\n if (uri.startsWith(\"http://localhost\") || uri.startsWith(\"http://127.0.0.1\")) {\n return true;\n }\n\n // Require HTTPS for non-localhost\n if (uri.startsWith(\"https://\")) {\n try {\n new URL(uri);\n return true;\n } catch {\n return false;\n }\n }\n\n // Allow custom schemes (e.g., myapp://oauth/callback)\n if (uri.includes(\"://\")) {\n const schemeMatch = uri.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):\\/\\//);\n return schemeMatch !== null;\n }\n\n return false;\n}\n\n/**\n * Dynamic input for managing OAuth redirect URIs\n *\n * @example\n * ```tsx\n * const [redirectUris, setRedirectUris] = useState<string[]>(['']);\n *\n * <OAuthRedirectUriInput\n * value={redirectUris}\n * onChange={setRedirectUris}\n * error={errors.redirectUris}\n * />\n * ```\n */\nexport function OAuthRedirectUriInput({\n value,\n onChange,\n error,\n disabled = false,\n label = \"Redirect URIs\",\n}: OAuthRedirectUriInputProps) {\n const handleAdd = useCallback(() => {\n onChange([...value, \"\"]);\n }, [value, onChange]);\n\n const handleRemove = useCallback(\n (index: number) => {\n const newUris = value.filter((_, i) => i !== index);\n // Keep at least one empty input\n onChange(newUris.length > 0 ? newUris : [\"\"]);\n },\n [value, onChange]\n );\n\n const handleChange = useCallback(\n (index: number, newValue: string) => {\n const newUris = [...value];\n newUris[index] = newValue;\n onChange(newUris);\n },\n [value, onChange]\n );\n\n return (\n <div className=\"space-y-2\">\n <Label>{label} *</Label>\n <p className=\"text-sm text-muted-foreground\">\n Enter the URIs where users will be redirected after authorization.\n Use https:// for production, or custom schemes for mobile apps.\n </p>\n\n <div className=\"space-y-2\">\n {value.map((uri, index) => {\n const isValid = !uri || isValidRedirectUri(uri);\n\n return (\n <div key={index} className=\"flex gap-2\">\n <div className=\"flex-1\">\n <Input\n value={uri}\n onChange={(e) => handleChange(index, e.target.value)}\n placeholder=\"https://example.com/callback or myapp://oauth\"\n disabled={disabled}\n className={!isValid ? \"border-destructive\" : \"\"}\n />\n {!isValid && (\n <p className=\"text-xs text-destructive mt-1\">\n Must be https://, http://localhost, or a custom scheme (app://)\n </p>\n )}\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => handleRemove(index)}\n disabled={disabled || value.length === 1}\n title=\"Remove URI\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n );\n })}\n </div>\n\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={handleAdd}\n disabled={disabled}\n className=\"mt-2\"\n >\n <Plus className=\"h-4 w-4 mr-2\" />\n Add Redirect URI\n </Button>\n\n {error && <p className=\"text-sm text-destructive\">{error}</p>}\n </div>\n );\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\nimport { Checkbox, Label } from \"../../../shadcnui\";\nimport { AVAILABLE_OAUTH_SCOPES, OAuthScopeInfo } from \"../interfaces/oauth.interface\";\n\nexport interface OAuthScopeSelectorProps {\n /** Currently selected scopes */\n value: string[];\n /** Called when selection changes */\n onChange: (scopes: string[]) => void;\n /** Available scopes to display (defaults to all) */\n availableScopes?: OAuthScopeInfo[];\n /** Whether selector is disabled */\n disabled?: boolean;\n /** Error message */\n error?: string;\n /** Label text */\n label?: string;\n}\n\n/**\n * Checkbox selector for OAuth scopes\n *\n * @example\n * ```tsx\n * const [scopes, setScopes] = useState<string[]>([]);\n *\n * <OAuthScopeSelector\n * value={scopes}\n * onChange={setScopes}\n * error={errors.scopes}\n * />\n * ```\n */\nexport function OAuthScopeSelector({\n value,\n onChange,\n availableScopes = AVAILABLE_OAUTH_SCOPES,\n disabled = false,\n error,\n label = \"Allowed Scopes\",\n}: OAuthScopeSelectorProps) {\n const handleToggle = useCallback(\n (scope: string, checked: boolean) => {\n if (checked) {\n onChange([...value, scope]);\n } else {\n onChange(value.filter((s) => s !== scope));\n }\n },\n [value, onChange]\n );\n\n // Group scopes by category (before the colon)\n const groupedScopes = availableScopes.reduce((acc, scope) => {\n const [category] = scope.scope.split(\":\");\n const groupName = category === scope.scope ? \"General\" : category;\n\n if (!acc[groupName]) {\n acc[groupName] = [];\n }\n acc[groupName].push(scope);\n return acc;\n }, {} as Record<string, OAuthScopeInfo[]>);\n\n return (\n <div className=\"space-y-4\">\n <div>\n <Label>{label} *</Label>\n <p className=\"text-sm text-muted-foreground\">\n Select the permissions your application needs.\n </p>\n </div>\n\n <div className=\"space-y-4\">\n {Object.entries(groupedScopes).map(([groupName, scopes]) => (\n <div key={groupName} className=\"space-y-2\">\n <h4 className=\"text-sm font-medium capitalize\">{groupName}</h4>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-2 pl-2\">\n {scopes.map((scopeInfo) => {\n const isChecked = value.includes(scopeInfo.scope);\n const isAdmin = scopeInfo.scope === \"admin\";\n\n return (\n <div\n key={scopeInfo.scope}\n className={`flex items-start space-x-3 p-2 rounded-md border ${\n isChecked ? \"bg-primary/5 border-primary/20\" : \"border-transparent\"\n } ${isAdmin ? \"bg-destructive/5\" : \"\"}`}\n >\n <Checkbox\n id={`scope-${scopeInfo.scope}`}\n checked={isChecked}\n onCheckedChange={(checked) =>\n handleToggle(scopeInfo.scope, checked === true)\n }\n disabled={disabled}\n />\n <div className=\"flex-1\">\n <Label\n htmlFor={`scope-${scopeInfo.scope}`}\n className=\"text-sm font-medium cursor-pointer\"\n >\n {scopeInfo.name}\n {isAdmin && (\n <span className=\"ml-2 text-xs text-destructive\">(Dangerous)</span>\n )}\n </Label>\n <p className=\"text-xs text-muted-foreground\">{scopeInfo.description}</p>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n\n {error && <p className=\"text-sm text-destructive\">{error}</p>}\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useCallback } from \"react\";\nimport { Copy, Check, AlertTriangle } from \"lucide-react\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Alert,\n AlertDescription,\n Input,\n} from \"../../../shadcnui\";\n\nexport interface OAuthClientSecretDisplayProps {\n /** The client secret to display */\n secret: string;\n /** Called when user dismisses the dialog */\n onDismiss: () => void;\n /** Whether the dialog is open */\n open: boolean;\n /** Optional client name for context */\n clientName?: string;\n}\n\n/**\n * Modal dialog for displaying a client secret ONE TIME\n * Shows warning that secret cannot be retrieved again\n *\n * @example\n * ```tsx\n * const [secret, setSecret] = useAtom(oauthNewClientSecretAtom);\n *\n * <OAuthClientSecretDisplay\n * secret={secret || ''}\n * open={!!secret}\n * onDismiss={() => setSecret(null)}\n * />\n * ```\n */\nexport function OAuthClientSecretDisplay({\n secret,\n onDismiss,\n open,\n clientName,\n}: OAuthClientSecretDisplayProps) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(secret);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n console.error(\"Failed to copy to clipboard:\", err);\n }\n }, [secret]);\n\n const handleDismiss = useCallback(() => {\n setCopied(false);\n onDismiss();\n }, [onDismiss]);\n\n return (\n <Dialog open={open} onOpenChange={(isOpen) => !isOpen && handleDismiss()}>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <AlertTriangle className=\"h-5 w-5 text-warning\" />\n Save Your Client Secret\n </DialogTitle>\n <DialogDescription>\n {clientName\n ? `Your client secret for \"${clientName}\" is shown below.`\n : \"Your client secret is shown below.\"}\n </DialogDescription>\n </DialogHeader>\n\n <Alert variant=\"destructive\" className=\"my-4\">\n <AlertTriangle className=\"h-4 w-4\" />\n <AlertDescription>\n <strong>This is the only time your client secret will be displayed.</strong>\n <br />\n Copy it now and store it securely. You will not be able to retrieve it later.\n </AlertDescription>\n </Alert>\n\n <div className=\"flex items-center space-x-2\">\n <div className=\"flex-1\">\n <Input\n value={secret}\n readOnly\n className=\"font-mono text-sm\"\n onClick={(e) => e.currentTarget.select()}\n />\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon\"\n onClick={handleCopy}\n title={copied ? \"Copied!\" : \"Copy to clipboard\"}\n >\n {copied ? (\n <Check className=\"h-4 w-4 text-green-600\" />\n ) : (\n <Copy className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n\n {copied && (\n <p className=\"text-sm text-green-600 text-center\">Copied to clipboard!</p>\n )}\n\n <DialogFooter className=\"mt-4\">\n <Button onClick={handleDismiss} className=\"w-full\">\n I've Saved My Secret\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","\"use client\";\n\nimport { formatDistanceToNow } from \"date-fns\";\nimport { Key, MoreVertical, Pencil, Trash2 } from \"lucide-react\";\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"../../../shadcnui\";\nimport { OAuthClientInterface } from \"../interfaces/oauth.interface\";\n\nexport interface OAuthClientCardProps {\n /** The OAuth client to display */\n client: OAuthClientInterface;\n /** Called when card is clicked */\n onClick?: () => void;\n /** Called when edit is clicked */\n onEdit?: () => void;\n /** Called when delete is clicked */\n onDelete?: () => void;\n}\n\n/**\n * Card component for displaying an OAuth client in a list\n */\nexport function OAuthClientCard({\n client,\n onClick,\n onEdit,\n onDelete,\n}: OAuthClientCardProps) {\n // Truncate client ID for display\n const truncatedId = client.clientId.length > 12\n ? `${client.clientId.slice(0, 8)}...${client.clientId.slice(-4)}`\n : client.clientId;\n\n const createdAgo = client.createdAt\n ? formatDistanceToNow(new Date(client.createdAt), { addSuffix: true })\n : \"Unknown\";\n\n return (\n <Card\n className={`cursor-pointer transition-colors hover:bg-accent/50 ${!client.isActive ? \"opacity-60\" : \"\"}`}\n onClick={onClick}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-2\">\n <Key className=\"h-5 w-5 text-muted-foreground\" />\n <CardTitle className=\"text-lg\">{client.name}</CardTitle>\n </div>\n <div className=\"flex items-center gap-2\">\n <Badge variant={client.isActive ? \"default\" : \"secondary\"}>\n {client.isActive ? \"Active\" : \"Inactive\"}\n </Badge>\n {(onEdit || onDelete) && (\n <DropdownMenu>\n <DropdownMenuTrigger onClick={(e) => e.stopPropagation()}>\n <Button render={<div />} nativeButton={false} variant=\"ghost\" size=\"icon\" className=\"h-8 w-8\">\n <MoreVertical className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {onEdit && (\n <DropdownMenuItem onClick={(e) => { e.stopPropagation(); onEdit(); }}>\n <Pencil className=\"h-4 w-4 mr-2\" />\n Edit\n </DropdownMenuItem>\n )}\n {onDelete && (\n <DropdownMenuItem\n onClick={(e) => { e.stopPropagation(); onDelete(); }}\n className=\"text-destructive\"\n >\n <Trash2 className=\"h-4 w-4 mr-2\" />\n Delete\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </div>\n </div>\n {client.description && (\n <CardDescription className=\"line-clamp-2\">{client.description}</CardDescription>\n )}\n </CardHeader>\n <CardContent>\n <div className=\"flex flex-wrap gap-x-4 gap-y-1 text-sm text-muted-foreground\">\n <span className=\"font-mono\">{truncatedId}</span>\n <span>Created {createdAgo}</span>\n <span>{client.isConfidential ? \"Confidential\" : \"Public\"}</span>\n </div>\n </CardContent>\n </Card>\n );\n}\n","\"use client\";\n\nimport { Plus, Key } from \"lucide-react\";\nimport { Button, Skeleton } from \"../../../shadcnui\";\nimport { OAuthClientCard } from \"./OAuthClientCard\";\nimport { OAuthClientInterface } from \"../interfaces/oauth.interface\";\n\nexport interface OAuthClientListProps {\n /** List of OAuth clients */\n clients: OAuthClientInterface[];\n /** Whether list is loading */\n isLoading?: boolean;\n /** Error to display */\n error?: Error | null;\n /** Called when a client is clicked */\n onClientClick?: (client: OAuthClientInterface) => void;\n /** Called when create button is clicked */\n onCreateClick?: () => void;\n /** Called when edit is clicked on a client */\n onEditClick?: (client: OAuthClientInterface) => void;\n /** Called when delete is clicked on a client */\n onDeleteClick?: (client: OAuthClientInterface) => void;\n /** Message to show when list is empty */\n emptyStateMessage?: string;\n /** Title for the list */\n title?: string;\n}\n\n/**\n * Component for displaying a list of OAuth clients\n */\nexport function OAuthClientList({\n clients,\n isLoading = false,\n error,\n onClientClick,\n onCreateClick,\n onEditClick,\n onDeleteClick,\n emptyStateMessage = \"No OAuth applications yet. Create one to get started.\",\n title = \"OAuth Applications\",\n}: OAuthClientListProps) {\n // Loading state\n if (isLoading && clients.length === 0) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-2xl font-bold\">{title}</h2>\n <Skeleton className=\"h-10 w-32\" />\n </div>\n <div className=\"space-y-3\">\n {[1, 2, 3].map((i) => (\n <Skeleton key={i} className=\"h-32 w-full\" />\n ))}\n </div>\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-2xl font-bold\">{title}</h2>\n </div>\n <div className=\"rounded-lg border border-destructive/50 bg-destructive/10 p-6 text-center\">\n <p className=\"text-destructive\">{error.message}</p>\n </div>\n </div>\n );\n }\n\n // Empty state\n if (clients.length === 0) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-2xl font-bold\">{title}</h2>\n {onCreateClick && (\n <Button onClick={onCreateClick}>\n <Plus className=\"h-4 w-4 mr-2\" />\n New App\n </Button>\n )}\n </div>\n <div className=\"rounded-lg border border-dashed p-12 text-center\">\n <Key className=\"h-12 w-12 mx-auto text-muted-foreground mb-4\" />\n <h3 className=\"text-lg font-medium mb-2\">No OAuth Applications</h3>\n <p className=\"text-muted-foreground mb-4\">{emptyStateMessage}</p>\n {onCreateClick && (\n <Button onClick={onCreateClick}>\n <Plus className=\"h-4 w-4 mr-2\" />\n Create Application\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n // List view\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-2xl font-bold\">{title}</h2>\n {onCreateClick && (\n <Button onClick={onCreateClick}>\n <Plus className=\"h-4 w-4 mr-2\" />\n New App\n </Button>\n )}\n </div>\n <div className=\"space-y-3\">\n {clients.map((client) => (\n <OAuthClientCard\n key={client.id || client.clientId}\n client={client}\n onClick={() => onClientClick?.(client)}\n onEdit={onEditClick ? () => onEditClick(client) : undefined}\n onDelete={onDeleteClick ? () => onDeleteClick(client) : undefined}\n />\n ))}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useCallback } from \"react\";\nimport {\n Button,\n Input,\n Label,\n Textarea,\n RadioGroup,\n RadioGroupItem,\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"../../../shadcnui\";\nimport { OAuthRedirectUriInput } from \"./OAuthRedirectUriInput\";\nimport { OAuthScopeSelector } from \"./OAuthScopeSelector\";\nimport { OAuthClientCreateRequest, OAuthClientInterface, DEFAULT_GRANT_TYPES } from \"../interfaces/oauth.interface\";\n\nexport interface OAuthClientFormProps {\n /** Existing client for edit mode (undefined = create mode) */\n client?: OAuthClientInterface;\n /** Called on form submit */\n onSubmit: (data: OAuthClientCreateRequest) => Promise<void>;\n /** Called on cancel */\n onCancel: () => void;\n /** Whether form is submitting */\n isLoading?: boolean;\n}\n\ninterface FormState {\n name: string;\n description: string;\n redirectUris: string[];\n allowedScopes: string[];\n isConfidential: boolean;\n}\n\ninterface FormErrors {\n name?: string;\n redirectUris?: string;\n allowedScopes?: string;\n}\n\n/**\n * Form for creating or editing an OAuth client\n */\nexport function OAuthClientForm({\n client,\n onSubmit,\n onCancel,\n isLoading = false,\n}: OAuthClientFormProps) {\n const isEditMode = !!client;\n\n const [formState, setFormState] = useState<FormState>({\n name: client?.name || \"\",\n description: client?.description || \"\",\n redirectUris: client?.redirectUris?.length ? client.redirectUris : [\"\"],\n allowedScopes: client?.allowedScopes || [],\n isConfidential: client?.isConfidential ?? true,\n });\n\n const [errors, setErrors] = useState<FormErrors>({});\n\n const validate = useCallback((): boolean => {\n const newErrors: FormErrors = {};\n\n if (!formState.name.trim()) {\n newErrors.name = \"Application name is required\";\n }\n\n const validUris = formState.redirectUris.filter((uri) => uri.trim());\n if (validUris.length === 0) {\n newErrors.redirectUris = \"At least one redirect URI is required\";\n }\n\n if (formState.allowedScopes.length === 0) {\n newErrors.allowedScopes = \"At least one scope must be selected\";\n }\n\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n }, [formState]);\n\n const handleSubmit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault();\n\n if (!validate()) return;\n\n const data: OAuthClientCreateRequest = {\n name: formState.name.trim(),\n description: formState.description.trim() || undefined,\n redirectUris: formState.redirectUris.filter((uri) => uri.trim()),\n allowedScopes: formState.allowedScopes,\n allowedGrantTypes: DEFAULT_GRANT_TYPES,\n isConfidential: formState.isConfidential,\n };\n\n await onSubmit(data);\n },\n [formState, validate, onSubmit]\n );\n\n return (\n <Card>\n <form onSubmit={handleSubmit}>\n <CardHeader>\n <CardTitle>{isEditMode ? \"Edit Application\" : \"Create OAuth Application\"}</CardTitle>\n <CardDescription>\n {isEditMode\n ? \"Update your OAuth application settings.\"\n : \"Register a new application to access the API.\"}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-6\">\n {/* Name */}\n <div className=\"space-y-2\">\n <Label htmlFor=\"name\">Application Name *</Label>\n <Input\n id=\"name\"\n value={formState.name}\n onChange={(e) => setFormState((s) => ({ ...s, name: e.target.value }))}\n placeholder=\"My Lightroom Plugin\"\n disabled={isLoading}\n className={errors.name ? \"border-destructive\" : \"\"}\n />\n {errors.name && <p className=\"text-sm text-destructive\">{errors.name}</p>}\n </div>\n\n {/* Description */}\n <div className=\"space-y-2\">\n <Label htmlFor=\"description\">Description</Label>\n <Textarea\n id=\"description\"\n value={formState.description}\n onChange={(e) => setFormState((s) => ({ ...s, description: e.target.value }))}\n placeholder=\"A brief description of your application\"\n disabled={isLoading}\n rows={3}\n />\n </div>\n\n {/* Redirect URIs */}\n <OAuthRedirectUriInput\n value={formState.redirectUris}\n onChange={(uris) => setFormState((s) => ({ ...s, redirectUris: uris }))}\n error={errors.redirectUris}\n disabled={isLoading}\n />\n\n {/* Scopes */}\n <OAuthScopeSelector\n value={formState.allowedScopes}\n onChange={(scopes) => setFormState((s) => ({ ...s, allowedScopes: scopes }))}\n error={errors.allowedScopes}\n disabled={isLoading}\n />\n\n {/* Client Type */}\n <div className=\"space-y-3\">\n <Label>Client Type</Label>\n <RadioGroup\n value={formState.isConfidential ? \"confidential\" : \"public\"}\n onValueChange={(v) => setFormState((s) => ({ ...s, isConfidential: v === \"confidential\" }))}\n disabled={isLoading || isEditMode}\n >\n <div className=\"flex items-start space-x-3 p-3 rounded-md border\">\n <RadioGroupItem value=\"confidential\" id=\"confidential\" className=\"mt-1\" />\n <div>\n <Label htmlFor=\"confidential\" className=\"font-medium cursor-pointer\">\n Confidential\n </Label>\n <p className=\"text-sm text-muted-foreground\">\n Server-side application that can securely store the client secret.\n </p>\n </div>\n </div>\n <div className=\"flex items-start space-x-3 p-3 rounded-md border\">\n <RadioGroupItem value=\"public\" id=\"public\" className=\"mt-1\" />\n <div>\n <Label htmlFor=\"public\" className=\"font-medium cursor-pointer\">\n Public\n </Label>\n <p className=\"text-sm text-muted-foreground\">\n Mobile or desktop application. Requires PKCE for authorization.\n </p>\n </div>\n </div>\n </RadioGroup>\n {isEditMode && (\n <p className=\"text-sm text-muted-foreground\">\n Client type cannot be changed after creation.\n </p>\n )}\n </div>\n </CardContent>\n <CardFooter className=\"flex justify-end gap-3\">\n <Button type=\"button\" variant=\"outline\" onClick={onCancel} disabled={isLoading}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={isLoading}>\n {isLoading ? \"Saving...\" : isEditMode ? \"Save Changes\" : \"Create Application\"}\n </Button>\n </CardFooter>\n </form>\n </Card>\n );\n}\n","\"use client\";\n\nimport { useState, useCallback } from \"react\";\nimport { format } from \"date-fns\";\nimport { Copy, Check, RefreshCw, Pencil, Trash2, ExternalLink } from \"lucide-react\";\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Input,\n Label,\n Separator,\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"../../../shadcnui\";\nimport { OAuthClientInterface, OAUTH_SCOPE_DISPLAY } from \"../interfaces/oauth.interface\";\n\nexport interface OAuthClientDetailProps {\n /** The OAuth client to display */\n client: OAuthClientInterface;\n /** Whether data is loading */\n isLoading?: boolean;\n /** Called when edit is clicked */\n onEdit?: () => void;\n /** Called when delete is clicked */\n onDelete?: () => Promise<void>;\n /** Called when regenerate secret is clicked */\n onRegenerateSecret?: () => Promise<void>;\n}\n\n/**\n * Detailed view of an OAuth client\n */\nexport function OAuthClientDetail({\n client,\n isLoading = false,\n onEdit,\n onDelete,\n onRegenerateSecret,\n}: OAuthClientDetailProps) {\n const [copiedField, setCopiedField] = useState<string | null>(null);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [showRegenerateConfirm, setShowRegenerateConfirm] = useState(false);\n const [isDeleting, setIsDeleting] = useState(false);\n const [isRegenerating, setIsRegenerating] = useState(false);\n\n const copyToClipboard = useCallback(async (text: string, field: string) => {\n try {\n await navigator.clipboard.writeText(text);\n setCopiedField(field);\n setTimeout(() => setCopiedField(null), 2000);\n } catch (err) {\n console.error(\"Failed to copy:\", err);\n }\n }, []);\n\n const handleDelete = useCallback(async () => {\n if (!onDelete) return;\n setIsDeleting(true);\n try {\n await onDelete();\n } finally {\n setIsDeleting(false);\n setShowDeleteConfirm(false);\n }\n }, [onDelete]);\n\n const handleRegenerateSecret = useCallback(async () => {\n if (!onRegenerateSecret) return;\n setIsRegenerating(true);\n try {\n await onRegenerateSecret();\n } finally {\n setIsRegenerating(false);\n setShowRegenerateConfirm(false);\n }\n }, [onRegenerateSecret]);\n\n const createdDate = client.createdAt\n ? format(new Date(client.createdAt), \"MMMM d, yyyy\")\n : \"Unknown\";\n\n return (\n <>\n <Card>\n <CardHeader>\n <div className=\"flex items-start justify-between\">\n <div>\n <CardTitle className=\"text-2xl\">{client.name}</CardTitle>\n {client.description && (\n <CardDescription className=\"mt-1\">{client.description}</CardDescription>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n <Badge variant={client.isActive ? \"default\" : \"secondary\"}>\n {client.isActive ? \"Active\" : \"Inactive\"}\n </Badge>\n <Badge variant=\"outline\">\n {client.isConfidential ? \"Confidential\" : \"Public\"}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-6\">\n {/* Client ID */}\n <div className=\"space-y-2\">\n <Label>Client ID</Label>\n <div className=\"flex gap-2\">\n <Input value={client.clientId} readOnly className=\"font-mono\" />\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => copyToClipboard(client.clientId, \"clientId\")}\n title=\"Copy Client ID\"\n >\n {copiedField === \"clientId\" ? (\n <Check className=\"h-4 w-4 text-green-600\" />\n ) : (\n <Copy className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n\n {/* Client Secret */}\n <div className=\"space-y-2\">\n <Label>Client Secret</Label>\n <div className=\"flex gap-2\">\n <Input value=\"••••••••••••••••••••••••••••••••\" readOnly className=\"font-mono\" />\n {onRegenerateSecret && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => setShowRegenerateConfirm(true)}\n title=\"Regenerate Secret\"\n disabled={isLoading}\n >\n <RefreshCw className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n <p className=\"text-xs text-muted-foreground\">\n Regenerating will invalidate the current secret and all existing tokens.\n </p>\n </div>\n\n <Separator />\n\n {/* Redirect URIs */}\n <div className=\"space-y-2\">\n <Label>Redirect URIs</Label>\n <ul className=\"space-y-1\">\n {client.redirectUris.map((uri, index) => (\n <li key={index} className=\"flex items-center gap-2 text-sm font-mono\">\n <ExternalLink className=\"h-3 w-3 text-muted-foreground\" />\n {uri}\n </li>\n ))}\n </ul>\n </div>\n\n {/* Scopes */}\n <div className=\"space-y-2\">\n <Label>Allowed Scopes</Label>\n <div className=\"flex flex-wrap gap-2\">\n {client.allowedScopes.map((scope) => (\n <Badge key={scope} variant=\"secondary\">\n {OAUTH_SCOPE_DISPLAY[scope]?.name || scope}\n </Badge>\n ))}\n </div>\n </div>\n\n {/* Grant Types */}\n <div className=\"space-y-2\">\n <Label>Grant Types</Label>\n <div className=\"flex flex-wrap gap-2\">\n {client.allowedGrantTypes.map((grant) => (\n <Badge key={grant} variant=\"outline\">\n {grant.replace(/_/g, \" \")}\n </Badge>\n ))}\n </div>\n </div>\n\n <Separator />\n\n {/* Metadata */}\n <div className=\"flex flex-wrap gap-x-6 gap-y-2 text-sm text-muted-foreground\">\n <span>Created: {createdDate}</span>\n </div>\n\n {/* Actions */}\n <div className=\"flex gap-3 pt-4\">\n {onEdit && (\n <Button variant=\"outline\" onClick={onEdit} disabled={isLoading}>\n <Pencil className=\"h-4 w-4 mr-2\" />\n Edit\n </Button>\n )}\n {onDelete && (\n <Button\n variant=\"destructive\"\n onClick={() => setShowDeleteConfirm(true)}\n disabled={isLoading}\n >\n <Trash2 className=\"h-4 w-4 mr-2\" />\n Delete\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n\n {/* Delete Confirmation */}\n <AlertDialog open={showDeleteConfirm} onOpenChange={setShowDeleteConfirm}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete OAuth Application?</AlertDialogTitle>\n <AlertDialogDescription>\n This will permanently delete \"{client.name}\" and revoke all access tokens.\n This action cannot be undone.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={isDeleting}>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={handleDelete}\n disabled={isDeleting}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n >\n {isDeleting ? \"Deleting...\" : \"Delete\"}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n\n {/* Regenerate Confirmation */}\n <AlertDialog open={showRegenerateConfirm} onOpenChange={setShowRegenerateConfirm}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Regenerate Client Secret?</AlertDialogTitle>\n <AlertDialogDescription>\n This will generate a new client secret and invalidate the old one.\n All existing tokens will be revoked. You will need to update your application\n with the new secret.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={isRegenerating}>Cancel</AlertDialogCancel>\n <AlertDialogAction onClick={handleRegenerateSecret} disabled={isRegenerating}>\n {isRegenerating ? \"Regenerating...\" : \"Regenerate\"}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </>\n );\n}\n","\"use client\";\n\nimport { Shield } from \"lucide-react\";\nimport { OAuthClientInterface } from \"../../interfaces/oauth.interface\";\n\nexport interface OAuthConsentHeaderProps {\n /** The requesting OAuth client */\n client: OAuthClientInterface;\n /** Optional logo URL override */\n logoUrl?: string;\n /** Application name (e.g., \"Only35\") */\n appName?: string;\n}\n\n/**\n * Header component for OAuth consent screen\n * Shows platform logo and requesting app information\n */\nexport function OAuthConsentHeader({\n client,\n logoUrl,\n appName = \"Only35\",\n}: OAuthConsentHeaderProps) {\n return (\n <div className=\"text-center space-y-4\">\n {/* Platform Logo */}\n <div className=\"flex justify-center\">\n {logoUrl ? (\n <img\n src={logoUrl}\n alt={appName}\n className=\"h-12 w-auto\"\n />\n ) : (\n <div className=\"h-12 w-12 rounded-full bg-primary flex items-center justify-center\">\n <Shield className=\"h-6 w-6 text-primary-foreground\" />\n </div>\n )}\n </div>\n\n {/* Authorization Request */}\n <div className=\"space-y-2\">\n <h1 className=\"text-2xl font-bold\">Authorize {client.name}</h1>\n <p className=\"text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{client.name}</span>\n {\" \"}wants to access your {appName} account\n </p>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n Eye,\n Pencil,\n Image,\n Upload,\n Film,\n FolderPlus,\n User,\n Shield,\n LucideIcon,\n} from \"lucide-react\";\nimport { OAuthScopeInfo } from \"../../interfaces/oauth.interface\";\n\nexport interface OAuthScopeListProps {\n /** List of requested scopes */\n scopes: OAuthScopeInfo[];\n}\n\n/** Map scope icons to Lucide components */\nconst SCOPE_ICONS: Record<string, LucideIcon> = {\n eye: Eye,\n pencil: Pencil,\n image: Image,\n upload: Upload,\n film: Film,\n \"folder-plus\": FolderPlus,\n user: User,\n shield: Shield,\n};\n\n/**\n * List of requested OAuth scopes for consent display\n */\nexport function OAuthScopeList({ scopes }: OAuthScopeListProps) {\n if (scopes.length === 0) {\n return null;\n }\n\n return (\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-medium text-muted-foreground uppercase tracking-wide\">\n This will allow the application to:\n </h2>\n <ul className=\"space-y-3\">\n {scopes.map((scope) => {\n const IconComponent = scope.icon ? SCOPE_ICONS[scope.icon] : Eye;\n\n return (\n <li\n key={scope.scope}\n className=\"flex items-start gap-3 p-3 rounded-lg bg-muted/50\"\n >\n <div className=\"flex-shrink-0 mt-0.5\">\n <div className=\"h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center\">\n {IconComponent && (\n <IconComponent className=\"h-4 w-4 text-primary\" />\n )}\n </div>\n </div>\n <div className=\"flex-1\">\n <p className=\"font-medium\">{scope.name}</p>\n <p className=\"text-sm text-muted-foreground\">{scope.description}</p>\n </div>\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n","\"use client\";\n\nimport { Button } from \"../../../../shadcnui\";\n\nexport interface OAuthConsentActionsProps {\n /** Called when user clicks Authorize */\n onApprove: () => void;\n /** Called when user clicks Deny */\n onDeny: () => void;\n /** Whether an action is in progress */\n isLoading?: boolean;\n}\n\n/**\n * Action buttons for OAuth consent screen\n */\nexport function OAuthConsentActions({\n onApprove,\n onDeny,\n isLoading = false,\n}: OAuthConsentActionsProps) {\n return (\n <div className=\"flex flex-col sm:flex-row gap-3\">\n <Button\n variant=\"outline\"\n onClick={onDeny}\n disabled={isLoading}\n className=\"flex-1\"\n >\n Deny\n </Button>\n <Button\n onClick={onApprove}\n disabled={isLoading}\n className=\"flex-1\"\n >\n {isLoading ? \"Authorizing...\" : \"Authorize\"}\n </Button>\n </div>\n );\n}\n","\"use client\";\n\nimport { ExternalLink, AlertTriangle, Loader2 } from \"lucide-react\";\nimport {\n Card,\n CardContent,\n CardFooter,\n Separator,\n Alert,\n AlertDescription,\n} from \"../../../../shadcnui\";\nimport { OAuthConsentHeader } from \"./OAuthConsentHeader\";\nimport { OAuthScopeList } from \"./OAuthScopeList\";\nimport { OAuthConsentActions } from \"./OAuthConsentActions\";\nimport { useOAuthConsent } from \"../../hooks/useOAuthConsent\";\nimport { OAuthConsentRequest } from \"../../interfaces/oauth.interface\";\n\nexport interface OAuthConsentScreenProps {\n /** OAuth authorization parameters */\n params: OAuthConsentRequest;\n /** Optional platform logo URL */\n logoUrl?: string;\n /** Platform name */\n appName?: string;\n /** Terms of Service URL */\n termsUrl?: string;\n /** Privacy Policy URL */\n privacyUrl?: string;\n}\n\n/**\n * Main OAuth consent screen component\n * Displays client info, requested scopes, and approve/deny buttons\n *\n * @example\n * ```tsx\n * <OAuthConsentScreen\n * params={{\n * clientId: searchParams.client_id,\n * redirectUri: searchParams.redirect_uri,\n * scope: searchParams.scope,\n * state: searchParams.state,\n * }}\n * />\n * ```\n */\nexport function OAuthConsentScreen({\n params,\n logoUrl,\n appName = \"Only35\",\n termsUrl = \"/terms\",\n privacyUrl = \"/privacy\",\n}: OAuthConsentScreenProps) {\n const { clientInfo, isLoading, error, approve, deny, isSubmitting } = useOAuthConsent(params);\n\n // Loading state\n if (isLoading) {\n return (\n <div className=\"min-h-screen flex items-center justify-center p-4\">\n <Card className=\"w-full max-w-md\">\n <CardContent className=\"flex flex-col items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n <p className=\"mt-4 text-muted-foreground\">Loading authorization request...</p>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n // Error state\n if (error || !clientInfo) {\n return (\n <div className=\"min-h-screen flex items-center justify-center p-4\">\n <Card className=\"w-full max-w-md\">\n <CardContent className=\"py-8\">\n <Alert variant=\"destructive\">\n <AlertTriangle className=\"h-4 w-4\" />\n <AlertDescription>\n {error?.message || \"Invalid authorization request. Please try again.\"}\n </AlertDescription>\n </Alert>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n const { client, scopes } = clientInfo;\n\n return (\n <div className=\"min-h-screen flex items-center justify-center p-4 bg-muted/30\">\n <Card className=\"w-full max-w-md\">\n <CardContent className=\"pt-6 space-y-6\">\n {/* Header */}\n <OAuthConsentHeader\n client={client}\n logoUrl={logoUrl}\n appName={appName}\n />\n\n <Separator />\n\n {/* Scopes */}\n <OAuthScopeList scopes={scopes} />\n\n <Separator />\n\n {/* Redirect URI Notice */}\n <div className=\"flex items-start gap-2 text-sm text-muted-foreground\">\n <ExternalLink className=\"h-4 w-4 mt-0.5 flex-shrink-0\" />\n <div>\n <span>Authorizing will redirect you to:</span>\n <p className=\"font-mono text-xs mt-1 break-all\">{params.redirectUri}</p>\n </div>\n </div>\n\n {/* Actions */}\n <OAuthConsentActions\n onApprove={approve}\n onDeny={deny}\n isLoading={isSubmitting}\n />\n </CardContent>\n\n {/* Footer */}\n <CardFooter className=\"justify-center\">\n <p className=\"text-xs text-center text-muted-foreground\">\n By authorizing, you agree to the app's{\" \"}\n <a href={termsUrl} className=\"underline hover:text-foreground\" target=\"_blank\" rel=\"noopener\">\n Terms of Service\n </a>\n {\" \"}and{\" \"}\n <a href={privacyUrl} className=\"underline hover:text-foreground\" target=\"_blank\" rel=\"noopener\">\n Privacy Policy\n </a>\n .\n </p>\n </CardFooter>\n </Card>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/chunk-XU4MY6OG.js","../src/contexts/HeaderChildrenContext.tsx","../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/contexts/SocketContext.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/input-group.tsx","../src/shadcnui/ui/input.tsx","../src/shadcnui/ui/textarea.tsx","../src/shadcnui/ui/context-menu.tsx","../src/shadcnui/ui/drawer.tsx","../src/shadcnui/ui/dropdown-menu.tsx","../src/shadcnui/ui/field.tsx","../src/shadcnui/ui/label.tsx","../src/shadcnui/ui/separator.tsx","../src/shadcnui/ui/form.tsx","../src/shadcnui/ui/hover-card.tsx","../src/shadcnui/ui/input-otp.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/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/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/components/forms/CommonAssociationForm.tsx","../src/components/forms/CommonDeleter.tsx","../src/components/errors/ErrorDetails.tsx","../src/components/errors/errorToast.ts","../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/FormFieldWrapper.tsx","../src/components/forms/FormCheckbox.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/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/details/TokenStatusIndicator.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/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/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/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/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/company/hooks/useSubscriptionStatus.ts","../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/features/oauth/hooks/useOAuthClients.ts","../src/features/oauth/atoms/oauth.atoms.ts","../src/features/oauth/hooks/useOAuthClient.ts","../src/features/oauth/hooks/useOAuthConsent.ts","../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","../src/features/oauth/components/OAuthRedirectUriInput.tsx","../src/features/oauth/components/OAuthScopeSelector.tsx","../src/features/oauth/components/OAuthClientSecretDisplay.tsx","../src/features/oauth/components/OAuthClientCard.tsx","../src/features/oauth/components/OAuthClientList.tsx","../src/features/oauth/components/OAuthClientForm.tsx","../src/features/oauth/components/OAuthClientDetail.tsx","../src/features/oauth/components/consent/OAuthConsentHeader.tsx","../src/features/oauth/components/consent/OAuthScopeList.tsx","../src/features/oauth/components/consent/OAuthConsentActions.tsx","../src/features/oauth/components/consent/OAuthConsentScreen.tsx"],"names":[],"mappings":"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AAAI,MAAA;AAAI,sBAAA;AAGT,MAAA;AAAI,IAAA;AAGR,EAAA;AAIR;AA/FgB;AtMozchB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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-XU4MY6OG.js","sourcesContent":[null,"\"use client\";\n\nimport { createContext, useContext, ReactNode } from \"react\";\n\ninterface HeaderChildrenContextType {\n headerChildren: ReactNode | null;\n}\n\nconst HeaderChildrenContext = createContext<HeaderChildrenContextType>({\n headerChildren: null,\n});\n\ninterface HeaderChildrenProviderProps {\n children: ReactNode;\n content: ReactNode;\n}\n\n/**\n * Provider to supply custom content to be rendered in the Header component.\n * Wrap your layout with this provider and pass the content you want in the header.\n */\nexport function HeaderChildrenProvider({ children, content }: HeaderChildrenProviderProps) {\n return <HeaderChildrenContext.Provider value={{ headerChildren: content }}>{children}</HeaderChildrenContext.Provider>;\n}\n\n/**\n * Hook to get the header children content from context.\n * Used internally by PageContainer to pass children to Header.\n */\nexport function useHeaderChildren(): ReactNode | null {\n const context = useContext(HeaderChildrenContext);\n return context.headerChildren;\n}\n","\"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: {\n page: ModuleWithPermissions | string;\n id?: string;\n childPage?: ModuleWithPermissions | string;\n childId?: string;\n }): void => {\n window.history.replaceState(\n null,\n \"\",\n generateUrl({\n page: params.page,\n id: params.id,\n childPage: params.childPage,\n childId: params.childId,\n language: locale,\n }),\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) return;\n\n // Prevent concurrent fetches (unless it's a pagination call)\n if (isFetchingRef.current && !fetchParams?.callNext && !fetchParams?.callPrevious) return;\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\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\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 if (thisRequestId === requestIdRef.current) {\n setIsLoaded(true);\n console.error(\"Error fetching data:\", error);\n }\n } finally {\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) {\n fetchData({ isRefresh: onlyNewRecords, callNext: true });\n }\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 setData(undefined); // Clear stale data immediately before fetching new data\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 { 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, useCallback, useContext, useEffect, useRef, useState } from \"react\";\nimport { Modules, rehydrate } from \"../../../core\";\nimport { Action, checkPermissions, ModuleWithPermissions } from \"../../../permissions\";\nimport { getRoleId } from \"../../../roles\";\nimport { CompanyInterface } from \"../../company/data/company.interface\";\nimport { FeatureInterface } from \"../../feature\";\nimport { RoleInterface } from \"../../role\";\nimport { UserInterface, UserService } from \"../data\";\nimport { useSocketContext } from \"../../../contexts/SocketContext\";\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 refreshUser: () => Promise<void>;\n isRefreshing: 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 // State for tracking refresh status\n const [isRefreshing, setIsRefreshing] = useState(false);\n\n // Function to refresh user data from the API\n const refreshUser = useCallback(async (): Promise<void> => {\n if (isRefreshing) return;\n\n setIsRefreshing(true);\n try {\n const fullUser = await UserService.findFullUser();\n if (fullUser) {\n setDehydratedUser(fullUser.dehydrate() as any);\n }\n } catch (error) {\n console.error(\"Failed to refresh user data:\", error);\n } finally {\n setIsRefreshing(false);\n }\n }, [isRefreshing, setDehydratedUser]);\n\n // WebSocket integration for real-time token updates\n const { socket, isConnected } = useSocketContext();\n\n // Use ref for stable refreshUser reference to avoid effect re-runs\n const refreshUserRef = useRef(refreshUser);\n refreshUserRef.current = refreshUser;\n\n // Track refresh in progress to prevent duplicate API calls\n const isRefreshingRef = useRef(false);\n\n // Listen for company:tokens_updated WebSocket events\n useEffect(() => {\n if (!socket || !isConnected || !currentUser?.company?.id) return;\n\n const handleTokensUpdated = (data: { companyId: string; type: string }) => {\n if (data.companyId === currentUser.company?.id && !isRefreshingRef.current) {\n isRefreshingRef.current = true;\n refreshUserRef.current().finally(() => {\n isRefreshingRef.current = false;\n });\n }\n };\n\n socket.on(\"company:tokens_updated\", handleTokensUpdated);\n\n return () => {\n socket.off(\"company:tokens_updated\", handleTokensUpdated);\n };\n }, [socket, isConnected, currentUser?.company?.id]);\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 refreshUser: refreshUser,\n isRefreshing: isRefreshing,\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 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","\"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 { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\"\n\nfunction Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n className={cn(\"overflow-hidden rounded-md border flex w-full flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\"data-open:bg-muted/50 not-last:border-b\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionPrimitive.Trigger.Props) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n \"**:data-[slot=accordion-trigger-icon]:text-muted-foreground gap-6 p-2 text-left text-xs/relaxed font-medium hover:underline **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 group/accordion-trigger relative flex flex-1 items-start justify-between border border-transparent transition-all outline-none disabled:pointer-events-none disabled:opacity-50\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronDownIcon data-slot=\"accordion-trigger-icon\" className=\"pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden\" />\n <ChevronUpIcon data-slot=\"accordion-trigger-icon\" className=\"pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: AccordionPrimitive.Panel.Props) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-content\"\n className=\"data-open:animate-accordion-down data-closed:animate-accordion-up px-2 text-xs/relaxed overflow-hidden\"\n {...props}\n >\n <div\n className={cn(\n \"pt-0 pb-4 [&_a]:hover:text-foreground h-(--accordion-panel-height) data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4\",\n className\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n )\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst alertVariants = cva(\"grid gap-0.5 rounded-lg border px-2 py-1.5 text-left text-xs/relaxed has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-1.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-3.5 w-full relative group/alert\", {\n variants: {\n variant: {\n default: \"bg-card text-card-foreground\",\n destructive: \"text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n})\n\nfunction Alert({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof alertVariants>) {\n return (\n <div\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-title\"\n className={cn(\n \"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDescription({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(\n \"text-muted-foreground text-xs/relaxed text-balance md:text-pretty [&_p:not(:last-child)]:mb-4 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-action\"\n className={cn(\"absolute top-1.5 right-2\", className)}\n {...props}\n />\n )\n}\n\nexport { Alert, AlertTitle, AlertDescription, AlertAction }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { AlertDialog as AlertDialogPrimitive } from \"@base-ui/react/alert-dialog\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\n\nfunction AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {\n return <AlertDialogPrimitive.Root data-slot=\"alert-dialog\" {...props} />\n}\n\nfunction AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {\n return (\n <AlertDialogPrimitive.Trigger data-slot=\"alert-dialog-trigger\" {...props} />\n )\n}\n\nfunction AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {\n return (\n <AlertDialogPrimitive.Portal data-slot=\"alert-dialog-portal\" {...props} />\n )\n}\n\nfunction AlertDialogOverlay({\n className,\n ...props\n}: AlertDialogPrimitive.Backdrop.Props) {\n return (\n <AlertDialogPrimitive.Backdrop\n data-slot=\"alert-dialog-overlay\"\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogContent({\n className,\n size = \"default\",\n ...props\n}: AlertDialogPrimitive.Popup.Props & {\n size?: \"default\" | \"sm\"\n}) {\n return (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Popup\n data-slot=\"alert-dialog-content\"\n data-size={size}\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-3 rounded-xl p-4 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-64 data-[size=default]:sm:max-w-sm group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 outline-none\",\n className\n )}\n {...props}\n />\n </AlertDialogPortal>\n )\n}\n\nfunction AlertDialogHeader({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-header\"\n className={cn(\"grid grid-rows-[auto_1fr] place-items-center gap-1 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogFooter({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogMedia({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-media\"\n className={cn(\"bg-muted mb-2 inline-flex size-8 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-4\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {\n return (\n <AlertDialogPrimitive.Title\n data-slot=\"alert-dialog-title\"\n className={cn(\"text-sm font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {\n return (\n <AlertDialogPrimitive.Description\n data-slot=\"alert-dialog-description\"\n className={cn(\"text-muted-foreground *:[a]:hover:text-foreground text-xs/relaxed text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: React.ComponentProps<typeof Button>) {\n return (\n <Button\n data-slot=\"alert-dialog-action\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogCancel({\n className,\n variant = \"outline\",\n size = \"default\",\n ...props\n}: AlertDialogPrimitive.Close.Props &\n Pick<React.ComponentProps<typeof Button>, \"variant\" | \"size\">) {\n return (\n <AlertDialogPrimitive.Close\n data-slot=\"alert-dialog-cancel\"\n className={cn(className)}\n render={<Button variant={variant} size={size} />}\n {...props}\n />\n )\n}\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogMedia,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n}\n","import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent bg-clip-padding text-xs/relaxed font-medium focus-visible:ring-[2px] aria-invalid:ring-[2px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline: \"border-border dark:bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground\",\n secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost: \"hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground\",\n destructive: \"bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-7 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n xs: \"h-5 gap-1 rounded-sm px-2 text-[0.625rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-2.5\",\n sm: \"h-6 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n lg: \"h-8 gap-1 px-2.5 text-xs/relaxed has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-4\",\n icon: \"size-7 [&_svg:not([class*='size-'])]:size-3.5\",\n \"icon-xs\": \"size-5 rounded-sm [&_svg:not([class*='size-'])]:size-2.5\",\n \"icon-sm\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-lg\": \"size-8 [&_svg:not([class*='size-'])]:size-4\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Avatar as AvatarPrimitive } from \"@base-ui/react/avatar\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Avatar({\n className,\n size = \"default\",\n ...props\n}: AvatarPrimitive.Root.Props & {\n size?: \"default\" | \"sm\" | \"lg\"\n}) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n data-size={size}\n className={cn(\n \"size-8 rounded-full after:rounded-full data-[size=lg]:size-10 data-[size=sm]:size-6 after:border-border group/avatar relative flex shrink-0 select-none after:absolute after:inset-0 after:border after:mix-blend-darken dark:after:mix-blend-lighten\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\n \"rounded-full aspect-square size-full object-cover\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: AvatarPrimitive.Fallback.Props) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"bg-muted text-muted-foreground rounded-full flex size-full items-center justify-center text-sm group-data-[size=sm]/avatar:text-xs\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarBadge({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"avatar-badge\"\n className={cn(\n \"bg-primary text-primary-foreground ring-background absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-blend-color ring-2 select-none\",\n \"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden\",\n \"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2\",\n \"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"avatar-group\"\n className={cn(\n \"*:data-[slot=avatar]:ring-background group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarGroupCount({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"avatar-group-count\"\n className={cn(\"bg-muted text-muted-foreground size-8 rounded-full text-xs/relaxed group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3 ring-background relative flex shrink-0 items-center justify-center ring-2\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Avatar,\n AvatarImage,\n AvatarFallback,\n AvatarGroup,\n AvatarGroupCount,\n AvatarBadge,\n}\n","import { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"h-5 gap-1 rounded-full border border-transparent px-2 py-0.5 text-[0.625rem] font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-2.5! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-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 transition-colors overflow-hidden group/badge\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n secondary: \"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80\",\n destructive: \"bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20\",\n outline: \"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground bg-input/20 dark:bg-input/30\",\n ghost: \"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant = \"default\",\n render,\n ...props\n}: useRender.ComponentProps<\"span\"> & VariantProps<typeof badgeVariants>) {\n return useRender({\n defaultTagName: \"span\",\n props: mergeProps<\"span\">(\n {\n className: cn(badgeVariants({ className, variant })),\n },\n props\n ),\n render,\n state: {\n slot: \"badge\",\n variant,\n },\n })\n}\n\nexport { Badge, badgeVariants }\n","import * as React from \"react\"\nimport { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronRightIcon, MoreHorizontalIcon } from \"lucide-react\"\n\nfunction Breadcrumb({ className, ...props }: React.ComponentProps<\"nav\">) {\n return (\n <nav\n aria-label=\"breadcrumb\"\n data-slot=\"breadcrumb\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbList({ className, ...props }: React.ComponentProps<\"ol\">) {\n return (\n <ol\n data-slot=\"breadcrumb-list\"\n className={cn(\n \"text-muted-foreground gap-1.5 text-xs/relaxed flex flex-wrap items-center break-words\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"breadcrumb-item\"\n className={cn(\"gap-1 inline-flex items-center\", className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbLink({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"a\">) {\n return useRender({\n defaultTagName: \"a\",\n props: mergeProps<\"a\">(\n {\n className: cn(\"hover:text-foreground transition-colors\", className),\n },\n props\n ),\n render,\n state: {\n slot: \"breadcrumb-link\",\n },\n })\n}\n\nfunction BreadcrumbPage({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"breadcrumb-page\"\n role=\"link\"\n aria-disabled=\"true\"\n aria-current=\"page\"\n className={cn(\"text-foreground font-normal\", className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"breadcrumb-separator\"\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"[&>svg]:size-3.5\", className)}\n {...props}\n >\n {children ?? (\n <ChevronRightIcon\n />\n )}\n </li>\n )\n}\n\nfunction BreadcrumbEllipsis({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"breadcrumb-ellipsis\"\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\n \"size-4 [&>svg]:size-3.5 flex items-center justify-center\",\n className\n )}\n {...props}\n >\n <MoreHorizontalIcon\n />\n <span className=\"sr-only\">More</span>\n </span>\n )\n}\n\nexport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport {\n DayPicker,\n getDefaultClassNames,\n type DayButton,\n} from \"react-day-picker\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button, buttonVariants } from \"@/components/ui/button\"\nimport { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from \"lucide-react\"\n\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n captionLayout = \"label\",\n buttonVariant = \"ghost\",\n formatters,\n components,\n ...props\n}: React.ComponentProps<typeof DayPicker> & {\n buttonVariant?: React.ComponentProps<typeof Button>[\"variant\"]\n}) {\n const defaultClassNames = getDefaultClassNames()\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\n \"p-3 [--cell-radius:var(--radius-md)] [--cell-size:--spacing(6)] bg-background group/calendar [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent\",\n String.raw`rtl:**:[.rdp-button\\_next>svg]:rotate-180`,\n String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\n className\n )}\n captionLayout={captionLayout}\n formatters={{\n formatMonthDropdown: (date) =>\n date.toLocaleString(\"default\", { month: \"short\" }),\n ...formatters,\n }}\n classNames={{\n root: cn(\"w-fit\", defaultClassNames.root),\n months: cn(\n \"flex gap-4 flex-col md:flex-row relative\",\n defaultClassNames.months\n ),\n month: cn(\"flex flex-col w-full gap-4\", defaultClassNames.month),\n nav: cn(\n \"flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between\",\n defaultClassNames.nav\n ),\n button_previous: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none\",\n defaultClassNames.button_previous\n ),\n button_next: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none\",\n defaultClassNames.button_next\n ),\n month_caption: cn(\n \"flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)\",\n defaultClassNames.month_caption\n ),\n dropdowns: cn(\n \"w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5\",\n defaultClassNames.dropdowns\n ),\n dropdown_root: cn(\n \"relative cn-calendar-dropdown-root rounded-(--cell-radius)\",\n defaultClassNames.dropdown_root\n ),\n dropdown: cn(\n \"absolute bg-popover inset-0 opacity-0\",\n defaultClassNames.dropdown\n ),\n caption_label: cn(\n \"select-none font-medium\",\n captionLayout === \"label\"\n ? \"text-sm\"\n : \"cn-calendar-caption-label rounded-(--cell-radius) flex items-center gap-1 text-sm [&>svg]:text-muted-foreground [&>svg]:size-3.5\",\n defaultClassNames.caption_label\n ),\n table: \"w-full border-collapse\",\n weekdays: cn(\"flex\", defaultClassNames.weekdays),\n weekday: cn(\n \"text-muted-foreground rounded-(--cell-radius) flex-1 font-normal text-[0.8rem] select-none\",\n defaultClassNames.weekday\n ),\n week: cn(\"flex w-full mt-2\", defaultClassNames.week),\n week_number_header: cn(\n \"select-none w-(--cell-size)\",\n defaultClassNames.week_number_header\n ),\n week_number: cn(\n \"text-[0.8rem] select-none text-muted-foreground\",\n defaultClassNames.week_number\n ),\n day: cn(\n \"relative w-full rounded-(--cell-radius) h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius) group/day aspect-square select-none\",\n props.showWeekNumber\n ? \"[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)\"\n : \"[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)\",\n defaultClassNames.day\n ),\n range_start: cn(\n \"rounded-l-(--cell-radius) bg-muted elative after:bg-muted after:absolute after:inset-y-0 after:w-4 after:right-0 -z-0 isolate\",\n defaultClassNames.range_start\n ),\n range_middle: cn(\"rounded-none\", defaultClassNames.range_middle),\n range_end: cn(\n \"rounded-r-(--cell-radius) bg-muted relative after:bg-muted after:absolute after:inset-y-0 after:w-4 after:left-0 -z-0 isolate\",\n defaultClassNames.range_end\n ),\n today: cn(\n \"bg-muted text-foreground rounded-(--cell-radius) data-[selected=true]:rounded-none\",\n defaultClassNames.today\n ),\n outside: cn(\n \"text-muted-foreground aria-selected:text-muted-foreground\",\n defaultClassNames.outside\n ),\n disabled: cn(\n \"text-muted-foreground opacity-50\",\n defaultClassNames.disabled\n ),\n hidden: cn(\"invisible\", defaultClassNames.hidden),\n ...classNames,\n }}\n components={{\n Root: ({ className, rootRef, ...props }) => {\n return (\n <div\n data-slot=\"calendar\"\n ref={rootRef}\n className={cn(className)}\n {...props}\n />\n )\n },\n Chevron: ({ className, orientation, ...props }) => {\n if (orientation === \"left\") {\n return (\n <ChevronLeftIcon className={cn(\"size-4\", className)} {...props} />\n )\n }\n\n if (orientation === \"right\") {\n return (\n <ChevronRightIcon className={cn(\"size-4\", className)} {...props} />\n )\n }\n\n return (\n <ChevronDownIcon className={cn(\"size-4\", className)} {...props} />\n )\n },\n DayButton: CalendarDayButton,\n WeekNumber: ({ children, ...props }) => {\n return (\n <td {...props}>\n <div className=\"flex size-(--cell-size) items-center justify-center text-center\">\n {children}\n </div>\n </td>\n )\n },\n ...components,\n }}\n {...props}\n />\n )\n}\n\nfunction CalendarDayButton({\n className,\n day,\n modifiers,\n ...props\n}: React.ComponentProps<typeof DayButton>) {\n const defaultClassNames = getDefaultClassNames()\n\n const ref = React.useRef<HTMLButtonElement>(null)\n React.useEffect(() => {\n if (modifiers.focused) ref.current?.focus()\n }, [modifiers.focused])\n\n return (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n data-day={day.date.toLocaleDateString()}\n data-selected-single={\n modifiers.selected &&\n !modifiers.range_start &&\n !modifiers.range_end &&\n !modifiers.range_middle\n }\n data-range-start={modifiers.range_start}\n data-range-end={modifiers.range_end}\n data-range-middle={modifiers.range_middle}\n className={cn(\n \"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-muted data-[range-middle=true]:text-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-foreground relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 border-0 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius) data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius) [&>span]:text-xs [&>span]:opacity-70\",\n defaultClassNames.day,\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Calendar, CalendarDayButton }\n","import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\"ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-lg py-4 text-xs/relaxed ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg group/card flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"gap-1 rounded-t-lg px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-muted-foreground text-xs/relaxed\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-4 group-data-[size=sm]/card:px-3\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"rounded-b-lg px-4 group-data-[size=sm]/card:px-3 [.border-t]:pt-4 group-data-[size=sm]/card:[.border-t]:pt-3 flex items-center\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-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\nfunction Carousel({\n orientation = \"horizontal\",\n opts,\n setApi,\n plugins,\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & CarouselProps) {\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) return\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) return\n setApi(api)\n }, [api, setApi])\n\n React.useEffect(() => {\n if (!api) return\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:\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n )\n}\n\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\n const { carouselRef, orientation } = useCarousel()\n\n return (\n <div\n ref={carouselRef}\n className=\"overflow-hidden\"\n data-slot=\"carousel-content\"\n >\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const { orientation } = useCarousel()\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n data-slot=\"carousel-item\"\n className={cn(\n \"min-w-0 shrink-0 grow-0 basis-full\",\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-previous\"\n variant={variant}\n size={size}\n className={cn(\n \"rounded-full absolute touch-manipulation\",\n orientation === \"horizontal\"\n ? \"top-1/2 -left-12 -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 <ChevronLeftIcon\n />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n )\n}\n\nfunction CarouselNext({\n className,\n variant = \"outline\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollNext, canScrollNext } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-next\"\n variant={variant}\n size={size}\n className={cn(\n \"rounded-full absolute touch-manipulation\",\n orientation === \"horizontal\"\n ? \"top-1/2 -right-12 -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 <ChevronRightIcon\n />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n )\n}\n\nexport {\n type CarouselApi,\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselPrevious,\n CarouselNext,\n useCarousel,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\n// Custom type for tooltip/legend payload items\ntype PayloadItem = {\n dataKey?: string | number\n name?: string\n value?: string | number\n type?: string\n color?: string\n payload?: Record<string, unknown> & { fill?: string }\n fill?: string\n}\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record<keyof typeof THEMES, string> }\n )\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<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"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>\n {children}\n </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(\n ([, config]) => config.theme || config.color\n )\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 =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n 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\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps<\"div\"> & {\n active?: boolean\n payload?: PayloadItem[]\n label?: string | number\n labelFormatter?: (label: unknown, payload: PayloadItem[]) => React.ReactNode\n formatter?: (value: unknown, name: string, item: PayloadItem, index: number, payload: unknown) => React.ReactNode\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n labelClassName?: string\n color?: string\n }) {\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 !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n <div className={cn(\"font-medium\", labelClassName)}>\n {labelFormatter(value, payload)}\n </div>\n )\n }\n\n if (!value) {\n return null\n }\n\n return <div className={cn(\"font-medium\", labelClassName)}>{value}</div>\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\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 gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs/relaxed shadow-xl grid min-w-[8rem] items-start\",\n className\n )}\n >\n {!nestLabel ? tooltipLabel : null}\n <div className=\"grid gap-1.5\">\n {payload\n .filter((item) => item.type !== \"none\")\n .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(\n \"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)\",\n {\n \"h-2.5 w-2.5\": indicator === \"dot\",\n \"w-1\": indicator === \"line\",\n \"w-0 border-[1.5px] border-dashed bg-transparent\":\n indicator === \"dashed\",\n \"my-0.5\": nestLabel && indicator === \"dashed\",\n }\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(\n \"flex flex-1 justify-between leading-none\",\n nestLabel ? \"items-end\" : \"items-center\"\n )}\n >\n <div className=\"grid gap-1.5\">\n {nestLabel ? tooltipLabel : null}\n <span className=\"text-muted-foreground\">\n {itemConfig?.label || item.name}\n </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\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n payload?: PayloadItem[]\n verticalAlign?: \"top\" | \"bottom\" | \"middle\"\n hideIcon?: boolean\n nameKey?: string\n }) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n <div\n className={cn(\n \"flex items-center justify-center gap-4\",\n verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\n className\n )}\n >\n {payload\n .filter((item) => item.type !== \"none\")\n .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(\n \"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3\"\n )}\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\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\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[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n","\"use client\"\n\nimport { Checkbox as CheckboxPrimitive } from \"@base-ui/react/checkbox\"\n\nimport { cn } from \"@/lib/utils\"\nimport { CheckIcon } from \"lucide-react\"\n\nfunction Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n \"border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-[4px] border transition-shadow group-has-disabled/field:opacity-50 focus-visible:ring-[2px] aria-invalid:ring-[2px] peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"[&>svg]:size-3.5 grid place-content-center text-current transition-none\"\n >\n <CheckIcon\n />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport { Checkbox }\n","\"use client\";\n\nimport { Collapsible as CollapsiblePrimitive } from \"@base-ui/react/collapsible\";\n\nfunction Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />;\n}\n\nfunction CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {\n return <CollapsiblePrimitive.Trigger data-slot=\"collapsible-trigger\" {...props} />;\n}\n\nfunction CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {\n return <CollapsiblePrimitive.Panel data-slot=\"collapsible-content\" {...props} />;\n}\n\nexport { Collapsible, CollapsibleContent, CollapsibleTrigger };\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Command as CommandPrimitive } from \"cmdk\"\n\nimport { cn } from \"@/lib/utils\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from \"@/components/ui/dialog\"\nimport {\n InputGroup,\n InputGroupAddon,\n} from \"@/components/ui/input-group\"\nimport { SearchIcon, CheckIcon } from \"lucide-react\"\n\nfunction Command({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive>) {\n return (\n <CommandPrimitive\n data-slot=\"command\"\n className={cn(\n \"bg-popover text-popover-foreground rounded-xl p-1 flex size-full flex-col overflow-hidden\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandDialog({\n title = \"Command Palette\",\n description = \"Search for a command to run...\",\n children,\n className,\n showCloseButton = false,\n ...props\n}: Omit<React.ComponentProps<typeof Dialog>, \"children\"> & {\n title?: string\n description?: string\n className?: string\n showCloseButton?: boolean\n children: React.ReactNode\n}) {\n return (\n <Dialog {...props}>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n <DialogContent\n className={cn(\"rounded-xl! p-0 overflow-hidden p-0\", className)}\n showCloseButton={showCloseButton}\n >\n {children}\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction CommandInput({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Input>) {\n return (\n <div data-slot=\"command-input-wrapper\" className=\"p-1 pb-0\">\n <InputGroup className=\"bg-input/20 dark:bg-input/30 h-8!\">\n <CommandPrimitive.Input\n data-slot=\"command-input\"\n className={cn(\n \"w-full text-xs/relaxed outline-hidden disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n <InputGroupAddon>\n <SearchIcon className=\"size-3.5 shrink-0 opacity-50\" />\n </InputGroupAddon>\n </InputGroup>\n </div>\n )\n}\n\nfunction CommandList({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.List>) {\n return (\n <CommandPrimitive.List\n data-slot=\"command-list\"\n className={cn(\n \"no-scrollbar max-h-72 scroll-py-1 outline-none overflow-x-hidden overflow-y-auto\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandEmpty({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n data-slot=\"command-empty\"\n className={cn(\"py-6 text-center text-xs/relaxed\", className)}\n {...props}\n />\n )\n}\n\nfunction CommandGroup({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n data-slot=\"command-group\"\n className={cn(\"text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CommandSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n data-slot=\"command-separator\"\n className={cn(\"bg-border/50 -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction CommandItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return (\n <CommandPrimitive.Item\n data-slot=\"command-item\"\n className={cn(\n \"data-selected:bg-muted data-selected:text-foreground data-selected:*:[svg]:text-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md px-2.5 py-1.5 text-xs/relaxed outline-hidden select-none [&_svg:not([class*='size-'])]:size-3.5 [[data-slot=dialog-content]_&]:rounded-md group/command-item data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n {children}\n <CheckIcon className=\"ml-auto opacity-0 group-has-[[data-slot=command-shortcut]]/command-item:hidden group-data-[checked=true]/command-item:opacity-100\" />\n </CommandPrimitive.Item>\n )\n}\n\nfunction CommandShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"command-shortcut\"\n className={cn(\"text-muted-foreground group-data-selected/command-item:text-foreground ml-auto text-[0.625rem] tracking-widest\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { XIcon } from \"lucide-react\"\n\nfunction Dialog({ ...props }: DialogPrimitive.Root.Props) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({ ...props }: DialogPrimitive.Close.Props) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: DialogPrimitive.Backdrop.Props) {\n return (\n <DialogPrimitive.Backdrop\n data-slot=\"dialog-overlay\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: DialogPrimitive.Popup.Props & {\n showCloseButton?: boolean\n}) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Popup\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid gap-4 rounded-xl p-4 text-xs/relaxed ring-1 duration-100 fixed top-1/2 left-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 outline-none\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-2 right-2\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon\n />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Popup>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"gap-1 flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({\n className,\n showCloseButton = false,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showCloseButton?: boolean\n}) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"gap-2 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close render={<Button variant=\"outline\" />}>\n Close\n </DialogPrimitive.Close>\n )}\n </div>\n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground *:[a]:hover:text-foreground text-xs/relaxed *:[a]:underline *:[a]:underline-offset-3\", className)}\n {...props}\n />\n )\n}\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 * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../utils/cn\"\nimport { Button } from \"./button\"\nimport { Input } from \"./input\"\nimport { Textarea } from \"./textarea\"\n\nfunction InputGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-group\"\n role=\"group\"\n className={cn(\n \"border-input bg-input/20 dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/30 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 h-7 rounded-md border transition-colors has-data-[align=block-end]:rounded-md has-data-[align=block-start]:rounded-md has-[[data-slot=input-group-control]:focus-visible]:ring-[2px] has-[[data-slot][aria-invalid=true]]:ring-[2px] has-[textarea]:rounded-md has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5 [[data-slot=combobox-content]_&]:focus-within:border-inherit [[data-slot=combobox-content]_&]:focus-within:ring-0 group/input-group relative flex w-full min-w-0 items-center outline-none has-[>textarea]:h-auto\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst inputGroupAddonVariants = cva(\n \"text-muted-foreground **:data-[slot=kbd]:bg-muted-foreground/10 h-auto gap-1 py-2 text-xs/relaxed font-medium group-data-[disabled=true]/input-group:opacity-50 **:data-[slot=kbd]:rounded-[calc(var(--radius-sm)-2px)] **:data-[slot=kbd]:px-1 **:data-[slot=kbd]:text-[0.625rem] [&>svg:not([class*='size-'])]:size-3.5 flex cursor-text items-center justify-center select-none\",\n {\n variants: {\n align: {\n \"inline-start\": \"pl-2 has-[>button]:ml-[-0.275rem] has-[>kbd]:ml-[-0.275rem] order-first\",\n \"inline-end\": \"pr-2 has-[>button]:mr-[-0.275rem] has-[>kbd]:mr-[-0.275rem] order-last\",\n \"block-start\":\n \"px-2 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2 order-first w-full justify-start\",\n \"block-end\":\n \"px-2 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2 order-last w-full justify-start\",\n },\n },\n defaultVariants: {\n align: \"inline-start\",\n },\n }\n)\n\nfunction InputGroupAddon({\n className,\n align = \"inline-start\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof inputGroupAddonVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"input-group-addon\"\n data-align={align}\n className={cn(inputGroupAddonVariants({ align }), className)}\n onClick={(e) => {\n if ((e.target as HTMLElement).closest(\"button\")) {\n return\n }\n e.currentTarget.parentElement?.querySelector(\"input\")?.focus()\n }}\n {...props}\n />\n )\n}\n\nconst inputGroupButtonVariants = cva(\n \"gap-2 rounded-md text-xs/relaxed shadow-none flex items-center\",\n {\n variants: {\n size: {\n xs: \"h-5 gap-1 rounded-[calc(var(--radius-sm)-2px)] px-1 [&>svg:not([class*='size-'])]:size-3\",\n sm: \"\",\n \"icon-xs\": \"size-6 p-0 has-[>svg]:p-0\",\n \"icon-sm\": \"size-8 p-0 has-[>svg]:p-0\",\n },\n },\n defaultVariants: {\n size: \"xs\",\n },\n }\n)\n\nfunction InputGroupButton({\n className,\n type = \"button\",\n variant = \"ghost\",\n size = \"xs\",\n ...props\n}: Omit<React.ComponentProps<typeof Button>, \"size\" | \"type\"> &\n VariantProps<typeof inputGroupButtonVariants> & {\n type?: \"button\" | \"submit\" | \"reset\"\n }) {\n return (\n <Button\n type={type}\n data-size={size}\n variant={variant}\n className={cn(inputGroupButtonVariants({ size }), className)}\n {...props}\n />\n )\n}\n\nfunction InputGroupText({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n className={cn(\n \"text-muted-foreground gap-2 text-xs/relaxed [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction InputGroupInput({\n className,\n ...props\n}: React.ComponentProps<\"input\">) {\n return (\n <Input\n data-slot=\"input-group-control\"\n className={cn(\"rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent flex-1\", className)}\n {...props}\n />\n )\n}\n\nfunction InputGroupTextarea({\n className,\n ...props\n}: React.ComponentProps<\"textarea\">) {\n return (\n <Textarea\n data-slot=\"input-group-control\"\n className={cn(\"rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent flex-1 resize-none\", className)}\n {...props}\n />\n )\n}\n\nexport {\n InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupText,\n InputGroupInput,\n InputGroupTextarea,\n}\n","import * as React from \"react\"\nimport { Input as InputPrimitive } from \"@base-ui/react/input\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <InputPrimitive\n type={type}\n data-slot=\"input\"\n className={cn(\n \"bg-input/20 dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 h-7 rounded-md border px-2 py-0.5 text-sm transition-colors file:h-6 file:text-xs/relaxed file:font-medium focus-visible:ring-[2px] aria-invalid:ring-[2px] md:text-xs/relaxed file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n","import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"border-input bg-input/20 dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 resize-none rounded-md border px-2 py-2 text-sm transition-colors focus-visible:ring-[2px] aria-invalid:ring-[2px] md:text-xs/relaxed placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Textarea }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { ContextMenu as ContextMenuPrimitive } from \"@base-ui/react/context-menu\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronRightIcon, CheckIcon } from \"lucide-react\"\n\nfunction ContextMenu({ ...props }: ContextMenuPrimitive.Root.Props) {\n return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />\n}\n\nfunction ContextMenuPortal({ ...props }: ContextMenuPrimitive.Portal.Props) {\n return (\n <ContextMenuPrimitive.Portal data-slot=\"context-menu-portal\" {...props} />\n )\n}\n\nfunction ContextMenuTrigger({\n className,\n ...props\n}: ContextMenuPrimitive.Trigger.Props) {\n return (\n <ContextMenuPrimitive.Trigger\n data-slot=\"context-menu-trigger\"\n className={cn(\"select-none\", className)}\n {...props}\n />\n )\n}\n\nfunction ContextMenuContent({\n className,\n align = \"start\",\n alignOffset = 4,\n side = \"right\",\n sideOffset = 0,\n ...props\n}: ContextMenuPrimitive.Popup.Props &\n Pick<\n ContextMenuPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Positioner\n className=\"isolate z-50 outline-none\"\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <ContextMenuPrimitive.Popup\n data-slot=\"context-menu-content\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 z-50 max-h-(--available-height) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none\", className )}\n {...props}\n />\n </ContextMenuPrimitive.Positioner>\n </ContextMenuPrimitive.Portal>\n )\n}\n\nfunction ContextMenuGroup({ ...props }: ContextMenuPrimitive.Group.Props) {\n return (\n <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />\n )\n}\n\nfunction ContextMenuLabel({\n className,\n inset,\n ...props\n}: ContextMenuPrimitive.GroupLabel.Props & {\n inset?: boolean\n}) {\n return (\n <ContextMenuPrimitive.GroupLabel\n data-slot=\"context-menu-label\"\n data-inset={inset}\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs data-[inset]:pl-8\", className)}\n {...props}\n />\n )\n}\n\nfunction ContextMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: ContextMenuPrimitive.Item.Props & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <ContextMenuPrimitive.Item\n data-slot=\"context-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed [&_svg:not([class*='size-'])]:size-3.5 group/context-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction ContextMenuSub({ ...props }: ContextMenuPrimitive.SubmenuRoot.Props) {\n return (\n <ContextMenuPrimitive.SubmenuRoot data-slot=\"context-menu-sub\" {...props} />\n )\n}\n\nfunction ContextMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: ContextMenuPrimitive.SubmenuTrigger.Props & {\n inset?: boolean\n}) {\n return (\n <ContextMenuPrimitive.SubmenuTrigger\n data-slot=\"context-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs [&_svg:not([class*='size-'])]:size-3.5 flex cursor-default items-center outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto\" />\n </ContextMenuPrimitive.SubmenuTrigger>\n )\n}\n\nfunction ContextMenuSubContent({\n ...props\n}: React.ComponentProps<typeof ContextMenuContent>) {\n return (\n <ContextMenuContent\n data-slot=\"context-menu-sub-content\"\n className=\"shadow-lg\"\n side=\"right\"\n {...props}\n />\n )\n}\n\nfunction ContextMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: ContextMenuPrimitive.CheckboxItem.Props) {\n return (\n <ContextMenuPrimitive.CheckboxItem\n data-slot=\"context-menu-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none\">\n <ContextMenuPrimitive.CheckboxItemIndicator>\n <CheckIcon\n />\n </ContextMenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n )\n}\n\nfunction ContextMenuRadioGroup({\n ...props\n}: ContextMenuPrimitive.RadioGroup.Props) {\n return (\n <ContextMenuPrimitive.RadioGroup\n data-slot=\"context-menu-radio-group\"\n {...props}\n />\n )\n}\n\nfunction ContextMenuRadioItem({\n className,\n children,\n ...props\n}: ContextMenuPrimitive.RadioItem.Props) {\n return (\n <ContextMenuPrimitive.RadioItem\n data-slot=\"context-menu-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none\">\n <ContextMenuPrimitive.RadioItemIndicator>\n <CheckIcon\n />\n </ContextMenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n )\n}\n\nfunction ContextMenuSeparator({\n className,\n ...props\n}: ContextMenuPrimitive.Separator.Props) {\n return (\n <ContextMenuPrimitive.Separator\n data-slot=\"context-menu-separator\"\n className={cn(\"bg-border/50 -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction ContextMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"context-menu-shortcut\"\n className={cn(\"text-muted-foreground group-focus/context-menu-item:text-accent-foreground ml-auto text-[0.625rem] tracking-widest\", className)}\n {...props}\n />\n )\n}\n\nexport {\n ContextMenu,\n ContextMenuTrigger,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuCheckboxItem,\n ContextMenuRadioItem,\n ContextMenuLabel,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuGroup,\n ContextMenuPortal,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuRadioGroup,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n return <DrawerPrimitive.Root data-slot=\"drawer\" {...props} />\n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\n return <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props} />\n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Close>) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Content>) {\n return (\n <DrawerPortal data-slot=\"drawer-portal\">\n <DrawerOverlay />\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n \"before:bg-background relative flex h-auto flex-col bg-transparent p-2 text-xs/relaxed before:absolute before:inset-2 before:-z-10 before:rounded-xl data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm group/drawer-content fixed z-50\",\n className\n )}\n {...props}\n >\n <div className=\"bg-muted mx-auto mt-4 hidden h-1.5 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block bg-muted mx-auto hidden shrink-0 group-data-[vaul-drawer-direction=bottom]/drawer-content:block\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n )\n}\n\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn(\"gap-1 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:text-left flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-footer\"\n className={cn(\"gap-2 p-4 mt-auto flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Title>) {\n return (\n <DrawerPrimitive.Title\n data-slot=\"drawer-title\"\n className={cn(\"text-foreground text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Description>) {\n return (\n <DrawerPrimitive.Description\n data-slot=\"drawer-description\"\n className={cn(\"text-muted-foreground text-xs/relaxed\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Drawer,\n DrawerPortal,\n DrawerOverlay,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronRightIcon, CheckIcon } from \"lucide-react\"\n\nfunction DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {\n return <MenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />\n}\n\nfunction DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\n}\n\nfunction DropdownMenuContent({\n align = \"start\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n className,\n ...props\n}: MenuPrimitive.Popup.Props &\n Pick<\n MenuPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner\n className=\"isolate z-50 outline-none\"\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <MenuPrimitive.Popup\n data-slot=\"dropdown-menu-content\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden\", className )}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {\n return <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: MenuPrimitive.GroupLabel.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.GroupLabel\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs data-[inset]:pl-8\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: MenuPrimitive.Item.Props & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <MenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed [&_svg:not([class*='size-'])]:size-3.5 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {\n return <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.SubmenuTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs [&_svg:not([class*='size-'])]:size-3.5 flex cursor-default items-center outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto\" />\n </MenuPrimitive.SubmenuTrigger>\n )\n}\n\nfunction DropdownMenuSubContent({\n align = \"start\",\n alignOffset = -3,\n side = \"right\",\n sideOffset = 0,\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuContent>) {\n return (\n <DropdownMenuContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 w-auto\", className)}\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: MenuPrimitive.CheckboxItem.Props) {\n return (\n <MenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none\"\n data-slot=\"dropdown-menu-checkbox-item-indicator\"\n >\n <MenuPrimitive.CheckboxItemIndicator>\n <CheckIcon\n />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n )\n}\n\nfunction DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {\n return (\n <MenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: MenuPrimitive.RadioItem.Props) {\n return (\n <MenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none\"\n data-slot=\"dropdown-menu-radio-item-indicator\"\n >\n <MenuPrimitive.RadioItemIndicator>\n <CheckIcon\n />\n </MenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n )\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: MenuPrimitive.Separator.Props) {\n return (\n <MenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"bg-border/50 -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\"text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-[0.625rem] tracking-widest\", className)}\n {...props}\n />\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n}\n","\"use client\"\n\nimport { useMemo } from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../utils/cn\"\nimport { Label } from \"./label\"\nimport { Separator } from \"./separator\"\n\nfunction FieldSet({ className, ...props }: React.ComponentProps<\"fieldset\">) {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn(\"gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction FieldLegend({\n className,\n variant = \"legend\",\n ...props\n}: React.ComponentProps<\"legend\"> & { variant?: \"legend\" | \"label\" }) {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(\"mb-2 font-medium data-[variant=label]:text-xs/relaxed data-[variant=legend]:text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction FieldGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n \"gap-4 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4 group/field-group @container/field-group flex w-full flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst fieldVariants = cva(\"data-[invalid=true]:text-destructive gap-2 group/field flex w-full\", {\n variants: {\n orientation: {\n vertical:\n \"flex-col [&>*]:w-full [&>.sr-only]:w-auto\",\n horizontal:\n \"flex-row items-center [&>[data-slot=field-label]]:flex-auto has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\",\n responsive:\n \"flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto @md/field-group:[&>[data-slot=field-label]]:flex-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\",\n },\n },\n defaultVariants: {\n orientation: \"vertical\",\n },\n})\n\nfunction Field({\n className,\n orientation = \"vertical\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof fieldVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"field\"\n data-orientation={orientation}\n className={cn(fieldVariants({ orientation }), className)}\n {...props}\n />\n )\n}\n\nfunction FieldContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-content\"\n className={cn(\n \"gap-0.5 group/field-content flex flex-1 flex-col leading-snug\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldLabel({\n className,\n ...props\n}: React.ComponentProps<typeof Label>) {\n return (\n <Label\n data-slot=\"field-label\"\n className={cn(\n \"has-data-checked:bg-primary/5 dark:has-data-checked:bg-primary/10 gap-2 group-data-[disabled=true]/field:opacity-50 has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-2 group/field-label peer/field-label flex w-fit leading-snug\",\n \"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-label\"\n className={cn(\n \"gap-2 text-xs/relaxed font-medium group-data-[disabled=true]/field:opacity-50 flex w-fit items-center leading-snug\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"field-description\"\n className={cn(\n \"text-muted-foreground text-left text-xs/relaxed [[data-variant=legend]+&]:-mt-1.5 leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance\",\n \"last:mt-0 nth-last-2:-mt-1\",\n \"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n children?: React.ReactNode\n}) {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn(\"-my-2 h-5 text-xs/relaxed group-data-[variant=outline]/field-group:-mb-2 relative\", className)}\n {...props}\n >\n <Separator className=\"absolute inset-0 top-1/2\" />\n {children && (\n <span\n className=\"text-muted-foreground px-2 bg-background relative mx-auto block w-fit\"\n data-slot=\"field-separator-content\"\n >\n {children}\n </span>\n )}\n </div>\n )\n}\n\nfunction FieldError({\n className,\n children,\n errors,\n ...props\n}: React.ComponentProps<\"div\"> & {\n errors?: Array<{ message?: string } | undefined>\n}) {\n const content = useMemo(() => {\n if (children) {\n return children\n }\n\n if (!errors?.length) {\n return null\n }\n\n const uniqueErrors = [\n ...new Map(errors.map((error) => [error?.message, error])).values(),\n ]\n\n if (uniqueErrors?.length == 1) {\n return uniqueErrors[0]?.message\n }\n\n return (\n <ul className=\"ml-4 flex list-disc flex-col gap-1\">\n {uniqueErrors.map(\n (error, index) =>\n error?.message && <li key={index}>{error.message}</li>\n )}\n </ul>\n )\n }, [children, errors])\n\n if (!content) {\n return null\n }\n\n return (\n <div\n role=\"alert\"\n data-slot=\"field-error\"\n className={cn(\"text-destructive text-xs/relaxed font-normal\", className)}\n {...props}\n >\n {content}\n </div>\n )\n}\n\nexport {\n Field,\n FieldLabel,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLegend,\n FieldSeparator,\n FieldSet,\n FieldContent,\n FieldTitle,\n}\n","\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Label({ className, ...props }: React.ComponentProps<\"label\">) {\n return (\n <label\n data-slot=\"label\"\n className={cn(\n \"gap-2 text-xs/relaxed leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Label }\n","\"use client\"\n\nimport { Separator as SeparatorPrimitive } from \"@base-ui/react/separator\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Separator({\n className,\n orientation = \"horizontal\",\n ...props\n}: SeparatorPrimitive.Props) {\n return (\n <SeparatorPrimitive\n data-slot=\"separator\"\n orientation={orientation}\n className={cn(\n \"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Separator }\n","\"use client\";\n\nimport { FormProvider } from \"react-hook-form\";\n\n/**\n * Form component is a wrapper around react-hook-form's FormProvider.\n * Use this to wrap your form and spread the form object into it.\n *\n * @example\n * const form = useForm<FormValues>();\n * return (\n * <Form {...form}>\n * <form onSubmit={form.handleSubmit(onSubmit)}>\n * <FormInput form={form} id=\"email\" name=\"Email\" />\n * </form>\n * </Form>\n * );\n */\nconst Form = FormProvider;\n\nexport { Form };\n","\"use client\"\n\nimport { PreviewCard as PreviewCardPrimitive } from \"@base-ui/react/preview-card\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction HoverCard({ ...props }: PreviewCardPrimitive.Root.Props) {\n return <PreviewCardPrimitive.Root data-slot=\"hover-card\" {...props} />\n}\n\nfunction HoverCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) {\n return (\n <PreviewCardPrimitive.Trigger data-slot=\"hover-card-trigger\" {...props} />\n )\n}\n\nfunction HoverCardContent({\n className,\n side = \"bottom\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 4,\n ...props\n}: PreviewCardPrimitive.Popup.Props &\n Pick<\n PreviewCardPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <PreviewCardPrimitive.Portal data-slot=\"hover-card-portal\">\n <PreviewCardPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <PreviewCardPrimitive.Popup\n data-slot=\"hover-card-content\"\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground w-72 rounded-lg p-2.5 text-xs/relaxed shadow-md ring-1 duration-100 z-50 origin-(--transform-origin) outline-hidden\",\n className\n )}\n {...props}\n />\n </PreviewCardPrimitive.Positioner>\n </PreviewCardPrimitive.Portal>\n )\n}\n\nexport { HoverCard, HoverCardTrigger, HoverCardContent }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { OTPInput, OTPInputContext } from \"input-otp\"\n\nimport { cn } from \"@/lib/utils\"\nimport { MinusIcon } from \"lucide-react\"\n\nfunction InputOTP({\n className,\n containerClassName,\n ...props\n}: React.ComponentProps<typeof OTPInput> & {\n containerClassName?: string\n}) {\n return (\n <OTPInput\n data-slot=\"input-otp\"\n containerClassName={cn(\n \"cn-input-otp flex items-center has-disabled:opacity-50\",\n containerClassName\n )}\n spellCheck={false}\n className={cn(\n \"disabled:cursor-not-allowed\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction InputOTPGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-otp-group\"\n className={cn(\"has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive rounded-md has-aria-invalid:ring-[2px] flex items-center\", className)}\n {...props}\n />\n )\n}\n\nfunction InputOTPSlot({\n index,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n index: number\n}) {\n const inputOTPContext = React.useContext(OTPInputContext)\n const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}\n\n return (\n <div\n data-slot=\"input-otp-slot\"\n data-active={isActive}\n className={cn(\n \"bg-input/20 dark:bg-input/30 border-input data-[active=true]:border-ring data-[active=true]:ring-ring/30 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive size-7 border-y border-r text-xs/relaxed transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:ring-[2px] relative flex items-center justify-center data-[active=true]:z-10\",\n className\n )}\n {...props}\n >\n {char}\n {hasFakeCaret && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"animate-caret-blink bg-foreground h-4 w-px duration-1000 bg-foreground h-4 w-px\" />\n </div>\n )}\n </div>\n )\n}\n\nfunction InputOTPSeparator({ ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-otp-separator\"\n className=\"[&_svg:not([class*='size-'])]:size-4 flex items-center\"\n role=\"separator\"\n {...props}\n >\n <MinusIcon\n />\n </div>\n )\n}\n\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }\n","import { NavigationMenu as NavigationMenuPrimitive } from \"@base-ui/react/navigation-menu\"\nimport { cva } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronDownIcon } from \"lucide-react\"\n\nfunction NavigationMenu({\n className,\n children,\n ...props\n}: NavigationMenuPrimitive.Root.Props) {\n return (\n <NavigationMenuPrimitive.Root\n data-slot=\"navigation-menu\"\n className={cn(\n \"max-w-max group/navigation-menu relative flex max-w-max flex-1 items-center justify-center\",\n className\n )}\n {...props}\n >\n {children}\n <NavigationMenuPositioner />\n </NavigationMenuPrimitive.Root>\n )\n}\n\nfunction NavigationMenuList({\n className,\n ...props\n}: NavigationMenuPrimitive.List.Props) {\n return (\n <NavigationMenuPrimitive.List\n data-slot=\"navigation-menu-list\"\n className={cn(\n \"gap-0 group flex flex-1 list-none items-center justify-center\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction NavigationMenuItem({\n className,\n ...props\n}: NavigationMenuPrimitive.Item.Props) {\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 \"bg-background hover:bg-muted focus:bg-muted data-open:hover:bg-muted data-open:focus:bg-muted data-open:bg-muted/50 focus-visible:ring-ring/30 data-popup-open:bg-muted/50 data-popup-open:hover:bg-muted rounded-md px-2.5 py-1.5 text-xs/relaxed font-medium transition-all focus-visible:ring-[2px] focus-visible:outline-1 disabled:opacity-50 group/navigation-menu-trigger inline-flex h-9 w-max items-center justify-center disabled:pointer-events-none outline-none\"\n)\n\nfunction NavigationMenuTrigger({\n className,\n children,\n ...props\n}: NavigationMenuPrimitive.Trigger.Props) {\n return (\n <NavigationMenuPrimitive.Trigger\n data-slot=\"navigation-menu-trigger\"\n className={cn(navigationMenuTriggerStyle(), \"group\", className)}\n {...props}\n >\n {children}{\" \"}\n <ChevronDownIcon className=\"relative top-[1px] ml-1 size-3 transition duration-300 group-data-open/navigation-menu-trigger:rotate-180 group-data-popup-open/navigation-menu-trigger:rotate-180\" aria-hidden=\"true\" />\n </NavigationMenuPrimitive.Trigger>\n )\n}\n\nfunction NavigationMenuContent({\n className,\n ...props\n}: NavigationMenuPrimitive.Content.Props) {\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 group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-open:animate-in group-data-[viewport=false]/navigation-menu:data-closed:animate-out group-data-[viewport=false]/navigation-menu:data-closed:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-open:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-open:fade-in-0 group-data-[viewport=false]/navigation-menu:data-closed:fade-out-0 group-data-[viewport=false]/navigation-menu:ring-foreground/10 p-1.5 ease-[cubic-bezier(0.22,1,0.36,1)] group-data-[viewport=false]/navigation-menu:rounded-xl group-data-[viewport=false]/navigation-menu:shadow-md group-data-[viewport=false]/navigation-menu:ring-1 group-data-[viewport=false]/navigation-menu:duration-300 h-full w-auto **: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 NavigationMenuPositioner({\n className,\n side = \"bottom\",\n sideOffset = 8,\n align = \"start\",\n alignOffset = 0,\n ...props\n}: NavigationMenuPrimitive.Positioner.Props) {\n return (\n <NavigationMenuPrimitive.Portal>\n <NavigationMenuPrimitive.Positioner\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n className={cn(\n \"transition-[top,left,right,bottom] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] data-[side=bottom]:before:top-[-10px] data-[side=bottom]:before:right-0 data-[side=bottom]:before:left-0 isolate z-50 h-[var(--positioner-height)] w-[var(--positioner-width)] max-w-[var(--available-width)] data-[instant]:transition-none\",\n className\n )}\n {...props}\n >\n <NavigationMenuPrimitive.Popup className=\"bg-popover text-popover-foreground ring-foreground/10 rounded-xl shadow ring-1 transition-all ease-[cubic-bezier(0.22,1,0.36,1)] outline-none data-[ending-style]:scale-90 data-[ending-style]:opacity-0 data-[ending-style]:duration-150 data-[starting-style]:scale-90 data-[starting-style]:opacity-0 xs:w-(--popup-width) relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin)\">\n <NavigationMenuPrimitive.Viewport className=\"relative size-full overflow-hidden\" />\n </NavigationMenuPrimitive.Popup>\n </NavigationMenuPrimitive.Positioner>\n </NavigationMenuPrimitive.Portal>\n )\n}\n\nfunction NavigationMenuLink({\n className,\n ...props\n}: NavigationMenuPrimitive.Link.Props) {\n return (\n <NavigationMenuPrimitive.Link\n data-slot=\"navigation-menu-link\"\n className={cn(\"data-[active=true]:focus:bg-muted data-[active=true]:hover:bg-muted data-[active=true]:bg-muted/50 focus-visible:ring-ring/30 hover:bg-muted focus:bg-muted flex items-center gap-1.5 rounded-lg p-2 text-xs/relaxed transition-all outline-none focus-visible:ring-[2px] focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4\", className)}\n {...props}\n />\n )\n}\n\nfunction NavigationMenuIndicator({\n className,\n ...props\n}: NavigationMenuPrimitive.Icon.Props) {\n return (\n <NavigationMenuPrimitive.Icon\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 rounded-tl-sm shadow-md relative top-[60%] h-2 w-2 rotate-45\" />\n </NavigationMenuPrimitive.Icon>\n )\n}\n\nexport {\n NavigationMenu,\n NavigationMenuContent,\n NavigationMenuIndicator,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n NavigationMenuTrigger,\n navigationMenuTriggerStyle,\n NavigationMenuPositioner,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Popover as PopoverPrimitive } from \"@base-ui/react/popover\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Popover({ ...props }: PopoverPrimitive.Root.Props) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\nfunction PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n ...props\n}: PopoverPrimitive.Popup.Props &\n Pick<\n PopoverPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <PopoverPrimitive.Popup\n data-slot=\"popover-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 flex flex-col gap-4 rounded-lg p-2.5 text-xs shadow-md ring-1 duration-100 z-50 w-72 origin-(--transform-origin) outline-hidden\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Positioner>\n </PopoverPrimitive.Portal>\n )\n}\n\nfunction PopoverHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\"flex flex-col gap-1 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {\n return (\n <PopoverPrimitive.Title\n data-slot=\"popover-title\"\n className={cn(\"text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverDescription({\n className,\n ...props\n}: PopoverPrimitive.Description.Props) {\n return (\n <PopoverPrimitive.Description\n data-slot=\"popover-description\"\n className={cn(\"text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Popover,\n PopoverContent,\n PopoverDescription,\n PopoverHeader,\n PopoverTitle,\n PopoverTrigger,\n}\n","\"use client\"\n\nimport { Progress as ProgressPrimitive } from \"@base-ui/react/progress\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Progress({\n className,\n children,\n value,\n ...props\n}: ProgressPrimitive.Root.Props) {\n return (\n <ProgressPrimitive.Root\n value={value}\n data-slot=\"progress\"\n className={cn(\"flex flex-wrap gap-3\", className)}\n {...props}\n >\n {children}\n <ProgressTrack>\n <ProgressIndicator />\n </ProgressTrack>\n </ProgressPrimitive.Root>\n )\n}\n\nfunction ProgressTrack({ className, ...props }: ProgressPrimitive.Track.Props) {\n return (\n <ProgressPrimitive.Track\n className={cn(\n \"bg-muted h-1 rounded-md relative flex w-full items-center overflow-x-hidden\",\n className\n )}\n data-slot=\"progress-track\"\n {...props}\n />\n )\n}\n\nfunction ProgressIndicator({\n className,\n ...props\n}: ProgressPrimitive.Indicator.Props) {\n return (\n <ProgressPrimitive.Indicator\n data-slot=\"progress-indicator\"\n className={cn(\"bg-primary h-full transition-all\", className)}\n {...props}\n />\n )\n}\n\nfunction ProgressLabel({ className, ...props }: ProgressPrimitive.Label.Props) {\n return (\n <ProgressPrimitive.Label\n className={cn(\"text-xs/relaxed font-medium\", className)}\n data-slot=\"progress-label\"\n {...props}\n />\n )\n}\n\nfunction ProgressValue({ className, ...props }: ProgressPrimitive.Value.Props) {\n return (\n <ProgressPrimitive.Value\n className={cn(\"text-muted-foreground ml-auto text-xs/relaxed tabular-nums\", className)}\n data-slot=\"progress-value\"\n {...props}\n />\n )\n}\n\nexport {\n Progress,\n ProgressTrack,\n ProgressIndicator,\n ProgressLabel,\n ProgressValue,\n}\n","\"use client\"\n\nimport { Radio as RadioPrimitive } from \"@base-ui/react/radio\"\nimport { RadioGroup as RadioGroupPrimitive } from \"@base-ui/react/radio-group\"\n\nimport { cn } from \"@/lib/utils\"\nimport { CircleIcon } from \"lucide-react\"\n\nfunction RadioGroup({ className, ...props }: RadioGroupPrimitive.Props) {\n return (\n <RadioGroupPrimitive\n data-slot=\"radio-group\"\n className={cn(\"grid gap-3 w-full\", className)}\n {...props}\n />\n )\n}\n\nfunction RadioGroupItem({ className, ...props }: RadioPrimitive.Root.Props) {\n return (\n <RadioPrimitive.Root\n data-slot=\"radio-group-item\"\n className={cn(\n \"border-input text-primary dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 data-checked:bg-primary data-checked:border-primary flex size-4 rounded-full transition-none focus-visible:ring-[2px] aria-invalid:ring-[2px] group/radio-group-item peer relative aspect-square shrink-0 border outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <RadioPrimitive.Indicator\n data-slot=\"radio-group-indicator\"\n className=\"group-aria-invalid/radio-group-item:text-destructive flex size-4 items-center justify-center text-white\"\n >\n <CircleIcon className=\"absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-current\" />\n </RadioPrimitive.Indicator>\n </RadioPrimitive.Root>\n )\n}\n\nexport { RadioGroup, RadioGroupItem }\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as ResizablePrimitive from \"react-resizable-panels\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction ResizablePanelGroup({\n className,\n ...props\n}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) {\n return (\n <ResizablePrimitive.PanelGroup\n data-slot=\"resizable-panel-group\"\n className={cn(\n \"flex h-full w-full data-[panel-group-direction=vertical]:flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction ResizablePanel({\n ...props\n}: 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-6 w-1 shrink-0 rounded-lg\" />\n )}\n </ResizablePrimitive.PanelResizeHandle>\n )\n}\n\nexport { ResizablePanelGroup, ResizablePanel, ResizableHandle }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { ScrollArea as ScrollAreaPrimitive } from \"@base-ui/react/scroll-area\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction ScrollArea({\n className,\n children,\n ...props\n}: ScrollAreaPrimitive.Root.Props) {\n return (\n <ScrollAreaPrimitive.Root\n data-slot=\"scroll-area\"\n className={cn(\"relative\", className)}\n {...props}\n >\n <ScrollAreaPrimitive.Viewport\n data-slot=\"scroll-area-viewport\"\n className=\"focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1\"\n >\n {children}\n </ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n )\n}\n\nfunction ScrollBar({\n className,\n orientation = \"vertical\",\n ...props\n}: ScrollAreaPrimitive.Scrollbar.Props) {\n return (\n <ScrollAreaPrimitive.Scrollbar\n data-slot=\"scroll-area-scrollbar\"\n data-orientation={orientation}\n orientation={orientation}\n className={cn(\n \"data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent flex touch-none p-px transition-colors select-none\",\n className\n )}\n {...props}\n >\n <ScrollAreaPrimitive.Thumb\n data-slot=\"scroll-area-thumb\"\n className=\"rounded-full bg-border relative flex-1\"\n />\n </ScrollAreaPrimitive.Scrollbar>\n )\n}\n\nexport { ScrollArea, ScrollBar }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronDownIcon, CheckIcon, ChevronUpIcon } from \"lucide-react\"\n\nconst Select = SelectPrimitive.Root\n\nfunction SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {\n return (\n <SelectPrimitive.Group\n data-slot=\"select-group\"\n className={cn(\"scroll-my-1 p-1\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {\n return (\n <SelectPrimitive.Value\n data-slot=\"select-value\"\n className={cn(\"flex flex-1 text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectTrigger({\n className,\n size = \"default\",\n children,\n ...props\n}: SelectPrimitive.Trigger.Props & {\n size?: \"sm\" | \"default\"\n}) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n \"border-input data-[placeholder]:text-muted-foreground bg-input/20 dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-1.5 rounded-md border px-2 py-1.5 text-xs/relaxed transition-colors focus-visible:ring-[2px] aria-invalid:ring-[2px] data-[size=default]:h-7 data-[size=sm]:h-6 *:data-[slot=select-value]:flex *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*='size-'])]:size-3.5 flex w-fit items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon\n render={\n <ChevronDownIcon className=\"text-muted-foreground size-3.5 pointer-events-none\" />\n }\n />\n </SelectPrimitive.Trigger>\n )\n}\n\nfunction SelectContent({\n className,\n children,\n side = \"bottom\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 0,\n alignItemWithTrigger = true,\n ...props\n}: SelectPrimitive.Popup.Props &\n Pick<\n SelectPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\" | \"alignItemWithTrigger\"\n >) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Positioner\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n alignItemWithTrigger={alignItemWithTrigger}\n className=\"isolate z-50\"\n >\n <SelectPrimitive.Popup\n data-slot=\"select-content\"\n className={cn(\"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 min-w-32 rounded-lg shadow-md ring-1 duration-100 relative isolate z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto\", className )}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.List>{children}</SelectPrimitive.List>\n <SelectScrollDownButton />\n </SelectPrimitive.Popup>\n </SelectPrimitive.Positioner>\n </SelectPrimitive.Portal>\n )\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: SelectPrimitive.GroupLabel.Props) {\n return (\n <SelectPrimitive.GroupLabel\n data-slot=\"select-label\"\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: SelectPrimitive.Item.Props) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed [&_svg:not([class*='size-'])]:size-3.5 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className\n )}\n {...props}\n >\n <SelectPrimitive.ItemText className=\"flex flex-1 gap-2 shrink-0 whitespace-nowrap\">\n {children}\n </SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator\n render={<span className=\"pointer-events-none absolute right-2 flex items-center justify-center\" />}\n >\n <CheckIcon className=\"pointer-events-none\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n )\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: SelectPrimitive.Separator.Props) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\"bg-border/50 -mx-1 my-1 h-px pointer-events-none\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>) {\n return (\n <SelectPrimitive.ScrollUpArrow\n data-slot=\"select-scroll-up-button\"\n className={cn(\"bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-3.5 top-0 w-full\", className)}\n {...props}\n >\n <ChevronUpIcon\n />\n </SelectPrimitive.ScrollUpArrow>\n )\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>) {\n return (\n <SelectPrimitive.ScrollDownArrow\n data-slot=\"select-scroll-down-button\"\n className={cn(\"bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-3.5 bottom-0 w-full\", className)}\n {...props}\n >\n <ChevronDownIcon\n />\n </SelectPrimitive.ScrollDownArrow>\n )\n}\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 { Dialog as SheetPrimitive } from \"@base-ui/react/dialog\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { XIcon } from \"lucide-react\"\n\nfunction Sheet({ ...props }: SheetPrimitive.Root.Props) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />\n}\n\nfunction SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose({ ...props }: SheetPrimitive.Close.Props) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />\n}\n\nfunction SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {\n return (\n <SheetPrimitive.Backdrop\n data-slot=\"sheet-overlay\"\n className={cn(\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-100 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n showCloseButton = true,\n ...props\n}: SheetPrimitive.Popup.Props & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n showCloseButton?: boolean\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Popup\n data-slot=\"sheet-content\"\n data-side={side}\n className={cn(\"bg-background data-open:animate-in data-closed:animate-out data-[side=right]:data-closed:slide-out-to-right-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=top]:data-closed:slide-out-to-top-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:fade-out-0 data-open:fade-in-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=bottom]:data-open:slide-in-from-bottom-10 fixed z-50 flex flex-col bg-clip-padding text-xs/relaxed shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm\", className)}\n {...props}\n >\n {children}\n {showCloseButton && (\n <SheetPrimitive.Close\n data-slot=\"sheet-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-4 right-4\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon\n />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n )}\n </SheetPrimitive.Popup>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"gap-1.5 p-6 flex flex-col\", 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(\"gap-2 p-6 mt-auto flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"text-foreground text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: SheetPrimitive.Description.Props) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-muted-foreground text-xs/relaxed\", 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 * as React from \"react\"\nimport { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { Input } from \"@/components/ui/input\"\nimport { Separator } from \"@/components/ui/separator\"\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n} from \"@/components/ui/sheet\"\nimport { Skeleton } from \"@/components/ui/skeleton\"\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\"\nimport { useIsMobile } from \"@/hooks/use-mobile\"\nimport { PanelLeftIcon } from \"lucide-react\"\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\"\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7\nconst SIDEBAR_WIDTH = \"16rem\"\nconst SIDEBAR_WIDTH_MOBILE = \"18rem\"\nconst SIDEBAR_WIDTH_ICON = \"3rem\"\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"b\"\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 (\n event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n (event.metaKey || event.ctrlKey)\n ) {\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 <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(\n \"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n </SidebarContext.Provider>\n )\n}\n\nfunction Sidebar({\n side = \"left\",\n variant = \"sidebar\",\n collapsible = \"offExamples\",\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n side?: \"left\" | \"right\"\n variant?: \"sidebar\" | \"floating\" | \"inset\"\n collapsible?: \"offExamples\" | \"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(\n \"bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col\",\n className\n )}\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 \"transition-[width] duration-200 ease-linear relative w-(--sidebar-width) bg-transparent\",\n \"group-data-[collapsible=offExamples]: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=offExamples]:left-[calc(var(--sidebar-width)*-1)]\"\n : \"right-0 group-data-[collapsible=offExamples]: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]:ring-sidebar-border group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 flex size-full flex-col\"\n >\n {children}\n </div>\n </div>\n </div>\n )\n}\n\nfunction SidebarTrigger({\n className,\n onClick,\n ...props\n}: 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-sm\"\n className={cn(className)}\n onClick={(event) => {\n onClick?.(event)\n toggleSidebar()\n }}\n {...props}\n >\n <PanelLeftIcon\n />\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=offExamples]:bg-sidebar group-data-[collapsible=offExamples]:translate-x-0 group-data-[collapsible=offExamples]:after:left-full\",\n \"[[data-side=left][data-collapsible=offExamples]_&]:-right-2\",\n \"[[data-side=right][data-collapsible=offExamples]_&]:-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 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 relative flex w-full flex-1 flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarInput({\n className,\n ...props\n}: React.ComponentProps<typeof Input>) {\n return (\n <Input\n data-slot=\"sidebar-input\"\n data-sidebar=\"input\"\n className={cn(\"bg-muted/20 dark:bg-muted/30 border-input h-8 w-full\", 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(\"gap-2 p-2 flex flex-col\", 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(\"gap-2 p-2 flex flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarSeparator({\n className,\n ...props\n}: 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 \"no-scrollbar gap-0 flex min-h-0 flex-1 flex-col 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(\n \"px-2 py-1 relative flex w-full min-w-0 flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarGroupLabel({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\"> & React.ComponentProps<\"div\">) {\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(\n {\n className: cn(\n \"text-sidebar-foreground/70 ring-sidebar-ring h-8 rounded-md px-2 text-xs transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 flex shrink-0 items-center outline-hidden [&>svg]:shrink-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-group-label\",\n sidebar: \"group-label\",\n },\n })\n}\n\nfunction SidebarGroupAction({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"button\"> & React.ComponentProps<\"button\">) {\n return useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\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 w-5 rounded-md p-0 focus-visible:ring-2 [&>svg]:size-4 flex aspect-square items-center justify-center outline-hidden transition-transform [&>svg]:shrink-0 after:absolute after:-inset-2 md:after:hidden group-data-[collapsible=icon]:hidden\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-group-action\",\n sidebar: \"group-action\",\n },\n })\n}\n\nfunction SidebarGroupContent({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-group-content\"\n data-sidebar=\"group-content\"\n className={cn(\"text-xs w-full\", 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(\"gap-px flex w-full min-w-0 flex-col\", 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 \"ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-[calc(var(--radius-sm)+2px)] p-2 text-left text-xs transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button 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 {\n variants: {\n variant: {\n default: \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n outline: \"bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]\",\n },\n size: {\n default: \"h-8 text-xs\",\n sm: \"h-7 text-xs\",\n lg: \"h-12 text-xs group-data-[collapsible=icon]:p-0!\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction SidebarMenuButton({\n render,\n isActive = false,\n variant = \"default\",\n size = \"default\",\n tooltip,\n className,\n ...props\n}: useRender.ComponentProps<\"button\"> &\n React.ComponentProps<\"button\"> & {\n isActive?: boolean\n tooltip?: string | React.ComponentProps<typeof TooltipContent>\n } & VariantProps<typeof sidebarMenuButtonVariants>) {\n const { isMobile, state } = useSidebar()\n const comp = useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\n className: cn(sidebarMenuButtonVariants({ variant, size }), className),\n },\n props\n ),\n render: !tooltip ? render : TooltipTrigger,\n state: {\n slot: \"sidebar-menu-button\",\n sidebar: \"menu-button\",\n size,\n active: isActive,\n },\n })\n\n if (!tooltip) {\n return comp\n }\n\n if (typeof tooltip === \"string\") {\n tooltip = {\n children: tooltip,\n }\n }\n\n return (\n <Tooltip>\n {comp}\n <TooltipContent\n side=\"right\"\n align=\"center\"\n hidden={state !== \"collapsed\" || isMobile}\n {...tooltip}\n />\n </Tooltip>\n )\n}\n\nfunction SidebarMenuAction({\n className,\n render,\n showOnHover = false,\n ...props\n}: useRender.ComponentProps<\"button\"> &\n React.ComponentProps<\"button\"> & {\n showOnHover?: boolean\n }) {\n return useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\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 aspect-square w-5 rounded-[calc(var(--radius-sm)-2px)] p-0 peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 focus-visible:ring-2 [&>svg]:size-4 flex items-center justify-center outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 md:after:hidden [&>svg]:shrink-0\",\n showOnHover &&\n \"peer-data-active/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-open:opacity-100 md:opacity-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-menu-action\",\n sidebar: \"menu-action\",\n },\n })\n}\n\nfunction SidebarMenuBadge({\n className,\n ...props\n}: 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 peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 rounded-[calc(var(--radius-sm)-2px)] px-1 text-xs font-medium peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 flex items-center justify-center tabular-nums select-none 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.useState(() => {\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(\"h-8 gap-2 rounded-md px-2 flex items-center\", className)}\n {...props}\n >\n {showIcon && (\n <Skeleton\n className=\"size-4 rounded-md\"\n data-sidebar=\"menu-skeleton-icon\"\n />\n )}\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(\"border-sidebar-border mx-3.5 translate-x-px gap-1 border-l px-2.5 py-0.5 group-data-[collapsible=icon]:hidden flex min-w-0 flex-col\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarMenuSubItem({\n className,\n ...props\n}: 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 render,\n size = \"md\",\n isActive = false,\n className,\n ...props\n}: useRender.ComponentProps<\"a\"> &\n React.ComponentProps<\"a\"> & {\n size?: \"sm\" | \"md\"\n isActive?: boolean\n }) {\n return useRender({\n defaultTagName: \"a\",\n props: mergeProps<\"a\">(\n {\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 data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground h-7 gap-2 rounded-md px-2 focus-visible:ring-2 data-[size=md]:text-xs data-[size=sm]:text-xs [&>svg]:size-4 flex min-w-0 -translate-x-px items-center overflow-hidden outline-hidden group-data-[collapsible=icon]:hidden disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:shrink-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-menu-sub-button\",\n sidebar: \"menu-sub-button\",\n size,\n active: isActive,\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 \"@/lib/utils\"\n\nfunction Skeleton({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"skeleton\"\n className={cn(\"bg-muted rounded-md animate-pulse\", className)}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n","\"use client\"\n\nimport { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction TooltipProvider({\n delay = 0,\n ...props\n}: TooltipPrimitive.Provider.Props) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delay={delay}\n {...props}\n />\n )\n}\n\nfunction Tooltip({ ...props }: TooltipPrimitive.Root.Props) {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n )\n}\n\nfunction TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />\n}\n\nfunction TooltipContent({\n className,\n side = \"top\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 0,\n children,\n ...props\n}: TooltipPrimitive.Popup.Props &\n Pick<\n TooltipPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <TooltipPrimitive.Popup\n data-slot=\"tooltip-content\"\n className={cn(\n \"data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-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 rounded-md px-3 py-1.5 text-xs **:data-[slot=kbd]:rounded-md bg-foreground text-background z-50 w-fit max-w-xs origin-(--transform-origin)\",\n className\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground z-50 data-[side=bottom]:top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5\" />\n </TooltipPrimitive.Popup>\n </TooltipPrimitive.Positioner>\n </TooltipPrimitive.Portal>\n )\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Slider as SliderPrimitive } from \"@base-ui/react/slider\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Slider({\n className,\n defaultValue,\n value,\n min = 0,\n max = 100,\n ...props\n}: SliderPrimitive.Root.Props) {\n const _values = React.useMemo(\n () =>\n Array.isArray(value)\n ? value\n : Array.isArray(defaultValue)\n ? defaultValue\n : [min, max],\n [value, defaultValue, min, max]\n )\n\n return (\n <SliderPrimitive.Root\n className=\"data-horizontal:w-full data-vertical:h-full\"\n data-slot=\"slider\"\n defaultValue={defaultValue}\n value={value}\n min={min}\n max={max}\n thumbAlignment=\"edge\"\n {...props}\n >\n <SliderPrimitive.Control\n className={cn(\n \"data-vertical:min-h-40 relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-vertical:h-full data-vertical:w-auto data-vertical:flex-col\",\n className\n )}\n >\n <SliderPrimitive.Track\n data-slot=\"slider-track\"\n className=\"bg-muted rounded-md data-horizontal:h-3 data-horizontal:w-full data-vertical:h-full data-vertical:w-3 relative overflow-hidden select-none\"\n >\n <SliderPrimitive.Indicator\n data-slot=\"slider-range\"\n className=\"bg-primary select-none data-horizontal:h-full data-vertical:w-full\"\n />\n </SliderPrimitive.Track>\n {Array.from({ length: _values.length }, (_, index) => (\n <SliderPrimitive.Thumb\n data-slot=\"slider-thumb\"\n key={index}\n className=\"border-primary ring-ring/30 size-4 rounded-md border bg-white shadow-sm transition-colors hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden block shrink-0 select-none disabled:pointer-events-none disabled:opacity-50\"\n />\n ))}\n </SliderPrimitive.Control>\n </SliderPrimitive.Root>\n )\n}\n\nexport { Slider }\n","\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, type ToasterProps } from \"sonner\"\nimport { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from \"lucide-react\"\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 icons={{\n success: (\n <CircleCheckIcon className=\"size-4\" />\n ),\n info: (\n <InfoIcon className=\"size-4\" />\n ),\n warning: (\n <TriangleAlertIcon className=\"size-4\" />\n ),\n error: (\n <OctagonXIcon className=\"size-4\" />\n ),\n loading: (\n <Loader2Icon className=\"size-4 animate-spin\" />\n ),\n }}\n style={\n {\n \"--normal-bg\": \"var(--popover)\",\n \"--normal-text\": \"var(--popover-foreground)\",\n \"--normal-border\": \"var(--border)\",\n \"--border-radius\": \"var(--radius)\",\n } as React.CSSProperties\n }\n toastOptions={{\n classNames: {\n toast: \"cn-toast\",\n },\n }}\n {...props}\n />\n )\n}\n\nexport { Toaster }\n","\"use client\"\n\nimport { Switch as SwitchPrimitive } from \"@base-ui/react/switch\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Switch({\n className,\n size = \"default\",\n children,\n ...props\n}: SwitchPrimitive.Root.Props & {\n size?: \"sm\" | \"default\"\n}) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-size={size}\n className={cn(\n \"data-checked:bg-primary data-unchecked:bg-input focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 dark:data-unchecked:bg-input/80 shrink-0 rounded-full border border-transparent focus-visible:ring-[2px] aria-invalid:ring-[2px] data-[size=default]:h-[16.6px] data-[size=default]:w-[28px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] peer group/switch relative inline-flex items-center transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n \"bg-background dark:data-unchecked:bg-foreground dark:data-checked:bg-primary-foreground rounded-full group-data-[size=default]/switch:size-3.5 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 pointer-events-none block ring-0 transition-transform\",\n children && \"flex items-center justify-center\"\n )}\n >\n {children}\n </SwitchPrimitive.Thumb>\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\n","\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Table({ className, ...props }: React.ComponentProps<\"table\">) {\n return (\n <div data-slot=\"table-container\" className=\"relative w-full overflow-x-auto\">\n <table\n data-slot=\"table\"\n className={cn(\"w-full caption-bottom text-xs\", className)}\n {...props}\n />\n </div>\n )\n}\n\nfunction TableHeader({ className, ...props }: React.ComponentProps<\"thead\">) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\"[&_tr]:border-b\", className)}\n {...props}\n />\n )\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<\"tbody\">) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<\"tfoot\">) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn(\"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<\"tr\">) {\n return (\n <tr\n data-slot=\"table-row\"\n className={cn(\"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors\", className)}\n {...props}\n />\n )\n}\n\nfunction TableHead({ className, ...props }: React.ComponentProps<\"th\">) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\"text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableCell({ className, ...props }: React.ComponentProps<\"td\">) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableCaption({\n className,\n ...props\n}: React.ComponentProps<\"caption\">) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn(\"text-muted-foreground mt-4 text-xs\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n","\"use client\"\n\nimport { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Tabs({\n className,\n orientation = \"horizontal\",\n ...props\n}: TabsPrimitive.Root.Props) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n data-orientation={orientation}\n className={cn(\n \"gap-2 group/tabs flex data-[orientation=horizontal]:flex-col\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst tabsListVariants = cva(\n \"rounded-lg p-[3px] group-data-horizontal/tabs:h-8 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col\",\n {\n variants: {\n variant: {\n default: \"bg-muted\",\n line: \"gap-1 bg-transparent\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction TabsList({\n className,\n variant = \"default\",\n ...props\n}: TabsPrimitive.List.Props & VariantProps<typeof tabsListVariants>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n data-variant={variant}\n className={cn(tabsListVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"tabs-trigger\"\n className={cn(\n \"gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-xs font-medium group-data-vertical/tabs:py-[calc(--spacing(1.25))] [&_svg:not([class*='size-'])]:size-3.5 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent\",\n \"data-active:bg-background dark:data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 data-active:text-foreground\",\n \"after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {\n return (\n <TabsPrimitive.Panel\n data-slot=\"tabs-content\"\n className={cn(\"text-xs/relaxed flex-1 outline-none\", className)}\n {...props}\n />\n )\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }\n","\"use client\"\n\nimport { Toggle as TogglePrimitive } from \"@base-ui/react/toggle\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst toggleVariants = cva(\n \"hover:text-foreground aria-pressed:bg-muted focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[state=on]:bg-muted gap-1 rounded-md text-xs font-medium transition-all [&_svg:not([class*='size-'])]:size-3.5 group/toggle hover:bg-muted inline-flex items-center justify-center whitespace-nowrap outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n outline: \"border-input hover:bg-muted border bg-transparent\",\n },\n size: {\n default: \"h-7 min-w-7 px-2\",\n sm: \"h-6 min-w-6 rounded-[min(var(--radius-md),8px)] px-1.5 text-[0.625rem] [&_svg:not([class*='size-'])]:size-3\",\n lg: \"h-8 min-w-8 px-2\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Toggle({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {\n return (\n <TogglePrimitive\n data-slot=\"toggle\"\n className={cn(toggleVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\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 * as React from \"react\";\nimport { getI18nLink } from \"../../i18n\";\nimport { cn } from \"../../utils/cn\";\n\n// Create our custom Link props interface\n// Note: We use 'any' for now since the actual Link is retrieved at runtime\nexport interface LinkProps {\n href: string;\n children: React.ReactNode;\n className?: string;\n [key: string]: any;\n}\n\nconst Link = React.forwardRef<HTMLAnchorElement, LinkProps>(({ className, href, children, ...props }, ref) => {\n // Get the configured next-intl Link component at runtime (after i18n is configured)\n const NextIntlLink = getI18nLink();\n return (\n <NextIntlLink prefetch={false} ref={ref} href={href} className={cn(`font-medium`, className)} {...props}>\n {children}\n </NextIntlLink>\n );\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 { cn } from \"../../utils/cn\";\nimport { Badge } from \"../ui/badge\";\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\";\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>, 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 * 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 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\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 </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\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\n key=\"all\"\n onSelect={toggleAll}\n className=\"cursor-pointer hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\n >\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 hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\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 hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\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/data/company.interface\";\nimport { RoleInterface } from \"../../../role\";\nimport { RoleService } from \"../../../role/data/role.service\";\nimport { S3Interface } from \"../../../s3\";\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>{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 { FormFieldWrapper } from \"../../../../components/forms\";\nimport { Modules } from \"../../../../core\";\nimport { DataListRetriever, useDataListRetriever, useDebounce } from \"../../../../hooks\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\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 <FormFieldWrapper form={form} name={id} label={label} isRequired={isRequired}>\n {() => (\n <MultiSelect\n options={userOptions}\n onValueChange={handleValueChange}\n defaultValue={selectedUserIds}\n placeholder={placeholder}\n maxCount={maxCount}\n animation={0}\n />\n )}\n </FormFieldWrapper>\n </div>\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>\n <Button render={<div />} nativeButton={false} 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","\"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","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>\n {isEdit ? (\n <Button render={<div />} nativeButton={false} size=\"sm\" variant={`ghost`} className=\"text-muted-foreground\">\n <PencilIcon />\n </Button>\n ) : (\n <Button render={<div />} nativeButton={false} 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>{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 if (!value) return;\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 if (!value) return;\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>\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\";\n\nexport type { DropzoneOptions } 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 { ReactNode } from \"react\";\nimport {\n Controller,\n ControllerFieldState,\n ControllerRenderProps,\n FieldValues,\n Path,\n UseFormReturn,\n} from \"react-hook-form\";\nimport { Field, FieldDescription, FieldError, FieldLabel } from \"../../shadcnui\";\n\ntype FormFieldWrapperProps<T extends FieldValues> = {\n form: UseFormReturn<T>;\n name: Path<T>;\n label?: string;\n description?: string;\n isRequired?: boolean;\n orientation?: \"vertical\" | \"horizontal\" | \"responsive\";\n children: (field: ControllerRenderProps<T, Path<T>>, fieldState: ControllerFieldState) => ReactNode;\n testId?: string;\n};\n\nexport function FormFieldWrapper<T extends FieldValues>({\n form,\n name,\n label,\n description,\n isRequired,\n orientation = \"vertical\",\n children,\n testId,\n}: FormFieldWrapperProps<T>) {\n return (\n <Controller\n control={form.control}\n name={name}\n render={({ field, fieldState }) => (\n <Field orientation={orientation} data-invalid={!!fieldState.error} data-testid={testId}>\n {label && (\n <FieldLabel>\n {label}\n {isRequired && <span className=\"text-destructive ml-1 font-semibold\">*</span>}\n </FieldLabel>\n )}\n {children(field, fieldState)}\n {description && <FieldDescription>{description}</FieldDescription>}\n {fieldState.error && <FieldError>{fieldState.error.message}</FieldError>}\n </Field>\n )}\n />\n );\n}\n","\"use client\";\n\nimport {\n Checkbox,\n FieldLabel,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FieldLabel htmlFor={id} className={`font-normal ${labelBefore ? \"\" : \"ml-3\"}`}>\n {name}\n </FieldLabel>\n );\n };\n\n const label = () => {\n if (!description) return simpleLabel();\n else\n return (\n <Tooltip>\n <TooltipTrigger>{simpleLabel()}</TooltipTrigger>\n <TooltipContent>{description}</TooltipContent>\n </Tooltip>\n );\n };\n\n return (\n <div className=\"flex w-full flex-col\">\n <FormFieldWrapper\n form={form}\n name={id}\n orientation=\"horizontal\"\n >\n {(field) => (\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 )}\n </FormFieldWrapper>\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 InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupInput,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n isRequired={isRequired}\n >\n {(field) => (\n <Popover open={open} onOpenChange={setOpen} modal={true}>\n <InputGroup>\n <InputGroupInput\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value, field)}\n placeholder={datePlaceholder}\n />\n <InputGroupAddon align=\"inline-end\">\n <PopoverTrigger render={<div />} nativeButton={false}>\n <InputGroupButton variant=\"ghost\" size=\"icon-xs\">\n <CalendarIcon className=\"h-4 w-4 opacity-50\" />\n </InputGroupButton>\n </PopoverTrigger>\n {field.value && (\n <InputGroupButton\n variant=\"ghost\"\n size=\"icon-xs\"\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 </InputGroupButton>\n )}\n </InputGroupAddon>\n </InputGroup>\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 if (!value) return;\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 if (!value) return;\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 )}\n </FormFieldWrapper>\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 Label,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n >\n {(field) => (\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\n render={\n <Button\n variant={\"outline\"}\n className={cn(\"w-full pl-3 text-left font-normal\", !field.value && \"text-muted-foreground\")}\n />\n }\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 </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 if (!value) return;\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 />\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 if (!value) return;\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 />\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 )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport { useTranslations } from \"next-intl\";\nimport React from \"react\";\nimport {\n Input,\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n InputGroupText,\n} from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n isRequired={isRequired}\n >\n {(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 const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\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 const inputProps = {\n ...field,\n autoFocus: autoFocus === true,\n type:\n type === \"number\" || type === \"currency\"\n ? \"number\"\n : type === \"password\"\n ? \"password\"\n : \"text\",\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,\n onChange: handleChange,\n \"data-testid\": testId,\n };\n\n // Use InputGroup for currency type to show Euro symbol\n if (type === \"currency\") {\n return (\n <InputGroup>\n <InputGroupAddon>\n <InputGroupText>{\"\\u20AC\"}</InputGroupText>\n </InputGroupAddon>\n <InputGroupInput {...inputProps} />\n </InputGroup>\n );\n }\n\n // Regular input for other types\n return <Input {...inputProps} />;\n }}\n </FormFieldWrapper>\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 { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n isRequired={isRequired}\n testId={testId}\n >\n {(field) => (\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 )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { Input } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper form={form} name={id} label={name} isRequired={isRequired}>\n {(field) => (\n <Input\n {...field}\n placeholder={placeholder}\n disabled={disabled}\n data-testid={testId}\n className={cn(\"w-full\", className)}\n />\n )}\n </FormFieldWrapper>\n </div>\n );\n }\n\n return (\n <div className=\"flex w-full flex-col\" ref={containerRef}>\n <FormFieldWrapper form={form} name={id} label={name} isRequired={isRequired}>\n {(field) => (\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 )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n orientation={useRows ? \"horizontal\" : \"vertical\"}\n testId={testId}\n >\n {(field) => (\n <Select\n onValueChange={(e) => {\n field.onChange(e);\n if (onChange) onChange(e);\n }}\n value={field.value}\n disabled={disabled}\n data-testid={testId}\n >\n <SelectTrigger className=\"w-full\">\n <SelectValue />\n </SelectTrigger>\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 )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport { useWatch } from \"react-hook-form\";\nimport { Slider } from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n label={name}\n >\n {() => (\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={(val) => {\n const newValue = Array.isArray(val) ? val[0] : val;\n form.setValue(id, newValue);\n }}\n value={[value]}\n max={100}\n step={5}\n disabled={disabled === true || form.formState.isSubmitting}\n />\n </div>\n )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport { FieldLabel, Switch } from \"../../shadcnui\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper\n form={form}\n name={id}\n orientation=\"horizontal\"\n >\n {(field) => (\n <div className=\"flex flex-row gap-x-4\">\n <Switch checked={field.value} onCheckedChange={field.onChange} disabled={disabled} />\n {name && <FieldLabel>{name}</FieldLabel>}\n </div>\n )}\n </FormFieldWrapper>\n </div>\n );\n}\n","\"use client\";\n\nimport { Textarea } from \"../../shadcnui\";\nimport { cn } from \"../../utils\";\nimport { FormFieldWrapper } from \"./FormFieldWrapper\";\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 <FormFieldWrapper form={form} name={id} label={name} testId={testId}>\n {(field) => (\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 )}\n </FormFieldWrapper>\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 { Checkbox, Label, ScrollArea } from \"../../../../shadcnui\";\nimport { FeatureInterface } from \"../../data\";\n\ntype FormFeaturesProps = {\n form: any;\n name?: string;\n features: FeatureInterface[];\n featureField?: string;\n};\n\nexport function FormFeatures({ form, name, features, featureField = \"featureIds\" }: FormFeaturesProps) {\n const selectedFeatures: string[] = form.watch(featureField);\n\n const toggleFeature = (feature: FeatureInterface, checked: boolean) => {\n let newFeatureIds = [...selectedFeatures];\n\n if (checked) {\n if (!newFeatureIds.includes(feature.id)) {\n newFeatureIds.push(feature.id);\n }\n } else {\n newFeatureIds = newFeatureIds.filter((id) => id !== feature.id);\n }\n form.setValue(featureField, newFeatureIds);\n };\n\n const isFeatureChecked = (feature: FeatureInterface) => selectedFeatures.includes(feature.id);\n\n return (\n <div className=\"flex w-full flex-col\">\n {name && <h2 className=\"mb-4 border-b text-lg font-semibold\">{name}</h2>}\n <ScrollArea className=\"h-[40vh]\">\n <div className=\"flex flex-col gap-y-2 pr-4\">\n {features\n .filter((feature) => !feature.isCore)\n .map((feature) => (\n <div key={feature.id} className=\"flex items-center\">\n <Checkbox\n id={feature.id}\n checked={isFeatureChecked(feature)}\n onCheckedChange={(val) => {\n toggleFeature(feature, val === true);\n }}\n />\n <Label htmlFor={feature.id} className=\"ml-3 cursor-pointer font-normal\">\n {feature.name}\n </Label>\n </div>\n ))}\n </div>\n </ScrollArea>\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>\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>\n <DialogTrigger>\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 { FormFieldWrapper } from \"../../../../components/forms\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n Command,\n CommandItem,\n CommandList,\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 <FormFieldWrapper\n form={form}\n name={id}\n label={label}\n isRequired={isRequired}\n >\n {(field) => (\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\n className=\"cursor-pointer hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\n key={user.id}\n onSelect={() => setUser(user)}\n >\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 )}\n </FormFieldWrapper>\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 showTooltip?: boolean;\n};\n\nexport function UserAvatar({ user, className, showFull, showLink, showTooltip = true }: 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 const content =\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: React.MouseEvent<HTMLAnchorElement>) => 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\n if (!showTooltip) {\n return content;\n }\n\n return (\n <Tooltip>\n <TooltipTrigger>{content}</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 module={Modules.User} 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/data/company.interface\";\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: React.MouseEvent<HTMLAnchorElement>) => 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: React.MouseEvent<HTMLAnchorElement>) => 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 hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\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 { Modules } from \"../../../../\";\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 module={Modules.Company} 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 { Battery, BatteryFull, BatteryLow, BatteryMedium, PlusCircle } from \"lucide-react\";\nimport Link from \"next/link\";\n\nimport { cn } from \"@/lib/utils\";\nimport { useTranslations } from \"next-intl\";\nimport { Button, Separator, Tooltip, TooltipContent, TooltipTrigger } from \"../../../../shadcnui\";\nimport { useCurrentUserContext } from \"../../../user/contexts\";\n\ninterface TokenStatusIndicatorProps {\n className?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n showExtraPages?: boolean;\n}\n\n/**\n * TokenStatusIndicator displays the current status of available monthly and extra pages\n * using battery icons to represent the percentage of monthly pages remaining.\n *\n * Battery levels:\n * - BatteryFull: >75% available\n * - BatteryMedium: 25-75% available\n * - BatteryLow: 5-25% available\n * - Battery (empty): <5% available\n */\nexport function TokenStatusIndicator({ className, size = \"md\", showExtraPages = true }: TokenStatusIndicatorProps) {\n const { company } = useCurrentUserContext();\n const t = useTranslations();\n\n // Don't render if no company data\n if (!company) return null;\n\n const monthlyTokens = company.monthlyTokens;\n const availableMonthlyTokens = company.availableMonthlyTokens;\n const availableExtraTokens = company.availableExtraTokens;\n\n // Calculate percentage of available monthly pages\n const percentage = monthlyTokens > 0 ? (availableMonthlyTokens / monthlyTokens) * 100 : 0;\n\n const sizeClasses = {\n sm: \"h-4 w-4\",\n md: \"h-5 w-5\",\n lg: \"h-6 w-6\",\n };\n\n const smallIconSizeClasses = {\n sm: \"h-3 w-3\",\n md: \"h-4 w-4\",\n lg: \"h-5 w-5\",\n };\n\n const textSizeClasses = {\n sm: \"text-xs\",\n md: \"text-sm\",\n lg: \"text-base\",\n };\n\n const iconSize = sizeClasses[size];\n const smallIconSize = smallIconSizeClasses[size];\n const textSize = textSizeClasses[size];\n\n const getBatteryIcon = () => {\n if (percentage > 75) {\n return <BatteryFull className={cn(iconSize, \"text-green-500\")} />;\n } else if (percentage >= 25) {\n return <BatteryMedium className={cn(iconSize, \"text-yellow-500\")} />;\n } else if (percentage >= 5) {\n return <BatteryLow className={cn(iconSize, \"text-orange-500\")} />;\n } else {\n return <Battery className={cn(iconSize, \"text-destructive\")} />;\n }\n };\n\n const getStatusColor = () => {\n if (percentage > 75) {\n return \"text-green-500\";\n } else if (percentage >= 25) {\n return \"text-yellow-500\";\n } else if (percentage >= 5) {\n return \"text-orange-500\";\n } else {\n return \"text-destructive\";\n }\n };\n\n const tooltipContent = (\n <div className=\"flex flex-col gap-2 p-1\">\n <div className=\"font-semibold text-sm\">{t(\"generic.tokens.status\", { defaultValue: \"Page Status\" })}</div>\n <div className=\"flex flex-col gap-1 text-xs\">\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-muted-foreground\">\n {t(\"generic.tokens.monthly\", { defaultValue: \"Monthly Pages\" })}:\n </span>\n <span className={cn(\"font-medium\", getStatusColor())}>\n {availableMonthlyTokens} / {monthlyTokens}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-muted-foreground\">{t(\"generic.tokens.available\", { defaultValue: \"Available\" })}:</span>\n <span className={cn(\"font-medium\", getStatusColor())}>{percentage.toFixed(0)}%</span>\n </div>\n <Link href=\"/settings/billing?action=subscribe\" className=\"w-full flex justify-end my-4\">\n <Button variant=\"outline\" size=\"sm\">\n {t(\"generic.tokens.upgrade_plan\", { defaultValue: \"Upgrade plan\" })}\n </Button>\n </Link>\n <Separator />\n <div className=\"flex items-center justify-between gap-4 pt-1 mt-1\">\n <span className=\"text-muted-foreground\">\n {t(\"generic.tokens.available_extra\", { defaultValue: \"Extra Pages\" })}:\n </span>\n <span className=\"font-medium text-blue-500\">{availableExtraTokens}</span>\n </div>\n <Link href=\"/settings/billing?action=subscribe\" className=\"w-full flex justify-end my-4\">\n <Button variant=\"outline\" size=\"sm\">\n {t(\"generic.tokens.purchase_extra\", { defaultValue: \"Purchase additional analysis\" })}\n </Button>\n </Link>\n </div>\n </div>\n );\n\n return (\n <Tooltip>\n <TooltipTrigger>\n <div\n className={cn(\"inline-flex items-center gap-1.5 cursor-default\", className)}\n aria-label={t(\"generic.tokens.status\", { defaultValue: \"Page Status\" })}\n >\n {getBatteryIcon()}\n <span className={cn(textSize, \"text-muted-foreground font-medium\")}>{availableMonthlyTokens}</span>\n {showExtraPages && availableExtraTokens > 0 && (\n <div className=\"inline-flex items-center gap-0.5\">\n <PlusCircle className={cn(smallIconSize, \"text-blue-500\")} />\n <span className={cn(textSize, \"text-blue-500 font-medium\")}>{availableExtraTokens}</span>\n </div>\n )}\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-xs\">\n {tooltipContent}\n </TooltipContent>\n </Tooltip>\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 { useCurrentUserContext } from \"../../../user/contexts\";\nimport { UserService } from \"../../../user/data/user.service\";\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>\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 { FormFieldWrapper } from \"../../../../components/forms\";\nimport { Checkbox, 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 <FormFieldWrapper\n key={currentField}\n form={form}\n name={currentField}\n label={label}\n description={type === \"checkbox\" ? placeholder : undefined}\n isRequired={isRequired}\n orientation={type === \"checkbox\" ? \"horizontal\" : \"vertical\"}\n >\n {(field) =>\n type === \"checkbox\" ? (\n <Checkbox\n id={currentField}\n checked={field.value}\n onCheckedChange={(checked) => {\n return checked ? field.onChange(true) : field.onChange(false);\n }}\n />\n ) : (\n <Input type={type} placeholder={placeholder} {...field} />\n )\n }\n </FormFieldWrapper>\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>\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 { FeatureService } from \"../../../feature/data/feature.service\";\nimport { S3Interface } from \"../../../s3\";\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.isCore));\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 { 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 // Use actionUrl from notification if available (for notifications without actor relationships)\n if (params.notification.actionUrl) {\n response.url = params.notification.actionUrl;\n }\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 message: notification.message ?? \"\",\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 message: notification.message ?? \"\",\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","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 { ModuleWithPermissions } from \"../../permissions\";\nimport { cn } from \"../../utils\";\n\ntype TitleProps = {\n type?: string | string[];\n element?: string;\n functions?: ReactNode;\n className?: string;\n module?: ModuleWithPermissions;\n};\n\nexport function ContentTitle({ module, 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 items-center justify-between gap-x-4 w-full`, className)}>\n <div className=\"flex flex-col w-full\">\n {type && (\n <div className={`text-muted-foreground text-xl font-light flex gap-x-2 items-center`}>\n {module && module.icon && <module.icon className=\"w-5 h-5 inline-block\" />}\n {type}\n </div>\n )}\n <div className={`text-primary w-full text-3xl font-semibold`}>{element}</div>\n </div>\n {isClient && clientFunctions && <div className=\"flex flex-row items-center justify-start\">{clientFunctions}</div>}\n </div>\n );\n}\n","\"use client\";\n\nimport { getRoleId } from \"@/roles\";\nimport { RefreshCwIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useSharedContext } from \"../../contexts/SharedContext\";\nimport { TokenStatusIndicator } from \"../../features/company/components/details\";\nimport { useCurrentUserContext } from \"../../features/user/contexts\";\nimport { Button, SidebarTrigger, Tooltip, TooltipContent, TooltipTrigger } from \"../../shadcnui\";\nimport { BreadcrumbNavigation } from \"./Breadcrumb\";\n\ntype HeaderProps = {\n children?: React.ReactNode;\n};\n\nexport function Header({ children }: HeaderProps) {\n const t = useTranslations();\n const { breadcrumbs } = useSharedContext();\n const { company, hasRole, refreshUser, isRefreshing } = useCurrentUserContext();\n const showTokenStatus = !hasRole(getRoleId().Administrator) && company;\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 <div className=\"flex flex-row items-center justify-end gap-x-4 whitespace-nowrap\">\n {showTokenStatus && (\n <div className=\"flex items-center gap-x-2\">\n <TokenStatusIndicator size=\"sm\" showExtraPages={true} />\n <Tooltip>\n <TooltipTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={() => refreshUser()}\n disabled={isRefreshing}\n aria-label={t(\"generic.refresh\", { defaultValue: \"Refresh\" })}\n />\n }\n >\n <RefreshCwIcon className={`h-3.5 w-3.5 ${isRefreshing ? \"animate-spin\" : \"\"}`} />\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">{t(\"generic.refresh\", { defaultValue: \"Refresh\" })}</TooltipContent>\n </Tooltip>\n </div>\n )}\n {children ? children : null}\n </div>\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>\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}`}>\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 { useHeaderChildren } from \"../../contexts/HeaderChildrenContext\";\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 const headerChildren = useHeaderChildren();\n\n return (\n <div className={`flex h-full w-full flex-col`} data-testid={testId}>\n <Header>{headerChildren}</Header>\n <main className={cn(`flex w-full flex-1 flex-col gap-y-4 pt-4 pl-4 pr-4 pb-20`, 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 { 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, useEffect, useState } from \"react\";\nimport { ResizableHandle, ResizablePanel, ResizablePanelGroup } from \"../../shadcnui\";\nimport { useIsMobile } from \"../../utils\";\n\ntype PageContentContainerProps = {\n header?: ReactNode;\n details?: ReactNode;\n footer?: ReactNode;\n content?: ReactNode;\n};\n\nexport function PageContentContainer({ header, details, footer, content }: PageContentContainerProps) {\n const [mounted, setMounted] = useState(false);\n const isMobile = useIsMobile();\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const isReady = mounted && isMobile !== undefined;\n\n if (!isReady) {\n return <div className=\"flex h-[calc(100vh-4rem)] w-full flex-col\" />;\n }\n\n return (\n <div className=\"flex h-[calc(100vh-4rem)] w-full flex-col transition-opacity duration-150 animate-in fade-in\">\n {header && <div className=\"mb-4 flex w-full shrink-0 border-b\">{header}</div>}\n <div className=\"min-h-0 flex-1\">\n {details || footer ? (\n <ResizablePanelGroup\n autoSaveId={`page-content-container-${isMobile ? \"mobile\" : \"desktop\"}`}\n direction={isMobile ? \"vertical\" : \"horizontal\"}\n className=\"h-full items-stretch\"\n >\n <ResizablePanel\n id=\"left-panel\"\n defaultSize={isMobile ? 10 : 32}\n minSize={isMobile ? 10 : 20}\n maxSize={isMobile ? 90 : 40}\n >\n <div className={`@container flex h-full flex-col ${isMobile ? \"pb-4\" : \"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={isMobile ? \"pt-4\" : \"pl-4\"}>\n <div className=\"h-full overflow-x-hidden overflow-y-auto p-2 pb-20\">{content}</div>\n </ResizablePanel>\n </ResizablePanelGroup>\n ) : (\n <div className=\"h-full overflow-x-hidden overflow-y-auto p-2 pb-20\">{content}</div>\n )}\n </div>\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 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 { useMemo } from \"react\";\nimport { useCurrentUserContext } from \"../../user/contexts/CurrentUserContext\";\n\nexport interface TrialSubscriptionStatus {\n status: \"loading\" | \"trial\" | \"active\" | \"expired\";\n trialEndsAt: Date | null;\n daysRemaining: number;\n isGracePeriod: boolean; // Last 3 days\n isBlocked: boolean;\n}\n\nconst TRIAL_DAYS = 14;\nconst GRACE_DAYS = 3;\n\nexport function useSubscriptionStatus(): TrialSubscriptionStatus {\n const { company, currentUser } = useCurrentUserContext();\n\n return useMemo(() => {\n // Still loading user data - don't block yet\n if (currentUser === null) {\n return {\n status: \"loading\",\n trialEndsAt: null,\n daysRemaining: 0,\n isGracePeriod: false,\n isBlocked: false,\n };\n }\n\n // No company after loading = blocked\n if (!company) {\n return {\n status: \"expired\",\n trialEndsAt: null,\n daysRemaining: 0,\n isGracePeriod: false,\n isBlocked: true,\n };\n }\n\n // Has active subscription = never blocked\n if (company.isActiveSubscription) {\n return {\n status: \"active\",\n trialEndsAt: null,\n daysRemaining: 0,\n isGracePeriod: false,\n isBlocked: false,\n };\n }\n\n // Calculate trial status from createdAt\n const createdAt = new Date(company.createdAt);\n const trialEndsAt = new Date(createdAt);\n trialEndsAt.setDate(trialEndsAt.getDate() + TRIAL_DAYS);\n\n const now = new Date();\n const msRemaining = trialEndsAt.getTime() - now.getTime();\n const daysRemaining = Math.ceil(msRemaining / (1000 * 60 * 60 * 24));\n\n return {\n status: daysRemaining > 0 ? \"trial\" : \"expired\",\n trialEndsAt,\n daysRemaining: Math.max(0, daysRemaining),\n isGracePeriod: daysRemaining > 0 && daysRemaining <= GRACE_DAYS,\n isBlocked: daysRemaining <= 0,\n };\n }, [company, currentUser]);\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\nimport { useAtom, useSetAtom } from \"jotai\";\nimport { useCallback, useEffect } from \"react\";\nimport {\n addOAuthClientAtom,\n oauthClientsAtom,\n oauthClientsErrorAtom,\n oauthClientsLoadingAtom,\n setNewClientSecretAtom,\n} from \"../atoms/oauth.atoms\";\nimport {\n OAuthClientCreateRequest,\n OAuthClientCreateResponse,\n OAuthClientInterface,\n} from \"../interfaces/oauth.interface\";\nimport { OAuthService } from \"../data/oauth.service\";\n\nexport interface UseOAuthClientsReturn {\n /** List of OAuth clients */\n clients: OAuthClientInterface[];\n /** Whether clients are being loaded */\n isLoading: boolean;\n /** Error from last operation */\n error: Error | null;\n /** Refetch clients from API */\n refetch: () => Promise<void>;\n /** Create a new OAuth client */\n createClient: (data: OAuthClientCreateRequest) => Promise<OAuthClientCreateResponse>;\n}\n\n/**\n * Hook for managing OAuth clients list\n *\n * @example\n * ```tsx\n * const { clients, isLoading, createClient } = useOAuthClients();\n *\n * const handleCreate = async (data) => {\n * const { client, clientSecret } = await createClient(data);\n * // clientSecret is shown only once!\n * };\n * ```\n */\nexport function useOAuthClients(): UseOAuthClientsReturn {\n const [clients, setClients] = useAtom(oauthClientsAtom);\n const [isLoading, setIsLoading] = useAtom(oauthClientsLoadingAtom);\n const [error, setError] = useAtom(oauthClientsErrorAtom);\n const addClient = useSetAtom(addOAuthClientAtom);\n const setNewClientSecret = useSetAtom(setNewClientSecretAtom);\n\n const fetchClients = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n const fetchedClients = await OAuthService.listClients();\n setClients(fetchedClients);\n } catch (err) {\n console.error(\"[useOAuthClients] Failed to fetch clients:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to fetch OAuth clients\"));\n } finally {\n setIsLoading(false);\n }\n }, [setClients, setIsLoading, setError]);\n\n // Fetch clients on mount\n useEffect(() => {\n fetchClients();\n }, [fetchClients]);\n\n const createClient = useCallback(\n async (data: OAuthClientCreateRequest): Promise<OAuthClientCreateResponse> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await OAuthService.createClient(data);\n\n // Add to local state\n addClient(result.client);\n\n // Store secret for one-time display\n if (result.clientSecret) {\n setNewClientSecret({\n clientId: result.client.clientId,\n secret: result.clientSecret,\n });\n }\n\n return result;\n } catch (err) {\n console.error(\"[useOAuthClients] Failed to create client:\", err);\n const error = err instanceof Error ? err : new Error(\"Failed to create OAuth client\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [addClient, setNewClientSecret, setIsLoading, setError],\n );\n\n return {\n clients,\n isLoading,\n error,\n refetch: fetchClients,\n createClient,\n };\n}\n","import { atom } from \"jotai\";\nimport { atomFamily } from \"jotai-family\";\nimport { OAuthClientInterface } from \"../interfaces/oauth.interface\";\n\n// ==========================================\n// OAUTH CLIENTS STATE\n// ==========================================\n\n/**\n * Primary store for OAuth clients\n * Populated by useOAuthClients hook\n */\nexport const oauthClientsAtom = atom<OAuthClientInterface[]>([]);\n\n/**\n * Loading state for OAuth clients list\n */\nexport const oauthClientsLoadingAtom = atom<boolean>(false);\n\n/**\n * Error state for OAuth client operations\n */\nexport const oauthClientsErrorAtom = atom<Error | null>(null);\n\n/**\n * Derived atom family for getting a single client by ID\n * Usage: const client = useAtomValue(oauthClientByIdAtom(clientId))\n *\n * @param clientId - The client ID (not the internal id, but the clientId field)\n * @returns The client if found, undefined otherwise\n */\nexport const oauthClientByIdAtom = atomFamily((clientId: string) =>\n atom((get) => {\n const clients = get(oauthClientsAtom);\n return clients.find((c) => c.clientId === clientId || c.id === clientId);\n }),\n);\n\n// ==========================================\n// ONE-TIME SECRET DISPLAY STATE\n// ==========================================\n\n/**\n * Stores the client secret for one-time display\n * Set after createClient or regenerateSecret, cleared after user acknowledges\n */\nexport const oauthNewClientSecretAtom = atom<string | null>(null);\n\n/**\n * The client ID associated with the new secret\n * Used to know which client the secret belongs to\n */\nexport const oauthNewClientIdAtom = atom<string | null>(null);\n\n// ==========================================\n// CONSENT FLOW STATE\n// ==========================================\n\n/**\n * Loading state for consent screen data fetch\n */\nexport const oauthConsentLoadingAtom = atom<boolean>(false);\n\n/**\n * Error state for consent flow\n */\nexport const oauthConsentErrorAtom = atom<Error | null>(null);\n\n// ==========================================\n// WRITE ATOMS (for actions)\n// ==========================================\n\n/**\n * Write atom to set a new client secret and associated client ID\n */\nexport const setNewClientSecretAtom = atom(null, (get, set, value: { clientId: string; secret: string } | null) => {\n if (value === null) {\n set(oauthNewClientSecretAtom, null);\n set(oauthNewClientIdAtom, null);\n } else {\n set(oauthNewClientSecretAtom, value.secret);\n set(oauthNewClientIdAtom, value.clientId);\n }\n});\n\n/**\n * Write atom to clear the new client secret (after user acknowledges)\n */\nexport const clearNewClientSecretAtom = atom(null, (get, set) => {\n set(oauthNewClientSecretAtom, null);\n set(oauthNewClientIdAtom, null);\n});\n\n/**\n * Write atom to update the clients list\n */\nexport const setOAuthClientsAtom = atom(null, (get, set, clients: OAuthClientInterface[]) => {\n set(oauthClientsAtom, clients);\n});\n\n/**\n * Write atom to add a client to the list\n */\nexport const addOAuthClientAtom = atom(null, (get, set, client: OAuthClientInterface) => {\n const clients = get(oauthClientsAtom);\n set(oauthClientsAtom, [...clients, client]);\n});\n\n/**\n * Write atom to update a client in the list\n */\nexport const updateOAuthClientAtom = atom(null, (get, set, updatedClient: OAuthClientInterface) => {\n const clients = get(oauthClientsAtom);\n const index = clients.findIndex((c) => c.id === updatedClient.id || c.clientId === updatedClient.clientId);\n if (index !== -1) {\n const newClients = [...clients];\n newClients[index] = updatedClient;\n set(oauthClientsAtom, newClients);\n }\n});\n\n/**\n * Write atom to remove a client from the list\n */\nexport const removeOAuthClientAtom = atom(null, (get, set, clientId: string) => {\n const clients = get(oauthClientsAtom);\n set(\n oauthClientsAtom,\n clients.filter((c) => c.id !== clientId && c.clientId !== clientId),\n );\n});\n","\"use client\";\n\nimport { useAtomValue, useSetAtom } from \"jotai\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport {\n oauthClientByIdAtom,\n removeOAuthClientAtom,\n setNewClientSecretAtom,\n updateOAuthClientAtom,\n} from \"../atoms/oauth.atoms\";\nimport { OAuthClientInput, OAuthClientInterface } from \"../interfaces/oauth.interface\";\nimport { OAuthService } from \"../data/oauth.service\";\n\nexport interface UseOAuthClientReturn {\n /** The OAuth client (from store or fetched) */\n client: OAuthClientInterface | null;\n /** Whether the client is being loaded */\n isLoading: boolean;\n /** Error from last operation */\n error: Error | null;\n /** Update the client */\n update: (data: Partial<OAuthClientInput>) => Promise<void>;\n /** Delete the client */\n deleteClient: () => Promise<void>;\n /** Regenerate the client secret */\n regenerateSecret: () => Promise<string>;\n /** Refetch client from API */\n refetch: () => Promise<void>;\n}\n\n/**\n * Hook for managing a single OAuth client\n *\n * @param clientId - The client ID to manage\n *\n * @example\n * ```tsx\n * const { client, update, deleteClient, regenerateSecret } = useOAuthClient(clientId);\n *\n * const handleRegenerate = async () => {\n * const newSecret = await regenerateSecret();\n * // newSecret is shown only once!\n * };\n * ```\n */\nexport function useOAuthClient(clientId: string): UseOAuthClientReturn {\n // Try to get from store first (populated by useOAuthClients)\n const storedClient = useAtomValue(oauthClientByIdAtom(clientId));\n const updateClientInStore = useSetAtom(updateOAuthClientAtom);\n const removeClientFromStore = useSetAtom(removeOAuthClientAtom);\n const setNewClientSecret = useSetAtom(setNewClientSecretAtom);\n\n // Local state for fetched client (if not in store)\n const [fetchedClient, setFetchedClient] = useState<OAuthClientInterface | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const client = storedClient || fetchedClient;\n\n const fetchClient = useCallback(async () => {\n if (!clientId) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const fetched = await OAuthService.getClient({ clientId });\n setFetchedClient(fetched);\n } catch (err) {\n console.error(\"[useOAuthClient] Failed to fetch client:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to fetch OAuth client\"));\n } finally {\n setIsLoading(false);\n }\n }, [clientId]);\n\n // Fetch if not in store\n useEffect(() => {\n if (!storedClient && clientId) {\n fetchClient();\n }\n }, [storedClient, clientId, fetchClient]);\n\n const update = useCallback(\n async (data: Partial<OAuthClientInput>): Promise<void> => {\n if (!clientId) throw new Error(\"No client ID\");\n\n setIsLoading(true);\n setError(null);\n\n try {\n const updated = await OAuthService.updateClient({ clientId, data });\n updateClientInStore(updated);\n setFetchedClient(updated);\n } catch (err) {\n console.error(\"[useOAuthClient] Failed to update client:\", err);\n const error = err instanceof Error ? err : new Error(\"Failed to update OAuth client\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n },\n [clientId, updateClientInStore],\n );\n\n const deleteClient = useCallback(async (): Promise<void> => {\n if (!clientId) throw new Error(\"No client ID\");\n\n setIsLoading(true);\n setError(null);\n\n try {\n await OAuthService.deleteClient({ clientId });\n removeClientFromStore(clientId);\n } catch (err) {\n console.error(\"[useOAuthClient] Failed to delete client:\", err);\n const error = err instanceof Error ? err : new Error(\"Failed to delete OAuth client\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, [clientId, removeClientFromStore]);\n\n const regenerateSecret = useCallback(async (): Promise<string> => {\n if (!clientId) throw new Error(\"No client ID\");\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await OAuthService.regenerateSecret({ clientId });\n\n // Store for one-time display\n setNewClientSecret({\n clientId,\n secret: result.clientSecret,\n });\n\n return result.clientSecret;\n } catch (err) {\n console.error(\"[useOAuthClient] Failed to regenerate secret:\", err);\n const error = err instanceof Error ? err : new Error(\"Failed to regenerate client secret\");\n setError(error);\n throw error;\n } finally {\n setIsLoading(false);\n }\n }, [clientId, setNewClientSecret]);\n\n return {\n client,\n isLoading,\n error,\n update,\n deleteClient,\n regenerateSecret,\n refetch: fetchClient,\n };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { OAuthConsentInfo, OAuthConsentRequest } from \"../interfaces/oauth.interface\";\nimport { OAuthService } from \"../data/oauth.service\";\n\nexport interface UseOAuthConsentReturn {\n /** Client and scope info for consent display */\n clientInfo: OAuthConsentInfo | null;\n /** Whether consent info is being loaded */\n isLoading: boolean;\n /** Error from consent flow */\n error: Error | null;\n /** Approve the authorization request */\n approve: () => Promise<void>;\n /** Deny the authorization request */\n deny: () => Promise<void>;\n /** Whether approve/deny is in progress */\n isSubmitting: boolean;\n}\n\n/**\n * Hook for managing the OAuth consent flow\n *\n * @param params - OAuth authorization parameters from URL\n *\n * @example\n * ```tsx\n * const { clientInfo, isLoading, approve, deny } = useOAuthConsent({\n * clientId: searchParams.client_id,\n * redirectUri: searchParams.redirect_uri,\n * scope: searchParams.scope,\n * state: searchParams.state,\n * });\n *\n * // Render consent screen with clientInfo\n * // On button click: approve() or deny()\n * ```\n */\nexport function useOAuthConsent(params: OAuthConsentRequest): UseOAuthConsentReturn {\n const [clientInfo, setClientInfo] = useState<OAuthConsentInfo | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n // Fetch client info on mount\n useEffect(() => {\n const fetchInfo = async () => {\n if (!params.clientId || !params.redirectUri || !params.scope) {\n setError(new Error(\"Missing required authorization parameters\"));\n setIsLoading(false);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const info = await OAuthService.getAuthorizationInfo(params);\n setClientInfo(info);\n } catch (err) {\n console.error(\"[useOAuthConsent] Failed to fetch authorization info:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to load authorization info\"));\n } finally {\n setIsLoading(false);\n }\n };\n\n fetchInfo();\n }, [\n params.clientId,\n params.redirectUri,\n params.scope,\n params.state,\n params.codeChallenge,\n params.codeChallengeMethod,\n ]);\n\n const approve = useCallback(async (): Promise<void> => {\n setIsSubmitting(true);\n setError(null);\n\n try {\n const result = await OAuthService.approveAuthorization(params);\n\n // Redirect to client with authorization code\n if (result.redirectUrl) {\n window.location.href = result.redirectUrl;\n }\n } catch (err) {\n console.error(\"[useOAuthConsent] Failed to approve authorization:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to approve authorization\"));\n setIsSubmitting(false);\n }\n // Note: Don't set isSubmitting to false on success - we're redirecting\n }, [params]);\n\n const deny = useCallback(async (): Promise<void> => {\n setIsSubmitting(true);\n setError(null);\n\n try {\n const result = await OAuthService.denyAuthorization(params);\n\n // Redirect to client with error\n if (result.redirectUrl) {\n window.location.href = result.redirectUrl;\n }\n } catch (err) {\n console.error(\"[useOAuthConsent] Failed to deny authorization:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to deny authorization\"));\n setIsSubmitting(false);\n }\n // Note: Don't set isSubmitting to false on success - we're redirecting\n }, [params]);\n\n return {\n clientInfo,\n isLoading,\n error,\n approve,\n deny,\n isSubmitting,\n };\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\";\nexport * from \"../features/oauth/hooks\";\nexport * from \"../features/company/hooks/useSubscriptionStatus\";\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 { ChevronLeft, ChevronRight } from \"lucide-react\";\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 <ChevronLeft 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 <ChevronRight 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 { isDiscordAuthEnabled, isInternalAuthEnabled, isRegistrationAllowed } from \"../../../../login\";\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 {isInternalAuthEnabled() && (\n <>\n {isRegistrationAllowed() && (\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 )}\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 {isDiscordAuthEnabled() && (\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 { getApiUrl } from \"../../../../client/config\";\nimport { errorToast, FormInput, FormPassword } from \"../../../../components\";\nimport { useI18nRouter, usePageUrlGenerator } from \"../../../../hooks\";\nimport { isDiscordAuthEnabled, isInternalAuthEnabled } from \"../../../../login\";\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 {isInternalAuthEnabled() && (\n <>\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 </>\n )}\n </CardContent>\n <CardFooter className=\"flex w-full flex-col gap-y-4 mt-4\">\n {isDiscordAuthEnabled() && (\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 <div 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 </div>\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 { useCurrentUserContext } from \"../../../user/contexts\";\nimport { UserService } from \"../../../user/data/user.service\";\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 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>\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>\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 loadNotifications,\n shouldRefresh,\n lastLoaded,\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 // Load notifications from API on mount if never loaded\n useEffect(() => {\n if (lastLoaded === 0) loadNotifications();\n }, [lastLoaded, loadNotifications]);\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 // Refresh notifications from API if cache is stale\n if (shouldRefresh) {\n loadNotifications();\n }\n\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>\n <SidebarMenuButton render={<div />} 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 { FormFieldWrapper } from \"../../../../components/forms\";\nimport {\n Checkbox,\n FieldLabel,\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 <FormFieldWrapper form={form} name={id} label={name}>\n {(field) => (\n <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>\n <FieldLabel className=\"ml-3 font-normal\">\n {t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) })}\n </FieldLabel>\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 )}\n </FormFieldWrapper>\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 hover:bg-muted data-selected:hover:bg-muted bg-transparent data-selected:bg-transparent\"\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","\"use client\";\n\nimport { useCallback } from \"react\";\nimport { Plus, Trash2 } from \"lucide-react\";\nimport { Button, Input, Label } from \"../../../shadcnui\";\n\nexport interface OAuthRedirectUriInputProps {\n /** Current array of redirect URIs */\n value: string[];\n /** Called when URIs change */\n onChange: (uris: string[]) => void;\n /** Error message to display */\n error?: string;\n /** Whether input is disabled */\n disabled?: boolean;\n /** Label text */\n label?: string;\n}\n\n/**\n * Validates a redirect URI\n * Allows: https://, http://localhost, custom schemes (myapp://)\n */\nfunction isValidRedirectUri(uri: string): boolean {\n if (!uri.trim()) return false;\n\n // Allow localhost for development\n if (uri.startsWith(\"http://localhost\") || uri.startsWith(\"http://127.0.0.1\")) {\n return true;\n }\n\n // Require HTTPS for non-localhost\n if (uri.startsWith(\"https://\")) {\n try {\n new URL(uri);\n return true;\n } catch {\n return false;\n }\n }\n\n // Allow custom schemes (e.g., myapp://oauth/callback)\n if (uri.includes(\"://\")) {\n const schemeMatch = uri.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):\\/\\//);\n return schemeMatch !== null;\n }\n\n return false;\n}\n\n/**\n * Dynamic input for managing OAuth redirect URIs\n *\n * @example\n * ```tsx\n * const [redirectUris, setRedirectUris] = useState<string[]>(['']);\n *\n * <OAuthRedirectUriInput\n * value={redirectUris}\n * onChange={setRedirectUris}\n * error={errors.redirectUris}\n * />\n * ```\n */\nexport function OAuthRedirectUriInput({\n value,\n onChange,\n error,\n disabled = false,\n label = \"Redirect URIs\",\n}: OAuthRedirectUriInputProps) {\n const handleAdd = useCallback(() => {\n onChange([...value, \"\"]);\n }, [value, onChange]);\n\n const handleRemove = useCallback(\n (index: number) => {\n const newUris = value.filter((_, i) => i !== index);\n // Keep at least one empty input\n onChange(newUris.length > 0 ? newUris : [\"\"]);\n },\n [value, onChange]\n );\n\n const handleChange = useCallback(\n (index: number, newValue: string) => {\n const newUris = [...value];\n newUris[index] = newValue;\n onChange(newUris);\n },\n [value, onChange]\n );\n\n return (\n <div className=\"space-y-2\">\n <Label>{label} *</Label>\n <p className=\"text-sm text-muted-foreground\">\n Enter the URIs where users will be redirected after authorization.\n Use https:// for production, or custom schemes for mobile apps.\n </p>\n\n <div className=\"space-y-2\">\n {value.map((uri, index) => {\n const isValid = !uri || isValidRedirectUri(uri);\n\n return (\n <div key={index} className=\"flex gap-2\">\n <div className=\"flex-1\">\n <Input\n value={uri}\n onChange={(e) => handleChange(index, e.target.value)}\n placeholder=\"https://example.com/callback or myapp://oauth\"\n disabled={disabled}\n className={!isValid ? \"border-destructive\" : \"\"}\n />\n {!isValid && (\n <p className=\"text-xs text-destructive mt-1\">\n Must be https://, http://localhost, or a custom scheme (app://)\n </p>\n )}\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => handleRemove(index)}\n disabled={disabled || value.length === 1}\n title=\"Remove URI\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n );\n })}\n </div>\n\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={handleAdd}\n disabled={disabled}\n className=\"mt-2\"\n >\n <Plus className=\"h-4 w-4 mr-2\" />\n Add Redirect URI\n </Button>\n\n {error && <p className=\"text-sm text-destructive\">{error}</p>}\n </div>\n );\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\nimport { Checkbox, Label } from \"../../../shadcnui\";\nimport { AVAILABLE_OAUTH_SCOPES, OAuthScopeInfo } from \"../interfaces/oauth.interface\";\n\nexport interface OAuthScopeSelectorProps {\n /** Currently selected scopes */\n value: string[];\n /** Called when selection changes */\n onChange: (scopes: string[]) => void;\n /** Available scopes to display (defaults to all) */\n availableScopes?: OAuthScopeInfo[];\n /** Whether selector is disabled */\n disabled?: boolean;\n /** Error message */\n error?: string;\n /** Label text */\n label?: string;\n}\n\n/**\n * Checkbox selector for OAuth scopes\n *\n * @example\n * ```tsx\n * const [scopes, setScopes] = useState<string[]>([]);\n *\n * <OAuthScopeSelector\n * value={scopes}\n * onChange={setScopes}\n * error={errors.scopes}\n * />\n * ```\n */\nexport function OAuthScopeSelector({\n value,\n onChange,\n availableScopes = AVAILABLE_OAUTH_SCOPES,\n disabled = false,\n error,\n label = \"Allowed Scopes\",\n}: OAuthScopeSelectorProps) {\n const handleToggle = useCallback(\n (scope: string, checked: boolean) => {\n if (checked) {\n onChange([...value, scope]);\n } else {\n onChange(value.filter((s) => s !== scope));\n }\n },\n [value, onChange]\n );\n\n // Group scopes by category (before the colon)\n const groupedScopes = availableScopes.reduce((acc, scope) => {\n const [category] = scope.scope.split(\":\");\n const groupName = category === scope.scope ? \"General\" : category;\n\n if (!acc[groupName]) {\n acc[groupName] = [];\n }\n acc[groupName].push(scope);\n return acc;\n }, {} as Record<string, OAuthScopeInfo[]>);\n\n return (\n <div className=\"space-y-4\">\n <div>\n <Label>{label} *</Label>\n <p className=\"text-sm text-muted-foreground\">\n Select the permissions your application needs.\n </p>\n </div>\n\n <div className=\"space-y-4\">\n {Object.entries(groupedScopes).map(([groupName, scopes]) => (\n <div key={groupName} className=\"space-y-2\">\n <h4 className=\"text-sm font-medium capitalize\">{groupName}</h4>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-2 pl-2\">\n {scopes.map((scopeInfo) => {\n const isChecked = value.includes(scopeInfo.scope);\n const isAdmin = scopeInfo.scope === \"admin\";\n\n return (\n <div\n key={scopeInfo.scope}\n className={`flex items-start space-x-3 p-2 rounded-md border ${\n isChecked ? \"bg-primary/5 border-primary/20\" : \"border-transparent\"\n } ${isAdmin ? \"bg-destructive/5\" : \"\"}`}\n >\n <Checkbox\n id={`scope-${scopeInfo.scope}`}\n checked={isChecked}\n onCheckedChange={(checked) =>\n handleToggle(scopeInfo.scope, checked === true)\n }\n disabled={disabled}\n />\n <div className=\"flex-1\">\n <Label\n htmlFor={`scope-${scopeInfo.scope}`}\n className=\"text-sm font-medium cursor-pointer\"\n >\n {scopeInfo.name}\n {isAdmin && (\n <span className=\"ml-2 text-xs text-destructive\">(Dangerous)</span>\n )}\n </Label>\n <p className=\"text-xs text-muted-foreground\">{scopeInfo.description}</p>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n\n {error && <p className=\"text-sm text-destructive\">{error}</p>}\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useCallback } from \"react\";\nimport { Copy, Check, AlertTriangle } from \"lucide-react\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Alert,\n AlertDescription,\n Input,\n} from \"../../../shadcnui\";\n\nexport interface OAuthClientSecretDisplayProps {\n /** The client secret to display */\n secret: string;\n /** Called when user dismisses the dialog */\n onDismiss: () => void;\n /** Whether the dialog is open */\n open: boolean;\n /** Optional client name for context */\n clientName?: string;\n}\n\n/**\n * Modal dialog for displaying a client secret ONE TIME\n * Shows warning that secret cannot be retrieved again\n *\n * @example\n * ```tsx\n * const [secret, setSecret] = useAtom(oauthNewClientSecretAtom);\n *\n * <OAuthClientSecretDisplay\n * secret={secret || ''}\n * open={!!secret}\n * onDismiss={() => setSecret(null)}\n * />\n * ```\n */\nexport function OAuthClientSecretDisplay({\n secret,\n onDismiss,\n open,\n clientName,\n}: OAuthClientSecretDisplayProps) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(secret);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n console.error(\"Failed to copy to clipboard:\", err);\n }\n }, [secret]);\n\n const handleDismiss = useCallback(() => {\n setCopied(false);\n onDismiss();\n }, [onDismiss]);\n\n return (\n <Dialog open={open} onOpenChange={(isOpen) => !isOpen && handleDismiss()}>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <AlertTriangle className=\"h-5 w-5 text-warning\" />\n Save Your Client Secret\n </DialogTitle>\n <DialogDescription>\n {clientName\n ? `Your client secret for \"${clientName}\" is shown below.`\n : \"Your client secret is shown below.\"}\n </DialogDescription>\n </DialogHeader>\n\n <Alert variant=\"destructive\" className=\"my-4\">\n <AlertTriangle className=\"h-4 w-4\" />\n <AlertDescription>\n <strong>This is the only time your client secret will be displayed.</strong>\n <br />\n Copy it now and store it securely. You will not be able to retrieve it later.\n </AlertDescription>\n </Alert>\n\n <div className=\"flex items-center space-x-2\">\n <div className=\"flex-1\">\n <Input\n value={secret}\n readOnly\n className=\"font-mono text-sm\"\n onClick={(e) => e.currentTarget.select()}\n />\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon\"\n onClick={handleCopy}\n title={copied ? \"Copied!\" : \"Copy to clipboard\"}\n >\n {copied ? (\n <Check className=\"h-4 w-4 text-green-600\" />\n ) : (\n <Copy className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n\n {copied && (\n <p className=\"text-sm text-green-600 text-center\">Copied to clipboard!</p>\n )}\n\n <DialogFooter className=\"mt-4\">\n <Button onClick={handleDismiss} className=\"w-full\">\n I've Saved My Secret\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","\"use client\";\n\nimport { formatDistanceToNow } from \"date-fns\";\nimport { Key, MoreVertical, Pencil, Trash2 } from \"lucide-react\";\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"../../../shadcnui\";\nimport { OAuthClientInterface } from \"../interfaces/oauth.interface\";\n\nexport interface OAuthClientCardProps {\n /** The OAuth client to display */\n client: OAuthClientInterface;\n /** Called when card is clicked */\n onClick?: () => void;\n /** Called when edit is clicked */\n onEdit?: () => void;\n /** Called when delete is clicked */\n onDelete?: () => void;\n}\n\n/**\n * Card component for displaying an OAuth client in a list\n */\nexport function OAuthClientCard({\n client,\n onClick,\n onEdit,\n onDelete,\n}: OAuthClientCardProps) {\n // Truncate client ID for display\n const truncatedId = client.clientId.length > 12\n ? `${client.clientId.slice(0, 8)}...${client.clientId.slice(-4)}`\n : client.clientId;\n\n const createdAgo = client.createdAt\n ? formatDistanceToNow(new Date(client.createdAt), { addSuffix: true })\n : \"Unknown\";\n\n return (\n <Card\n className={`cursor-pointer transition-colors hover:bg-accent/50 ${!client.isActive ? \"opacity-60\" : \"\"}`}\n onClick={onClick}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-2\">\n <Key className=\"h-5 w-5 text-muted-foreground\" />\n <CardTitle className=\"text-lg\">{client.name}</CardTitle>\n </div>\n <div className=\"flex items-center gap-2\">\n <Badge variant={client.isActive ? \"default\" : \"secondary\"}>\n {client.isActive ? \"Active\" : \"Inactive\"}\n </Badge>\n {(onEdit || onDelete) && (\n <DropdownMenu>\n <DropdownMenuTrigger onClick={(e) => e.stopPropagation()}>\n <Button render={<div />} nativeButton={false} variant=\"ghost\" size=\"icon\" className=\"h-8 w-8\">\n <MoreVertical className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {onEdit && (\n <DropdownMenuItem onClick={(e) => { e.stopPropagation(); onEdit(); }}>\n <Pencil className=\"h-4 w-4 mr-2\" />\n Edit\n </DropdownMenuItem>\n )}\n {onDelete && (\n <DropdownMenuItem\n onClick={(e) => { e.stopPropagation(); onDelete(); }}\n className=\"text-destructive\"\n >\n <Trash2 className=\"h-4 w-4 mr-2\" />\n Delete\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </div>\n </div>\n {client.description && (\n <CardDescription className=\"line-clamp-2\">{client.description}</CardDescription>\n )}\n </CardHeader>\n <CardContent>\n <div className=\"flex flex-wrap gap-x-4 gap-y-1 text-sm text-muted-foreground\">\n <span className=\"font-mono\">{truncatedId}</span>\n <span>Created {createdAgo}</span>\n <span>{client.isConfidential ? \"Confidential\" : \"Public\"}</span>\n </div>\n </CardContent>\n </Card>\n );\n}\n","\"use client\";\n\nimport { Plus, Key } from \"lucide-react\";\nimport { Button, Skeleton } from \"../../../shadcnui\";\nimport { OAuthClientCard } from \"./OAuthClientCard\";\nimport { OAuthClientInterface } from \"../interfaces/oauth.interface\";\n\nexport interface OAuthClientListProps {\n /** List of OAuth clients */\n clients: OAuthClientInterface[];\n /** Whether list is loading */\n isLoading?: boolean;\n /** Error to display */\n error?: Error | null;\n /** Called when a client is clicked */\n onClientClick?: (client: OAuthClientInterface) => void;\n /** Called when create button is clicked */\n onCreateClick?: () => void;\n /** Called when edit is clicked on a client */\n onEditClick?: (client: OAuthClientInterface) => void;\n /** Called when delete is clicked on a client */\n onDeleteClick?: (client: OAuthClientInterface) => void;\n /** Message to show when list is empty */\n emptyStateMessage?: string;\n /** Title for the list */\n title?: string;\n}\n\n/**\n * Component for displaying a list of OAuth clients\n */\nexport function OAuthClientList({\n clients,\n isLoading = false,\n error,\n onClientClick,\n onCreateClick,\n onEditClick,\n onDeleteClick,\n emptyStateMessage = \"No OAuth applications yet. Create one to get started.\",\n title = \"OAuth Applications\",\n}: OAuthClientListProps) {\n // Loading state\n if (isLoading && clients.length === 0) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-2xl font-bold\">{title}</h2>\n <Skeleton className=\"h-10 w-32\" />\n </div>\n <div className=\"space-y-3\">\n {[1, 2, 3].map((i) => (\n <Skeleton key={i} className=\"h-32 w-full\" />\n ))}\n </div>\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-2xl font-bold\">{title}</h2>\n </div>\n <div className=\"rounded-lg border border-destructive/50 bg-destructive/10 p-6 text-center\">\n <p className=\"text-destructive\">{error.message}</p>\n </div>\n </div>\n );\n }\n\n // Empty state\n if (clients.length === 0) {\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-2xl font-bold\">{title}</h2>\n {onCreateClick && (\n <Button onClick={onCreateClick}>\n <Plus className=\"h-4 w-4 mr-2\" />\n New App\n </Button>\n )}\n </div>\n <div className=\"rounded-lg border border-dashed p-12 text-center\">\n <Key className=\"h-12 w-12 mx-auto text-muted-foreground mb-4\" />\n <h3 className=\"text-lg font-medium mb-2\">No OAuth Applications</h3>\n <p className=\"text-muted-foreground mb-4\">{emptyStateMessage}</p>\n {onCreateClick && (\n <Button onClick={onCreateClick}>\n <Plus className=\"h-4 w-4 mr-2\" />\n Create Application\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n // List view\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-2xl font-bold\">{title}</h2>\n {onCreateClick && (\n <Button onClick={onCreateClick}>\n <Plus className=\"h-4 w-4 mr-2\" />\n New App\n </Button>\n )}\n </div>\n <div className=\"space-y-3\">\n {clients.map((client) => (\n <OAuthClientCard\n key={client.id || client.clientId}\n client={client}\n onClick={() => onClientClick?.(client)}\n onEdit={onEditClick ? () => onEditClick(client) : undefined}\n onDelete={onDeleteClick ? () => onDeleteClick(client) : undefined}\n />\n ))}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useCallback } from \"react\";\nimport {\n Button,\n Input,\n Label,\n Textarea,\n RadioGroup,\n RadioGroupItem,\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"../../../shadcnui\";\nimport { OAuthRedirectUriInput } from \"./OAuthRedirectUriInput\";\nimport { OAuthScopeSelector } from \"./OAuthScopeSelector\";\nimport { OAuthClientCreateRequest, OAuthClientInterface, DEFAULT_GRANT_TYPES } from \"../interfaces/oauth.interface\";\n\nexport interface OAuthClientFormProps {\n /** Existing client for edit mode (undefined = create mode) */\n client?: OAuthClientInterface;\n /** Called on form submit */\n onSubmit: (data: OAuthClientCreateRequest) => Promise<void>;\n /** Called on cancel */\n onCancel: () => void;\n /** Whether form is submitting */\n isLoading?: boolean;\n}\n\ninterface FormState {\n name: string;\n description: string;\n redirectUris: string[];\n allowedScopes: string[];\n isConfidential: boolean;\n}\n\ninterface FormErrors {\n name?: string;\n redirectUris?: string;\n allowedScopes?: string;\n}\n\n/**\n * Form for creating or editing an OAuth client\n */\nexport function OAuthClientForm({\n client,\n onSubmit,\n onCancel,\n isLoading = false,\n}: OAuthClientFormProps) {\n const isEditMode = !!client;\n\n const [formState, setFormState] = useState<FormState>({\n name: client?.name || \"\",\n description: client?.description || \"\",\n redirectUris: client?.redirectUris?.length ? client.redirectUris : [\"\"],\n allowedScopes: client?.allowedScopes || [],\n isConfidential: client?.isConfidential ?? true,\n });\n\n const [errors, setErrors] = useState<FormErrors>({});\n\n const validate = useCallback((): boolean => {\n const newErrors: FormErrors = {};\n\n if (!formState.name.trim()) {\n newErrors.name = \"Application name is required\";\n }\n\n const validUris = formState.redirectUris.filter((uri) => uri.trim());\n if (validUris.length === 0) {\n newErrors.redirectUris = \"At least one redirect URI is required\";\n }\n\n if (formState.allowedScopes.length === 0) {\n newErrors.allowedScopes = \"At least one scope must be selected\";\n }\n\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n }, [formState]);\n\n const handleSubmit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault();\n\n if (!validate()) return;\n\n const data: OAuthClientCreateRequest = {\n name: formState.name.trim(),\n description: formState.description.trim() || undefined,\n redirectUris: formState.redirectUris.filter((uri) => uri.trim()),\n allowedScopes: formState.allowedScopes,\n allowedGrantTypes: DEFAULT_GRANT_TYPES,\n isConfidential: formState.isConfidential,\n };\n\n await onSubmit(data);\n },\n [formState, validate, onSubmit]\n );\n\n return (\n <Card>\n <form onSubmit={handleSubmit}>\n <CardHeader>\n <CardTitle>{isEditMode ? \"Edit Application\" : \"Create OAuth Application\"}</CardTitle>\n <CardDescription>\n {isEditMode\n ? \"Update your OAuth application settings.\"\n : \"Register a new application to access the API.\"}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-6\">\n {/* Name */}\n <div className=\"space-y-2\">\n <Label htmlFor=\"name\">Application Name *</Label>\n <Input\n id=\"name\"\n value={formState.name}\n onChange={(e) => setFormState((s) => ({ ...s, name: e.target.value }))}\n placeholder=\"My Lightroom Plugin\"\n disabled={isLoading}\n className={errors.name ? \"border-destructive\" : \"\"}\n />\n {errors.name && <p className=\"text-sm text-destructive\">{errors.name}</p>}\n </div>\n\n {/* Description */}\n <div className=\"space-y-2\">\n <Label htmlFor=\"description\">Description</Label>\n <Textarea\n id=\"description\"\n value={formState.description}\n onChange={(e) => setFormState((s) => ({ ...s, description: e.target.value }))}\n placeholder=\"A brief description of your application\"\n disabled={isLoading}\n rows={3}\n />\n </div>\n\n {/* Redirect URIs */}\n <OAuthRedirectUriInput\n value={formState.redirectUris}\n onChange={(uris) => setFormState((s) => ({ ...s, redirectUris: uris }))}\n error={errors.redirectUris}\n disabled={isLoading}\n />\n\n {/* Scopes */}\n <OAuthScopeSelector\n value={formState.allowedScopes}\n onChange={(scopes) => setFormState((s) => ({ ...s, allowedScopes: scopes }))}\n error={errors.allowedScopes}\n disabled={isLoading}\n />\n\n {/* Client Type */}\n <div className=\"space-y-3\">\n <Label>Client Type</Label>\n <RadioGroup\n value={formState.isConfidential ? \"confidential\" : \"public\"}\n onValueChange={(v) => setFormState((s) => ({ ...s, isConfidential: v === \"confidential\" }))}\n disabled={isLoading || isEditMode}\n >\n <div className=\"flex items-start space-x-3 p-3 rounded-md border\">\n <RadioGroupItem value=\"confidential\" id=\"confidential\" className=\"mt-1\" />\n <div>\n <Label htmlFor=\"confidential\" className=\"font-medium cursor-pointer\">\n Confidential\n </Label>\n <p className=\"text-sm text-muted-foreground\">\n Server-side application that can securely store the client secret.\n </p>\n </div>\n </div>\n <div className=\"flex items-start space-x-3 p-3 rounded-md border\">\n <RadioGroupItem value=\"public\" id=\"public\" className=\"mt-1\" />\n <div>\n <Label htmlFor=\"public\" className=\"font-medium cursor-pointer\">\n Public\n </Label>\n <p className=\"text-sm text-muted-foreground\">\n Mobile or desktop application. Requires PKCE for authorization.\n </p>\n </div>\n </div>\n </RadioGroup>\n {isEditMode && (\n <p className=\"text-sm text-muted-foreground\">\n Client type cannot be changed after creation.\n </p>\n )}\n </div>\n </CardContent>\n <CardFooter className=\"flex justify-end gap-3\">\n <Button type=\"button\" variant=\"outline\" onClick={onCancel} disabled={isLoading}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={isLoading}>\n {isLoading ? \"Saving...\" : isEditMode ? \"Save Changes\" : \"Create Application\"}\n </Button>\n </CardFooter>\n </form>\n </Card>\n );\n}\n","\"use client\";\n\nimport { useState, useCallback } from \"react\";\nimport { format } from \"date-fns\";\nimport { Copy, Check, RefreshCw, Pencil, Trash2, ExternalLink } from \"lucide-react\";\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Input,\n Label,\n Separator,\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"../../../shadcnui\";\nimport { OAuthClientInterface, OAUTH_SCOPE_DISPLAY } from \"../interfaces/oauth.interface\";\n\nexport interface OAuthClientDetailProps {\n /** The OAuth client to display */\n client: OAuthClientInterface;\n /** Whether data is loading */\n isLoading?: boolean;\n /** Called when edit is clicked */\n onEdit?: () => void;\n /** Called when delete is clicked */\n onDelete?: () => Promise<void>;\n /** Called when regenerate secret is clicked */\n onRegenerateSecret?: () => Promise<void>;\n}\n\n/**\n * Detailed view of an OAuth client\n */\nexport function OAuthClientDetail({\n client,\n isLoading = false,\n onEdit,\n onDelete,\n onRegenerateSecret,\n}: OAuthClientDetailProps) {\n const [copiedField, setCopiedField] = useState<string | null>(null);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [showRegenerateConfirm, setShowRegenerateConfirm] = useState(false);\n const [isDeleting, setIsDeleting] = useState(false);\n const [isRegenerating, setIsRegenerating] = useState(false);\n\n const copyToClipboard = useCallback(async (text: string, field: string) => {\n try {\n await navigator.clipboard.writeText(text);\n setCopiedField(field);\n setTimeout(() => setCopiedField(null), 2000);\n } catch (err) {\n console.error(\"Failed to copy:\", err);\n }\n }, []);\n\n const handleDelete = useCallback(async () => {\n if (!onDelete) return;\n setIsDeleting(true);\n try {\n await onDelete();\n } finally {\n setIsDeleting(false);\n setShowDeleteConfirm(false);\n }\n }, [onDelete]);\n\n const handleRegenerateSecret = useCallback(async () => {\n if (!onRegenerateSecret) return;\n setIsRegenerating(true);\n try {\n await onRegenerateSecret();\n } finally {\n setIsRegenerating(false);\n setShowRegenerateConfirm(false);\n }\n }, [onRegenerateSecret]);\n\n const createdDate = client.createdAt\n ? format(new Date(client.createdAt), \"MMMM d, yyyy\")\n : \"Unknown\";\n\n return (\n <>\n <Card>\n <CardHeader>\n <div className=\"flex items-start justify-between\">\n <div>\n <CardTitle className=\"text-2xl\">{client.name}</CardTitle>\n {client.description && (\n <CardDescription className=\"mt-1\">{client.description}</CardDescription>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n <Badge variant={client.isActive ? \"default\" : \"secondary\"}>\n {client.isActive ? \"Active\" : \"Inactive\"}\n </Badge>\n <Badge variant=\"outline\">\n {client.isConfidential ? \"Confidential\" : \"Public\"}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-6\">\n {/* Client ID */}\n <div className=\"space-y-2\">\n <Label>Client ID</Label>\n <div className=\"flex gap-2\">\n <Input value={client.clientId} readOnly className=\"font-mono\" />\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => copyToClipboard(client.clientId, \"clientId\")}\n title=\"Copy Client ID\"\n >\n {copiedField === \"clientId\" ? (\n <Check className=\"h-4 w-4 text-green-600\" />\n ) : (\n <Copy className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n\n {/* Client Secret */}\n <div className=\"space-y-2\">\n <Label>Client Secret</Label>\n <div className=\"flex gap-2\">\n <Input value=\"••••••••••••••••••••••••••••••••\" readOnly className=\"font-mono\" />\n {onRegenerateSecret && (\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => setShowRegenerateConfirm(true)}\n title=\"Regenerate Secret\"\n disabled={isLoading}\n >\n <RefreshCw className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n <p className=\"text-xs text-muted-foreground\">\n Regenerating will invalidate the current secret and all existing tokens.\n </p>\n </div>\n\n <Separator />\n\n {/* Redirect URIs */}\n <div className=\"space-y-2\">\n <Label>Redirect URIs</Label>\n <ul className=\"space-y-1\">\n {client.redirectUris.map((uri, index) => (\n <li key={index} className=\"flex items-center gap-2 text-sm font-mono\">\n <ExternalLink className=\"h-3 w-3 text-muted-foreground\" />\n {uri}\n </li>\n ))}\n </ul>\n </div>\n\n {/* Scopes */}\n <div className=\"space-y-2\">\n <Label>Allowed Scopes</Label>\n <div className=\"flex flex-wrap gap-2\">\n {client.allowedScopes.map((scope) => (\n <Badge key={scope} variant=\"secondary\">\n {OAUTH_SCOPE_DISPLAY[scope]?.name || scope}\n </Badge>\n ))}\n </div>\n </div>\n\n {/* Grant Types */}\n <div className=\"space-y-2\">\n <Label>Grant Types</Label>\n <div className=\"flex flex-wrap gap-2\">\n {client.allowedGrantTypes.map((grant) => (\n <Badge key={grant} variant=\"outline\">\n {grant.replace(/_/g, \" \")}\n </Badge>\n ))}\n </div>\n </div>\n\n <Separator />\n\n {/* Metadata */}\n <div className=\"flex flex-wrap gap-x-6 gap-y-2 text-sm text-muted-foreground\">\n <span>Created: {createdDate}</span>\n </div>\n\n {/* Actions */}\n <div className=\"flex gap-3 pt-4\">\n {onEdit && (\n <Button variant=\"outline\" onClick={onEdit} disabled={isLoading}>\n <Pencil className=\"h-4 w-4 mr-2\" />\n Edit\n </Button>\n )}\n {onDelete && (\n <Button\n variant=\"destructive\"\n onClick={() => setShowDeleteConfirm(true)}\n disabled={isLoading}\n >\n <Trash2 className=\"h-4 w-4 mr-2\" />\n Delete\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n\n {/* Delete Confirmation */}\n <AlertDialog open={showDeleteConfirm} onOpenChange={setShowDeleteConfirm}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete OAuth Application?</AlertDialogTitle>\n <AlertDialogDescription>\n This will permanently delete \"{client.name}\" and revoke all access tokens.\n This action cannot be undone.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={isDeleting}>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={handleDelete}\n disabled={isDeleting}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n >\n {isDeleting ? \"Deleting...\" : \"Delete\"}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n\n {/* Regenerate Confirmation */}\n <AlertDialog open={showRegenerateConfirm} onOpenChange={setShowRegenerateConfirm}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Regenerate Client Secret?</AlertDialogTitle>\n <AlertDialogDescription>\n This will generate a new client secret and invalidate the old one.\n All existing tokens will be revoked. You will need to update your application\n with the new secret.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={isRegenerating}>Cancel</AlertDialogCancel>\n <AlertDialogAction onClick={handleRegenerateSecret} disabled={isRegenerating}>\n {isRegenerating ? \"Regenerating...\" : \"Regenerate\"}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </>\n );\n}\n","\"use client\";\n\nimport { Shield } from \"lucide-react\";\nimport { OAuthClientInterface } from \"../../interfaces/oauth.interface\";\n\nexport interface OAuthConsentHeaderProps {\n /** The requesting OAuth client */\n client: OAuthClientInterface;\n /** Optional logo URL override */\n logoUrl?: string;\n /** Application name (e.g., \"Only35\") */\n appName?: string;\n}\n\n/**\n * Header component for OAuth consent screen\n * Shows platform logo and requesting app information\n */\nexport function OAuthConsentHeader({\n client,\n logoUrl,\n appName = \"Only35\",\n}: OAuthConsentHeaderProps) {\n return (\n <div className=\"text-center space-y-4\">\n {/* Platform Logo */}\n <div className=\"flex justify-center\">\n {logoUrl ? (\n <img\n src={logoUrl}\n alt={appName}\n className=\"h-12 w-auto\"\n />\n ) : (\n <div className=\"h-12 w-12 rounded-full bg-primary flex items-center justify-center\">\n <Shield className=\"h-6 w-6 text-primary-foreground\" />\n </div>\n )}\n </div>\n\n {/* Authorization Request */}\n <div className=\"space-y-2\">\n <h1 className=\"text-2xl font-bold\">Authorize {client.name}</h1>\n <p className=\"text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{client.name}</span>\n {\" \"}wants to access your {appName} account\n </p>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n Eye,\n Pencil,\n Image,\n Upload,\n Film,\n FolderPlus,\n User,\n Shield,\n LucideIcon,\n} from \"lucide-react\";\nimport { OAuthScopeInfo } from \"../../interfaces/oauth.interface\";\n\nexport interface OAuthScopeListProps {\n /** List of requested scopes */\n scopes: OAuthScopeInfo[];\n}\n\n/** Map scope icons to Lucide components */\nconst SCOPE_ICONS: Record<string, LucideIcon> = {\n eye: Eye,\n pencil: Pencil,\n image: Image,\n upload: Upload,\n film: Film,\n \"folder-plus\": FolderPlus,\n user: User,\n shield: Shield,\n};\n\n/**\n * List of requested OAuth scopes for consent display\n */\nexport function OAuthScopeList({ scopes }: OAuthScopeListProps) {\n if (scopes.length === 0) {\n return null;\n }\n\n return (\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-medium text-muted-foreground uppercase tracking-wide\">\n This will allow the application to:\n </h2>\n <ul className=\"space-y-3\">\n {scopes.map((scope) => {\n const IconComponent = scope.icon ? SCOPE_ICONS[scope.icon] : Eye;\n\n return (\n <li\n key={scope.scope}\n className=\"flex items-start gap-3 p-3 rounded-lg bg-muted/50\"\n >\n <div className=\"flex-shrink-0 mt-0.5\">\n <div className=\"h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center\">\n {IconComponent && (\n <IconComponent className=\"h-4 w-4 text-primary\" />\n )}\n </div>\n </div>\n <div className=\"flex-1\">\n <p className=\"font-medium\">{scope.name}</p>\n <p className=\"text-sm text-muted-foreground\">{scope.description}</p>\n </div>\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n","\"use client\";\n\nimport { Button } from \"../../../../shadcnui\";\n\nexport interface OAuthConsentActionsProps {\n /** Called when user clicks Authorize */\n onApprove: () => void;\n /** Called when user clicks Deny */\n onDeny: () => void;\n /** Whether an action is in progress */\n isLoading?: boolean;\n}\n\n/**\n * Action buttons for OAuth consent screen\n */\nexport function OAuthConsentActions({\n onApprove,\n onDeny,\n isLoading = false,\n}: OAuthConsentActionsProps) {\n return (\n <div className=\"flex flex-col sm:flex-row gap-3\">\n <Button\n variant=\"outline\"\n onClick={onDeny}\n disabled={isLoading}\n className=\"flex-1\"\n >\n Deny\n </Button>\n <Button\n onClick={onApprove}\n disabled={isLoading}\n className=\"flex-1\"\n >\n {isLoading ? \"Authorizing...\" : \"Authorize\"}\n </Button>\n </div>\n );\n}\n","\"use client\";\n\nimport { ExternalLink, AlertTriangle, Loader2 } from \"lucide-react\";\nimport {\n Card,\n CardContent,\n CardFooter,\n Separator,\n Alert,\n AlertDescription,\n} from \"../../../../shadcnui\";\nimport { OAuthConsentHeader } from \"./OAuthConsentHeader\";\nimport { OAuthScopeList } from \"./OAuthScopeList\";\nimport { OAuthConsentActions } from \"./OAuthConsentActions\";\nimport { useOAuthConsent } from \"../../hooks/useOAuthConsent\";\nimport { OAuthConsentRequest } from \"../../interfaces/oauth.interface\";\n\nexport interface OAuthConsentScreenProps {\n /** OAuth authorization parameters */\n params: OAuthConsentRequest;\n /** Optional platform logo URL */\n logoUrl?: string;\n /** Platform name */\n appName?: string;\n /** Terms of Service URL */\n termsUrl?: string;\n /** Privacy Policy URL */\n privacyUrl?: string;\n}\n\n/**\n * Main OAuth consent screen component\n * Displays client info, requested scopes, and approve/deny buttons\n *\n * @example\n * ```tsx\n * <OAuthConsentScreen\n * params={{\n * clientId: searchParams.client_id,\n * redirectUri: searchParams.redirect_uri,\n * scope: searchParams.scope,\n * state: searchParams.state,\n * }}\n * />\n * ```\n */\nexport function OAuthConsentScreen({\n params,\n logoUrl,\n appName = \"Only35\",\n termsUrl = \"/terms\",\n privacyUrl = \"/privacy\",\n}: OAuthConsentScreenProps) {\n const { clientInfo, isLoading, error, approve, deny, isSubmitting } = useOAuthConsent(params);\n\n // Loading state\n if (isLoading) {\n return (\n <div className=\"min-h-screen flex items-center justify-center p-4\">\n <Card className=\"w-full max-w-md\">\n <CardContent className=\"flex flex-col items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n <p className=\"mt-4 text-muted-foreground\">Loading authorization request...</p>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n // Error state\n if (error || !clientInfo) {\n return (\n <div className=\"min-h-screen flex items-center justify-center p-4\">\n <Card className=\"w-full max-w-md\">\n <CardContent className=\"py-8\">\n <Alert variant=\"destructive\">\n <AlertTriangle className=\"h-4 w-4\" />\n <AlertDescription>\n {error?.message || \"Invalid authorization request. Please try again.\"}\n </AlertDescription>\n </Alert>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n const { client, scopes } = clientInfo;\n\n return (\n <div className=\"min-h-screen flex items-center justify-center p-4 bg-muted/30\">\n <Card className=\"w-full max-w-md\">\n <CardContent className=\"pt-6 space-y-6\">\n {/* Header */}\n <OAuthConsentHeader\n client={client}\n logoUrl={logoUrl}\n appName={appName}\n />\n\n <Separator />\n\n {/* Scopes */}\n <OAuthScopeList scopes={scopes} />\n\n <Separator />\n\n {/* Redirect URI Notice */}\n <div className=\"flex items-start gap-2 text-sm text-muted-foreground\">\n <ExternalLink className=\"h-4 w-4 mt-0.5 flex-shrink-0\" />\n <div>\n <span>Authorizing will redirect you to:</span>\n <p className=\"font-mono text-xs mt-1 break-all\">{params.redirectUri}</p>\n </div>\n </div>\n\n {/* Actions */}\n <OAuthConsentActions\n onApprove={approve}\n onDeny={deny}\n isLoading={isSubmitting}\n />\n </CardContent>\n\n {/* Footer */}\n <CardFooter className=\"justify-center\">\n <p className=\"text-xs text-center text-muted-foreground\">\n By authorizing, you agree to the app's{\" \"}\n <a href={termsUrl} className=\"underline hover:text-foreground\" target=\"_blank\" rel=\"noopener\">\n Terms of Service\n </a>\n {\" \"}and{\" \"}\n <a href={privacyUrl} className=\"underline hover:text-foreground\" target=\"_blank\" rel=\"noopener\">\n Privacy Policy\n </a>\n .\n </p>\n </CardFooter>\n </Card>\n </div>\n );\n}\n"]}
|