@m5kdev/web-ui 0.9.1 → 0.9.3

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.
Files changed (238) hide show
  1. package/dist/src/components/AvatarUpload.js +2 -2
  2. package/dist/src/components/AvatarUpload.mjs +3 -3
  3. package/dist/src/components/AvatarUpload.mjs.map +1 -1
  4. package/dist/src/components/Calendar.d.mts +1 -1
  5. package/dist/src/components/CardsSelect.js +2 -2
  6. package/dist/src/components/CardsSelect.mjs +2 -2
  7. package/dist/src/components/CollapsibleSidebarMenuItem.d.mts +1 -1
  8. package/dist/src/components/CollapsibleSidebarMenuItem.js +1 -1
  9. package/dist/src/components/CollapsibleSidebarMenuItem.mjs +1 -1
  10. package/dist/src/components/ColorPicker.js +2 -2
  11. package/dist/src/components/ColorPicker.mjs +2 -2
  12. package/dist/src/components/CopyButton.js +3 -3
  13. package/dist/src/components/CopyButton.mjs +4 -4
  14. package/dist/src/components/CopyButton.mjs.map +1 -1
  15. package/dist/src/components/CropDialog.js +2 -2
  16. package/dist/src/components/CropDialog.mjs +2 -2
  17. package/dist/src/components/DialogProvider.js +1 -1
  18. package/dist/src/components/DialogProvider.mjs +2 -2
  19. package/dist/src/components/DialogProvider.mjs.map +1 -1
  20. package/dist/src/components/FileDropzone.js +2 -2
  21. package/dist/src/components/FileDropzone.mjs +4 -4
  22. package/dist/src/components/FileDropzone.mjs.map +1 -1
  23. package/dist/src/components/MultiSelectDropdown.js +2 -2
  24. package/dist/src/components/MultiSelectDropdown.mjs +8 -8
  25. package/dist/src/components/MultiSelectDropdown.mjs.map +1 -1
  26. package/dist/src/components/Orb.js +1 -1
  27. package/dist/src/components/Orb.mjs +1 -1
  28. package/dist/src/components/PageAlert.d.mts +1 -1
  29. package/dist/src/components/PageAlert.d.ts +1 -1
  30. package/dist/src/components/PageAlert.js +4 -3
  31. package/dist/src/components/PageAlert.js.map +1 -1
  32. package/dist/src/components/PageAlert.mjs +2 -2
  33. package/dist/src/components/SidebarItem.d.mts +1 -1
  34. package/dist/src/components/Steps.js +1 -1
  35. package/dist/src/components/Steps.mjs +1 -1
  36. package/dist/src/components/app-header.js +1 -1
  37. package/dist/src/components/app-header.mjs +2 -2
  38. package/dist/src/components/app-header.mjs.map +1 -1
  39. package/dist/src/components/blur-card.d.mts +1 -1
  40. package/dist/src/components/blur-card.js +1 -1
  41. package/dist/src/components/blur-card.mjs +1 -1
  42. package/dist/src/components/features-section-demo-1.js +1 -1
  43. package/dist/src/components/features-section-demo-1.mjs +1 -1
  44. package/dist/src/components/features-section-demo-3.js +1 -1
  45. package/dist/src/components/features-section-demo-3.mjs +1 -1
  46. package/dist/src/components/mode-toggle.js +1 -1
  47. package/dist/src/components/mode-toggle.mjs +1 -1
  48. package/dist/src/components/nav-main.d.mts +1 -1
  49. package/dist/src/components/nav-main.js +1 -1
  50. package/dist/src/components/nav-main.mjs +1 -1
  51. package/dist/src/components/pricing-cards.js +1 -1
  52. package/dist/src/components/pricing-cards.mjs +1 -1
  53. package/dist/src/components/shared/ButtonCopy.js +2 -2
  54. package/dist/src/components/shared/ButtonCopy.mjs +3 -3
  55. package/dist/src/components/shared/ButtonCopy.mjs.map +1 -1
  56. package/dist/src/components/team-switcher.d.mts +1 -1
  57. package/dist/src/components/team-switcher.js +2 -2
  58. package/dist/src/components/team-switcher.mjs +2 -2
  59. package/dist/src/components/theme-provider.js +1 -1
  60. package/dist/src/components/theme-provider.mjs +1 -1
  61. package/dist/src/components/typewriter.js +1 -1
  62. package/dist/src/components/typewriter.mjs +1 -1
  63. package/dist/src/components/ui/alert-dialog.d.mts +1 -1
  64. package/dist/src/components/ui/alert.d.mts +1 -1
  65. package/dist/src/components/ui/alert.js +2 -1
  66. package/dist/src/components/ui/alert.js.map +1 -1
  67. package/dist/src/components/ui/alert.mjs +1 -1
  68. package/dist/src/components/ui/avatar.js +1 -1
  69. package/dist/src/components/ui/avatar.mjs +1 -1
  70. package/dist/src/components/ui/badge.d.mts +1 -1
  71. package/dist/src/components/ui/badge.js +2 -1
  72. package/dist/src/components/ui/badge.js.map +1 -1
  73. package/dist/src/components/ui/badge.mjs +1 -1
  74. package/dist/src/components/ui/bento-grid2.d.mts +1 -1
  75. package/dist/src/components/ui/breadcrumb.d.mts +1 -1
  76. package/dist/src/components/ui/breadcrumb.js +2 -2
  77. package/dist/src/components/ui/breadcrumb.mjs +2 -2
  78. package/dist/src/components/ui/button.js +3 -2
  79. package/dist/src/components/ui/button.js.map +1 -1
  80. package/dist/src/components/ui/button.mjs +1 -1
  81. package/dist/src/components/ui/card.js +1 -1
  82. package/dist/src/components/ui/card.mjs +1 -1
  83. package/dist/src/components/ui/checkbox.js +2 -2
  84. package/dist/src/components/ui/checkbox.mjs +2 -2
  85. package/dist/src/components/ui/dialog.d.mts +1 -1
  86. package/dist/src/components/ui/dialog.js +1 -1
  87. package/dist/src/components/ui/dialog.mjs +1 -1
  88. package/dist/src/components/ui/dropdown-menu.d.mts +1 -1
  89. package/dist/src/components/ui/dropdown-menu.js +2 -2
  90. package/dist/src/components/ui/dropdown-menu.mjs +2 -2
  91. package/dist/src/components/ui/floating-navbar.d.mts +1 -1
  92. package/dist/src/components/ui/floating-navbar.js +1 -1
  93. package/dist/src/components/ui/floating-navbar.mjs +1 -1
  94. package/dist/src/components/ui/form.d.mts +1 -1
  95. package/dist/src/components/ui/form.js +1 -1
  96. package/dist/src/components/ui/form.mjs +1 -1
  97. package/dist/src/components/ui/image.js +1 -1
  98. package/dist/src/components/ui/image.mjs +1 -1
  99. package/dist/src/components/ui/input.js +1 -1
  100. package/dist/src/components/ui/input.mjs +1 -1
  101. package/dist/src/components/ui/label.js +1 -1
  102. package/dist/src/components/ui/label.mjs +1 -1
  103. package/dist/src/components/ui/pagination.d.mts +1 -1
  104. package/dist/src/components/ui/pagination.js +1 -1
  105. package/dist/src/components/ui/pagination.mjs +1 -1
  106. package/dist/src/components/ui/progress.js +1 -1
  107. package/dist/src/components/ui/progress.mjs +1 -1
  108. package/dist/src/components/ui/resizable-navbar.d.mts +1 -1
  109. package/dist/src/components/ui/resizable-navbar.js +2 -2
  110. package/dist/src/components/ui/resizable-navbar.mjs +2 -2
  111. package/dist/src/components/ui/segment-control.js +1 -1
  112. package/dist/src/components/ui/segment-control.mjs +3 -3
  113. package/dist/src/components/ui/segment-control.mjs.map +1 -1
  114. package/dist/src/components/ui/select.js +2 -2
  115. package/dist/src/components/ui/select.mjs +2 -2
  116. package/dist/src/components/ui/separator.js +1 -1
  117. package/dist/src/components/ui/separator.mjs +1 -1
  118. package/dist/src/components/ui/sheet.d.mts +1 -1
  119. package/dist/src/components/ui/sheet.js +2 -2
  120. package/dist/src/components/ui/sheet.mjs +2 -2
  121. package/dist/src/components/ui/sidebar.js +3 -3
  122. package/dist/src/components/ui/sidebar.mjs +3 -3
  123. package/dist/src/components/ui/slider.js +1 -1
  124. package/dist/src/components/ui/slider.mjs +1 -1
  125. package/dist/src/components/ui/spinner.d.mts +1 -1
  126. package/dist/src/components/ui/spinner.js +1 -1
  127. package/dist/src/components/ui/spinner.mjs +1 -1
  128. package/dist/src/components/ui/switch.js +1 -1
  129. package/dist/src/components/ui/switch.mjs +1 -1
  130. package/dist/src/components/ui/table.d.mts +1 -1
  131. package/dist/src/components/ui/tabs.d.mts +1 -1
  132. package/dist/src/components/ui/textarea.d.mts +1 -1
  133. package/dist/src/components/ui/timeline.d.mts +1 -1
  134. package/dist/src/components/ui/timeline.js +1 -1
  135. package/dist/src/components/ui/timeline.mjs +1 -1
  136. package/dist/src/components/ui/toast.js +2 -2
  137. package/dist/src/components/ui/toast.mjs +2 -2
  138. package/dist/src/components/ui/tooltip.d.mts +1 -1
  139. package/dist/src/components/ui/typewriter-effect.js +1 -1
  140. package/dist/src/components/ui/typewriter-effect.mjs +1 -1
  141. package/dist/src/icons/GoogleIcon.d.mts +1 -1
  142. package/dist/src/icons/LinkedInIcon.d.mts +1 -1
  143. package/dist/src/icons/MicrosoftIcon.d.mts +1 -1
  144. package/dist/src/modules/app/components/AppShell.d.mts +1 -1
  145. package/dist/src/modules/app/components/AppSidebar.d.mts +1 -1
  146. package/dist/src/modules/app/components/AppSidebarHeader.js +2 -2
  147. package/dist/src/modules/app/components/AppSidebarHeader.mjs +3 -3
  148. package/dist/src/modules/app/components/AppSidebarHeader.mjs.map +1 -1
  149. package/dist/src/modules/app/components/AppSidebarInvites.js +2 -2
  150. package/dist/src/modules/app/components/AppSidebarInvites.mjs +4 -4
  151. package/dist/src/modules/app/components/AppSidebarInvites.mjs.map +1 -1
  152. package/dist/src/modules/app/components/AppSidebarUser.js +1 -1
  153. package/dist/src/modules/app/components/AppSidebarUser.mjs +1 -1
  154. package/dist/src/modules/auth/components/AdminUserManagement.js +4 -4
  155. package/dist/src/modules/auth/components/AdminUserManagement.mjs +8 -8
  156. package/dist/src/modules/auth/components/AdminUserManagement.mjs.map +1 -1
  157. package/dist/src/modules/auth/components/AdminWaitlist.js +2 -2
  158. package/dist/src/modules/auth/components/AdminWaitlist.mjs +4 -4
  159. package/dist/src/modules/auth/components/AdminWaitlist.mjs.map +1 -1
  160. package/dist/src/modules/auth/components/AuthLayout.d.mts +1 -1
  161. package/dist/src/modules/auth/components/AuthProviders.js +1 -1
  162. package/dist/src/modules/auth/components/AuthProviders.mjs +1 -1
  163. package/dist/src/modules/auth/components/AuthRouter.d.mts +1 -1
  164. package/dist/src/modules/auth/components/ClaimAccountRoute.js +2 -2
  165. package/dist/src/modules/auth/components/ClaimAccountRoute.mjs +2 -2
  166. package/dist/src/modules/auth/components/ErrorAuthRoute.js +2 -2
  167. package/dist/src/modules/auth/components/ErrorAuthRoute.mjs +5 -5
  168. package/dist/src/modules/auth/components/ErrorAuthRoute.mjs.map +1 -1
  169. package/dist/src/modules/auth/components/ForgotPasswordForm.js +2 -2
  170. package/dist/src/modules/auth/components/ForgotPasswordForm.mjs +2 -2
  171. package/dist/src/modules/auth/components/ForgotPasswordRoute.js +2 -2
  172. package/dist/src/modules/auth/components/ForgotPasswordRoute.mjs +3 -3
  173. package/dist/src/modules/auth/components/ForgotPasswordRoute.mjs.map +1 -1
  174. package/dist/src/modules/auth/components/InviteFriends.js +2 -2
  175. package/dist/src/modules/auth/components/InviteFriends.mjs +2 -2
  176. package/dist/src/modules/auth/components/LastUsedBadge.d.mts +1 -1
  177. package/dist/src/modules/auth/components/LastUsedBadge.js +1 -1
  178. package/dist/src/modules/auth/components/LastUsedBadge.mjs +1 -1
  179. package/dist/src/modules/auth/components/LoginForm.js +2 -2
  180. package/dist/src/modules/auth/components/LoginForm.mjs +4 -4
  181. package/dist/src/modules/auth/components/LoginForm.mjs.map +1 -1
  182. package/dist/src/modules/auth/components/LoginRoute.js +2 -2
  183. package/dist/src/modules/auth/components/LoginRoute.mjs +4 -4
  184. package/dist/src/modules/auth/components/LoginRoute.mjs.map +1 -1
  185. package/dist/src/modules/auth/components/LogoutRoute.js +2 -2
  186. package/dist/src/modules/auth/components/LogoutRoute.mjs +2 -2
  187. package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.js +2 -2
  188. package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.mjs +2 -2
  189. package/dist/src/modules/auth/components/OrganizationMembersRoute.js +4 -4
  190. package/dist/src/modules/auth/components/OrganizationMembersRoute.mjs +4 -4
  191. package/dist/src/modules/auth/components/OrganizationPreferences.js +2 -2
  192. package/dist/src/modules/auth/components/OrganizationPreferences.mjs +2 -2
  193. package/dist/src/modules/auth/components/OrganizationSettingsRoute.js +3 -3
  194. package/dist/src/modules/auth/components/OrganizationSettingsRoute.mjs +3 -3
  195. package/dist/src/modules/auth/components/OrganizationSwitcher.js +4 -4
  196. package/dist/src/modules/auth/components/OrganizationSwitcher.mjs +6 -6
  197. package/dist/src/modules/auth/components/OrganizationSwitcher.mjs.map +1 -1
  198. package/dist/src/modules/auth/components/ProfileRoute.js +1 -1
  199. package/dist/src/modules/auth/components/ProfileRoute.mjs +1 -1
  200. package/dist/src/modules/auth/components/RangeNuqsDatePicker.js +2 -2
  201. package/dist/src/modules/auth/components/RangeNuqsDatePicker.mjs +2 -2
  202. package/dist/src/modules/auth/components/ResetPasswordForm.js +2 -2
  203. package/dist/src/modules/auth/components/ResetPasswordForm.mjs +3 -3
  204. package/dist/src/modules/auth/components/ResetPasswordForm.mjs.map +1 -1
  205. package/dist/src/modules/auth/components/ResetPasswordRoute.js +2 -2
  206. package/dist/src/modules/auth/components/ResetPasswordRoute.mjs +3 -3
  207. package/dist/src/modules/auth/components/ResetPasswordRoute.mjs.map +1 -1
  208. package/dist/src/modules/auth/components/SignupFormRoute.js +2 -2
  209. package/dist/src/modules/auth/components/SignupFormRoute.mjs +2 -2
  210. package/dist/src/modules/auth/components/SignupRoute.js +2 -2
  211. package/dist/src/modules/auth/components/SignupRoute.mjs +3 -3
  212. package/dist/src/modules/auth/components/SignupRoute.mjs.map +1 -1
  213. package/dist/src/modules/auth/components/UserPreferences.js +1 -1
  214. package/dist/src/modules/auth/components/UserPreferences.mjs +1 -1
  215. package/dist/src/modules/auth/components/WaitlistCard.js +2 -2
  216. package/dist/src/modules/auth/components/WaitlistCard.mjs +2 -2
  217. package/dist/src/modules/auth/components/WaitlistCodeValidation.js +1 -1
  218. package/dist/src/modules/auth/components/WaitlistCodeValidation.mjs +1 -1
  219. package/dist/src/modules/billing/components/BillingBetaPage.d.mts +1 -1
  220. package/dist/src/modules/billing/components/BillingBetaPage.js +1 -1
  221. package/dist/src/modules/billing/components/BillingBetaPage.mjs +1 -1
  222. package/dist/src/modules/billing/components/BillingInvoicePage.js +2 -2
  223. package/dist/src/modules/billing/components/BillingInvoicePage.mjs +2 -2
  224. package/dist/src/modules/billing/components/BillingSinglePlanSelect.js +3 -3
  225. package/dist/src/modules/billing/components/BillingSinglePlanSelect.mjs +5 -5
  226. package/dist/src/modules/billing/components/BillingSinglePlanSelect.mjs.map +1 -1
  227. package/dist/src/modules/table/components/ColumnOrderAndVisibility.js +2 -2
  228. package/dist/src/modules/table/components/ColumnOrderAndVisibility.mjs +2 -2
  229. package/dist/src/modules/table/components/NuqsTable.js +2 -2
  230. package/dist/src/modules/table/components/NuqsTable.mjs +4 -4
  231. package/dist/src/modules/table/components/NuqsTable.mjs.map +1 -1
  232. package/dist/src/modules/table/components/TableFiltering.js +2 -2
  233. package/dist/src/modules/table/components/TableFiltering.mjs +2 -2
  234. package/dist/src/modules/table/components/TableGroupBy.js +1 -1
  235. package/dist/src/modules/table/components/TableGroupBy.mjs +1 -1
  236. package/dist/src/modules/table/components/TablePagination.js +1 -1
  237. package/dist/src/modules/table/components/TablePagination.mjs +1 -1
  238. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"AdminUserManagement.mjs","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
