@m5kdev/web-ui 0.7.0 → 0.8.0
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/src/animations/card.motion.d.ts +7 -2
- package/dist/src/animations/card.motion.js +25 -6
- package/dist/src/animations/card.motion.js.map +1 -0
- package/dist/src/components/AvatarUpload.d.ts +14 -5
- package/dist/src/components/AvatarUpload.js +105 -63
- package/dist/src/components/AvatarUpload.js.map +1 -0
- package/dist/src/components/Button.d.ts +14 -4
- package/dist/src/components/Button.js +13 -4
- package/dist/src/components/Button.js.map +1 -0
- package/dist/src/components/Calendar.d.ts +33 -31
- package/dist/src/components/Calendar.js +14 -6
- package/dist/src/components/Calendar.js.map +1 -0
- package/dist/src/components/{Calendar.css → Calendar2.css} +757 -684
- package/dist/src/components/CardsSelect.d.ts +25 -21
- package/dist/src/components/CardsSelect.js +75 -42
- package/dist/src/components/CardsSelect.js.map +1 -0
- package/dist/src/components/CollapsibleSidebarMenuItem.d.ts +22 -9
- package/dist/src/components/CollapsibleSidebarMenuItem.js +31 -8
- package/dist/src/components/CollapsibleSidebarMenuItem.js.map +1 -0
- package/dist/src/components/ColorPicker.d.ts +15 -4
- package/dist/src/components/ColorPicker.js +46 -16
- package/dist/src/components/ColorPicker.js.map +1 -0
- package/dist/src/components/CopyButton.d.ts +18 -6
- package/dist/src/components/CopyButton.js +28 -19
- package/dist/src/components/CopyButton.js.map +1 -0
- package/dist/src/components/CropDialog.d.ts +20 -8
- package/dist/src/components/CropDialog.js +108 -62
- package/dist/src/components/CropDialog.js.map +1 -0
- package/dist/src/components/DialogProvider.d.ts +22 -14
- package/dist/src/components/DialogProvider.js +67 -45
- package/dist/src/components/DialogProvider.js.map +1 -0
- package/dist/src/components/ErrorFallback.d.ts +13 -4
- package/dist/src/components/ErrorFallback.js +29 -4
- package/dist/src/components/ErrorFallback.js.map +1 -0
- package/dist/src/components/FileDropzone.d.ts +12 -4
- package/dist/src/components/FileDropzone.js +98 -60
- package/dist/src/components/FileDropzone.js.map +1 -0
- package/dist/src/components/MultiSelectDropdown.d.ts +25 -22
- package/dist/src/components/MultiSelectDropdown.js +99 -49
- package/dist/src/components/MultiSelectDropdown.js.map +1 -0
- package/dist/src/components/Orb.d.ts +17 -6
- package/dist/src/components/Orb.js +263 -255
- package/dist/src/components/Orb.js.map +1 -0
- package/dist/src/components/PageAlert.d.ts +20 -15
- package/dist/src/components/PageAlert.js +67 -39
- package/dist/src/components/PageAlert.js.map +1 -0
- package/dist/src/components/SelectChips.d.ts +21 -10
- package/dist/src/components/SelectChips.js +21 -9
- package/dist/src/components/SelectChips.js.map +1 -0
- package/dist/src/components/SidebarItem.d.ts +18 -7
- package/dist/src/components/SidebarItem.js +16 -4
- package/dist/src/components/SidebarItem.js.map +1 -0
- package/dist/src/components/Steps.d.ts +21 -16
- package/dist/src/components/Steps.js +193 -27
- package/dist/src/components/Steps.js.map +1 -0
- package/dist/src/components/TablerIconPicker.d.ts +13 -2
- package/dist/src/components/TablerIconPicker.js +4254 -4234
- package/dist/src/components/TablerIconPicker.js.map +1 -0
- package/dist/src/components/app-header.d.ts +14 -6
- package/dist/src/components/app-header.js +27 -6
- package/dist/src/components/app-header.js.map +1 -0
- package/dist/src/components/blur-card.d.ts +25 -11
- package/dist/src/components/blur-card.js +134 -31
- package/dist/src/components/blur-card.js.map +1 -0
- package/dist/src/components/features-section-demo-1.d.ts +22 -6
- package/dist/src/components/features-section-demo-1.js +119 -47
- package/dist/src/components/features-section-demo-1.js.map +1 -0
- package/dist/src/components/features-section-demo-2.d.ts +7 -1
- package/dist/src/components/features-section-demo-2.js +80 -49
- package/dist/src/components/features-section-demo-2.js.map +1 -0
- package/dist/src/components/features-section-demo-3.d.ts +16 -8
- package/dist/src/components/features-section-demo-3.js +239 -103
- package/dist/src/components/features-section-demo-3.js.map +1 -0
- package/dist/src/components/mode-toggle.d.ts +7 -1
- package/dist/src/components/mode-toggle.js +42 -7
- package/dist/src/components/mode-toggle.js.map +1 -0
- package/dist/src/components/nav-main.d.ts +20 -12
- package/dist/src/components/nav-main.js +31 -5
- package/dist/src/components/nav-main.js.map +1 -0
- package/dist/src/components/pricing-cards.d.ts +7 -1
- package/dist/src/components/pricing-cards.js +125 -24
- package/dist/src/components/pricing-cards.js.map +1 -0
- package/dist/src/components/shared/ButtonCopy.d.ts +17 -6
- package/dist/src/components/shared/ButtonCopy.js +31 -20
- package/dist/src/components/shared/ButtonCopy.js.map +1 -0
- package/dist/src/components/team-switcher.d.ts +16 -8
- package/dist/src/components/team-switcher.js +70 -8
- package/dist/src/components/team-switcher.js.map +1 -0
- package/dist/src/components/theme-provider.d.ts +18 -8
- package/dist/src/components/theme-provider.js +42 -38
- package/dist/src/components/theme-provider.js.map +1 -0
- package/dist/src/components/typewriter.d.ts +35 -14
- package/dist/src/components/typewriter.js +45 -36
- package/dist/src/components/typewriter.js.map +1 -0
- package/dist/src/components/ui/alert-dialog.d.ts +48 -13
- package/dist/src/components/ui/alert-dialog.js +58 -15
- package/dist/src/components/ui/alert-dialog.js.map +1 -0
- package/dist/src/components/ui/alert.d.ts +24 -8
- package/dist/src/components/ui/alert.js +28 -15
- package/dist/src/components/ui/alert.js.map +1 -0
- package/dist/src/components/ui/avatar.d.ts +9 -5
- package/dist/src/components/ui/avatar.js +23 -7
- package/dist/src/components/ui/avatar.js.map +1 -0
- package/dist/src/components/ui/badge.d.ts +17 -8
- package/dist/src/components/ui/badge.js +17 -14
- package/dist/src/components/ui/badge.js.map +1 -0
- package/dist/src/components/ui/bento-grid.d.ts +26 -11
- package/dist/src/components/ui/bento-grid.js +30 -6
- package/dist/src/components/ui/bento-grid.js.map +1 -0
- package/dist/src/components/ui/bento-grid2.d.ts +30 -14
- package/dist/src/components/ui/bento-grid2.js +45 -9
- package/dist/src/components/ui/bento-grid2.js.map +1 -0
- package/dist/src/components/ui/breadcrumb.d.ts +27 -15
- package/dist/src/components/ui/breadcrumb.js +54 -14
- package/dist/src/components/ui/breadcrumb.js.map +1 -0
- package/dist/src/components/ui/button.d.ts +14 -9
- package/dist/src/components/ui/button.js +37 -26
- package/dist/src/components/ui/button.js.map +1 -0
- package/dist/src/components/ui/card.d.ts +12 -8
- package/dist/src/components/ui/card.js +38 -10
- package/dist/src/components/ui/card.js.map +1 -0
- package/dist/src/components/ui/checkbox.d.ts +6 -2
- package/dist/src/components/ui/checkbox.js +17 -5
- package/dist/src/components/ui/checkbox.js.map +1 -0
- package/dist/src/components/ui/collapsible.d.ts +9 -4
- package/dist/src/components/ui/collapsible.js +5 -1
- package/dist/src/components/ui/collapsible.js.map +1 -0
- package/dist/src/components/ui/dialog.d.ts +44 -12
- package/dist/src/components/ui/dialog.js +64 -14
- package/dist/src/components/ui/dialog.js.map +1 -0
- package/dist/src/components/ui/dropdown-menu.d.ts +32 -24
- package/dist/src/components/ui/dropdown-menu.js +64 -14
- package/dist/src/components/ui/dropdown-menu.js.map +1 -0
- package/dist/src/components/ui/floating-navbar.d.ts +18 -9
- package/dist/src/components/ui/floating-navbar.js +49 -35
- package/dist/src/components/ui/floating-navbar.js.map +1 -0
- package/dist/src/components/ui/form.d.ts +30 -21
- package/dist/src/components/ui/form.js +76 -44
- package/dist/src/components/ui/form.js.map +1 -0
- package/dist/src/components/ui/image.d.ts +6 -2
- package/dist/src/components/ui/image.js +51 -11
- package/dist/src/components/ui/image.js.map +1 -0
- package/dist/src/components/ui/input.d.ts +6 -2
- package/dist/src/components/ui/input.js +14 -5
- package/dist/src/components/ui/input.js.map +1 -0
- package/dist/src/components/ui/label.d.ts +8 -3
- package/dist/src/components/ui/label.js +13 -5
- package/dist/src/components/ui/label.js.map +1 -0
- package/dist/src/components/ui/pagination.d.ts +39 -12
- package/dist/src/components/ui/pagination.js +64 -14
- package/dist/src/components/ui/pagination.js.map +1 -0
- package/dist/src/components/ui/progress.d.ts +6 -2
- package/dist/src/components/ui/progress.js +16 -4
- package/dist/src/components/ui/progress.js.map +1 -0
- package/dist/src/components/ui/resizable-navbar.d.ts +84 -43
- package/dist/src/components/ui/resizable-navbar.js +126 -74
- package/dist/src/components/ui/resizable-navbar.js.map +1 -0
- package/dist/src/components/ui/segment-control.d.ts +10 -7
- package/dist/src/components/ui/segment-control.js +83 -38
- package/dist/src/components/ui/segment-control.js.map +1 -0
- package/dist/src/components/ui/select.d.ts +16 -12
- package/dist/src/components/ui/select.js +63 -14
- package/dist/src/components/ui/select.js.map +1 -0
- package/dist/src/components/ui/separator.d.ts +6 -2
- package/dist/src/components/ui/separator.js +14 -4
- package/dist/src/components/ui/separator.js.map +1 -0
- package/dist/src/components/ui/sheet.d.ts +30 -19
- package/dist/src/components/ui/sheet.js +52 -23
- package/dist/src/components/ui/sheet.js.map +1 -0
- package/dist/src/components/ui/sidebar.d.ts +69 -62
- package/dist/src/components/ui/sidebar.js +326 -171
- package/dist/src/components/ui/sidebar.js.map +1 -0
- package/dist/src/components/ui/skeleton.d.ts +9 -1
- package/dist/src/components/ui/skeleton.js +10 -3
- package/dist/src/components/ui/skeleton.js.map +1 -0
- package/dist/src/components/ui/slider.d.ts +6 -2
- package/dist/src/components/ui/slider.js +16 -4
- package/dist/src/components/ui/slider.js.map +1 -0
- package/dist/src/components/ui/sonner.d.ts +10 -3
- package/dist/src/components/ui/sonner.js +18 -11
- package/dist/src/components/ui/sonner.js.map +1 -0
- package/dist/src/components/ui/spinner.d.ts +21 -10
- package/dist/src/components/ui/spinner.js +24 -24
- package/dist/src/components/ui/spinner.js.map +1 -0
- package/dist/src/components/ui/switch.d.ts +6 -2
- package/dist/src/components/ui/switch.js +13 -4
- package/dist/src/components/ui/switch.js.map +1 -0
- package/dist/src/components/ui/table.d.ts +39 -10
- package/dist/src/components/ui/table.js +51 -11
- package/dist/src/components/ui/table.js.map +1 -0
- package/dist/src/components/ui/tabs.d.ts +23 -6
- package/dist/src/components/ui/tabs.js +27 -7
- package/dist/src/components/ui/tabs.js.map +1 -0
- package/dist/src/components/ui/textarea.d.ts +10 -2
- package/dist/src/components/ui/textarea.js +11 -3
- package/dist/src/components/ui/textarea.js.map +1 -0
- package/dist/src/components/ui/timeline.d.ts +16 -9
- package/dist/src/components/ui/timeline.js +87 -24
- package/dist/src/components/ui/timeline.js.map +1 -0
- package/dist/src/components/ui/toast.d.ts +19 -14
- package/dist/src/components/ui/toast.js +48 -22
- package/dist/src/components/ui/toast.js.map +1 -0
- package/dist/src/components/ui/tooltip.d.ts +23 -6
- package/dist/src/components/ui/tooltip.js +27 -7
- package/dist/src/components/ui/tooltip.js.map +1 -0
- package/dist/src/components/ui/typewriter-effect.d.ts +28 -14
- package/dist/src/components/ui/typewriter-effect.js +102 -72
- package/dist/src/components/ui/typewriter-effect.js.map +1 -0
- package/dist/src/hooks/use-mobile.d.ts +5 -1
- package/dist/src/hooks/use-mobile.js +18 -13
- package/dist/src/hooks/use-mobile.js.map +1 -0
- package/dist/src/hooks/useDialog.d.ts +8 -4
- package/dist/src/hooks/useDialog.js +24 -20
- package/dist/src/hooks/useDialog.js.map +1 -0
- package/dist/src/icons/GoogleIcon.d.ts +9 -5
- package/dist/src/icons/GoogleIcon.js +32 -3
- package/dist/src/icons/GoogleIcon.js.map +1 -0
- package/dist/src/icons/LinkedInIcon.d.ts +9 -5
- package/dist/src/icons/LinkedInIcon.js +27 -3
- package/dist/src/icons/LinkedInIcon.js.map +1 -0
- package/dist/src/icons/MicrosoftIcon.d.ts +9 -5
- package/dist/src/icons/MicrosoftIcon.js +31 -3
- package/dist/src/icons/MicrosoftIcon.js.map +1 -0
- package/dist/src/lib/chatwoot.d.ts +19 -10
- package/dist/src/lib/chatwoot.js +25 -27
- package/dist/src/lib/chatwoot.js.map +1 -0
- package/dist/src/lib/utils.d.ts +7 -2
- package/dist/src/lib/utils.js +7 -2
- package/dist/src/lib/utils.js.map +1 -0
- package/dist/src/modules/app/components/AppLoader.d.ts +8 -2
- package/dist/src/modules/app/components/AppLoader.js +14 -3
- package/dist/src/modules/app/components/AppLoader.js.map +1 -0
- package/dist/src/modules/app/components/AppShell.d.ts +15 -6
- package/dist/src/modules/app/components/AppShell.js +14 -5
- package/dist/src/modules/app/components/AppShell.js.map +1 -0
- package/dist/src/modules/app/components/AppSidebar.d.ts +16 -6
- package/dist/src/modules/app/components/AppSidebar.js +17 -4
- package/dist/src/modules/app/components/AppSidebar.js.map +1 -0
- package/dist/src/modules/app/components/AppSidebarContent.d.ts +22 -13
- package/dist/src/modules/app/components/AppSidebarContent.js +34 -5
- package/dist/src/modules/app/components/AppSidebarContent.js.map +1 -0
- package/dist/src/modules/app/components/AppSidebarHeader.d.ts +18 -8
- package/dist/src/modules/app/components/AppSidebarHeader.js +37 -6
- package/dist/src/modules/app/components/AppSidebarHeader.js.map +1 -0
- package/dist/src/modules/app/components/AppSidebarInvites.d.ts +11 -3
- package/dist/src/modules/app/components/AppSidebarInvites.js +39 -8
- package/dist/src/modules/app/components/AppSidebarInvites.js.map +1 -0
- package/dist/src/modules/app/components/AppSidebarUser.d.ts +20 -10
- package/dist/src/modules/app/components/AppSidebarUser.js +121 -12
- package/dist/src/modules/app/components/AppSidebarUser.js.map +1 -0
- package/dist/src/modules/auth/components/AdminUserManagement.d.ts +11 -4
- package/dist/src/modules/auth/components/AdminUserManagement.js +970 -418
- package/dist/src/modules/auth/components/AdminUserManagement.js.map +1 -0
- package/dist/src/modules/auth/components/AdminWaitlist.d.ts +11 -4
- package/dist/src/modules/auth/components/AdminWaitlist.js +284 -115
- package/dist/src/modules/auth/components/AdminWaitlist.js.map +1 -0
- package/dist/src/modules/auth/components/AuthLayout.d.ts +12 -4
- package/dist/src/modules/auth/components/AuthLayout.js +17 -3
- package/dist/src/modules/auth/components/AuthLayout.js.map +1 -0
- package/dist/src/modules/auth/components/AuthProviders.d.ts +17 -6
- package/dist/src/modules/auth/components/AuthProviders.js +80 -41
- package/dist/src/modules/auth/components/AuthProviders.js.map +1 -0
- package/dist/src/modules/auth/components/AuthRouter.d.ts +16 -7
- package/dist/src/modules/auth/components/AuthRouter.js +46 -10
- package/dist/src/modules/auth/components/AuthRouter.js.map +1 -0
- package/dist/src/modules/auth/components/ClaimAccountRoute.d.ts +12 -4
- package/dist/src/modules/auth/components/ClaimAccountRoute.js +202 -139
- package/dist/src/modules/auth/components/ClaimAccountRoute.js.map +1 -0
- package/dist/src/modules/auth/components/ErrorAuthRoute.d.ts +7 -1
- package/dist/src/modules/auth/components/ErrorAuthRoute.js +125 -89
- package/dist/src/modules/auth/components/ErrorAuthRoute.js.map +1 -0
- package/dist/src/modules/auth/components/ForgotPasswordForm.d.ts +7 -1
- package/dist/src/modules/auth/components/ForgotPasswordForm.js +49 -23
- package/dist/src/modules/auth/components/ForgotPasswordForm.js.map +1 -0
- package/dist/src/modules/auth/components/ForgotPasswordRoute.d.ts +7 -1
- package/dist/src/modules/auth/components/ForgotPasswordRoute.js +34 -6
- package/dist/src/modules/auth/components/ForgotPasswordRoute.js.map +1 -0
- package/dist/src/modules/auth/components/InviteFriends.d.ts +12 -4
- package/dist/src/modules/auth/components/InviteFriends.js +275 -69
- package/dist/src/modules/auth/components/InviteFriends.js.map +1 -0
- package/dist/src/modules/auth/components/LastUsedBadge.d.ts +17 -5
- package/dist/src/modules/auth/components/LastUsedBadge.js +16 -6
- package/dist/src/modules/auth/components/LastUsedBadge.js.map +1 -0
- package/dist/src/modules/auth/components/LoginForm.d.ts +11 -3
- package/dist/src/modules/auth/components/LoginForm.js +107 -40
- package/dist/src/modules/auth/components/LoginForm.js.map +1 -0
- package/dist/src/modules/auth/components/LoginRoute.d.ts +11 -3
- package/dist/src/modules/auth/components/LoginRoute.js +41 -8
- package/dist/src/modules/auth/components/LoginRoute.js.map +1 -0
- package/dist/src/modules/auth/components/LogoutRoute.d.ts +7 -1
- package/dist/src/modules/auth/components/LogoutRoute.js +18 -12
- package/dist/src/modules/auth/components/LogoutRoute.js.map +1 -0
- package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.d.ts +21 -8
- package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.js +107 -97
- package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.js.map +1 -0
- package/dist/src/modules/auth/components/OrganizationMembersRoute.d.ts +58 -48
- package/dist/src/modules/auth/components/OrganizationMembersRoute.js +448 -349
- package/dist/src/modules/auth/components/OrganizationMembersRoute.js.map +1 -0
- package/dist/src/modules/auth/components/OrganizationPreferences.d.ts +27 -16
- package/dist/src/modules/auth/components/OrganizationPreferences.js +129 -124
- package/dist/src/modules/auth/components/OrganizationPreferences.js.map +1 -0
- package/dist/src/modules/auth/components/OrganizationSettingsRoute.d.ts +27 -18
- package/dist/src/modules/auth/components/OrganizationSettingsRoute.js +184 -144
- package/dist/src/modules/auth/components/OrganizationSettingsRoute.js.map +1 -0
- package/dist/src/modules/auth/components/OrganizationSwitcher.d.ts +17 -6
- package/dist/src/modules/auth/components/OrganizationSwitcher.js +91 -69
- package/dist/src/modules/auth/components/OrganizationSwitcher.js.map +1 -0
- package/dist/src/modules/auth/components/PreferencesEditor.d.ts +44 -33
- package/dist/src/modules/auth/components/PreferencesEditor.js +82 -58
- package/dist/src/modules/auth/components/PreferencesEditor.js.map +1 -0
- package/dist/src/modules/auth/components/ProfileRoute.d.ts +7 -1
- package/dist/src/modules/auth/components/ProfileRoute.js +79 -36
- package/dist/src/modules/auth/components/ProfileRoute.js.map +1 -0
- package/dist/src/modules/auth/components/RangeNuqsDatePicker.d.ts +44 -30
- package/dist/src/modules/auth/components/RangeNuqsDatePicker.js +234 -242
- package/dist/src/modules/auth/components/RangeNuqsDatePicker.js.map +1 -0
- package/dist/src/modules/auth/components/ResetPasswordForm.d.ts +7 -1
- package/dist/src/modules/auth/components/ResetPasswordForm.js +97 -35
- package/dist/src/modules/auth/components/ResetPasswordForm.js.map +1 -0
- package/dist/src/modules/auth/components/ResetPasswordRoute.d.ts +7 -1
- package/dist/src/modules/auth/components/ResetPasswordRoute.js +34 -6
- package/dist/src/modules/auth/components/ResetPasswordRoute.js.map +1 -0
- package/dist/src/modules/auth/components/SignupFormRoute.d.ts +15 -5
- package/dist/src/modules/auth/components/SignupFormRoute.js +142 -99
- package/dist/src/modules/auth/components/SignupFormRoute.js.map +1 -0
- package/dist/src/modules/auth/components/SignupRoute.d.ts +13 -5
- package/dist/src/modules/auth/components/SignupRoute.js +59 -13
- package/dist/src/modules/auth/components/SignupRoute.js.map +1 -0
- package/dist/src/modules/auth/components/UserPreferences.d.ts +22 -11
- package/dist/src/modules/auth/components/UserPreferences.js +24 -12
- package/dist/src/modules/auth/components/UserPreferences.js.map +1 -0
- package/dist/src/modules/auth/components/WaitlistCard.d.ts +11 -4
- package/dist/src/modules/auth/components/WaitlistCard.js +63 -28
- package/dist/src/modules/auth/components/WaitlistCard.js.map +1 -0
- package/dist/src/modules/auth/components/WaitlistCodeValidation.d.ts +13 -5
- package/dist/src/modules/auth/components/WaitlistCodeValidation.js +42 -40
- package/dist/src/modules/auth/components/WaitlistCodeValidation.js.map +1 -0
- package/dist/src/modules/billing/components/BillingBetaPage.d.ts +15 -6
- package/dist/src/modules/billing/components/BillingBetaPage.js +155 -8
- package/dist/src/modules/billing/components/BillingBetaPage.js.map +1 -0
- package/dist/src/modules/billing/components/BillingInvoicePage.d.ts +13 -5
- package/dist/src/modules/billing/components/BillingInvoicePage.js +160 -30
- package/dist/src/modules/billing/components/BillingInvoicePage.js.map +1 -0
- package/dist/src/modules/billing/components/BillingPlanSelect.d.ts +11 -4
- package/dist/src/modules/billing/components/BillingPlanSelect.js +10 -7
- package/dist/src/modules/billing/components/BillingPlanSelect.js.map +1 -0
- package/dist/src/modules/billing/components/BillingRouter.d.ts +15 -7
- package/dist/src/modules/billing/components/BillingRouter.js +19 -6
- package/dist/src/modules/billing/components/BillingRouter.js.map +1 -0
- package/dist/src/modules/billing/components/BillingSinglePlanSelect.d.ts +17 -7
- package/dist/src/modules/billing/components/BillingSinglePlanSelect.js +163 -42
- package/dist/src/modules/billing/components/BillingSinglePlanSelect.js.map +1 -0
- package/dist/src/modules/table/components/ColumnOrderAndVisibility.d.ts +18 -8
- package/dist/src/modules/table/components/ColumnOrderAndVisibility.js +81 -38
- package/dist/src/modules/table/components/ColumnOrderAndVisibility.js.map +1 -0
- package/dist/src/modules/table/components/NuqsTable.d.ts +33 -21
- package/dist/src/modules/table/components/NuqsTable.js +295 -221
- package/dist/src/modules/table/components/NuqsTable.js.map +1 -0
- package/dist/src/modules/table/components/TableFiltering.d.ts +33 -21
- package/dist/src/modules/table/components/TableFiltering.js +408 -226
- package/dist/src/modules/table/components/TableFiltering.js.map +1 -0
- package/dist/src/modules/table/components/TableGroupBy.d.ts +18 -8
- package/dist/src/modules/table/components/TableGroupBy.js +56 -16
- package/dist/src/modules/table/components/TableGroupBy.js.map +1 -0
- package/dist/src/modules/table/components/TablePagination.d.ts +17 -7
- package/dist/src/modules/table/components/TablePagination.js +64 -32
- package/dist/src/modules/table/components/TablePagination.js.map +1 -0
- package/dist/src/modules/table/components/table.types.d.ts +15 -10
- package/dist/src/modules/table/components/table.types.js +0 -1
- package/dist/src/modules/table/filterTransformers.d.ts +35 -30
- package/dist/src/modules/table/filterTransformers.js +198 -261
- package/dist/src/modules/table/filterTransformers.js.map +1 -0
- package/dist/src/types.d.ts +8 -3
- package/dist/src/types.js +0 -1
- package/package.json +8 -6
- package/dist/translations/en/web-ui.json +0 -209
- package/dist/tsconfig.lib.tsbuildinfo +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminUserManagement.js","names":[],"sources":["../../../../../src/modules/auth/components/AdminUserManagement.tsx"],"sourcesContent":["import {\r\n Button,\r\n Dropdown,\r\n DropdownItem,\r\n DropdownMenu,\r\n DropdownTrigger,\r\n Input,\r\n Modal,\r\n ModalBody,\r\n ModalContent,\r\n ModalFooter,\r\n ModalHeader,\r\n Select,\r\n SelectItem,\r\n Spinner,\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableColumn,\r\n TableHeader,\r\n TableRow,\r\n Tooltip,\r\n} from \"@heroui/react\";\r\nimport { authClient } from \"@m5kdev/frontend/modules/auth/auth.lib\";\r\nimport * as authAdmin from \"@m5kdev/frontend/modules/auth/hooks/useAuthAdmin\";\r\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\r\nimport {\r\n BarChart3,\r\n CalendarClock,\r\n ChevronDown,\r\n ChevronUp,\r\n Copy,\r\n Filter,\r\n Info,\r\n Link2,\r\n List,\r\n MoreHorizontal,\r\n Search,\r\n UserPlus,\r\n X,\r\n} from \"lucide-react\";\r\nimport { useCallback, useEffect, useId, useState } from \"react\";\r\nimport { useNavigate } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport type { UseBackendTRPC } from \"../../../types\";\r\n\r\ntype SortField = \"name\" | \"email\" | \"role\" | \"createdAt\";\r\ntype SortOrder = \"asc\" | \"desc\";\r\ntype StatusFilter = \"all\" | \"banned\" | \"active\";\r\n\r\ninterface AdminUserManagementProps {\r\n useTRPC?: UseBackendTRPC;\r\n}\r\n\r\nexport function AdminUserManagement({ useTRPC }: AdminUserManagementProps) {\r\n const banReasonInputId = useId();\r\n const customDurationId = useId();\r\n const nameInputId = useId();\r\n const emailInputId = useId();\r\n const passwordInputId = useId();\r\n const roleSelectId = useId();\r\n const [page, setPage] = useState(0);\r\n const [limit] = useState(10);\r\n const [userToDelete, setUserToDelete] = useState<string | null>(null);\r\n const [userToBan, setUserToBan] = useState<{ id: string; name: string } | null>(null);\r\n const [banReason, setBanReason] = useState(\"\");\r\n const [banExpiry, setBanExpiry] = useState(\"never\"); // \"never\", \"1d\", \"7d\", \"30d\", \"custom\"\r\n const [customBanDays, setCustomBanDays] = useState(1);\r\n const [isBanningUser, setIsBanningUser] = useState(false);\r\n const [isUnbanningUser, setIsUnbanningUser] = useState<Record<string, boolean>>({});\r\n const [isImpersonatingUser, setIsImpersonatingUser] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState(\"\");\r\n const [statusFilter, setStatusFilter] = useState<StatusFilter>(\"all\");\r\n const [sortField, setSortField] = useState<SortField>(\"createdAt\");\r\n const [sortOrder, setSortOrder] = useState<SortOrder>(\"desc\");\r\n const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(\"\");\r\n const [isCreateUserModalOpen, setIsCreateUserModalOpen] = useState(false);\r\n const [newUserData, setNewUserData] = useState({\r\n name: \"\",\r\n email: \"\",\r\n password: \"\",\r\n role: \"user\",\r\n });\r\n const [isCreatingUser, setIsCreatingUser] = useState(false);\r\n const [userForUsage, setUserForUsage] = useState<{ id: string; name: string } | null>(null);\r\n const [userForMagicLink, setUserForMagicLink] = useState<{\r\n id: string;\r\n name: string;\r\n email: string | null;\r\n } | null>(null);\r\n const [claimEmail, setClaimEmail] = useState(\"\");\r\n const [generatedMagicLink, setGeneratedMagicLink] = useState<string | null>(null);\r\n const [isGeneratingMagicLink, setIsGeneratingMagicLink] = useState(false);\r\n const navigate = useNavigate();\r\n const magicLinkEmailInputId = useId();\r\n const generatedMagicLinkInputId = useId();\r\n\r\n // AI Usage query\r\n const trpc = useTRPC?.();\r\n const queryClient = useQueryClient();\r\n const usageQueryEnabled = !!userForUsage && !!trpc;\r\n const usageQueryOptions = trpc?.ai.getUserUsage.queryOptions({ userId: userForUsage?.id ?? \"\" });\r\n const usageQuery = useQuery({\r\n ...(usageQueryOptions ?? {\r\n queryKey: [[\"ai\", \"getUserUsage\"], { input: { userId: \"\" } }] as const,\r\n queryFn: () =>\r\n Promise.resolve({ inputTokens: null, outputTokens: null, totalTokens: null, cost: null }),\r\n }),\r\n enabled: usageQueryEnabled,\r\n });\r\n const usageData = usageQuery.data;\r\n const isLoadingUsage = usageQuery.isLoading;\r\n\r\n const refetchUsage = () => {\r\n if (usageQueryOptions) {\r\n queryClient.invalidateQueries({ queryKey: usageQueryOptions.queryKey });\r\n }\r\n };\r\n\r\n // Reset page on filter change\r\n const resetPage = useCallback(() => {\r\n setPage(0);\r\n }, []);\r\n\r\n // Debounce search query\r\n useEffect(() => {\r\n const timer = setTimeout(() => {\r\n setDebouncedSearchQuery(searchQuery);\r\n resetPage();\r\n }, 300);\r\n\r\n return () => clearTimeout(timer);\r\n }, [searchQuery, resetPage]);\r\n\r\n // Handle status filter change\r\n const handleStatusFilterChange = useCallback(\r\n (value: StatusFilter) => {\r\n setStatusFilter(value);\r\n resetPage();\r\n },\r\n [resetPage]\r\n );\r\n\r\n const {\r\n data: listUsers = {\r\n users: [],\r\n total: 0,\r\n },\r\n isLoading,\r\n refetch,\r\n } = authAdmin.useListUsers({\r\n query: {\r\n searchField: \"name\",\r\n searchOperator: \"contains\",\r\n searchValue: debouncedSearchQuery,\r\n limit,\r\n offset: page * limit,\r\n sortBy: sortField,\r\n sortDirection: sortOrder,\r\n },\r\n });\r\n\r\n const { users, total: totalUsers } = listUsers;\r\n\r\n const { mutate: deleteUser, isPending: isDeleting } = authAdmin.useRemoveUser({\r\n onSuccess: () => {\r\n toast.success(\"User deleted successfully\");\r\n refetch();\r\n },\r\n onError: (error) => {\r\n toast.error(`Error deleting user: ${error.message}`);\r\n },\r\n });\r\n\r\n const { mutate: updateUser } = authAdmin.useUpdateUser({\r\n onSuccess: () => {\r\n toast.success(\"User updated successfully\");\r\n refetch();\r\n },\r\n onError: (error) => {\r\n toast.error(`Error updating user: ${error.message}`);\r\n },\r\n });\r\n\r\n const totalPages = totalUsers ? Math.ceil(totalUsers / limit) : 0;\r\n\r\n const confirmDelete = (userId: string) => {\r\n setUserToDelete(userId);\r\n };\r\n\r\n const handleDelete = () => {\r\n if (userToDelete) {\r\n deleteUser({ id: userToDelete });\r\n setUserToDelete(null);\r\n }\r\n };\r\n\r\n const openBanModal = (userId: string, userName: string) => {\r\n setUserToBan({ id: userId, name: userName });\r\n setBanReason(\"\");\r\n setBanExpiry(\"never\");\r\n setCustomBanDays(1);\r\n };\r\n\r\n const getBanExpiryInSeconds = () => {\r\n switch (banExpiry) {\r\n case \"never\":\r\n return undefined; // No expiry\r\n case \"1d\":\r\n return 60 * 60 * 24; // 1 day in seconds\r\n case \"7d\":\r\n return 60 * 60 * 24 * 7; // 7 days in seconds\r\n case \"30d\":\r\n return 60 * 60 * 24 * 30; // 30 days in seconds\r\n case \"custom\":\r\n return 60 * 60 * 24 * customBanDays; // Custom days in seconds\r\n default:\r\n return undefined;\r\n }\r\n };\r\n\r\n const formatBanExpiry = (expiryTimestamp: number | null) => {\r\n if (!expiryTimestamp) return \"Never\";\r\n\r\n const expiryDate = new Date(expiryTimestamp);\r\n const now = new Date();\r\n\r\n // If it's expired, return that\r\n if (expiryDate < now) return \"Expired\";\r\n\r\n // Format the date\r\n const dateString = expiryDate.toLocaleDateString(undefined, {\r\n year: \"numeric\",\r\n month: \"short\",\r\n day: \"numeric\",\r\n });\r\n\r\n // Calculate time remaining\r\n const timeRemaining = expiryDate.getTime() - now.getTime();\r\n const daysRemaining = Math.ceil(timeRemaining / (1000 * 60 * 60 * 24));\r\n\r\n return `${dateString} (${daysRemaining} days)`;\r\n };\r\n\r\n const handleBanUser = async () => {\r\n if (!userToBan) return;\r\n\r\n try {\r\n setIsBanningUser(true);\r\n await authClient.admin.banUser({\r\n userId: userToBan.id,\r\n banReason: banReason || \"No reason provided\",\r\n banExpiresIn: getBanExpiryInSeconds(),\r\n });\r\n\r\n toast.success(`User ${userToBan.name} has been banned`);\r\n setUserToBan(null);\r\n await refetch();\r\n } catch (error) {\r\n toast.error(`Failed to ban user: ${error instanceof Error ? error.message : String(error)}`);\r\n } finally {\r\n setIsBanningUser(false);\r\n }\r\n };\r\n\r\n const handleUnbanUser = async (userId: string) => {\r\n try {\r\n setIsUnbanningUser((prev) => ({ ...prev, [userId]: true }));\r\n await authClient.admin.unbanUser({\r\n userId,\r\n });\r\n\r\n toast.success(\"User has been unbanned\");\r\n await refetch();\r\n } catch (error) {\r\n toast.error(\r\n `Failed to unban user: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n } finally {\r\n setIsUnbanningUser((prev) => ({ ...prev, [userId]: false }));\r\n }\r\n };\r\n\r\n const handleSetOnboardingUser = async (userId: string) => {\r\n const onboardingStep = window.prompt(`Set onboarding step for user ${userId}`, \"4\");\r\n const onboardingStepNumber = Number.parseInt(onboardingStep || \"0\");\r\n if (onboardingStepNumber) {\r\n updateUser({\r\n userId,\r\n data: { onboarding: onboardingStepNumber },\r\n });\r\n }\r\n };\r\n\r\n const handleImpersonateUser = async (userId: string) => {\r\n try {\r\n setIsImpersonatingUser(true);\r\n await authClient.admin.impersonateUser({\r\n userId,\r\n });\r\n\r\n toast.success(\"Now impersonating user\");\r\n window.location.assign(\"/\"); // Force full reload to apply impersonated session immediately\r\n } catch (error) {\r\n setIsImpersonatingUser(false);\r\n toast.error(\r\n `Failed to impersonate user: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n }\r\n };\r\n\r\n const handlePageChange = (newPage: number) => {\r\n if (newPage >= 0 && newPage < totalPages) {\r\n setPage(newPage);\r\n }\r\n };\r\n\r\n const handleSort = (field: SortField) => {\r\n if (sortField === field) {\r\n // Toggle order if same field\r\n setSortOrder(sortOrder === \"asc\" ? \"desc\" : \"asc\");\r\n } else {\r\n // Set new field and default to ascending\r\n setSortField(field);\r\n setSortOrder(\"asc\");\r\n }\r\n };\r\n\r\n const renderSortIcon = (field: SortField) => {\r\n if (sortField !== field) return null;\r\n\r\n return sortOrder === \"asc\" ? (\r\n <ChevronUp className=\"h-4 w-4 inline ml-1\" />\r\n ) : (\r\n <ChevronDown className=\"h-4 w-4 inline ml-1\" />\r\n );\r\n };\r\n\r\n const clearFilters = () => {\r\n setSearchQuery(\"\");\r\n setStatusFilter(\"all\");\r\n setSortField(\"createdAt\");\r\n setSortOrder(\"desc\");\r\n };\r\n\r\n const openCreateUserModal = () => {\r\n setNewUserData({\r\n name: \"\",\r\n email: \"\",\r\n password: \"\",\r\n role: \"user\",\r\n });\r\n setIsCreateUserModalOpen(true);\r\n };\r\n\r\n const handleCreateUser = async () => {\r\n if (!newUserData.name || !newUserData.email || !newUserData.password) {\r\n toast.error(\"Please fill in all required fields\");\r\n return;\r\n }\r\n\r\n try {\r\n setIsCreatingUser(true);\r\n await authClient.admin.createUser({\r\n name: newUserData.name,\r\n email: newUserData.email,\r\n password: newUserData.password,\r\n role: newUserData.role as \"user\" | \"admin\",\r\n });\r\n\r\n toast.success(`User ${newUserData.name} has been created`);\r\n setIsCreateUserModalOpen(false);\r\n await refetch();\r\n } catch (error) {\r\n toast.error(\r\n `Failed to create user: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n } finally {\r\n setIsCreatingUser(false);\r\n }\r\n };\r\n\r\n const handleNewUserDataChange = (field: keyof typeof newUserData, value: string) => {\r\n setNewUserData((prev) => ({\r\n ...prev,\r\n [field]: value,\r\n }));\r\n };\r\n\r\n const openUsageModal = (userId: string, userName: string) => {\r\n setUserForUsage({ id: userId, name: userName });\r\n refetchUsage();\r\n };\r\n\r\n const formatTokenCount = (count: number | null | undefined): string => {\r\n if (count === null || count === undefined) return \"—\";\r\n return count.toLocaleString();\r\n };\r\n\r\n const formatCost = (cost: number | null | undefined): string => {\r\n if (cost === null || cost === undefined) return \"—\";\r\n return `$${cost.toFixed(4)}`;\r\n };\r\n\r\n const createAccountClaimCodeMutation = useMutation(\r\n trpc\r\n ? trpc.auth.createAccountClaimCode.mutationOptions()\r\n : {\r\n mutationFn: async () => {\r\n throw new Error(\"Account claim actions are not available in this app\");\r\n },\r\n }\r\n );\r\n\r\n const generateAccountClaimMagicLinkMutation = useMutation(\r\n trpc\r\n ? trpc.auth.generateAccountClaimMagicLink.mutationOptions()\r\n : {\r\n mutationFn: async () => {\r\n throw new Error(\"Account claim actions are not available in this app\");\r\n },\r\n }\r\n );\r\n\r\n const openMagicLinkModal = (userId: string, userName: string, userEmail: string | null) => {\r\n setUserForMagicLink({ id: userId, name: userName, email: userEmail });\r\n setClaimEmail(userEmail ?? \"\");\r\n setGeneratedMagicLink(null);\r\n };\r\n\r\n const handleGenerateMagicLink = async () => {\r\n if (!trpc) {\r\n toast.error(\"Account claim actions are not available in this app\");\r\n return;\r\n }\r\n\r\n if (!userForMagicLink) return;\r\n\r\n const normalizedEmail = claimEmail.trim().toLowerCase();\r\n if (!normalizedEmail) {\r\n toast.error(\"Email is required\");\r\n return;\r\n }\r\n\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n if (!emailRegex.test(normalizedEmail)) {\r\n toast.error(\"Please enter a valid email address\");\r\n return;\r\n }\r\n\r\n try {\r\n setIsGeneratingMagicLink(true);\r\n const claim = await createAccountClaimCodeMutation.mutateAsync({\r\n userId: userForMagicLink.id,\r\n });\r\n const link = await generateAccountClaimMagicLinkMutation.mutateAsync({\r\n claimId: claim.id,\r\n email: normalizedEmail,\r\n });\r\n setGeneratedMagicLink(link.url);\r\n toast.success(\"Magic login link generated\");\r\n } catch (error) {\r\n toast.error(\r\n `Failed to generate magic link: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n } finally {\r\n setIsGeneratingMagicLink(false);\r\n }\r\n };\r\n\r\n const copyGeneratedMagicLink = async () => {\r\n if (!generatedMagicLink) return;\r\n\r\n try {\r\n await navigator.clipboard.writeText(generatedMagicLink);\r\n toast.success(\"Magic link copied\");\r\n } catch {\r\n toast.error(\"Failed to copy link\");\r\n }\r\n };\r\n\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex justify-center p-8\">\r\n <Spinner />\r\n </div>\r\n );\r\n }\r\n\r\n const openWaitlistModal = () => {\r\n navigate(\"/admin/waitlist\");\r\n };\r\n\r\n const hasActiveFilters =\r\n debouncedSearchQuery ||\r\n statusFilter !== \"all\" ||\r\n sortField !== \"createdAt\" ||\r\n sortOrder !== \"desc\";\r\n\r\n return (\r\n <div className=\"space-y-4 p-4\">\r\n <div className=\"flex justify-between items-center\">\r\n <h2 className=\"text-xl font-semibold\">User Management</h2>\r\n <div className=\"flex items-center gap-2\">\r\n <Button onPress={openWaitlistModal} size=\"sm\">\r\n <List className=\"h-4 w-4 mr-2\" />\r\n Waitlist\r\n </Button>\r\n <Button onPress={openCreateUserModal} size=\"sm\">\r\n <UserPlus className=\"h-4 w-4 mr-2\" />\r\n Create User\r\n </Button>\r\n <div className=\"text-sm text-muted-foreground\">Total users: {totalUsers || 0}</div>\r\n </div>\r\n </div>\r\n\r\n {/* Search and filters */}\r\n <div className=\"flex flex-col sm:flex-row gap-3 items-start sm:items-center\">\r\n <form\r\n className=\"relative flex-1\"\r\n onSubmit={(e) => {\r\n e.preventDefault();\r\n setDebouncedSearchQuery(searchQuery);\r\n resetPage();\r\n }}\r\n >\r\n <Search className=\"absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground\" />\r\n <Input\r\n aria-label=\"Search users\"\r\n placeholder=\"Search users by name or email...\"\r\n className=\"pl-8 w-full\"\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n variant=\"bordered\"\r\n />\r\n {searchQuery && (\r\n <button\r\n type=\"button\"\r\n onClick={() => setSearchQuery(\"\")}\r\n className=\"absolute right-2.5 top-2.5 text-muted-foreground hover:text-foreground\"\r\n aria-label=\"Clear search\"\r\n >\r\n <X className=\"h-4 w-4\" />\r\n </button>\r\n )}\r\n </form>\r\n\r\n <div className=\"flex gap-2\">\r\n <Select\r\n aria-label=\"Status filter\"\r\n selectedKeys={new Set([statusFilter])}\r\n onSelectionChange={(keys) =>\r\n handleStatusFilterChange(Array.from(keys)[0] as StatusFilter)\r\n }\r\n className=\"w-[160px]\"\r\n startContent={<Filter className=\"mr-1 h-4 w-4\" />}\r\n >\r\n <SelectItem key=\"all\">All Users</SelectItem>\r\n <SelectItem key=\"active\">Active Only</SelectItem>\r\n <SelectItem key=\"banned\">Banned Only</SelectItem>\r\n </Select>\r\n\r\n {hasActiveFilters && (\r\n <Button variant=\"bordered\" size=\"sm\" onPress={clearFilters}>\r\n <X className=\"mr-1 h-4 w-4\" />\r\n Clear Filters\r\n </Button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <div className=\"border rounded-lg overflow-hidden\">\r\n <Table aria-label=\"Users table\" removeWrapper>\r\n <TableHeader>\r\n <TableColumn>ID</TableColumn>\r\n <TableColumn className=\"cursor-pointer\" onClick={() => handleSort(\"name\")}>\r\n Name {renderSortIcon(\"name\")}\r\n </TableColumn>\r\n <TableColumn className=\"cursor-pointer\" onClick={() => handleSort(\"email\")}>\r\n Email {renderSortIcon(\"email\")}\r\n </TableColumn>\r\n <TableColumn className=\"cursor-pointer\" onClick={() => handleSort(\"role\")}>\r\n Role {renderSortIcon(\"role\")}\r\n </TableColumn>\r\n <TableColumn>Status</TableColumn>\r\n <TableColumn>Onboarding</TableColumn>\r\n <TableColumn className=\"cursor-pointer\" onClick={() => handleSort(\"createdAt\")}>\r\n Created At {renderSortIcon(\"createdAt\")}\r\n </TableColumn>\r\n <TableColumn className=\"text-right\">Actions</TableColumn>\r\n </TableHeader>\r\n <TableBody\r\n items={users ?? []}\r\n emptyContent={\r\n hasActiveFilters ? \"No users found matching your filters\" : \"No users found\"\r\n }\r\n >\r\n {(user) => {\r\n const onboarding = (user as { onboarding?: string | number }).onboarding;\r\n return (\r\n <TableRow key={user.id}>\r\n <TableCell className=\"font-mono text-xs\">{user.id}</TableCell>\r\n <TableCell>{user.name}</TableCell>\r\n <TableCell>{user.email}</TableCell>\r\n <TableCell>{user.role || \"user\"}</TableCell>\r\n <TableCell>\r\n {user.banned ? (\r\n <Tooltip\r\n content={\r\n <div className=\"space-y-1 text-xs\">\r\n <p>\r\n <strong>Reason:</strong> {user.banReason || \"No reason provided\"}\r\n </p>\r\n {user.banExpires && (\r\n <p className=\"flex items-center gap-1\">\r\n <CalendarClock className=\"h-3 w-3\" />\r\n <span>\r\n <strong>Expires:</strong>{\" \"}\r\n {formatBanExpiry(user.banExpires.getTime())}\r\n </span>\r\n </p>\r\n )}\r\n </div>\r\n }\r\n >\r\n <span className=\"inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800\">\r\n Banned\r\n {user.banReason && <Info className=\"h-3 w-3\" />}\r\n </span>\r\n </Tooltip>\r\n ) : (\r\n <span className=\"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800\">\r\n Active\r\n </span>\r\n )}\r\n </TableCell>\r\n <TableCell>{onboarding ?? \"—\"}</TableCell>\r\n <TableCell>\r\n {user.createdAt ? new Date(user.createdAt).toLocaleDateString() : \"N/A\"}\r\n </TableCell>\r\n <TableCell className=\"text-right\">\r\n <Dropdown placement=\"bottom-end\">\r\n <DropdownTrigger>\r\n <Button variant=\"light\" size=\"sm\" isIconOnly>\r\n <MoreHorizontal className=\"h-4 w-4\" />\r\n </Button>\r\n </DropdownTrigger>\r\n <DropdownMenu aria-label=\"User actions\">\r\n <DropdownItem\r\n key=\"onboarding\"\r\n onClick={() => handleSetOnboardingUser(user.id)}\r\n >\r\n Set Onboarding\r\n </DropdownItem>\r\n <DropdownItem\r\n key=\"usage\"\r\n onClick={() => openUsageModal(user.id, user.name)}\r\n className={useTRPC ? \"\" : \"hidden\"}\r\n >\r\n <span className=\"flex items-center gap-2\">\r\n <BarChart3 className=\"h-4 w-4\" />\r\n View AI Usage\r\n </span>\r\n </DropdownItem>\r\n <DropdownItem\r\n key=\"impersonate\"\r\n onClick={() => handleImpersonateUser(user.id)}\r\n isDisabled={user.banned || isImpersonatingUser}\r\n >\r\n {isImpersonatingUser ? (\r\n <>\r\n <Spinner className=\"mr-2 h-3 w-3\" />\r\n Impersonating...\r\n </>\r\n ) : (\r\n \"Impersonate\"\r\n )}\r\n </DropdownItem>\r\n <DropdownItem\r\n key=\"magic-link\"\r\n onClick={() => openMagicLinkModal(user.id, user.name, user.email ?? null)}\r\n className={trpc ? \"\" : \"hidden\"}\r\n >\r\n <span className=\"flex items-center gap-2\">\r\n <Link2 className=\"h-4 w-4\" />\r\n Generate Magic Login Link\r\n </span>\r\n </DropdownItem>\r\n {user.banned ? (\r\n <DropdownItem\r\n key=\"unban\"\r\n onClick={() => handleUnbanUser(user.id)}\r\n isDisabled={isUnbanningUser[user.id]}\r\n >\r\n {isUnbanningUser[user.id] ? (\r\n <>\r\n <Spinner className=\"mr-2 h-3 w-3\" />\r\n Unbanning...\r\n </>\r\n ) : (\r\n \"Unban\"\r\n )}\r\n </DropdownItem>\r\n ) : (\r\n <DropdownItem key=\"ban\" onClick={() => openBanModal(user.id, user.name)}>\r\n Ban\r\n </DropdownItem>\r\n )}\r\n <DropdownItem key=\"remove\" onClick={() => confirmDelete(user.id)}>\r\n Remove\r\n </DropdownItem>\r\n </DropdownMenu>\r\n </Dropdown>\r\n </TableCell>\r\n </TableRow>\r\n );\r\n }}\r\n </TableBody>\r\n </Table>\r\n </div>\r\n\r\n {/* Pagination */}\r\n {totalPages > 0 && (\r\n <div className=\"flex items-center justify-end space-x-2 py-4\">\r\n <Button\r\n variant=\"bordered\"\r\n size=\"sm\"\r\n onClick={() => handlePageChange(page - 1)}\r\n isDisabled={page === 0}\r\n >\r\n Previous\r\n </Button>\r\n <div className=\"text-sm text-muted-foreground\">\r\n Page {page + 1} of {totalPages}\r\n </div>\r\n <Button\r\n variant=\"bordered\"\r\n size=\"sm\"\r\n onClick={() => handlePageChange(page + 1)}\r\n isDisabled={page === totalPages - 1}\r\n >\r\n Next\r\n </Button>\r\n </div>\r\n )}\r\n\r\n {/* Delete confirmation modal */}\r\n <Modal\r\n isOpen={!!userToDelete}\r\n onOpenChange={(open) => {\r\n if (!open) setUserToDelete(null);\r\n }}\r\n >\r\n <ModalContent>\r\n {(onClose) => (\r\n <>\r\n <ModalHeader className=\"flex flex-col gap-1\">\r\n <p className=\"text-lg font-semibold\">Are you sure?</p>\r\n <p className=\"text-sm text-default-600\">\r\n This action cannot be undone. This will permanently delete the user and all their\r\n data.\r\n </p>\r\n </ModalHeader>\r\n <ModalFooter>\r\n <Button variant=\"bordered\" onPress={onClose}>\r\n Cancel\r\n </Button>\r\n <Button color=\"danger\" onPress={handleDelete} isLoading={isDeleting}>\r\n Delete\r\n </Button>\r\n </ModalFooter>\r\n </>\r\n )}\r\n </ModalContent>\r\n </Modal>\r\n\r\n {/* Ban user modal */}\r\n <Modal\r\n isOpen={!!userToBan}\r\n onOpenChange={(open) => {\r\n if (!open) setUserToBan(null);\r\n }}\r\n >\r\n <ModalContent>\r\n {(onClose) => (\r\n <form\r\n onSubmit={(e) => {\r\n e.preventDefault();\r\n handleBanUser();\r\n }}\r\n className=\"space-y-4\"\r\n >\r\n <ModalHeader className=\"flex flex-col gap-1\">\r\n <p className=\"text-lg font-semibold\">Ban User</p>\r\n <p className=\"text-sm text-default-600\">\r\n {userToBan &&\r\n `You are about to ban ${userToBan.name}. This will prevent them from signing in.`}\r\n </p>\r\n </ModalHeader>\r\n\r\n <ModalBody className=\"space-y-4\">\r\n <div className=\"space-y-2\">\r\n <label htmlFor={banReasonInputId} className=\"text-sm font-medium\">\r\n Ban Reason\r\n </label>\r\n <Input\r\n id={banReasonInputId}\r\n placeholder=\"Enter reason for ban\"\r\n value={banReason}\r\n onChange={(e) => setBanReason(e.target.value)}\r\n variant=\"bordered\"\r\n labelPlacement=\"outside\"\r\n label=\"Ban Reason\"\r\n />\r\n </div>\r\n\r\n <div className=\"space-y-2\">\r\n <p className=\"text-sm font-medium\">Ban Duration</p>\r\n <div className=\"grid grid-cols-2 gap-2\">\r\n <Button\r\n type=\"button\"\r\n variant={banExpiry === \"never\" ? \"solid\" : \"bordered\"}\r\n onClick={() => setBanExpiry(\"never\")}\r\n >\r\n Permanent\r\n </Button>\r\n <Button\r\n type=\"button\"\r\n variant={banExpiry === \"1d\" ? \"solid\" : \"bordered\"}\r\n onClick={() => setBanExpiry(\"1d\")}\r\n >\r\n 1 Day\r\n </Button>\r\n <Button\r\n type=\"button\"\r\n variant={banExpiry === \"7d\" ? \"solid\" : \"bordered\"}\r\n onClick={() => setBanExpiry(\"7d\")}\r\n >\r\n 7 Days\r\n </Button>\r\n <Button\r\n type=\"button\"\r\n variant={banExpiry === \"30d\" ? \"solid\" : \"bordered\"}\r\n onClick={() => setBanExpiry(\"30d\")}\r\n >\r\n 30 Days\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n <div className=\"space-y-2\">\r\n <div className=\"flex items-center gap-2\">\r\n <input\r\n type=\"checkbox\"\r\n id={customDurationId}\r\n checked={banExpiry === \"custom\"}\r\n onChange={(e) =>\r\n e.target.checked ? setBanExpiry(\"custom\") : setBanExpiry(\"never\")\r\n }\r\n />\r\n <label htmlFor={customDurationId} className=\"text-sm font-medium\">\r\n Custom Duration\r\n </label>\r\n </div>\r\n\r\n {banExpiry === \"custom\" && (\r\n <div className=\"flex items-center gap-2\">\r\n <Input\r\n type=\"number\"\r\n min=\"1\"\r\n value={customBanDays.toString()}\r\n onChange={(e) => setCustomBanDays(Number(e.target.value))}\r\n variant=\"bordered\"\r\n labelPlacement=\"outside\"\r\n label=\"Custom duration (days)\"\r\n />\r\n <span className=\"text-sm\">Days</span>\r\n </div>\r\n )}\r\n </div>\r\n </ModalBody>\r\n\r\n <ModalFooter>\r\n <Button variant=\"bordered\" type=\"button\" onPress={onClose}>\r\n Cancel\r\n </Button>\r\n <Button color=\"danger\" type=\"submit\" isDisabled={isBanningUser}>\r\n {isBanningUser ? <Spinner className=\"mr-2 h-4 w-4\" /> : null}\r\n {isBanningUser ? \"Banning...\" : \"Ban User\"}\r\n </Button>\r\n </ModalFooter>\r\n </form>\r\n )}\r\n </ModalContent>\r\n </Modal>\r\n\r\n {/* Create user modal */}\r\n <Modal\r\n isOpen={isCreateUserModalOpen}\r\n onOpenChange={(open) => {\r\n if (!open) setIsCreateUserModalOpen(false);\r\n }}\r\n >\r\n <ModalContent>\r\n {(onClose) => (\r\n <form\r\n onSubmit={(e) => {\r\n e.preventDefault();\r\n handleCreateUser();\r\n }}\r\n className=\"space-y-4\"\r\n >\r\n <ModalHeader className=\"flex flex-col gap-1\">\r\n <p className=\"text-lg font-semibold\">Create New User</p>\r\n <p className=\"text-sm text-default-600\">\r\n Fill in the details below to create a new user account.\r\n </p>\r\n </ModalHeader>\r\n\r\n <ModalBody className=\"space-y-4\">\r\n <div className=\"space-y-2\">\r\n <Input\r\n id={nameInputId}\r\n label=\"Name *\"\r\n labelPlacement=\"outside\"\r\n placeholder=\"Enter user's name\"\r\n value={newUserData.name}\r\n onChange={(e) => handleNewUserDataChange(\"name\", e.target.value)}\r\n variant=\"bordered\"\r\n />\r\n </div>\r\n\r\n <div className=\"space-y-2\">\r\n <Input\r\n id={emailInputId}\r\n label=\"Email *\"\r\n labelPlacement=\"outside\"\r\n type=\"email\"\r\n placeholder=\"Enter user's email\"\r\n value={newUserData.email}\r\n onChange={(e) => handleNewUserDataChange(\"email\", e.target.value)}\r\n variant=\"bordered\"\r\n />\r\n </div>\r\n\r\n <div className=\"space-y-2\">\r\n <Input\r\n id={passwordInputId}\r\n label=\"Password *\"\r\n labelPlacement=\"outside\"\r\n type=\"password\"\r\n placeholder=\"Enter password\"\r\n value={newUserData.password}\r\n onChange={(e) => handleNewUserDataChange(\"password\", e.target.value)}\r\n variant=\"bordered\"\r\n />\r\n </div>\r\n\r\n <div className=\"space-y-2\">\r\n <p className=\"text-sm font-medium\" id={roleSelectId}>\r\n Role\r\n </p>\r\n <Select\r\n aria-label=\"Select role\"\r\n aria-labelledby={roleSelectId}\r\n selectedKeys={new Set([newUserData.role])}\r\n onSelectionChange={(keys) =>\r\n handleNewUserDataChange(\"role\", Array.from(keys)[0] as string)\r\n }\r\n >\r\n <SelectItem key=\"user\">User</SelectItem>\r\n <SelectItem key=\"admin\">Admin</SelectItem>\r\n </Select>\r\n </div>\r\n </ModalBody>\r\n\r\n <ModalFooter>\r\n <Button variant=\"bordered\" type=\"button\" onPress={onClose}>\r\n Cancel\r\n </Button>\r\n <Button type=\"submit\" color=\"primary\" isDisabled={isCreatingUser}>\r\n {isCreatingUser ? <Spinner className=\"mr-2 h-4 w-4\" /> : null}\r\n {isCreatingUser ? \"Creating...\" : \"Create User\"}\r\n </Button>\r\n </ModalFooter>\r\n </form>\r\n )}\r\n </ModalContent>\r\n </Modal>\r\n\r\n {/* AI Usage modal */}\r\n <Modal\r\n isOpen={!!userForUsage}\r\n onOpenChange={(open) => {\r\n if (!open) setUserForUsage(null);\r\n }}\r\n >\r\n <ModalContent>\r\n {(onClose) => (\r\n <>\r\n <ModalHeader className=\"flex flex-col gap-1\">\r\n <p className=\"text-lg font-semibold flex items-center gap-2\">\r\n <BarChart3 className=\"h-5 w-5\" />\r\n AI Usage\r\n </p>\r\n <p className=\"text-sm text-default-600\">\r\n {userForUsage && `Usage statistics for ${userForUsage.name}`}\r\n </p>\r\n </ModalHeader>\r\n\r\n <ModalBody>\r\n {isLoadingUsage ? (\r\n <div className=\"flex justify-center py-8\">\r\n <Spinner />\r\n </div>\r\n ) : usageData ? (\r\n <div className=\"space-y-4\">\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div className=\"p-4 rounded-lg bg-default-100\">\r\n <p className=\"text-sm text-default-600\">Input Tokens</p>\r\n <p className=\"text-2xl font-semibold\">\r\n {formatTokenCount(usageData.inputTokens)}\r\n </p>\r\n </div>\r\n <div className=\"p-4 rounded-lg bg-default-100\">\r\n <p className=\"text-sm text-default-600\">Output Tokens</p>\r\n <p className=\"text-2xl font-semibold\">\r\n {formatTokenCount(usageData.outputTokens)}\r\n </p>\r\n </div>\r\n <div className=\"p-4 rounded-lg bg-default-100\">\r\n <p className=\"text-sm text-default-600\">Total Tokens</p>\r\n <p className=\"text-2xl font-semibold\">\r\n {formatTokenCount(usageData.totalTokens)}\r\n </p>\r\n </div>\r\n <div className=\"p-4 rounded-lg bg-primary-100\">\r\n <p className=\"text-sm text-primary-600\">Estimated Cost</p>\r\n <p className=\"text-2xl font-semibold text-primary\">\r\n {formatCost(usageData.cost)}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"text-center py-8 text-default-600\">No usage data available</div>\r\n )}\r\n </ModalBody>\r\n\r\n <ModalFooter>\r\n <Button variant=\"bordered\" onPress={onClose}>\r\n Close\r\n </Button>\r\n </ModalFooter>\r\n </>\r\n )}\r\n </ModalContent>\r\n </Modal>\r\n\r\n {/* Magic login link modal */}\r\n <Modal\r\n isOpen={!!userForMagicLink}\r\n onOpenChange={(open) => {\r\n if (!open) {\r\n setUserForMagicLink(null);\r\n setGeneratedMagicLink(null);\r\n setClaimEmail(\"\");\r\n }\r\n }}\r\n >\r\n <ModalContent>\r\n {(onClose) => (\r\n <form\r\n onSubmit={(e) => {\r\n e.preventDefault();\r\n handleGenerateMagicLink();\r\n }}\r\n className=\"space-y-4\"\r\n >\r\n <ModalHeader className=\"flex flex-col gap-1\">\r\n <p className=\"text-lg font-semibold\">Generate Magic Login Link</p>\r\n <p className=\"text-sm text-default-600\">\r\n {userForMagicLink &&\r\n `Generate a one-time claim sign-in link for ${userForMagicLink.name}.`}\r\n </p>\r\n </ModalHeader>\r\n\r\n <ModalBody className=\"space-y-4\">\r\n <Input\r\n id={magicLinkEmailInputId}\r\n label=\"Claim email\"\r\n labelPlacement=\"outside\"\r\n type=\"email\"\r\n placeholder=\"person@example.com\"\r\n value={claimEmail}\r\n onChange={(e) => setClaimEmail(e.target.value)}\r\n variant=\"bordered\"\r\n description=\"This email is used for provider linking and future sign-ins.\"\r\n />\r\n\r\n <Input\r\n id={generatedMagicLinkInputId}\r\n label=\"Generated link\"\r\n labelPlacement=\"outside\"\r\n value={generatedMagicLink ?? \"\"}\r\n readOnly\r\n variant=\"bordered\"\r\n placeholder=\"Generate link to see it here\"\r\n />\r\n </ModalBody>\r\n\r\n <ModalFooter>\r\n <Button variant=\"bordered\" type=\"button\" onPress={onClose}>\r\n Close\r\n </Button>\r\n <Button\r\n variant=\"bordered\"\r\n type=\"button\"\r\n onPress={copyGeneratedMagicLink}\r\n isDisabled={!generatedMagicLink}\r\n >\r\n <Copy className=\"h-4 w-4 mr-2\" />\r\n Copy Link\r\n </Button>\r\n <Button color=\"primary\" type=\"submit\" isDisabled={isGeneratingMagicLink}>\r\n {isGeneratingMagicLink ? <Spinner className=\"mr-2 h-4 w-4\" /> : null}\r\n {isGeneratingMagicLink ? \"Generating...\" : \"Generate Link\"}\r\n </Button>\r\n </ModalFooter>\r\n </form>\r\n )}\r\n </ModalContent>\r\n </Modal>\r\n </div>\r\n );\r\n}\r\n"],"mappings":"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"}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { UseBackendTRPC } from "../../../types.js";
|
|
2
|
+
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/modules/auth/components/AdminWaitlist.d.ts
|
|
2
5
|
interface AdminWaitlistProps {
|
|
3
|
-
|
|
6
|
+
useTRPC: UseBackendTRPC;
|
|
4
7
|
}
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
declare function AdminWaitlist({
|
|
9
|
+
useTRPC
|
|
10
|
+
}: AdminWaitlistProps): _$react_jsx_runtime0.JSX.Element;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { AdminWaitlist };
|
|
13
|
+
//# sourceMappingURL=AdminWaitlist.d.ts.map
|
|
@@ -1,118 +1,287 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Input, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, Spinner, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow, } from "@heroui/react";
|
|
3
|
-
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
|
-
import { Mail, MoreHorizontal, Search, Trash2, UserPlus, X } from "lucide-react";
|
|
5
1
|
import { useEffect, useId, useState } from "react";
|
|
2
|
+
import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Input, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, Spinner, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from "@heroui/react";
|
|
3
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Mail, MoreHorizontal, Search, Trash2, UserPlus, X } from "lucide-react";
|
|
6
5
|
import { toast } from "sonner";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
6
|
+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
7
|
+
//#region src/modules/auth/components/AdminWaitlist.tsx
|
|
8
|
+
function AdminWaitlist({ useTRPC }) {
|
|
9
|
+
const trpc = useTRPC();
|
|
10
|
+
const queryClient = useQueryClient();
|
|
11
|
+
const { data: waitlist = [], isLoading } = useQuery(trpc.auth.listAdminWaitlist.queryOptions());
|
|
12
|
+
const { mutate: invite, isPending: isInviting } = useMutation(trpc.auth.inviteFromWaitlist.mutationOptions({
|
|
13
|
+
onSuccess: () => {
|
|
14
|
+
queryClient.invalidateQueries({ queryKey: trpc.auth.listAdminWaitlist.queryKey() });
|
|
15
|
+
toast.success("Invitation sent successfully");
|
|
16
|
+
},
|
|
17
|
+
onError: (error) => {
|
|
18
|
+
toast.error(`Failed to send invitation: ${error instanceof Error ? error.message : String(error)}`);
|
|
19
|
+
}
|
|
20
|
+
}));
|
|
21
|
+
const { mutate: remove, isPending: isRemoving } = useMutation(trpc.auth.removeFromWaitlist.mutationOptions({
|
|
22
|
+
onSuccess: () => {
|
|
23
|
+
queryClient.invalidateQueries({ queryKey: trpc.auth.listAdminWaitlist.queryKey() });
|
|
24
|
+
toast.success("Removed from waitlist successfully");
|
|
25
|
+
},
|
|
26
|
+
onError: (error) => {
|
|
27
|
+
toast.error(`Failed to remove: ${error instanceof Error ? error.message : String(error)}`);
|
|
28
|
+
},
|
|
29
|
+
onSettled: () => {
|
|
30
|
+
setItemToDelete(null);
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
const { mutate: add, isPending: isAdding } = useMutation(trpc.auth.addToWaitlist.mutationOptions({
|
|
34
|
+
onSuccess: () => {
|
|
35
|
+
queryClient.invalidateQueries({ queryKey: trpc.auth.listAdminWaitlist.queryKey() });
|
|
36
|
+
toast.success("Added to waitlist successfully");
|
|
37
|
+
},
|
|
38
|
+
onError: (error) => {
|
|
39
|
+
toast.error(`Failed to add to waitlist: ${error instanceof Error ? error.message : String(error)}`);
|
|
40
|
+
}
|
|
41
|
+
}));
|
|
42
|
+
const emailInputId = useId();
|
|
43
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
44
|
+
const [debouncedSearchQuery, setDebouncedSearchQuery] = useState("");
|
|
45
|
+
const [itemToDelete, setItemToDelete] = useState(null);
|
|
46
|
+
const [isAddModalOpen, setIsAddModalOpen] = useState(false);
|
|
47
|
+
const [newEmail, setNewEmail] = useState("");
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
const timer = setTimeout(() => {
|
|
50
|
+
setDebouncedSearchQuery(searchQuery);
|
|
51
|
+
}, 300);
|
|
52
|
+
return () => clearTimeout(timer);
|
|
53
|
+
}, [searchQuery]);
|
|
54
|
+
const filteredWaitlist = waitlist.filter((item) => item.email?.toLowerCase().includes(debouncedSearchQuery?.toLowerCase() ?? ""));
|
|
55
|
+
const handleInvite = (id) => {
|
|
56
|
+
invite({ id });
|
|
57
|
+
};
|
|
58
|
+
const handleRemove = () => {
|
|
59
|
+
if (itemToDelete) remove({ id: itemToDelete });
|
|
60
|
+
};
|
|
61
|
+
const handleAdd = async () => {
|
|
62
|
+
if (!newEmail.trim()) {
|
|
63
|
+
toast.error("Please enter an email address");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(newEmail.trim())) {
|
|
67
|
+
toast.error("Please enter a valid email address");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
add({ email: newEmail.trim() });
|
|
71
|
+
setNewEmail("");
|
|
72
|
+
setIsAddModalOpen(false);
|
|
73
|
+
};
|
|
74
|
+
const formatDate = (date) => {
|
|
75
|
+
if (!date) return "N/A";
|
|
76
|
+
return (typeof date === "string" ? new Date(date) : date).toLocaleDateString(void 0, {
|
|
77
|
+
year: "numeric",
|
|
78
|
+
month: "short",
|
|
79
|
+
day: "numeric",
|
|
80
|
+
hour: "2-digit",
|
|
81
|
+
minute: "2-digit"
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
const getStatusBadge = (status) => {
|
|
85
|
+
const statusLower = status.toLowerCase();
|
|
86
|
+
if (statusLower === "invited" || statusLower === "active") return /* @__PURE__ */ jsx("span", {
|
|
87
|
+
className: "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800",
|
|
88
|
+
children: status
|
|
89
|
+
});
|
|
90
|
+
if (statusLower === "pending") return /* @__PURE__ */ jsx("span", {
|
|
91
|
+
className: "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800",
|
|
92
|
+
children: status
|
|
93
|
+
});
|
|
94
|
+
return /* @__PURE__ */ jsx("span", {
|
|
95
|
+
className: "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800",
|
|
96
|
+
children: status
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
if (isLoading) return /* @__PURE__ */ jsx("div", {
|
|
100
|
+
className: "flex justify-center p-8",
|
|
101
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
102
|
+
});
|
|
103
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
104
|
+
className: "space-y-4 p-4",
|
|
105
|
+
children: [
|
|
106
|
+
/* @__PURE__ */ jsxs("div", {
|
|
107
|
+
className: "flex justify-between items-center",
|
|
108
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
109
|
+
className: "text-xl font-semibold",
|
|
110
|
+
children: "Waitlist Management"
|
|
111
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
112
|
+
className: "flex items-center gap-2",
|
|
113
|
+
children: [/* @__PURE__ */ jsxs(Button, {
|
|
114
|
+
onPress: () => setIsAddModalOpen(true),
|
|
115
|
+
size: "sm",
|
|
116
|
+
children: [/* @__PURE__ */ jsx(UserPlus, { className: "h-4 w-4 mr-2" }), "Add to Waitlist"]
|
|
117
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
118
|
+
className: "text-sm text-muted-foreground",
|
|
119
|
+
children: ["Total: ", waitlist.length]
|
|
120
|
+
})]
|
|
121
|
+
})]
|
|
122
|
+
}),
|
|
123
|
+
/* @__PURE__ */ jsx("div", {
|
|
124
|
+
className: "flex flex-col sm:flex-row gap-3 items-start sm:items-center",
|
|
125
|
+
children: /* @__PURE__ */ jsxs("form", {
|
|
126
|
+
className: "relative flex-1",
|
|
127
|
+
onSubmit: (e) => {
|
|
128
|
+
e.preventDefault();
|
|
129
|
+
setDebouncedSearchQuery(searchQuery);
|
|
130
|
+
},
|
|
131
|
+
children: [
|
|
132
|
+
/* @__PURE__ */ jsx(Search, { className: "absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" }),
|
|
133
|
+
/* @__PURE__ */ jsx(Input, {
|
|
134
|
+
"aria-label": "Search by email",
|
|
135
|
+
placeholder: "Search by email...",
|
|
136
|
+
className: "pl-8 w-full",
|
|
137
|
+
value: searchQuery,
|
|
138
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
139
|
+
variant: "bordered"
|
|
140
|
+
}),
|
|
141
|
+
searchQuery && /* @__PURE__ */ jsx("button", {
|
|
142
|
+
type: "button",
|
|
143
|
+
onClick: () => setSearchQuery(""),
|
|
144
|
+
className: "absolute right-2.5 top-2.5 text-muted-foreground hover:text-foreground",
|
|
145
|
+
"aria-label": "Clear search",
|
|
146
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
147
|
+
})
|
|
148
|
+
]
|
|
149
|
+
})
|
|
150
|
+
}),
|
|
151
|
+
/* @__PURE__ */ jsx("div", {
|
|
152
|
+
className: "border rounded-lg overflow-hidden",
|
|
153
|
+
children: /* @__PURE__ */ jsxs(Table, {
|
|
154
|
+
"aria-label": "Waitlist table",
|
|
155
|
+
removeWrapper: true,
|
|
156
|
+
children: [/* @__PURE__ */ jsxs(TableHeader, { children: [
|
|
157
|
+
/* @__PURE__ */ jsx(TableColumn, { children: "Email" }),
|
|
158
|
+
/* @__PURE__ */ jsx(TableColumn, { children: "Status" }),
|
|
159
|
+
/* @__PURE__ */ jsx(TableColumn, { children: "Created At" }),
|
|
160
|
+
/* @__PURE__ */ jsx(TableColumn, { children: "Updated At" }),
|
|
161
|
+
/* @__PURE__ */ jsx(TableColumn, {
|
|
162
|
+
className: "text-right",
|
|
163
|
+
children: "Actions"
|
|
164
|
+
})
|
|
165
|
+
] }), /* @__PURE__ */ jsx(TableBody, {
|
|
166
|
+
items: filteredWaitlist,
|
|
167
|
+
emptyContent: searchQuery ? "No waitlist entries found matching your search" : "No waitlist entries found",
|
|
168
|
+
children: (item) => /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
169
|
+
/* @__PURE__ */ jsx(TableCell, {
|
|
170
|
+
className: "font-medium",
|
|
171
|
+
children: item.email
|
|
172
|
+
}),
|
|
173
|
+
/* @__PURE__ */ jsx(TableCell, { children: getStatusBadge(item.status) }),
|
|
174
|
+
/* @__PURE__ */ jsx(TableCell, { children: formatDate(item.createdAt) }),
|
|
175
|
+
/* @__PURE__ */ jsx(TableCell, { children: formatDate(item.updatedAt) }),
|
|
176
|
+
/* @__PURE__ */ jsx(TableCell, {
|
|
177
|
+
className: "text-right",
|
|
178
|
+
children: /* @__PURE__ */ jsxs(Dropdown, {
|
|
179
|
+
placement: "bottom-end",
|
|
180
|
+
children: [/* @__PURE__ */ jsx(DropdownTrigger, { children: /* @__PURE__ */ jsx(Button, {
|
|
181
|
+
variant: "light",
|
|
182
|
+
size: "sm",
|
|
183
|
+
isIconOnly: true,
|
|
184
|
+
children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-4 w-4" })
|
|
185
|
+
}) }), /* @__PURE__ */ jsxs(DropdownMenu, {
|
|
186
|
+
"aria-label": "Waitlist actions",
|
|
187
|
+
children: [/* @__PURE__ */ jsx(DropdownItem, {
|
|
188
|
+
onPress: () => handleInvite(item.id),
|
|
189
|
+
isDisabled: isInviting,
|
|
190
|
+
children: isInviting ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Spinner, { className: "mr-2 h-3 w-3" }), "Inviting..."] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Mail, { className: "mr-2 h-4 w-4" }), "Send Invitation"] })
|
|
191
|
+
}, "invite"), /* @__PURE__ */ jsxs(DropdownItem, {
|
|
192
|
+
className: "text-danger",
|
|
193
|
+
onClick: () => setItemToDelete(item.id),
|
|
194
|
+
children: [/* @__PURE__ */ jsx(Trash2, { className: "mr-2 h-4 w-4" }), "Remove"]
|
|
195
|
+
}, "remove")]
|
|
196
|
+
})]
|
|
197
|
+
})
|
|
198
|
+
})
|
|
199
|
+
] }, item.id)
|
|
200
|
+
})]
|
|
201
|
+
})
|
|
202
|
+
}),
|
|
203
|
+
/* @__PURE__ */ jsx(Modal, {
|
|
204
|
+
isOpen: !!itemToDelete,
|
|
205
|
+
onOpenChange: (open) => {
|
|
206
|
+
if (!open) setItemToDelete(null);
|
|
207
|
+
},
|
|
208
|
+
children: /* @__PURE__ */ jsx(ModalContent, { children: (onClose) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(ModalHeader, {
|
|
209
|
+
className: "flex flex-col gap-1",
|
|
210
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
211
|
+
className: "text-lg font-semibold",
|
|
212
|
+
children: "Are you sure?"
|
|
213
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
214
|
+
className: "text-sm text-default-600",
|
|
215
|
+
children: "This action cannot be undone. This will permanently remove this entry from the waitlist."
|
|
216
|
+
})]
|
|
217
|
+
}), /* @__PURE__ */ jsxs(ModalFooter, { children: [/* @__PURE__ */ jsx(Button, {
|
|
218
|
+
variant: "bordered",
|
|
219
|
+
onPress: onClose,
|
|
220
|
+
children: "Cancel"
|
|
221
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
222
|
+
color: "danger",
|
|
223
|
+
onPress: handleRemove,
|
|
224
|
+
isLoading: isRemoving,
|
|
225
|
+
children: "Remove"
|
|
226
|
+
})] })] }) })
|
|
227
|
+
}),
|
|
228
|
+
/* @__PURE__ */ jsx(Modal, {
|
|
229
|
+
isOpen: isAddModalOpen,
|
|
230
|
+
onOpenChange: (open) => {
|
|
231
|
+
if (!open) setIsAddModalOpen(false);
|
|
232
|
+
},
|
|
233
|
+
children: /* @__PURE__ */ jsx(ModalContent, { children: (onClose) => /* @__PURE__ */ jsxs("form", {
|
|
234
|
+
onSubmit: (e) => {
|
|
235
|
+
e.preventDefault();
|
|
236
|
+
handleAdd();
|
|
237
|
+
},
|
|
238
|
+
className: "space-y-4",
|
|
239
|
+
children: [
|
|
240
|
+
/* @__PURE__ */ jsxs(ModalHeader, {
|
|
241
|
+
className: "flex flex-col gap-1",
|
|
242
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
243
|
+
className: "text-lg font-semibold",
|
|
244
|
+
children: "Add to Waitlist"
|
|
245
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
246
|
+
className: "text-sm text-default-600",
|
|
247
|
+
children: "Enter an email address to add someone to the waitlist."
|
|
248
|
+
})]
|
|
249
|
+
}),
|
|
250
|
+
/* @__PURE__ */ jsx(ModalBody, {
|
|
251
|
+
className: "space-y-4",
|
|
252
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
253
|
+
className: "space-y-2",
|
|
254
|
+
children: /* @__PURE__ */ jsx(Input, {
|
|
255
|
+
id: emailInputId,
|
|
256
|
+
label: "Email *",
|
|
257
|
+
labelPlacement: "outside",
|
|
258
|
+
type: "email",
|
|
259
|
+
placeholder: "Enter email address",
|
|
260
|
+
value: newEmail,
|
|
261
|
+
onChange: (e) => setNewEmail(e.target.value),
|
|
262
|
+
variant: "bordered"
|
|
263
|
+
})
|
|
264
|
+
})
|
|
265
|
+
}),
|
|
266
|
+
/* @__PURE__ */ jsxs(ModalFooter, { children: [/* @__PURE__ */ jsx(Button, {
|
|
267
|
+
variant: "bordered",
|
|
268
|
+
type: "button",
|
|
269
|
+
onPress: onClose,
|
|
270
|
+
children: "Cancel"
|
|
271
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
272
|
+
type: "submit",
|
|
273
|
+
color: "primary",
|
|
274
|
+
isDisabled: isAdding,
|
|
275
|
+
isLoading: isAdding,
|
|
276
|
+
children: isAdding ? "Adding..." : "Add to Waitlist"
|
|
277
|
+
})] })
|
|
278
|
+
]
|
|
279
|
+
}) })
|
|
280
|
+
})
|
|
281
|
+
]
|
|
282
|
+
});
|
|
118
283
|
}
|
|
284
|
+
//#endregion
|
|
285
|
+
export { AdminWaitlist };
|
|
286
|
+
|
|
287
|
+
//# sourceMappingURL=AdminWaitlist.js.map
|