+ {"version":3,"file":"AdminUserManagement.mjs","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,9 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../../../_virtual/_rolldown/runtime.js");
3
- let react_jsx_runtime = require("react/jsx-runtime");
3
+ let lucide_react = require("lucide-react");
4
4
  let react = require("react");
5
+ let react_jsx_runtime = require("react/jsx-runtime");
5
6
  let _heroui_react = require("@heroui/react");
6
- let lucide_react = require("lucide-react");
7
7
  let sonner = require("sonner");
8
8
  let _tanstack_react_query = require("@tanstack/react-query");
9
9
  //#region src/modules/auth/components/AdminWaitlist.tsx
@@ -1,7 +1,7 @@
1
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
1
+ import { Mail, MoreHorizontal, Search, Trash2, UserPlus, X } from "lucide-react";
2
2
  import { useEffect, useId, useState } from "react";
3
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
3
4
  import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Input, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, Spinner, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from "@heroui/react";
4
- import { Mail, MoreHorizontal, Search, Trash2, UserPlus, X } from "lucide-react";
5
5
  import { toast } from "sonner";
6
6
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
7
7
  //#region src/modules/auth/components/AdminWaitlist.tsx
@@ -187,7 +187,7 @@ function AdminWaitlist({ useTRPC }) {
187
187
  children: [/* @__PURE__ */ jsx(DropdownItem, {
188
188
  onPress: () => handleInvite(item.id),
189
189
  isDisabled: isInviting,
190
- children: isInviting ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Spinner, { className: "mr-2 h-3 w-3" }), "Inviting..."] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Mail, { className: "mr-2 h-4 w-4" }), "Send Invitation"] })
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
191
  }, "invite"), /* @__PURE__ */ jsxs(DropdownItem, {
192
192
  className: "text-danger",
193
193
  onClick: () => setItemToDelete(item.id),
@@ -205,7 +205,7 @@ function AdminWaitlist({ useTRPC }) {
205
205
  onOpenChange: (open) => {
206
206
  if (!open) setItemToDelete(null);
207
207
  },
208
- children: /* @__PURE__ */ jsx(ModalContent, { children: (onClose) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(ModalHeader, {
208
+ children: /* @__PURE__ */ jsx(ModalContent, { children: (onClose) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(ModalHeader, {
209
209
  className: "flex flex-col gap-1",
210
210
  children: [/* @__PURE__ */ jsx("p", {
211
211
  className: "text-lg font-semibold",
@@ -1 +1 @@
1
- {"version":3,"file":"AdminWaitlist.mjs","names":[],"sources":["../../../../../src/modules/auth/components/AdminWaitlist.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 Spinner,\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableColumn,\r\n TableHeader,\r\n TableRow,\r\n} from \"@heroui/react\";\r\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\r\nimport { Mail, MoreHorizontal, Search, Trash2, UserPlus, X } from \"lucide-react\";\r\nimport { useEffect, useId, useState } from \"react\";\r\nimport { toast } from \"sonner\";\r\nimport type { UseBackendTRPC } from \"../../../types\";\r\n\r\ninterface AdminWaitlistProps {\r\n useTRPC: UseBackendTRPC;\r\n}\r\n\r\nexport function AdminWaitlist({ useTRPC }: AdminWaitlistProps) {\r\n const trpc = useTRPC();\r\n const queryClient = useQueryClient();\r\n\r\n const { data: waitlist = [], isLoading } = useQuery(trpc.auth.listAdminWaitlist.queryOptions());\r\n const { mutate: invite, isPending: isInviting } = useMutation(\r\n trpc.auth.inviteFromWaitlist.mutationOptions({\r\n onSuccess: () => {\r\n queryClient.invalidateQueries({ queryKey: trpc.auth.listAdminWaitlist.queryKey() });\r\n toast.success(\"Invitation sent successfully\");\r\n },\r\n onError: (error) => {\r\n toast.error(\r\n `Failed to send invitation: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n },\r\n })\r\n );\r\n const { mutate: remove, isPending: isRemoving } = useMutation(\r\n trpc.auth.removeFromWaitlist.mutationOptions({\r\n onSuccess: () => {\r\n queryClient.invalidateQueries({ queryKey: trpc.auth.listAdminWaitlist.queryKey() });\r\n toast.success(\"Removed from waitlist successfully\");\r\n },\r\n onError: (error) => {\r\n toast.error(`Failed to remove: ${error instanceof Error ? error.message : String(error)}`);\r\n },\r\n onSettled: () => {\r\n setItemToDelete(null);\r\n },\r\n })\r\n );\r\n const { mutate: add, isPending: isAdding } = useMutation(\r\n trpc.auth.addToWaitlist.mutationOptions({\r\n onSuccess: () => {\r\n queryClient.invalidateQueries({ queryKey: trpc.auth.listAdminWaitlist.queryKey() });\r\n toast.success(\"Added to waitlist successfully\");\r\n },\r\n onError: (error) => {\r\n toast.error(\r\n `Failed to add to waitlist: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n },\r\n })\r\n );\r\n const emailInputId = useId();\r\n const [searchQuery, setSearchQuery] = useState(\"\");\r\n const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(\"\");\r\n const [itemToDelete, setItemToDelete] = useState<string | null>(null);\r\n const [isAddModalOpen, setIsAddModalOpen] = useState(false);\r\n const [newEmail, setNewEmail] = useState(\"\");\r\n\r\n // Debounce search query\r\n useEffect(() => {\r\n const timer = setTimeout(() => {\r\n setDebouncedSearchQuery(searchQuery);\r\n }, 300);\r\n\r\n return () => clearTimeout(timer);\r\n }, [searchQuery]);\r\n\r\n const filteredWaitlist = waitlist.filter((item) =>\r\n item.email?.toLowerCase().includes(debouncedSearchQuery?.toLowerCase() ?? \"\")\r\n );\r\n\r\n const handleInvite = (id: string) => {\r\n invite({ id });\r\n };\r\n\r\n const handleRemove = () => {\r\n if (itemToDelete) {\r\n remove({ id: itemToDelete });\r\n }\r\n };\r\n\r\n const handleAdd = async () => {\r\n if (!newEmail.trim()) {\r\n toast.error(\"Please enter an email address\");\r\n return;\r\n }\r\n\r\n // Basic email validation\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n if (!emailRegex.test(newEmail.trim())) {\r\n toast.error(\"Please enter a valid email address\");\r\n return;\r\n }\r\n\r\n add({ email: newEmail.trim() });\r\n setNewEmail(\"\");\r\n setIsAddModalOpen(false);\r\n };\r\n\r\n const formatDate = (date: Date | string | null) => {\r\n if (!date) return \"N/A\";\r\n const dateObj = typeof date === \"string\" ? new Date(date) : date;\r\n return dateObj.toLocaleDateString(undefined, {\r\n year: \"numeric\",\r\n month: \"short\",\r\n day: \"numeric\",\r\n hour: \"2-digit\",\r\n minute: \"2-digit\",\r\n });\r\n };\r\n\r\n const getStatusBadge = (status: string) => {\r\n const statusLower = status.toLowerCase();\r\n if (statusLower === \"invited\" || statusLower === \"active\") {\r\n return (\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 {status}\r\n </span>\r\n );\r\n }\r\n if (statusLower === \"pending\") {\r\n return (\r\n <span className=\"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800\">\r\n {status}\r\n </span>\r\n );\r\n }\r\n return (\r\n <span className=\"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800\">\r\n {status}\r\n </span>\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 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\">Waitlist Management</h2>\r\n <div className=\"flex items-center gap-2\">\r\n <Button onPress={() => setIsAddModalOpen(true)} size=\"sm\">\r\n <UserPlus className=\"h-4 w-4 mr-2\" />\r\n Add to Waitlist\r\n </Button>\r\n <div className=\"text-sm text-muted-foreground\">Total: {waitlist.length}</div>\r\n </div>\r\n </div>\r\n\r\n {/* Search */}\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 }}\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 by email\"\r\n placeholder=\"Search by 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 </div>\r\n\r\n <div className=\"border rounded-lg overflow-hidden\">\r\n <Table aria-label=\"Waitlist table\" removeWrapper>\r\n <TableHeader>\r\n <TableColumn>Email</TableColumn>\r\n <TableColumn>Status</TableColumn>\r\n <TableColumn>Created At</TableColumn>\r\n <TableColumn>Updated At</TableColumn>\r\n <TableColumn className=\"text-right\">Actions</TableColumn>\r\n </TableHeader>\r\n <TableBody\r\n items={filteredWaitlist}\r\n emptyContent={\r\n searchQuery\r\n ? \"No waitlist entries found matching your search\"\r\n : \"No waitlist entries found\"\r\n }\r\n >\r\n {(item) => (\r\n <TableRow key={item.id}>\r\n <TableCell className=\"font-medium\">{item.email}</TableCell>\r\n <TableCell>{getStatusBadge(item.status)}</TableCell>\r\n <TableCell>{formatDate(item.createdAt)}</TableCell>\r\n <TableCell>{formatDate(item.updatedAt)}</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=\"Waitlist actions\">\r\n <DropdownItem\r\n key=\"invite\"\r\n onPress={() => handleInvite(item.id)}\r\n isDisabled={isInviting}\r\n >\r\n {isInviting ? (\r\n <>\r\n <Spinner className=\"mr-2 h-3 w-3\" />\r\n Inviting...\r\n </>\r\n ) : (\r\n <>\r\n <Mail className=\"mr-2 h-4 w-4\" />\r\n Send Invitation\r\n </>\r\n )}\r\n </DropdownItem>\r\n <DropdownItem\r\n key=\"remove\"\r\n className=\"text-danger\"\r\n onClick={() => setItemToDelete(item.id)}\r\n >\r\n <Trash2 className=\"mr-2 h-4 w-4\" />\r\n Remove\r\n </DropdownItem>\r\n </DropdownMenu>\r\n </Dropdown>\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n </TableBody>\r\n </Table>\r\n </div>\r\n\r\n {/* Remove confirmation modal */}\r\n <Modal\r\n isOpen={!!itemToDelete}\r\n onOpenChange={(open) => {\r\n if (!open) setItemToDelete(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 remove this entry from the\r\n waitlist.\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={handleRemove} isLoading={isRemoving}>\r\n Remove\r\n </Button>\r\n </ModalFooter>\r\n </>\r\n )}\r\n </ModalContent>\r\n </Modal>\r\n\r\n {/* Add to waitlist modal */}\r\n <Modal\r\n isOpen={isAddModalOpen}\r\n onOpenChange={(open) => {\r\n if (!open) setIsAddModalOpen(false);\r\n }}\r\n >\r\n <ModalContent>\r\n {(onClose) => (\r\n <form\r\n onSubmit={(e) => {\r\n e.preventDefault();\r\n handleAdd();\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\">Add to Waitlist</p>\r\n <p className=\"text-sm text-default-600\">\r\n Enter an email address to add someone to the waitlist.\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={emailInputId}\r\n label=\"Email *\"\r\n labelPlacement=\"outside\"\r\n type=\"email\"\r\n placeholder=\"Enter email address\"\r\n value={newEmail}\r\n onChange={(e) => setNewEmail(e.target.value)}\r\n variant=\"bordered\"\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 type=\"submit\" color=\"primary\" isDisabled={isAdding} isLoading={isAdding}>\r\n {isAdding ? \"Adding...\" : \"Add to Waitlist\"}\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
+ {"version":3,"file":"AdminWaitlist.mjs","names":[],"sources":["../../../../../src/modules/auth/components/AdminWaitlist.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 Spinner,\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableColumn,\r\n TableHeader,\r\n TableRow,\r\n} from \"@heroui/react\";\r\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\r\nimport { Mail, MoreHorizontal, Search, Trash2, UserPlus, X } from \"lucide-react\";\r\nimport { useEffect, useId, useState } from \"react\";\r\nimport { toast } from \"sonner\";\r\nimport type { UseBackendTRPC } from \"../../../types\";\r\n\r\ninterface AdminWaitlistProps {\r\n useTRPC: UseBackendTRPC;\r\n}\r\n\r\nexport function AdminWaitlist({ useTRPC }: AdminWaitlistProps) {\r\n const trpc = useTRPC();\r\n const queryClient = useQueryClient();\r\n\r\n const { data: waitlist = [], isLoading } = useQuery(trpc.auth.listAdminWaitlist.queryOptions());\r\n const { mutate: invite, isPending: isInviting } = useMutation(\r\n trpc.auth.inviteFromWaitlist.mutationOptions({\r\n onSuccess: () => {\r\n queryClient.invalidateQueries({ queryKey: trpc.auth.listAdminWaitlist.queryKey() });\r\n toast.success(\"Invitation sent successfully\");\r\n },\r\n onError: (error) => {\r\n toast.error(\r\n `Failed to send invitation: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n },\r\n })\r\n );\r\n const { mutate: remove, isPending: isRemoving } = useMutation(\r\n trpc.auth.removeFromWaitlist.mutationOptions({\r\n onSuccess: () => {\r\n queryClient.invalidateQueries({ queryKey: trpc.auth.listAdminWaitlist.queryKey() });\r\n toast.success(\"Removed from waitlist successfully\");\r\n },\r\n onError: (error) => {\r\n toast.error(`Failed to remove: ${error instanceof Error ? error.message : String(error)}`);\r\n },\r\n onSettled: () => {\r\n setItemToDelete(null);\r\n },\r\n })\r\n );\r\n const { mutate: add, isPending: isAdding } = useMutation(\r\n trpc.auth.addToWaitlist.mutationOptions({\r\n onSuccess: () => {\r\n queryClient.invalidateQueries({ queryKey: trpc.auth.listAdminWaitlist.queryKey() });\r\n toast.success(\"Added to waitlist successfully\");\r\n },\r\n onError: (error) => {\r\n toast.error(\r\n `Failed to add to waitlist: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n },\r\n })\r\n );\r\n const emailInputId = useId();\r\n const [searchQuery, setSearchQuery] = useState(\"\");\r\n const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(\"\");\r\n const [itemToDelete, setItemToDelete] = useState<string | null>(null);\r\n const [isAddModalOpen, setIsAddModalOpen] = useState(false);\r\n const [newEmail, setNewEmail] = useState(\"\");\r\n\r\n // Debounce search query\r\n useEffect(() => {\r\n const timer = setTimeout(() => {\r\n setDebouncedSearchQuery(searchQuery);\r\n }, 300);\r\n\r\n return () => clearTimeout(timer);\r\n }, [searchQuery]);\r\n\r\n const filteredWaitlist = waitlist.filter((item) =>\r\n item.email?.toLowerCase().includes(debouncedSearchQuery?.toLowerCase() ?? \"\")\r\n );\r\n\r\n const handleInvite = (id: string) => {\r\n invite({ id });\r\n };\r\n\r\n const handleRemove = () => {\r\n if (itemToDelete) {\r\n remove({ id: itemToDelete });\r\n }\r\n };\r\n\r\n const handleAdd = async () => {\r\n if (!newEmail.trim()) {\r\n toast.error(\"Please enter an email address\");\r\n return;\r\n }\r\n\r\n // Basic email validation\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n if (!emailRegex.test(newEmail.trim())) {\r\n toast.error(\"Please enter a valid email address\");\r\n return;\r\n }\r\n\r\n add({ email: newEmail.trim() });\r\n setNewEmail(\"\");\r\n setIsAddModalOpen(false);\r\n };\r\n\r\n const formatDate = (date: Date | string | null) => {\r\n if (!date) return \"N/A\";\r\n const dateObj = typeof date === \"string\" ? new Date(date) : date;\r\n return dateObj.toLocaleDateString(undefined, {\r\n year: \"numeric\",\r\n month: \"short\",\r\n day: \"numeric\",\r\n hour: \"2-digit\",\r\n minute: \"2-digit\",\r\n });\r\n };\r\n\r\n const getStatusBadge = (status: string) => {\r\n const statusLower = status.toLowerCase();\r\n if (statusLower === \"invited\" || statusLower === \"active\") {\r\n return (\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 {status}\r\n </span>\r\n );\r\n }\r\n if (statusLower === \"pending\") {\r\n return (\r\n <span className=\"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800\">\r\n {status}\r\n </span>\r\n );\r\n }\r\n return (\r\n <span className=\"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800\">\r\n {status}\r\n </span>\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 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\">Waitlist Management</h2>\r\n <div className=\"flex items-center gap-2\">\r\n <Button onPress={() => setIsAddModalOpen(true)} size=\"sm\">\r\n <UserPlus className=\"h-4 w-4 mr-2\" />\r\n Add to Waitlist\r\n </Button>\r\n <div className=\"text-sm text-muted-foreground\">Total: {waitlist.length}</div>\r\n </div>\r\n </div>\r\n\r\n {/* Search */}\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 }}\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 by email\"\r\n placeholder=\"Search by 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 </div>\r\n\r\n <div className=\"border rounded-lg overflow-hidden\">\r\n <Table aria-label=\"Waitlist table\" removeWrapper>\r\n <TableHeader>\r\n <TableColumn>Email</TableColumn>\r\n <TableColumn>Status</TableColumn>\r\n <TableColumn>Created At</TableColumn>\r\n <TableColumn>Updated At</TableColumn>\r\n <TableColumn className=\"text-right\">Actions</TableColumn>\r\n </TableHeader>\r\n <TableBody\r\n items={filteredWaitlist}\r\n emptyContent={\r\n searchQuery\r\n ? \"No waitlist entries found matching your search\"\r\n : \"No waitlist entries found\"\r\n }\r\n >\r\n {(item) => (\r\n <TableRow key={item.id}>\r\n <TableCell className=\"font-medium\">{item.email}</TableCell>\r\n <TableCell>{getStatusBadge(item.status)}</TableCell>\r\n <TableCell>{formatDate(item.createdAt)}</TableCell>\r\n <TableCell>{formatDate(item.updatedAt)}</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=\"Waitlist actions\">\r\n <DropdownItem\r\n key=\"invite\"\r\n onPress={() => handleInvite(item.id)}\r\n isDisabled={isInviting}\r\n >\r\n {isInviting ? (\r\n <>\r\n <Spinner className=\"mr-2 h-3 w-3\" />\r\n Inviting...\r\n </>\r\n ) : (\r\n <>\r\n <Mail className=\"mr-2 h-4 w-4\" />\r\n Send Invitation\r\n </>\r\n )}\r\n </DropdownItem>\r\n <DropdownItem\r\n key=\"remove\"\r\n className=\"text-danger\"\r\n onClick={() => setItemToDelete(item.id)}\r\n >\r\n <Trash2 className=\"mr-2 h-4 w-4\" />\r\n Remove\r\n </DropdownItem>\r\n </DropdownMenu>\r\n </Dropdown>\r\n </TableCell>\r\n </TableRow>\r\n )}\r\n </TableBody>\r\n </Table>\r\n </div>\r\n\r\n {/* Remove confirmation modal */}\r\n <Modal\r\n isOpen={!!itemToDelete}\r\n onOpenChange={(open) => {\r\n if (!open) setItemToDelete(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 remove this entry from the\r\n waitlist.\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={handleRemove} isLoading={isRemoving}>\r\n Remove\r\n </Button>\r\n </ModalFooter>\r\n </>\r\n )}\r\n </ModalContent>\r\n </Modal>\r\n\r\n {/* Add to waitlist modal */}\r\n <Modal\r\n isOpen={isAddModalOpen}\r\n onOpenChange={(open) => {\r\n if (!open) setIsAddModalOpen(false);\r\n }}\r\n >\r\n <ModalContent>\r\n {(onClose) => (\r\n <form\r\n onSubmit={(e) => {\r\n e.preventDefault();\r\n handleAdd();\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\">Add to Waitlist</p>\r\n <p className=\"text-sm text-default-600\">\r\n Enter an email address to add someone to the waitlist.\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={emailInputId}\r\n label=\"Email *\"\r\n labelPlacement=\"outside\"\r\n type=\"email\"\r\n placeholder=\"Enter email address\"\r\n value={newEmail}\r\n onChange={(e) => setNewEmail(e.target.value)}\r\n variant=\"bordered\"\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 type=\"submit\" color=\"primary\" isDisabled={isAdding} isLoading={isAdding}>\r\n {isAdding ? \"Adding...\" : \"Add to Waitlist\"}\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":";;;;;;;AA8BA,SAAgB,cAAc,EAAE,WAA+B;CAC7D,MAAM,OAAO,SAAS;CACtB,MAAM,cAAc,gBAAgB;CAEpC,MAAM,EAAE,MAAM,WAAW,EAAE,EAAE,cAAc,SAAS,KAAK,KAAK,kBAAkB,cAAc,CAAC;CAC/F,MAAM,EAAE,QAAQ,QAAQ,WAAW,eAAe,YAChD,KAAK,KAAK,mBAAmB,gBAAgB;EAC3C,iBAAiB;AACf,eAAY,kBAAkB,EAAE,UAAU,KAAK,KAAK,kBAAkB,UAAU,EAAE,CAAC;AACnF,SAAM,QAAQ,+BAA+B;;EAE/C,UAAU,UAAU;AAClB,SAAM,MACJ,8BAA8B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACrF;;EAEJ,CAAC,CACH;CACD,MAAM,EAAE,QAAQ,QAAQ,WAAW,eAAe,YAChD,KAAK,KAAK,mBAAmB,gBAAgB;EAC3C,iBAAiB;AACf,eAAY,kBAAkB,EAAE,UAAU,KAAK,KAAK,kBAAkB,UAAU,EAAE,CAAC;AACnF,SAAM,QAAQ,qCAAqC;;EAErD,UAAU,UAAU;AAClB,SAAM,MAAM,qBAAqB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAAG;;EAE5F,iBAAiB;AACf,mBAAgB,KAAK;;EAExB,CAAC,CACH;CACD,MAAM,EAAE,QAAQ,KAAK,WAAW,aAAa,YAC3C,KAAK,KAAK,cAAc,gBAAgB;EACtC,iBAAiB;AACf,eAAY,kBAAkB,EAAE,UAAU,KAAK,KAAK,kBAAkB,UAAU,EAAE,CAAC;AACnF,SAAM,QAAQ,iCAAiC;;EAEjD,UAAU,UAAU;AAClB,SAAM,MACJ,8BAA8B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACrF;;EAEJ,CAAC,CACH;CACD,MAAM,eAAe,OAAO;CAC5B,MAAM,CAAC,aAAa,kBAAkB,SAAS,GAAG;CAClD,MAAM,CAAC,sBAAsB,2BAA2B,SAAS,GAAG;CACpE,MAAM,CAAC,cAAc,mBAAmB,SAAwB,KAAK;CACrE,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,MAAM;CAC3D,MAAM,CAAC,UAAU,eAAe,SAAS,GAAG;AAG5C,iBAAgB;EACd,MAAM,QAAQ,iBAAiB;AAC7B,2BAAwB,YAAY;KACnC,IAAI;AAEP,eAAa,aAAa,MAAM;IAC/B,CAAC,YAAY,CAAC;CAEjB,MAAM,mBAAmB,SAAS,QAAQ,SACxC,KAAK,OAAO,aAAa,CAAC,SAAS,sBAAsB,aAAa,IAAI,GAAG,CAC9E;CAED,MAAM,gBAAgB,OAAe;AACnC,SAAO,EAAE,IAAI,CAAC;;CAGhB,MAAM,qBAAqB;AACzB,MAAI,aACF,QAAO,EAAE,IAAI,cAAc,CAAC;;CAIhC,MAAM,YAAY,YAAY;AAC5B,MAAI,CAAC,SAAS,MAAM,EAAE;AACpB,SAAM,MAAM,gCAAgC;AAC5C;;AAKF,MAAI,CADe,6BACH,KAAK,SAAS,MAAM,CAAC,EAAE;AACrC,SAAM,MAAM,qCAAqC;AACjD;;AAGF,MAAI,EAAE,OAAO,SAAS,MAAM,EAAE,CAAC;AAC/B,cAAY,GAAG;AACf,oBAAkB,MAAM;;CAG1B,MAAM,cAAc,SAA+B;AACjD,MAAI,CAAC,KAAM,QAAO;AAElB,UADgB,OAAO,SAAS,WAAW,IAAI,KAAK,KAAK,GAAG,MAC7C,mBAAmB,KAAA,GAAW;GAC3C,MAAM;GACN,OAAO;GACP,KAAK;GACL,MAAM;GACN,QAAQ;GACT,CAAC;;CAGJ,MAAM,kBAAkB,WAAmB;EACzC,MAAM,cAAc,OAAO,aAAa;AACxC,MAAI,gBAAgB,aAAa,gBAAgB,SAC/C,QACE,oBAAC,QAAD;GAAM,WAAU;aACb;GACI,CAAA;AAGX,MAAI,gBAAgB,UAClB,QACE,oBAAC,QAAD;GAAM,WAAU;aACb;GACI,CAAA;AAGX,SACE,oBAAC,QAAD;GAAM,WAAU;aACb;GACI,CAAA;;AAIX,KAAI,UACF,QACE,oBAAC,OAAD;EAAK,WAAU;YACb,oBAAC,SAAD,EAAW,CAAA;EACP,CAAA;AAIV,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACE,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,MAAD;KAAI,WAAU;eAAwB;KAAwB,CAAA,EAC9D,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,qBAAC,QAAD;MAAQ,eAAe,kBAAkB,KAAK;MAAE,MAAK;gBAArD,CACE,oBAAC,UAAD,EAAU,WAAU,gBAAiB,CAAA,EAAA,kBAE9B;SACT,qBAAC,OAAD;MAAK,WAAU;gBAAf,CAA+C,WAAQ,SAAS,OAAa;QACzE;OACF;;GAGN,oBAAC,OAAD;IAAK,WAAU;cACb,qBAAC,QAAD;KACE,WAAU;KACV,WAAW,MAAM;AACf,QAAE,gBAAgB;AAClB,8BAAwB,YAAY;;eAJxC;MAOE,oBAAC,QAAD,EAAQ,WAAU,2DAA4D,CAAA;MAC9E,oBAAC,OAAD;OACE,cAAW;OACX,aAAY;OACZ,WAAU;OACV,OAAO;OACP,WAAW,MAAM,eAAe,EAAE,OAAO,MAAM;OAC/C,SAAQ;OACR,CAAA;MACD,eACC,oBAAC,UAAD;OACE,MAAK;OACL,eAAe,eAAe,GAAG;OACjC,WAAU;OACV,cAAW;iBAEX,oBAAC,GAAD,EAAG,WAAU,WAAY,CAAA;OAClB,CAAA;MAEN;;IACH,CAAA;GAEN,oBAAC,OAAD;IAAK,WAAU;cACb,qBAAC,OAAD;KAAO,cAAW;KAAiB,eAAA;eAAnC,CACE,qBAAC,aAAD,EAAA,UAAA;MACE,oBAAC,aAAD,EAAA,UAAa,SAAmB,CAAA;MAChC,oBAAC,aAAD,EAAA,UAAa,UAAoB,CAAA;MACjC,oBAAC,aAAD,EAAA,UAAa,cAAwB,CAAA;MACrC,oBAAC,aAAD,EAAA,UAAa,cAAwB,CAAA;MACrC,oBAAC,aAAD;OAAa,WAAU;iBAAa;OAAqB,CAAA;MAC7C,EAAA,CAAA,EACd,oBAAC,WAAD;MACE,OAAO;MACP,cACE,cACI,mDACA;iBAGJ,SACA,qBAAC,UAAD,EAAA,UAAA;OACE,oBAAC,WAAD;QAAW,WAAU;kBAAe,KAAK;QAAkB,CAAA;OAC3D,oBAAC,WAAD,EAAA,UAAY,eAAe,KAAK,OAAO,EAAa,CAAA;OACpD,oBAAC,WAAD,EAAA,UAAY,WAAW,KAAK,UAAU,EAAa,CAAA;OACnD,oBAAC,WAAD,EAAA,UAAY,WAAW,KAAK,UAAU,EAAa,CAAA;OACnD,oBAAC,WAAD;QAAW,WAAU;kBACnB,qBAAC,UAAD;SAAU,WAAU;mBAApB,CACE,oBAAC,iBAAD,EAAA,UACE,oBAAC,QAAD;UAAQ,SAAQ;UAAQ,MAAK;UAAK,YAAA;oBAChC,oBAAC,gBAAD,EAAgB,WAAU,WAAY,CAAA;UAC/B,CAAA,EACO,CAAA,EAClB,qBAAC,cAAD;UAAc,cAAW;oBAAzB,CACE,oBAAC,cAAD;WAEE,eAAe,aAAa,KAAK,GAAG;WACpC,YAAY;qBAEX,aACC,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,SAAD,EAAS,WAAU,gBAAiB,CAAA,EAAA,cAEnC,EAAA,CAAA,GAEH,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,MAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,kBAEhC,EAAA,CAAA;WAEQ,EAfT,SAeS,EACf,qBAAC,cAAD;WAEE,WAAU;WACV,eAAe,gBAAgB,KAAK,GAAG;qBAHzC,CAKE,oBAAC,QAAD,EAAQ,WAAU,gBAAiB,CAAA,EAAA,SAEtB;aANT,SAMS,CACF;YACN;;QACD,CAAA;OACH,EAAA,EAzCI,KAAK,GAyCT;MAEH,CAAA,CACN;;IACJ,CAAA;GAGN,oBAAC,OAAD;IACE,QAAQ,CAAC,CAAC;IACV,eAAe,SAAS;AACtB,SAAI,CAAC,KAAM,iBAAgB,KAAK;;cAGlC,oBAAC,cAAD,EAAA,WACI,YACA,qBAAA,YAAA,EAAA,UAAA,CACE,qBAAC,aAAD;KAAa,WAAU;eAAvB,CACE,oBAAC,KAAD;MAAG,WAAU;gBAAwB;MAAiB,CAAA,EACtD,oBAAC,KAAD;MAAG,WAAU;gBAA2B;MAGpC,CAAA,CACQ;QACd,qBAAC,aAAD,EAAA,UAAA,CACE,oBAAC,QAAD;KAAQ,SAAQ;KAAW,SAAS;eAAS;KAEpC,CAAA,EACT,oBAAC,QAAD;KAAQ,OAAM;KAAS,SAAS;KAAc,WAAW;eAAY;KAE5D,CAAA,CACG,EAAA,CAAA,CACb,EAAA,CAAA,EAEQ,CAAA;IACT,CAAA;GAGR,oBAAC,OAAD;IACE,QAAQ;IACR,eAAe,SAAS;AACtB,SAAI,CAAC,KAAM,mBAAkB,MAAM;;cAGrC,oBAAC,cAAD,EAAA,WACI,YACA,qBAAC,QAAD;KACE,WAAW,MAAM;AACf,QAAE,gBAAgB;AAClB,iBAAW;;KAEb,WAAU;eALZ;MAOE,qBAAC,aAAD;OAAa,WAAU;iBAAvB,CACE,oBAAC,KAAD;QAAG,WAAU;kBAAwB;QAAmB,CAAA,EACxD,oBAAC,KAAD;QAAG,WAAU;kBAA2B;QAEpC,CAAA,CACQ;;MAEd,oBAAC,WAAD;OAAW,WAAU;iBACnB,oBAAC,OAAD;QAAK,WAAU;kBACb,oBAAC,OAAD;SACE,IAAI;SACJ,OAAM;SACN,gBAAe;SACf,MAAK;SACL,aAAY;SACZ,OAAO;SACP,WAAW,MAAM,YAAY,EAAE,OAAO,MAAM;SAC5C,SAAQ;SACR,CAAA;QACE,CAAA;OACI,CAAA;MAEZ,qBAAC,aAAD,EAAA,UAAA,CACE,oBAAC,QAAD;OAAQ,SAAQ;OAAW,MAAK;OAAS,SAAS;iBAAS;OAElD,CAAA,EACT,oBAAC,QAAD;OAAQ,MAAK;OAAS,OAAM;OAAU,YAAY;OAAU,WAAW;iBACpE,WAAW,cAAc;OACnB,CAAA,CACG,EAAA,CAAA;MACT;QAEI,CAAA;IACT,CAAA;GACJ"}
@@ -1,5 +1,5 @@
1
- import * as _$react_jsx_runtime0 from "react/jsx-runtime";
2
1
  import { ReactNode } from "react";
2
+ import * as _$react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/modules/auth/components/AuthLayout.d.ts
5
5
  declare function AuthLayout({
@@ -4,9 +4,9 @@ const require_src_icons_GoogleIcon = require("../../../icons/GoogleIcon.js");
4
4
  const require_src_icons_LinkedInIcon = require("../../../icons/LinkedInIcon.js");
5
5
  const require_src_icons_MicrosoftIcon = require("../../../icons/MicrosoftIcon.js");
6
6
  const require_src_modules_auth_components_LastUsedBadge = require("./LastUsedBadge.js");
7
+ let react_i18next = require("react-i18next");
7
8
  let react_jsx_runtime = require("react/jsx-runtime");
8
9
  let _heroui_react = require("@heroui/react");
9
- let react_i18next = require("react-i18next");
10
10
  let sonner = require("sonner");
11
11
  let _m5kdev_frontend_modules_auth_auth_lib = require("@m5kdev/frontend/modules/auth/auth.lib");
12
12
  //#region src/modules/auth/components/AuthProviders.tsx
@@ -2,9 +2,9 @@ import { GoogleIcon } from "../../../icons/GoogleIcon.mjs";
2
2
  import { LinkedInIcon } from "../../../icons/LinkedInIcon.mjs";
3
3
  import { MicrosoftIcon } from "../../../icons/MicrosoftIcon.mjs";
4
4
  import { LastUsedBadge } from "./LastUsedBadge.mjs";
5
+ import { useTranslation } from "react-i18next";
5
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
7
  import { Button } from "@heroui/react";
7
- import { useTranslation } from "react-i18next";
8
8
  import { toast } from "sonner";
9
9
  import { authClient } from "@m5kdev/frontend/modules/auth/auth.lib";
10
10
  //#region src/modules/auth/components/AuthProviders.tsx
@@ -1,6 +1,6 @@
1
1
  import { UseBackendTRPC } from "../../../types.mjs";
2
- import * as _$react_jsx_runtime0 from "react/jsx-runtime";
3
2
  import { ReactNode } from "react";
3
+ import * as _$react_jsx_runtime0 from "react/jsx-runtime";
4
4
 
5
5
  //#region src/modules/auth/components/AuthRouter.d.ts
6
6
  interface AuthRouterProps {
@@ -3,10 +3,10 @@ require("../../../../_virtual/_rolldown/runtime.js");
3
3
  const require_src_icons_GoogleIcon = require("../../../icons/GoogleIcon.js");
4
4
  const require_src_icons_LinkedInIcon = require("../../../icons/LinkedInIcon.js");
5
5
  const require_src_icons_MicrosoftIcon = require("../../../icons/MicrosoftIcon.js");
6
- let react_jsx_runtime = require("react/jsx-runtime");
7
6
  let react = require("react");
8
- let _heroui_react = require("@heroui/react");
7
+ let react_jsx_runtime = require("react/jsx-runtime");
9
8
  let react_router = require("react-router");
9
+ let _heroui_react = require("@heroui/react");
10
10
  let sonner = require("sonner");
11
11
  let _tanstack_react_query = require("@tanstack/react-query");
12
12
  let _m5kdev_frontend_modules_auth_hooks_useSession = require("@m5kdev/frontend/modules/auth/hooks/useSession");
@@ -1,10 +1,10 @@
1
1
  import { GoogleIcon } from "../../../icons/GoogleIcon.mjs";
2
2
  import { LinkedInIcon } from "../../../icons/LinkedInIcon.mjs";
3
3
  import { MicrosoftIcon } from "../../../icons/MicrosoftIcon.mjs";
4
- import { jsx, jsxs } from "react/jsx-runtime";
5
4
  import { useEffect, useMemo, useState } from "react";
6
- import { Alert, Button, Card, CardBody, CardHeader, Input } from "@heroui/react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
7
6
  import { useLocation, useNavigate } from "react-router";
7
+ import { Alert, Button, Card, CardBody, CardHeader, Input } from "@heroui/react";
8
8
  import { toast } from "sonner";
9
9
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
10
10
  import { useSession } from "@m5kdev/frontend/modules/auth/hooks/useSession";
@@ -1,10 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../../../_virtual/_rolldown/runtime.js");
3
- let react_jsx_runtime = require("react/jsx-runtime");
4
- let _heroui_react = require("@heroui/react");
5
3
  let lucide_react = require("lucide-react");
6
4
  let react_i18next = require("react-i18next");
5
+ let react_jsx_runtime = require("react/jsx-runtime");
7
6
  let react_router = require("react-router");
7
+ let _heroui_react = require("@heroui/react");
8
8
  let nuqs = require("nuqs");
9
9
  //#region src/modules/auth/components/ErrorAuthRoute.tsx
10
10
  function ErrorAuthRoute() {
@@ -1,8 +1,8 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import { Button, Card, CardBody, CardHeader } from "@heroui/react";
3
1
  import { AlertCircle } from "lucide-react";
4
2
  import { useTranslation } from "react-i18next";
5
- import { Link as Link$1 } from "react-router";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { Link } from "react-router";
5
+ import { Button, Card, CardBody, CardHeader } from "@heroui/react";
6
6
  import { useQueryState } from "nuqs";
7
7
  //#region src/modules/auth/components/ErrorAuthRoute.tsx
8
8
  function ErrorAuthRoute() {
@@ -109,12 +109,12 @@ function ErrorAuthRoute() {
109
109
  children: /* @__PURE__ */ jsxs("div", {
110
110
  className: "flex flex-col gap-2",
111
111
  children: [buttons.includes("login") && /* @__PURE__ */ jsx(Button, {
112
- as: Link$1,
112
+ as: Link,
113
113
  to: "/login",
114
114
  variant: "bordered",
115
115
  children: t("web-ui:auth.error.backToLogin")
116
116
  }), buttons.includes("signup") && /* @__PURE__ */ jsx(Button, {
117
- as: Link$1,
117
+ as: Link,
118
118
  to: "/signup",
119
119
  variant: "bordered",
120
120
  children: signupLabel || t("web-ui:auth.error.backToSignup")