@burdenoff/microfe-admin 2026.511.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -0
- package/dist/admin/AdminRoot.d.ts +31 -0
- package/dist/admin/AdminRoot.d.ts.map +1 -0
- package/dist/admin/AdminRoot.js +175 -0
- package/dist/admin/AdminRoot.js.map +1 -0
- package/dist/admin/AdminRoutes.d.ts +29 -0
- package/dist/admin/AdminRoutes.d.ts.map +1 -0
- package/dist/admin/AdminRoutes.js +143 -0
- package/dist/admin/AdminRoutes.js.map +1 -0
- package/dist/admin/components/AccessDenied.d.ts +8 -0
- package/dist/admin/components/AccessDenied.d.ts.map +1 -0
- package/dist/admin/components/AccessDenied.js +28 -0
- package/dist/admin/components/AccessDenied.js.map +1 -0
- package/dist/admin/components/ActivityFeed.d.ts +20 -0
- package/dist/admin/components/ActivityFeed.d.ts.map +1 -0
- package/dist/admin/components/ActivityFeed.js +91 -0
- package/dist/admin/components/ActivityFeed.js.map +1 -0
- package/dist/admin/components/Charts.d.ts +33 -0
- package/dist/admin/components/Charts.d.ts.map +1 -0
- package/dist/admin/components/Charts.js +37 -0
- package/dist/admin/components/Charts.js.map +1 -0
- package/dist/admin/components/ConfirmDialog.d.ts +45 -0
- package/dist/admin/components/ConfirmDialog.d.ts.map +1 -0
- package/dist/admin/components/ConfirmDialog.js +4 -0
- package/dist/admin/components/DataTable.d.ts +64 -0
- package/dist/admin/components/DataTable.d.ts.map +1 -0
- package/dist/admin/components/DataTable.js +127 -0
- package/dist/admin/components/DataTable.js.map +1 -0
- package/dist/admin/components/FormSheet.d.ts +79 -0
- package/dist/admin/components/FormSheet.d.ts.map +1 -0
- package/dist/admin/components/FormSheet.js +111 -0
- package/dist/admin/components/FormSheet.js.map +1 -0
- package/dist/admin/components/MetricCard.d.ts +40 -0
- package/dist/admin/components/MetricCard.d.ts.map +1 -0
- package/dist/admin/components/MetricCard.js +57 -0
- package/dist/admin/components/MetricCard.js.map +1 -0
- package/dist/admin/components/PageLayout.d.ts +34 -0
- package/dist/admin/components/PageLayout.d.ts.map +1 -0
- package/dist/admin/components/PageLayout.js +31 -0
- package/dist/admin/components/PageLayout.js.map +1 -0
- package/dist/admin/components/PermissionGuard.d.ts +12 -0
- package/dist/admin/components/PermissionGuard.d.ts.map +1 -0
- package/dist/admin/components/PermissionGuard.js +18 -0
- package/dist/admin/components/PermissionGuard.js.map +1 -0
- package/dist/admin/components/RowActions.d.ts +41 -0
- package/dist/admin/components/RowActions.d.ts.map +1 -0
- package/dist/admin/components/RowActions.js +93 -0
- package/dist/admin/components/RowActions.js.map +1 -0
- package/dist/admin/components/StatusBadge.d.ts +35 -0
- package/dist/admin/components/StatusBadge.d.ts.map +1 -0
- package/dist/admin/components/StatusBadge.js +41 -0
- package/dist/admin/components/StatusBadge.js.map +1 -0
- package/dist/admin/components/Toast.d.ts +26 -0
- package/dist/admin/components/Toast.d.ts.map +1 -0
- package/dist/admin/components/Toast.js +133 -0
- package/dist/admin/components/Toast.js.map +1 -0
- package/dist/admin/components/forms/SubscriptionForm.d.ts +57 -0
- package/dist/admin/components/forms/SubscriptionForm.d.ts.map +1 -0
- package/dist/admin/components/forms/SubscriptionForm.js +299 -0
- package/dist/admin/components/forms/SubscriptionForm.js.map +1 -0
- package/dist/admin/components/forms/TenantForm.d.ts +68 -0
- package/dist/admin/components/forms/TenantForm.d.ts.map +1 -0
- package/dist/admin/components/forms/TenantForm.js +346 -0
- package/dist/admin/components/forms/TenantForm.js.map +1 -0
- package/dist/admin/components/forms/TicketForm.d.ts +67 -0
- package/dist/admin/components/forms/TicketForm.d.ts.map +1 -0
- package/dist/admin/components/forms/TicketForm.js +55 -0
- package/dist/admin/components/forms/TicketForm.js.map +1 -0
- package/dist/admin/components/forms/UserForm.d.ts +57 -0
- package/dist/admin/components/forms/UserForm.d.ts.map +1 -0
- package/dist/admin/components/forms/UserForm.js +253 -0
- package/dist/admin/components/forms/UserForm.js.map +1 -0
- package/dist/admin/components/forms/index.d.ts +5 -0
- package/dist/admin/components/forms/index.d.ts.map +1 -0
- package/dist/admin/components/forms/index.js +4 -0
- package/dist/admin/components/index.d.ts +15 -0
- package/dist/admin/components/index.d.ts.map +1 -0
- package/dist/admin/components/index.js +17 -0
- package/dist/admin/components/ui.d.ts +52 -0
- package/dist/admin/components/ui.d.ts.map +1 -0
- package/dist/admin/components/ui.js +140 -0
- package/dist/admin/components/ui.js.map +1 -0
- package/dist/admin/constants/index.d.ts +75 -0
- package/dist/admin/constants/index.d.ts.map +1 -0
- package/dist/admin/constants/index.js +90 -0
- package/dist/admin/constants/index.js.map +1 -0
- package/dist/admin/constants/permissions.d.ts +27 -0
- package/dist/admin/constants/permissions.d.ts.map +1 -0
- package/dist/admin/constants/permissions.js +23 -0
- package/dist/admin/constants/permissions.js.map +1 -0
- package/dist/admin/hooks/useAdminPermissions.d.ts +30 -0
- package/dist/admin/hooks/useAdminPermissions.d.ts.map +1 -0
- package/dist/admin/hooks/useAdminPermissions.js +56 -0
- package/dist/admin/hooks/useAdminPermissions.js.map +1 -0
- package/dist/admin/index.d.ts +31 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +9 -0
- package/dist/admin/pages/AuditLogsPage.d.ts +5 -0
- package/dist/admin/pages/AuditLogsPage.d.ts.map +1 -0
- package/dist/admin/pages/AuditLogsPage.js +209 -0
- package/dist/admin/pages/AuditLogsPage.js.map +1 -0
- package/dist/admin/pages/BillingPage.d.ts +2 -0
- package/dist/admin/pages/BillingPage.d.ts.map +1 -0
- package/dist/admin/pages/BillingPage.js +164 -0
- package/dist/admin/pages/BillingPage.js.map +1 -0
- package/dist/admin/pages/CommunicationsPage.d.ts +2 -0
- package/dist/admin/pages/CommunicationsPage.d.ts.map +1 -0
- package/dist/admin/pages/CommunicationsPage.js +118 -0
- package/dist/admin/pages/CommunicationsPage.js.map +1 -0
- package/dist/admin/pages/DashboardPage.d.ts +5 -0
- package/dist/admin/pages/DashboardPage.d.ts.map +1 -0
- package/dist/admin/pages/DashboardPage.js +121 -0
- package/dist/admin/pages/DashboardPage.js.map +1 -0
- package/dist/admin/pages/FeatureFlagsPage.d.ts +2 -0
- package/dist/admin/pages/FeatureFlagsPage.d.ts.map +1 -0
- package/dist/admin/pages/FeatureFlagsPage.js +116 -0
- package/dist/admin/pages/FeatureFlagsPage.js.map +1 -0
- package/dist/admin/pages/OrganizationsListPage.d.ts +2 -0
- package/dist/admin/pages/OrganizationsListPage.d.ts.map +1 -0
- package/dist/admin/pages/OrganizationsListPage.js +112 -0
- package/dist/admin/pages/OrganizationsListPage.js.map +1 -0
- package/dist/admin/pages/ProductsPage.d.ts +5 -0
- package/dist/admin/pages/ProductsPage.d.ts.map +1 -0
- package/dist/admin/pages/ProductsPage.js +392 -0
- package/dist/admin/pages/ProductsPage.js.map +1 -0
- package/dist/admin/pages/ReferralsPage.d.ts +2 -0
- package/dist/admin/pages/ReferralsPage.d.ts.map +1 -0
- package/dist/admin/pages/ReferralsPage.js +272 -0
- package/dist/admin/pages/ReferralsPage.js.map +1 -0
- package/dist/admin/pages/RolesPermissionsPage.d.ts +2 -0
- package/dist/admin/pages/RolesPermissionsPage.d.ts.map +1 -0
- package/dist/admin/pages/RolesPermissionsPage.js +145 -0
- package/dist/admin/pages/RolesPermissionsPage.js.map +1 -0
- package/dist/admin/pages/SREPage.d.ts +5 -0
- package/dist/admin/pages/SREPage.d.ts.map +1 -0
- package/dist/admin/pages/SREPage.js +405 -0
- package/dist/admin/pages/SREPage.js.map +1 -0
- package/dist/admin/pages/SandboxSettingsPage.d.ts +7 -0
- package/dist/admin/pages/SandboxSettingsPage.d.ts.map +1 -0
- package/dist/admin/pages/SandboxSettingsPage.js +497 -0
- package/dist/admin/pages/SandboxSettingsPage.js.map +1 -0
- package/dist/admin/pages/SettingsPage.d.ts +5 -0
- package/dist/admin/pages/SettingsPage.d.ts.map +1 -0
- package/dist/admin/pages/SettingsPage.js +279 -0
- package/dist/admin/pages/SettingsPage.js.map +1 -0
- package/dist/admin/pages/TenantDetailPage.d.ts +5 -0
- package/dist/admin/pages/TenantDetailPage.d.ts.map +1 -0
- package/dist/admin/pages/TenantDetailPage.js +274 -0
- package/dist/admin/pages/TenantDetailPage.js.map +1 -0
- package/dist/admin/pages/TenantFormRoutePage.d.ts +6 -0
- package/dist/admin/pages/TenantFormRoutePage.d.ts.map +1 -0
- package/dist/admin/pages/TenantFormRoutePage.js +136 -0
- package/dist/admin/pages/TenantFormRoutePage.js.map +1 -0
- package/dist/admin/pages/TenantsListPage.d.ts +5 -0
- package/dist/admin/pages/TenantsListPage.d.ts.map +1 -0
- package/dist/admin/pages/TenantsListPage.js +339 -0
- package/dist/admin/pages/TenantsListPage.js.map +1 -0
- package/dist/admin/pages/UsersListPage.d.ts +5 -0
- package/dist/admin/pages/UsersListPage.d.ts.map +1 -0
- package/dist/admin/pages/UsersListPage.js +250 -0
- package/dist/admin/pages/UsersListPage.js.map +1 -0
- package/dist/admin/pages/WaitlistPage.d.ts +2 -0
- package/dist/admin/pages/WaitlistPage.d.ts.map +1 -0
- package/dist/admin/pages/WaitlistPage.js +241 -0
- package/dist/admin/pages/WaitlistPage.js.map +1 -0
- package/dist/admin/pages/WorkflowsPage.d.ts +2 -0
- package/dist/admin/pages/WorkflowsPage.d.ts.map +1 -0
- package/dist/admin/pages/WorkflowsPage.js +126 -0
- package/dist/admin/pages/WorkflowsPage.js.map +1 -0
- package/dist/admin/pages/WorkspacesListPage.d.ts +2 -0
- package/dist/admin/pages/WorkspacesListPage.d.ts.map +1 -0
- package/dist/admin/pages/WorkspacesListPage.js +100 -0
- package/dist/admin/pages/WorkspacesListPage.js.map +1 -0
- package/dist/admin/pages/index.d.ts +20 -0
- package/dist/admin/pages/index.d.ts.map +1 -0
- package/dist/admin/pages/index.js +19 -0
- package/dist/admin/providers/AdminProvider.d.ts +13 -0
- package/dist/admin/providers/AdminProvider.d.ts.map +1 -0
- package/dist/admin/providers/AdminProvider.js +43 -0
- package/dist/admin/providers/AdminProvider.js.map +1 -0
- package/dist/admin/schemas/index.d.ts +409 -0
- package/dist/admin/schemas/index.d.ts.map +1 -0
- package/dist/admin/schemas/index.js +111 -0
- package/dist/admin/schemas/index.js.map +1 -0
- package/dist/admin/store/adminStore.d.ts +28 -0
- package/dist/admin/store/adminStore.d.ts.map +1 -0
- package/dist/admin/store/adminStore.js +48 -0
- package/dist/admin/store/adminStore.js.map +1 -0
- package/dist/admin/types/index.d.ts +325 -0
- package/dist/admin/types/index.d.ts.map +1 -0
- package/dist/admin/utils/cn.d.ts +7 -0
- package/dist/admin/utils/cn.d.ts.map +1 -0
- package/dist/admin/utils/cn.js +10 -0
- package/dist/admin/utils/cn.js.map +1 -0
- package/dist/admin/utils/directActivityGraphql.d.ts +11 -0
- package/dist/admin/utils/directActivityGraphql.d.ts.map +1 -0
- package/dist/admin/utils/directActivityGraphql.js +25 -0
- package/dist/admin/utils/directActivityGraphql.js.map +1 -0
- package/dist/admin/utils/formatters.d.ts +33 -0
- package/dist/admin/utils/formatters.d.ts.map +1 -0
- package/dist/admin/utils/formatters.js +54 -0
- package/dist/admin/utils/formatters.js.map +1 -0
- package/dist/admin/utils/gatewayGraphql.d.ts +9 -0
- package/dist/admin/utils/gatewayGraphql.d.ts.map +1 -0
- package/dist/admin/utils/i18n.d.ts +6 -0
- package/dist/admin/utils/i18n.d.ts.map +1 -0
- package/dist/admin/utils/i18n.js +15 -0
- package/dist/admin/utils/i18n.js.map +1 -0
- package/dist/admin/utils/mappers.d.ts +15 -0
- package/dist/admin/utils/mappers.d.ts.map +1 -0
- package/dist/admin/utils/mappers.js +73 -0
- package/dist/admin/utils/mappers.js.map +1 -0
- package/dist/admin/utils/navigation.d.ts +9 -0
- package/dist/admin/utils/navigation.d.ts.map +1 -0
- package/dist/admin/utils/navigation.js +8 -0
- package/dist/admin/utils/navigation.js.map +1 -0
- package/dist/admin/utils/tenantEvents.d.ts +11 -0
- package/dist/admin/utils/tenantEvents.d.ts.map +1 -0
- package/dist/admin/utils/tenantEvents.js +8 -0
- package/dist/admin/utils/tenantEvents.js.map +1 -0
- package/dist/dev/main.d.ts +2 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/generated/global-operations.d.ts +2749 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-operations.js +907 -0
- package/dist/generated/global-operations.js.map +1 -0
- package/dist/generated/global-types.d.ts +20773 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/global-types.js +12 -0
- package/dist/generated/global-types.js.map +1 -0
- package/dist/generated/wspace-operations.d.ts +132 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-operations.js +65 -0
- package/dist/generated/wspace-operations.js.map +1 -0
- package/dist/generated/wspace-types.d.ts +53363 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/node_modules/@hookform/resolvers/dist/resolvers.js +34 -0
- package/dist/node_modules/@hookform/resolvers/dist/resolvers.js.map +1 -0
- package/dist/node_modules/@hookform/resolvers/zod/dist/zod.js +118 -0
- package/dist/node_modules/@hookform/resolvers/zod/dist/zod.js.map +1 -0
- package/dist/node_modules/clsx/dist/clsx.js +18 -0
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/date-fns/_lib/addLeadingZeros.js +8 -0
- package/dist/node_modules/date-fns/_lib/addLeadingZeros.js.map +1 -0
- package/dist/node_modules/date-fns/_lib/defaultOptions.js +9 -0
- package/dist/node_modules/date-fns/_lib/defaultOptions.js.map +1 -0
- package/dist/node_modules/date-fns/_lib/format/formatters.js +384 -0
- package/dist/node_modules/date-fns/_lib/format/formatters.js.map +1 -0
- package/dist/node_modules/date-fns/_lib/format/lightFormatters.js +45 -0
- package/dist/node_modules/date-fns/_lib/format/lightFormatters.js.map +1 -0
- package/dist/node_modules/date-fns/_lib/format/longFormatters.js +42 -0
- package/dist/node_modules/date-fns/_lib/format/longFormatters.js.map +1 -0
- package/dist/node_modules/date-fns/_lib/getRoundingMethod.js +11 -0
- package/dist/node_modules/date-fns/_lib/getRoundingMethod.js.map +1 -0
- package/dist/node_modules/date-fns/_lib/getTimezoneOffsetInMilliseconds.js +10 -0
- package/dist/node_modules/date-fns/_lib/getTimezoneOffsetInMilliseconds.js.map +1 -0
- package/dist/node_modules/date-fns/_lib/normalizeDates.js +10 -0
- package/dist/node_modules/date-fns/_lib/normalizeDates.js.map +1 -0
- package/dist/node_modules/date-fns/_lib/protectedTokens.js +25 -0
- package/dist/node_modules/date-fns/_lib/protectedTokens.js.map +1 -0
- package/dist/node_modules/date-fns/compareAsc.js +10 -0
- package/dist/node_modules/date-fns/compareAsc.js.map +1 -0
- package/dist/node_modules/date-fns/constants.js +8 -0
- package/dist/node_modules/date-fns/constants.js.map +1 -0
- package/dist/node_modules/date-fns/constructFrom.js +9 -0
- package/dist/node_modules/date-fns/constructFrom.js.map +1 -0
- package/dist/node_modules/date-fns/constructNow.js +9 -0
- package/dist/node_modules/date-fns/constructNow.js.map +1 -0
- package/dist/node_modules/date-fns/differenceInCalendarDays.js +13 -0
- package/dist/node_modules/date-fns/differenceInCalendarDays.js.map +1 -0
- package/dist/node_modules/date-fns/differenceInCalendarMonths.js +10 -0
- package/dist/node_modules/date-fns/differenceInCalendarMonths.js.map +1 -0
- package/dist/node_modules/date-fns/differenceInMilliseconds.js +9 -0
- package/dist/node_modules/date-fns/differenceInMilliseconds.js.map +1 -0
- package/dist/node_modules/date-fns/differenceInMonths.js +18 -0
- package/dist/node_modules/date-fns/differenceInMonths.js.map +1 -0
- package/dist/node_modules/date-fns/differenceInSeconds.js +11 -0
- package/dist/node_modules/date-fns/differenceInSeconds.js.map +1 -0
- package/dist/node_modules/date-fns/endOfDay.js +10 -0
- package/dist/node_modules/date-fns/endOfDay.js.map +1 -0
- package/dist/node_modules/date-fns/endOfMonth.js +10 -0
- package/dist/node_modules/date-fns/endOfMonth.js.map +1 -0
- package/dist/node_modules/date-fns/format.js +61 -0
- package/dist/node_modules/date-fns/format.js.map +1 -0
- package/dist/node_modules/date-fns/formatDistance.js +39 -0
- package/dist/node_modules/date-fns/formatDistance.js.map +1 -0
- package/dist/node_modules/date-fns/formatDistanceToNow.js +10 -0
- package/dist/node_modules/date-fns/formatDistanceToNow.js.map +1 -0
- package/dist/node_modules/date-fns/getDayOfYear.js +12 -0
- package/dist/node_modules/date-fns/getDayOfYear.js.map +1 -0
- package/dist/node_modules/date-fns/getISOWeek.js +13 -0
- package/dist/node_modules/date-fns/getISOWeek.js.map +1 -0
- package/dist/node_modules/date-fns/getISOWeekYear.js +16 -0
- package/dist/node_modules/date-fns/getISOWeekYear.js.map +1 -0
- package/dist/node_modules/date-fns/getWeek.js +13 -0
- package/dist/node_modules/date-fns/getWeek.js.map +1 -0
- package/dist/node_modules/date-fns/getWeekYear.js +17 -0
- package/dist/node_modules/date-fns/getWeekYear.js.map +1 -0
- package/dist/node_modules/date-fns/isDate.js +8 -0
- package/dist/node_modules/date-fns/isDate.js.map +1 -0
- package/dist/node_modules/date-fns/isLastDayOfMonth.js +12 -0
- package/dist/node_modules/date-fns/isLastDayOfMonth.js.map +1 -0
- package/dist/node_modules/date-fns/isValid.js +10 -0
- package/dist/node_modules/date-fns/isValid.js.map +1 -0
- package/dist/node_modules/date-fns/locale/_lib/buildFormatLongFn.js +11 -0
- package/dist/node_modules/date-fns/locale/_lib/buildFormatLongFn.js.map +1 -0
- package/dist/node_modules/date-fns/locale/_lib/buildLocalizeFn.js +19 -0
- package/dist/node_modules/date-fns/locale/_lib/buildLocalizeFn.js.map +1 -0
- package/dist/node_modules/date-fns/locale/_lib/buildMatchFn.js +24 -0
- package/dist/node_modules/date-fns/locale/_lib/buildMatchFn.js.map +1 -0
- package/dist/node_modules/date-fns/locale/_lib/buildMatchPatternFn.js +20 -0
- package/dist/node_modules/date-fns/locale/_lib/buildMatchPatternFn.js.map +1 -0
- package/dist/node_modules/date-fns/locale/en-US/_lib/formatDistance.js +71 -0
- package/dist/node_modules/date-fns/locale/en-US/_lib/formatDistance.js.map +1 -0
- package/dist/node_modules/date-fns/locale/en-US/_lib/formatLong.js +34 -0
- package/dist/node_modules/date-fns/locale/en-US/_lib/formatLong.js.map +1 -0
- package/dist/node_modules/date-fns/locale/en-US/_lib/formatRelative.js +13 -0
- package/dist/node_modules/date-fns/locale/en-US/_lib/formatRelative.js.map +1 -0
- package/dist/node_modules/date-fns/locale/en-US/_lib/localize.js +204 -0
- package/dist/node_modules/date-fns/locale/en-US/_lib/localize.js.map +1 -0
- package/dist/node_modules/date-fns/locale/en-US/_lib/match.js +126 -0
- package/dist/node_modules/date-fns/locale/en-US/_lib/match.js.map +1 -0
- package/dist/node_modules/date-fns/locale/en-US.js +22 -0
- package/dist/node_modules/date-fns/locale/en-US.js.map +1 -0
- package/dist/node_modules/date-fns/parseISO.js +119 -0
- package/dist/node_modules/date-fns/parseISO.js.map +1 -0
- package/dist/node_modules/date-fns/startOfDay.js +10 -0
- package/dist/node_modules/date-fns/startOfDay.js.map +1 -0
- package/dist/node_modules/date-fns/startOfISOWeek.js +12 -0
- package/dist/node_modules/date-fns/startOfISOWeek.js.map +1 -0
- package/dist/node_modules/date-fns/startOfISOWeekYear.js +12 -0
- package/dist/node_modules/date-fns/startOfISOWeekYear.js.map +1 -0
- package/dist/node_modules/date-fns/startOfWeek.js +11 -0
- package/dist/node_modules/date-fns/startOfWeek.js.map +1 -0
- package/dist/node_modules/date-fns/startOfWeekYear.js +13 -0
- package/dist/node_modules/date-fns/startOfWeekYear.js.map +1 -0
- package/dist/node_modules/date-fns/startOfYear.js +10 -0
- package/dist/node_modules/date-fns/startOfYear.js.map +1 -0
- package/dist/node_modules/date-fns/toDate.js +9 -0
- package/dist/node_modules/date-fns/toDate.js.map +1 -0
- package/dist/node_modules/react-hook-form/dist/index.esm.js +1210 -0
- package/dist/node_modules/react-hook-form/dist/index.esm.js.map +1 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/dist/node_modules/zod/v3/ZodError.js +82 -0
- package/dist/node_modules/zod/v3/ZodError.js.map +1 -0
- package/dist/node_modules/zod/v3/errors.js +10 -0
- package/dist/node_modules/zod/v3/errors.js.map +1 -0
- package/dist/node_modules/zod/v3/helpers/errorUtil.js +9 -0
- package/dist/node_modules/zod/v3/helpers/errorUtil.js.map +1 -0
- package/dist/node_modules/zod/v3/helpers/parseUtil.js +93 -0
- package/dist/node_modules/zod/v3/helpers/parseUtil.js.map +1 -0
- package/dist/node_modules/zod/v3/helpers/util.js +76 -0
- package/dist/node_modules/zod/v3/helpers/util.js.map +1 -0
- package/dist/node_modules/zod/v3/locales/en.js +62 -0
- package/dist/node_modules/zod/v3/locales/en.js.map +1 -0
- package/dist/node_modules/zod/v3/types.js +2459 -0
- package/dist/node_modules/zod/v3/types.js.map +1 -0
- package/dist/node_modules/zod/v4/core/core.js +35 -0
- package/dist/node_modules/zod/v4/core/core.js.map +1 -0
- package/dist/node_modules/zod/v4/core/errors.js +24 -0
- package/dist/node_modules/zod/v4/core/errors.js.map +1 -0
- package/dist/node_modules/zod/v4/core/parse.js +29 -0
- package/dist/node_modules/zod/v4/core/parse.js.map +1 -0
- package/dist/node_modules/zod/v4/core/util.js +20 -0
- package/dist/node_modules/zod/v4/core/util.js.map +1 -0
- package/package.json +111 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TenantsListPage.js","names":[],"sources":["../../../src/admin/pages/TenantsListPage.tsx"],"sourcesContent":["import { useState, useMemo, useCallback } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Plus, Search, Building2 } from 'lucide-react';\nimport { useAdmin } from '../providers/AdminProvider';\nimport { useAdminStore } from '../store/adminStore';\nimport { useAdminPermissions } from '../hooks/useAdminPermissions';\nimport {\n PageLayout,\n Button,\n Input,\n DataTable,\n Pagination,\n TenantStatusBadge,\n EmptyState,\n Avatar,\n TenantForm,\n RowActions,\n createRowActions,\n useToast,\n PermissionGuard,\n} from '../components';\nimport { joinPath } from '../utils/navigation';\nimport { formatDate, formatNumber, formatBytes } from '../utils/formatters';\nimport { mapTenantToUi } from '../utils/mappers';\nimport type { Tenant, TenantFilter } from '../types';\nimport type { CreateTenantInput, UpdateTenantInput } from '../schemas';\nimport {\n useListTenantsQuery,\n useCreateTenantMutation,\n useUpdateTenantMutation,\n useSuspendTenantMutation,\n useActivateTenantMutation,\n} from '../../generated/global-operations';\nimport type { RowAction } from '../components/RowActions';\nimport type { TenantStatus as GqlTenantStatus } from '../../generated/global-types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useFeatureFlag } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\nimport { tWithFallback } from '../utils/i18n';\nimport { emitTenantLifecycle } from '../utils/tenantEvents';\n\nconst PAGE_SIZE = 20;\n\n/**\n * Tenants list page\n */\nexport function TenantsListPage() {\n const { canViewTenants, canManageTenants, isLoading: permissionsLoading } = useAdminPermissions();\n\n const navigate = useNavigate();\n const { basePath = '' } = useAdmin();\n const { tenantFilter, updateTenantFilter, resetTenantFilter } = useAdminStore();\n const toast = useToast();\n const { t } = useI18n();\n // Page-level feature flags. Default-allow keeps prior behavior intact.\n // Both list-page entry points (the Create CTA and the row Edit action that\n // opens the local TenantForm modal) have to honor the flags — otherwise\n // turning the edit flag off would still let an admin edit via the modal\n // even though the route-level gate denies /admin/tenants/:id/edit.\n const createFlagEnabled = useFeatureFlag('admin.tenant.create', true);\n const editFlagEnabled = useFeatureFlag('admin.tenant.edit', true);\n const events = useEventBus();\n const tr = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string =>\n tWithFallback(t, key, fallback, params),\n [t]\n );\n\n const [page, setPage] = useState(1);\n\n // Form state\n const [formOpen, setFormOpen] = useState(false);\n const [editingTenant, setEditingTenant] = useState<Tenant | undefined>(undefined);\n\n // Build filter for GraphQL — only pass supported fields\n const gqlFilter = useMemo(() => {\n const f: { search?: string; status?: GqlTenantStatus } = {};\n if (tenantFilter.search) f.search = tenantFilter.search;\n const statusMap: Record<string, GqlTenantStatus> = {\n active: 'ACTIVE' as GqlTenantStatus,\n suspended: 'SUSPENDED' as GqlTenantStatus,\n deleted: 'DELETED' as GqlTenantStatus,\n };\n if (tenantFilter.status !== 'all' && statusMap[tenantFilter.status]) {\n f.status = statusMap[tenantFilter.status];\n }\n return f;\n }, [tenantFilter.search, tenantFilter.status]);\n\n const skipQueries = permissionsLoading || !canViewTenants;\n\n // Query tenants from backend\n const { data, loading, error, refetch } = useListTenantsQuery({\n variables: {\n filter: gqlFilter,\n limit: PAGE_SIZE,\n offset: (page - 1) * PAGE_SIZE,\n },\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n\n // Mutations\n const [createTenant, { loading: creating }] = useCreateTenantMutation({\n onCompleted: () => {\n void refetch();\n },\n });\n const [updateTenant, { loading: updating }] = useUpdateTenantMutation({\n onCompleted: () => {\n void refetch();\n },\n });\n const [suspendTenant] = useSuspendTenantMutation({\n onCompleted: () => {\n void refetch();\n },\n });\n const [activateTenant] = useActivateTenantMutation({\n onCompleted: () => {\n void refetch();\n },\n });\n\n const tenants: Tenant[] = useMemo(() => (data?.tenants?.items ?? []).map(mapTenantToUi), [data]);\n\n const total = data?.tenants?.total ?? 0;\n const totalPages = Math.ceil(total / PAGE_SIZE);\n\n const handleCreateTenant = useCallback(() => {\n setEditingTenant(undefined);\n setFormOpen(true);\n }, []);\n\n const handleEditTenant = useCallback((tenant: Tenant) => {\n setEditingTenant(tenant);\n setFormOpen(true);\n }, []);\n\n const handleSuspendTenant = useCallback(\n async (tenant: Tenant) => {\n try {\n await suspendTenant({ variables: { id: tenant.id } });\n emitTenantLifecycle(events, 'tenant.tenant.suspended', {\n tenantId: tenant.id,\n tenantSlug: tenant.slug,\n status: 'SUSPENDED',\n });\n toast.success(\n tr('admin.tenants.toast.suspendedTitle', 'Tenant suspended'),\n tr('admin.tenants.toast.suspendedDescription', '{{name}} has been suspended.', {\n name: tenant.name,\n })\n );\n } catch {\n toast.error(\n tr('admin.tenants.toast.errorTitle', 'Error'),\n tr('admin.tenants.toast.suspendFailed', 'Failed to suspend tenant.')\n );\n }\n },\n [suspendTenant, toast, tr, events]\n );\n\n const handleActivateTenant = useCallback(\n async (tenant: Tenant) => {\n try {\n await activateTenant({ variables: { id: tenant.id } });\n emitTenantLifecycle(events, 'tenant.tenant.activated', {\n tenantId: tenant.id,\n tenantSlug: tenant.slug,\n status: 'ACTIVE',\n });\n toast.success(\n tr('admin.tenants.toast.activatedTitle', 'Tenant activated'),\n tr('admin.tenants.toast.activatedDescription', '{{name}} has been activated.', {\n name: tenant.name,\n })\n );\n } catch {\n toast.error(\n tr('admin.tenants.toast.errorTitle', 'Error'),\n tr('admin.tenants.toast.activateFailed', 'Failed to activate tenant.')\n );\n }\n },\n [activateTenant, toast, tr, events]\n );\n\n const handleSaveTenant = useCallback(\n async (data: CreateTenantInput | UpdateTenantInput) => {\n const isEditing = 'id' in data && data.id;\n try {\n if (isEditing) {\n const updated = await updateTenant({\n variables: {\n id: (data as UpdateTenantInput).id,\n input: {\n name: data.name,\n customDomain: data.domain,\n metadata: {\n ownerEmail: data.ownerEmail,\n billingEmail: data.billingEmail,\n plan: data.plan,\n } as Record<string, unknown>,\n },\n },\n });\n const updatedId = updated.data?.updateTenant?.id ?? (data as UpdateTenantInput).id;\n // Use the slug from the persisted record. The update mutation does\n // not accept slug as input, so reading it from the form would emit\n // a value that may not match what the backend actually has.\n const persistedSlug = updated.data?.updateTenant?.slug;\n emitTenantLifecycle(events, 'tenant.tenant.updated', {\n tenantId: updatedId,\n tenantSlug: persistedSlug,\n });\n toast.success(\n tr('admin.tenants.toast.updatedTitle', 'Tenant updated'),\n tr('admin.tenants.toast.updatedDescription', '{{name}} has been updated.', {\n name: data.name ?? '',\n })\n );\n } else {\n const created = await createTenant({\n variables: {\n input: {\n name: data.name!,\n slug: data.slug!,\n customDomain: data.domain,\n metadata: {\n ownerEmail: data.ownerEmail,\n billingEmail: data.billingEmail,\n plan: data.plan,\n } as Record<string, unknown>,\n },\n },\n });\n const createdRecord = created.data?.createTenant;\n if (createdRecord?.id) {\n // Slug from the server-confirmed record so listeners never see a\n // form value the backend rejected (e.g. uniqueness collision).\n emitTenantLifecycle(events, 'tenant.tenant.created', {\n tenantId: createdRecord.id,\n tenantSlug: createdRecord.slug,\n });\n }\n toast.success(\n tr('admin.tenants.toast.createdTitle', 'Tenant created'),\n tr('admin.tenants.toast.createdDescription', '{{name}} has been created.', {\n name: data.name ?? '',\n })\n );\n }\n setFormOpen(false);\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Unknown error';\n toast.error(\n isEditing\n ? tr('admin.tenants.toast.updateFailedTitle', 'Update failed')\n : tr('admin.tenants.toast.createFailedTitle', 'Create failed'),\n msg\n );\n // Rethrow so TenantForm.onSubmit's await rejects and the modal stays\n // open with the user's input intact. Symmetric to the rethrow already\n // applied in TenantFormRoutePage.handleSave.\n throw err;\n }\n },\n [createTenant, updateTenant, toast, tr, events]\n );\n\n const handleRowClick = (tenant: Tenant) => {\n navigate(joinPath(basePath, `tenants/${tenant.id}`));\n };\n\n const getRowActions = useCallback(\n (tenant: Tenant): RowAction[] => {\n const actions = createRowActions({\n onView: () => navigate(joinPath(basePath, `tenants/${tenant.id}`)),\n onEdit: canManageTenants && editFlagEnabled ? () => handleEditTenant(tenant) : undefined,\n });\n if (canManageTenants) {\n actions.push({\n key: tenant.status === 'active' ? 'suspend' : 'activate',\n label:\n tenant.status === 'active'\n ? tr('admin.tenants.actions.suspend', 'Suspend')\n : tr('admin.tenants.actions.activate', 'Activate'),\n separator: true,\n onClick:\n tenant.status === 'active'\n ? () => handleSuspendTenant(tenant)\n : () => handleActivateTenant(tenant),\n });\n }\n return actions;\n },\n [\n navigate,\n basePath,\n canManageTenants,\n editFlagEnabled,\n handleEditTenant,\n handleSuspendTenant,\n handleActivateTenant,\n tr,\n ]\n );\n\n const columns = [\n {\n key: 'name',\n header: tr('admin.tenants.table.tenant', 'Tenant'),\n sortable: true,\n render: (tenant: Tenant) => (\n <div className=\"flex items-center gap-3\">\n <Avatar fallback={tenant.name.slice(0, 2).toUpperCase()} size=\"sm\" />\n <div className=\"min-w-0\">\n <div className=\"truncate font-medium text-foreground\">{tenant.name}</div>\n <div className=\"truncate text-xs text-muted-foreground\">{tenant.slug}</div>\n </div>\n </div>\n ),\n },\n {\n key: 'status',\n header: tr('admin.tenants.table.status', 'Status'),\n width: '120px',\n render: (tenant: Tenant) => <TenantStatusBadge status={tenant.status} />,\n },\n {\n key: 'plan',\n header: tr('admin.tenants.table.plan', 'Plan'),\n width: '100px',\n },\n {\n key: 'userCount',\n header: tr('admin.tenants.table.users', 'Users'),\n width: '80px',\n align: 'right' as const,\n sortable: true,\n render: (tenant: Tenant) => formatNumber(tenant.userCount),\n },\n {\n key: 'storageUsed',\n header: tr('admin.tenants.table.storage', 'Storage'),\n width: '100px',\n align: 'right' as const,\n render: (tenant: Tenant) => formatBytes(tenant.storageUsed),\n },\n {\n key: 'createdAt',\n header: tr('admin.tenants.table.created', 'Created'),\n width: '120px',\n sortable: true,\n render: (tenant: Tenant) => formatDate(tenant.createdAt),\n },\n {\n key: 'actions',\n header: '',\n width: '50px',\n align: 'right' as const,\n render: (tenant: Tenant) => (\n <RowActions\n actions={getRowActions(tenant)}\n ariaLabel={tr('admin.tenants.table.actionsFor', 'Actions for {{name}}', {\n name: tenant.name,\n })}\n />\n ),\n },\n ];\n\n return (\n <PermissionGuard\n allowed={canViewTenants}\n isLoading={permissionsLoading}\n pageTitle={tr('admin.tenants.title', 'Tenants')}\n denyMessage={tr('admin.tenants.denyMessage', \"You don't have permission to view tenants.\")}\n >\n <PageLayout\n title={tr('admin.tenants.title', 'Tenants')}\n description={\n total\n ? tr(\n 'admin.tenants.descriptionWithTotal',\n 'Manage all tenants on the platform · {{total}} total',\n { total }\n )\n : tr('admin.tenants.description', 'Manage all tenants on the platform')\n }\n actions={\n canManageTenants && createFlagEnabled ? (\n <Button onClick={handleCreateTenant} disabled={creating || updating}>\n <Plus className=\"mr-2 h-4 w-4\" />\n {tr('admin.tenants.actions.createTenant', 'Create Tenant')}\n </Button>\n ) : undefined\n }\n >\n <div className=\"space-y-4\">\n {/* Filters */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"relative max-w-sm flex-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n placeholder={tr('admin.tenants.searchPlaceholder', 'Search tenants...')}\n value={tenantFilter.search}\n onChange={(e) => {\n setPage(1);\n updateTenantFilter({ search: e.target.value });\n }}\n className=\"pl-9\"\n />\n </div>\n <div className=\"flex items-center gap-2\">\n <select\n value={tenantFilter.status}\n onChange={(e) => {\n setPage(1);\n updateTenantFilter({ status: e.target.value as TenantFilter['status'] });\n }}\n className=\"h-10 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\"\n >\n <option value=\"all\">{tr('admin.tenants.filters.status.all', 'All Status')}</option>\n <option value=\"active\">\n {tr('admin.tenants.filters.status.active', 'Active')}\n </option>\n <option value=\"suspended\">\n {tr('admin.tenants.filters.status.suspended', 'Suspended')}\n </option>\n <option value=\"deleted\">\n {tr('admin.tenants.filters.status.deleted', 'Deleted')}\n </option>\n </select>\n {(tenantFilter.search || tenantFilter.status !== 'all') && (\n <Button\n variant=\"ghost\"\n onClick={() => {\n setPage(1);\n resetTenantFilter();\n }}\n >\n {tr('admin.tenants.filters.clear', 'Clear')}\n </Button>\n )}\n </div>\n </div>\n\n {/* Error state */}\n {error && (\n <div className=\"rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive\">\n {tr('admin.tenants.error.loadFailed', 'Failed to load tenants')}: {error.message}\n </div>\n )}\n\n {/* Table */}\n <DataTable\n columns={columns}\n data={tenants}\n keyExtractor={(t) => t.id}\n onRowClick={handleRowClick}\n sortBy={tenantFilter.sortBy}\n sortOrder={tenantFilter.sortOrder}\n onSort={(column, order) =>\n updateTenantFilter({\n sortBy: column as TenantFilter['sortBy'],\n sortOrder: order,\n })\n }\n loading={loading}\n emptyState={\n <EmptyState\n icon={<Building2 className=\"h-8 w-8\" />}\n title={tr('admin.tenants.empty.title', 'No tenants found')}\n description={tr(\n 'admin.tenants.empty.description',\n 'Try adjusting your search or filters'\n )}\n action={\n <Button\n variant=\"outline\"\n onClick={() => {\n setPage(1);\n resetTenantFilter();\n }}\n >\n {tr('admin.tenants.empty.clearFilters', 'Clear filters')}\n </Button>\n }\n />\n }\n />\n\n {/* Pagination */}\n {total > PAGE_SIZE && (\n <Pagination\n page={page}\n totalPages={totalPages}\n totalItems={total}\n pageSize={PAGE_SIZE}\n onPageChange={setPage}\n />\n )}\n </div>\n\n {/* Tenant Form */}\n <TenantForm\n open={formOpen}\n onClose={() => setFormOpen(false)}\n tenant={editingTenant}\n onSave={handleSaveTenant}\n />\n </PageLayout>\n </PermissionGuard>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UsersListPage.d.ts","sourceRoot":"","sources":["../../../src/admin/pages/UsersListPage.tsx"],"names":[],"mappings":"AA8BA;;GAEG;AACH,wBAAgB,aAAa,4CAsS5B"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { useToast as e } from "../components/Toast.js";
|
|
2
|
+
import { useAdmin as t } from "../providers/AdminProvider.js";
|
|
3
|
+
import { useAdminPermissions as n } from "../hooks/useAdminPermissions.js";
|
|
4
|
+
import { Avatar as r, Button as i, EmptyState as a, Input as o } from "../components/ui.js";
|
|
5
|
+
import { PageLayout as s } from "../components/PageLayout.js";
|
|
6
|
+
import { UserStatusBadge as c } from "../components/StatusBadge.js";
|
|
7
|
+
import { formatDate as ee, formatRelativeTime as l } from "../utils/formatters.js";
|
|
8
|
+
import { DataTable as u, Pagination as d } from "../components/DataTable.js";
|
|
9
|
+
import { tWithFallback as f } from "../utils/i18n.js";
|
|
10
|
+
import { RowActions as p } from "../components/RowActions.js";
|
|
11
|
+
import { PermissionGuard as m } from "../components/PermissionGuard.js";
|
|
12
|
+
import "../components/index.js";
|
|
13
|
+
import { joinPath as h } from "../utils/navigation.js";
|
|
14
|
+
import { mapUserToUi as g } from "../utils/mappers.js";
|
|
15
|
+
import { useListUsersQuery as _, useUpdateUserMutation as v } from "../../generated/global-operations.js";
|
|
16
|
+
import { useAdminStore as y } from "../store/adminStore.js";
|
|
17
|
+
import { UserStatus as b } from "../../generated/global-types.js";
|
|
18
|
+
import { useCallback as x, useMemo as S, useState as C } from "react";
|
|
19
|
+
import { Search as w, Users as T } from "lucide-react";
|
|
20
|
+
import { useNavigate as E } from "react-router-dom";
|
|
21
|
+
import { jsx as D, jsxs as O } from "react/jsx-runtime";
|
|
22
|
+
import { useI18n as k } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
23
|
+
//#region src/admin/pages/UsersListPage.tsx
|
|
24
|
+
var A = 20;
|
|
25
|
+
function j() {
|
|
26
|
+
let { canViewUsers: j, canUpdateUsers: M, isLoading: N } = n(), P = E(), { basePath: F = "" } = t(), { userFilter: I, updateUserFilter: L } = y(), R = e(), { t: z } = k(), B = x((e, t, n) => f(z, e, t, n), [z]), [V, H] = C(1), U = S(() => {
|
|
27
|
+
let e = {};
|
|
28
|
+
I.search && (e.search = I.search);
|
|
29
|
+
let t = {
|
|
30
|
+
active: b.Active,
|
|
31
|
+
inactive: b.Inactive,
|
|
32
|
+
blocked: b.Suspended
|
|
33
|
+
};
|
|
34
|
+
return I.status !== "all" && t[I.status] && (e.status = t[I.status]), e;
|
|
35
|
+
}, [I.search, I.status]), W = N || !j, { data: G, loading: K, error: q, refetch: J } = _({
|
|
36
|
+
variables: {
|
|
37
|
+
filter: U,
|
|
38
|
+
pagination: {
|
|
39
|
+
limit: A,
|
|
40
|
+
offset: (V - 1) * A
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
fetchPolicy: "cache-and-network",
|
|
44
|
+
skip: W
|
|
45
|
+
}), [Y, { loading: X }] = v({
|
|
46
|
+
onCompleted: () => {
|
|
47
|
+
R.success(B("admin.users.toast.updatedTitle", "User updated"), B("admin.users.toast.updatedDescription", "User status has been successfully updated.")), J();
|
|
48
|
+
},
|
|
49
|
+
onError: (e) => {
|
|
50
|
+
R.error(B("admin.users.toast.updateFailedTitle", "Update failed"), e.message);
|
|
51
|
+
}
|
|
52
|
+
}), Z = x(async (e) => {
|
|
53
|
+
let t = e.status === "active" ? b.Inactive : b.Active;
|
|
54
|
+
await Y({ variables: {
|
|
55
|
+
id: e.id,
|
|
56
|
+
input: { status: t }
|
|
57
|
+
} });
|
|
58
|
+
}, [Y]), Q = S(() => (G?.users?.users ?? []).map(g), [G]), $ = G?.users?.totalCount ?? 0, te = Math.ceil($ / A), ne = x((e) => {
|
|
59
|
+
let t = [{
|
|
60
|
+
key: "view",
|
|
61
|
+
label: B("admin.users.actions.viewDetails", "View Details"),
|
|
62
|
+
onClick: () => P(h(F, `users/${e.id}`))
|
|
63
|
+
}];
|
|
64
|
+
return M && t.push({
|
|
65
|
+
key: "toggle-status",
|
|
66
|
+
label: e.status === "active" ? B("admin.users.actions.disableUser", "Disable User") : B("admin.users.actions.enableUser", "Enable User"),
|
|
67
|
+
onClick: () => Z(e)
|
|
68
|
+
}), t;
|
|
69
|
+
}, [
|
|
70
|
+
P,
|
|
71
|
+
F,
|
|
72
|
+
M,
|
|
73
|
+
Z,
|
|
74
|
+
B
|
|
75
|
+
]), re = [
|
|
76
|
+
{
|
|
77
|
+
key: "name",
|
|
78
|
+
header: B("admin.users.table.user", "User"),
|
|
79
|
+
render: (e) => /* @__PURE__ */ O("div", {
|
|
80
|
+
className: "flex items-center gap-3",
|
|
81
|
+
children: [/* @__PURE__ */ D(r, {
|
|
82
|
+
fallback: (e.firstName?.[0] ?? e.email[0]).toUpperCase(),
|
|
83
|
+
size: "sm"
|
|
84
|
+
}), /* @__PURE__ */ O("div", {
|
|
85
|
+
className: "min-w-0",
|
|
86
|
+
children: [/* @__PURE__ */ D("div", {
|
|
87
|
+
className: "truncate font-medium text-foreground",
|
|
88
|
+
children: e.name || e.email
|
|
89
|
+
}), /* @__PURE__ */ D("div", {
|
|
90
|
+
className: "truncate text-xs text-muted-foreground",
|
|
91
|
+
children: e.email
|
|
92
|
+
})]
|
|
93
|
+
})]
|
|
94
|
+
})
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
key: "status",
|
|
98
|
+
header: B("admin.users.table.status", "Status"),
|
|
99
|
+
width: "120px",
|
|
100
|
+
render: (e) => /* @__PURE__ */ D(c, { status: e.status })
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
key: "role",
|
|
104
|
+
header: B("admin.users.table.role", "Role"),
|
|
105
|
+
width: "120px"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
key: "tenantId",
|
|
109
|
+
header: B("admin.users.table.tenant", "Tenant"),
|
|
110
|
+
width: "150px",
|
|
111
|
+
render: (e) => /* @__PURE__ */ D("span", {
|
|
112
|
+
className: "text-xs text-muted-foreground",
|
|
113
|
+
children: e.tenantId || "—"
|
|
114
|
+
})
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
key: "createdAt",
|
|
118
|
+
header: B("admin.users.table.joined", "Joined"),
|
|
119
|
+
width: "120px",
|
|
120
|
+
sortable: !0,
|
|
121
|
+
render: (e) => ee(e.createdAt)
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
key: "lastLoginAt",
|
|
125
|
+
header: B("admin.users.table.lastLogin", "Last Login"),
|
|
126
|
+
width: "130px",
|
|
127
|
+
render: (e) => e.lastLoginAt ? l(e.lastLoginAt) : B("admin.users.table.never", "Never")
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
key: "actions",
|
|
131
|
+
header: "",
|
|
132
|
+
width: "50px",
|
|
133
|
+
align: "right",
|
|
134
|
+
render: (e) => /* @__PURE__ */ D(p, {
|
|
135
|
+
actions: ne(e),
|
|
136
|
+
ariaLabel: B("admin.users.table.actionsFor", "Actions for {{email}}", { email: e.email })
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
];
|
|
140
|
+
return /* @__PURE__ */ D(m, {
|
|
141
|
+
allowed: j,
|
|
142
|
+
isLoading: N,
|
|
143
|
+
pageTitle: B("admin.users.title", "Users"),
|
|
144
|
+
denyMessage: B("admin.users.denyMessage", "You don't have permission to view users."),
|
|
145
|
+
children: /* @__PURE__ */ D(s, {
|
|
146
|
+
title: B("admin.users.title", "Users"),
|
|
147
|
+
description: $ ? B("admin.users.descriptionWithTotal", "Manage all users on the platform · {{total}} total", { total: $ }) : B("admin.users.description", "Manage all users on the platform"),
|
|
148
|
+
children: /* @__PURE__ */ O("div", {
|
|
149
|
+
className: "space-y-4",
|
|
150
|
+
children: [
|
|
151
|
+
/* @__PURE__ */ O("div", {
|
|
152
|
+
className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
|
|
153
|
+
children: [/* @__PURE__ */ O("div", {
|
|
154
|
+
className: "relative max-w-sm flex-1",
|
|
155
|
+
children: [/* @__PURE__ */ D(w, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), /* @__PURE__ */ D(o, {
|
|
156
|
+
placeholder: B("admin.users.searchPlaceholder", "Search by email or name..."),
|
|
157
|
+
value: I.search,
|
|
158
|
+
onChange: (e) => {
|
|
159
|
+
H(1), L({ search: e.target.value });
|
|
160
|
+
},
|
|
161
|
+
className: "pl-9"
|
|
162
|
+
})]
|
|
163
|
+
}), /* @__PURE__ */ O("div", {
|
|
164
|
+
className: "flex items-center gap-2",
|
|
165
|
+
children: [/* @__PURE__ */ O("select", {
|
|
166
|
+
value: I.status,
|
|
167
|
+
onChange: (e) => {
|
|
168
|
+
H(1), L({ status: e.target.value });
|
|
169
|
+
},
|
|
170
|
+
className: "h-10 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
171
|
+
children: [
|
|
172
|
+
/* @__PURE__ */ D("option", {
|
|
173
|
+
value: "all",
|
|
174
|
+
children: B("admin.users.filters.status.all", "All Status")
|
|
175
|
+
}),
|
|
176
|
+
/* @__PURE__ */ D("option", {
|
|
177
|
+
value: "active",
|
|
178
|
+
children: B("admin.users.filters.status.active", "Active")
|
|
179
|
+
}),
|
|
180
|
+
/* @__PURE__ */ D("option", {
|
|
181
|
+
value: "inactive",
|
|
182
|
+
children: B("admin.users.filters.status.inactive", "Inactive")
|
|
183
|
+
}),
|
|
184
|
+
/* @__PURE__ */ D("option", {
|
|
185
|
+
value: "blocked",
|
|
186
|
+
children: B("admin.users.filters.status.suspended", "Suspended")
|
|
187
|
+
})
|
|
188
|
+
]
|
|
189
|
+
}), (I.search || I.status !== "all") && /* @__PURE__ */ D(i, {
|
|
190
|
+
variant: "ghost",
|
|
191
|
+
onClick: () => {
|
|
192
|
+
H(1), L({
|
|
193
|
+
search: "",
|
|
194
|
+
status: "all"
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
children: B("admin.users.filters.clear", "Clear")
|
|
198
|
+
})]
|
|
199
|
+
})]
|
|
200
|
+
}),
|
|
201
|
+
q && /* @__PURE__ */ O("div", {
|
|
202
|
+
className: "rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive",
|
|
203
|
+
children: [
|
|
204
|
+
B("admin.users.error.loadFailed", "Failed to load users"),
|
|
205
|
+
": ",
|
|
206
|
+
q.message
|
|
207
|
+
]
|
|
208
|
+
}),
|
|
209
|
+
/* @__PURE__ */ D(u, {
|
|
210
|
+
columns: re,
|
|
211
|
+
data: Q,
|
|
212
|
+
keyExtractor: (e) => e.id,
|
|
213
|
+
onRowClick: (e) => P(h(F, `users/${e.id}`)),
|
|
214
|
+
sortBy: I.sortBy,
|
|
215
|
+
sortOrder: I.sortOrder,
|
|
216
|
+
onSort: (e, t) => L({
|
|
217
|
+
sortBy: e,
|
|
218
|
+
sortOrder: t
|
|
219
|
+
}),
|
|
220
|
+
loading: K || X,
|
|
221
|
+
emptyState: /* @__PURE__ */ D(a, {
|
|
222
|
+
icon: /* @__PURE__ */ D(T, { className: "h-8 w-8" }),
|
|
223
|
+
title: B("admin.users.empty.title", "No users found"),
|
|
224
|
+
description: B("admin.users.empty.description", "Try adjusting your search or filters"),
|
|
225
|
+
action: /* @__PURE__ */ D(i, {
|
|
226
|
+
variant: "outline",
|
|
227
|
+
onClick: () => L({
|
|
228
|
+
search: "",
|
|
229
|
+
status: "all"
|
|
230
|
+
}),
|
|
231
|
+
children: B("admin.users.empty.clearFilters", "Clear filters")
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
}),
|
|
235
|
+
$ > A && /* @__PURE__ */ D(d, {
|
|
236
|
+
page: V,
|
|
237
|
+
totalPages: te,
|
|
238
|
+
totalItems: $,
|
|
239
|
+
pageSize: A,
|
|
240
|
+
onPageChange: H
|
|
241
|
+
})
|
|
242
|
+
]
|
|
243
|
+
})
|
|
244
|
+
})
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
//#endregion
|
|
248
|
+
export { j as UsersListPage };
|
|
249
|
+
|
|
250
|
+
//# sourceMappingURL=UsersListPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UsersListPage.js","names":[],"sources":["../../../src/admin/pages/UsersListPage.tsx"],"sourcesContent":["import { useState, useMemo, useCallback } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Search, Users as UsersIcon } from 'lucide-react';\nimport { useAdmin } from '../providers/AdminProvider';\nimport { useAdminStore } from '../store/adminStore';\nimport { useAdminPermissions } from '../hooks/useAdminPermissions';\nimport {\n PageLayout,\n Input,\n DataTable,\n Pagination,\n UserStatusBadge,\n EmptyState,\n Avatar,\n Button,\n RowActions,\n useToast,\n PermissionGuard,\n} from '../components';\nimport { joinPath } from '../utils/navigation';\nimport { formatDate, formatRelativeTime } from '../utils/formatters';\nimport { mapUserToUi } from '../utils/mappers';\nimport type { User, UserFilter } from '../types';\nimport { useListUsersQuery, useUpdateUserMutation } from '../../generated/global-operations';\nimport { UserStatus as GqlUserStatus } from '../../generated/global-types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\n\nconst PAGE_SIZE = 20;\n\n/**\n * Users list page — connected to real backend with enable/disable actions\n */\nexport function UsersListPage() {\n const { canViewUsers, canUpdateUsers, isLoading: permissionsLoading } = useAdminPermissions();\n\n const navigate = useNavigate();\n const { basePath = '' } = useAdmin();\n const { userFilter, updateUserFilter } = useAdminStore();\n const toast = useToast();\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string =>\n tWithFallback(t, key, fallback, params),\n [t]\n );\n\n const [page, setPage] = useState(1);\n\n // Build GraphQL filter\n const gqlFilter = useMemo(() => {\n const f: {\n search?: string;\n status?: GqlUserStatus;\n } = {};\n if (userFilter.search) f.search = userFilter.search;\n const statusMap: Record<string, GqlUserStatus> = {\n active: GqlUserStatus.Active,\n inactive: GqlUserStatus.Inactive,\n blocked: GqlUserStatus.Suspended,\n };\n if (userFilter.status !== 'all' && statusMap[userFilter.status]) {\n f.status = statusMap[userFilter.status];\n }\n return f;\n }, [userFilter.search, userFilter.status]);\n\n const skipQueries = permissionsLoading || !canViewUsers;\n\n const { data, loading, error, refetch } = useListUsersQuery({\n variables: {\n filter: gqlFilter,\n pagination: {\n limit: PAGE_SIZE,\n offset: (page - 1) * PAGE_SIZE,\n },\n },\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n\n const [updateUser, { loading: isUpdating }] = useUpdateUserMutation({\n onCompleted: () => {\n toast.success(\n tr('admin.users.toast.updatedTitle', 'User updated'),\n tr('admin.users.toast.updatedDescription', 'User status has been successfully updated.')\n );\n void refetch();\n },\n onError: (err) => {\n toast.error(tr('admin.users.toast.updateFailedTitle', 'Update failed'), err.message);\n },\n });\n\n const handleToggleStatus = useCallback(\n async (user: User) => {\n const newStatus = user.status === 'active' ? GqlUserStatus.Inactive : GqlUserStatus.Active;\n await updateUser({\n variables: {\n id: user.id,\n input: {\n status: newStatus,\n },\n },\n });\n },\n [updateUser]\n );\n\n const users: User[] = useMemo(() => (data?.users?.users ?? []).map(mapUserToUi), [data]);\n\n const total = data?.users?.totalCount ?? 0;\n const totalPages = Math.ceil(total / PAGE_SIZE);\n\n const getRowActions = useCallback(\n (user: User) => {\n const actions = [\n {\n key: 'view',\n label: tr('admin.users.actions.viewDetails', 'View Details'),\n onClick: () => navigate(joinPath(basePath, `users/${user.id}`)),\n },\n ];\n\n if (canUpdateUsers) {\n actions.push({\n key: 'toggle-status',\n label:\n user.status === 'active'\n ? tr('admin.users.actions.disableUser', 'Disable User')\n : tr('admin.users.actions.enableUser', 'Enable User'),\n onClick: () => handleToggleStatus(user),\n });\n }\n\n return actions;\n },\n [navigate, basePath, canUpdateUsers, handleToggleStatus, tr]\n );\n\n const columns = [\n {\n key: 'name',\n header: tr('admin.users.table.user', 'User'),\n render: (user: User) => (\n <div className=\"flex items-center gap-3\">\n <Avatar fallback={(user.firstName?.[0] ?? user.email[0]).toUpperCase()} size=\"sm\" />\n <div className=\"min-w-0\">\n <div className=\"truncate font-medium text-foreground\">{user.name || user.email}</div>\n <div className=\"truncate text-xs text-muted-foreground\">{user.email}</div>\n </div>\n </div>\n ),\n },\n {\n key: 'status',\n header: tr('admin.users.table.status', 'Status'),\n width: '120px',\n render: (user: User) => <UserStatusBadge status={user.status} />,\n },\n {\n key: 'role',\n header: tr('admin.users.table.role', 'Role'),\n width: '120px',\n },\n {\n key: 'tenantId',\n header: tr('admin.users.table.tenant', 'Tenant'),\n width: '150px',\n render: (user: User) => (\n <span className=\"text-xs text-muted-foreground\">{user.tenantId || '—'}</span>\n ),\n },\n {\n key: 'createdAt',\n header: tr('admin.users.table.joined', 'Joined'),\n width: '120px',\n sortable: true,\n render: (user: User) => formatDate(user.createdAt),\n },\n {\n key: 'lastLoginAt',\n header: tr('admin.users.table.lastLogin', 'Last Login'),\n width: '130px',\n render: (user: User) =>\n user.lastLoginAt\n ? formatRelativeTime(user.lastLoginAt)\n : tr('admin.users.table.never', 'Never'),\n },\n {\n key: 'actions',\n header: '',\n width: '50px',\n align: 'right' as const,\n render: (user: User) => (\n <RowActions\n actions={getRowActions(user)}\n ariaLabel={tr('admin.users.table.actionsFor', 'Actions for {{email}}', {\n email: user.email,\n })}\n />\n ),\n },\n ];\n\n return (\n <PermissionGuard\n allowed={canViewUsers}\n isLoading={permissionsLoading}\n pageTitle={tr('admin.users.title', 'Users')}\n denyMessage={tr('admin.users.denyMessage', \"You don't have permission to view users.\")}\n >\n <PageLayout\n title={tr('admin.users.title', 'Users')}\n description={\n total\n ? tr(\n 'admin.users.descriptionWithTotal',\n 'Manage all users on the platform · {{total}} total',\n { total }\n )\n : tr('admin.users.description', 'Manage all users on the platform')\n }\n >\n <div className=\"space-y-4\">\n {/* Filters */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"relative max-w-sm flex-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n placeholder={tr('admin.users.searchPlaceholder', 'Search by email or name...')}\n value={userFilter.search}\n onChange={(e) => {\n setPage(1);\n updateUserFilter({ search: e.target.value });\n }}\n className=\"pl-9\"\n />\n </div>\n <div className=\"flex items-center gap-2\">\n <select\n value={userFilter.status}\n onChange={(e) => {\n setPage(1);\n updateUserFilter({ status: e.target.value as UserFilter['status'] });\n }}\n className=\"h-10 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\"\n >\n <option value=\"all\">{tr('admin.users.filters.status.all', 'All Status')}</option>\n <option value=\"active\">{tr('admin.users.filters.status.active', 'Active')}</option>\n <option value=\"inactive\">\n {tr('admin.users.filters.status.inactive', 'Inactive')}\n </option>\n <option value=\"blocked\">\n {tr('admin.users.filters.status.suspended', 'Suspended')}\n </option>\n </select>\n {(userFilter.search || userFilter.status !== 'all') && (\n <Button\n variant=\"ghost\"\n onClick={() => {\n setPage(1);\n updateUserFilter({ search: '', status: 'all' });\n }}\n >\n {tr('admin.users.filters.clear', 'Clear')}\n </Button>\n )}\n </div>\n </div>\n\n {/* Error */}\n {error && (\n <div className=\"rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive\">\n {tr('admin.users.error.loadFailed', 'Failed to load users')}: {error.message}\n </div>\n )}\n\n {/* Table */}\n <DataTable\n columns={columns}\n data={users}\n keyExtractor={(u) => u.id}\n onRowClick={(u) => navigate(joinPath(basePath, `users/${u.id}`))}\n sortBy={userFilter.sortBy}\n sortOrder={userFilter.sortOrder}\n onSort={(column, order) =>\n updateUserFilter({\n sortBy: column as UserFilter['sortBy'],\n sortOrder: order,\n })\n }\n loading={loading || isUpdating}\n emptyState={\n <EmptyState\n icon={<UsersIcon className=\"h-8 w-8\" />}\n title={tr('admin.users.empty.title', 'No users found')}\n description={tr(\n 'admin.users.empty.description',\n 'Try adjusting your search or filters'\n )}\n action={\n <Button\n variant=\"outline\"\n onClick={() => updateUserFilter({ search: '', status: 'all' })}\n >\n {tr('admin.users.empty.clearFilters', 'Clear filters')}\n </Button>\n }\n />\n }\n />\n\n {/* Pagination */}\n {total > PAGE_SIZE && (\n <Pagination\n page={page}\n totalPages={totalPages}\n totalItems={total}\n pageSize={PAGE_SIZE}\n onPageChange={setPage}\n />\n )}\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WaitlistPage.d.ts","sourceRoot":"","sources":["../../../src/admin/pages/WaitlistPage.tsx"],"names":[],"mappings":"AAmFA,wBAAgB,YAAY,4CA4O3B"}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { useAdminPermissions as e } from "../hooks/useAdminPermissions.js";
|
|
2
|
+
import { Badge as t, EmptyState as n, Input as r } from "../components/ui.js";
|
|
3
|
+
import { PageLayout as i } from "../components/PageLayout.js";
|
|
4
|
+
import { formatDate as a } from "../utils/formatters.js";
|
|
5
|
+
import { DataTable as o, Pagination as s } from "../components/DataTable.js";
|
|
6
|
+
import { PermissionGuard as c } from "../components/PermissionGuard.js";
|
|
7
|
+
import "../components/index.js";
|
|
8
|
+
import { useCallback as l, useEffect as u, useMemo as d, useState as f } from "react";
|
|
9
|
+
import { Check as p, ClipboardList as m, Search as h, Trash2 as g, X as _ } from "lucide-react";
|
|
10
|
+
import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
|
|
11
|
+
import { gql as x } from "@apollo/client";
|
|
12
|
+
import { useGatewayClient as S } from "@burdenoff/fe-libs/shared/graphql";
|
|
13
|
+
//#region src/admin/pages/WaitlistPage.tsx
|
|
14
|
+
var C = 20, w = {
|
|
15
|
+
PENDING: "outline",
|
|
16
|
+
APPROVED: "default",
|
|
17
|
+
REJECTED: "destructive"
|
|
18
|
+
}, T = x`
|
|
19
|
+
query GetWaitlist($filter: WaitlistFilterInput) {
|
|
20
|
+
waitlist(filter: $filter) {
|
|
21
|
+
id
|
|
22
|
+
email
|
|
23
|
+
name
|
|
24
|
+
company
|
|
25
|
+
platformProductId
|
|
26
|
+
status
|
|
27
|
+
reason
|
|
28
|
+
rejectionReason
|
|
29
|
+
processedAt
|
|
30
|
+
processedBy
|
|
31
|
+
createdAt
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
`, E = x`
|
|
35
|
+
mutation ApproveWaitlist($input: ApproveWaitlistInput!) {
|
|
36
|
+
approveWaitlist(input: $input) {
|
|
37
|
+
id
|
|
38
|
+
status
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
`, D = x`
|
|
42
|
+
mutation RejectWaitlist($input: RejectWaitlistInput!) {
|
|
43
|
+
rejectWaitlist(input: $input) {
|
|
44
|
+
id
|
|
45
|
+
status
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
`, O = x`
|
|
49
|
+
mutation RemoveFromWaitlist($id: ID!) {
|
|
50
|
+
removeFromWaitlist(id: $id)
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
function k() {
|
|
54
|
+
let { canViewWaitlist: x, canManageWaitlist: k, isLoading: A } = e(), j = S("global"), [M, N] = f(1), [P, F] = f(""), [I, L] = f(""), [R, z] = f(null), [B, V] = f(!1), [H, U] = f(null), [W, G] = f(0), K = d(() => {
|
|
55
|
+
let e = {};
|
|
56
|
+
return I && (e.status = I), Object.keys(e).length > 0 ? e : void 0;
|
|
57
|
+
}, [I]), q = l(() => G((e) => e + 1), []);
|
|
58
|
+
u(() => {
|
|
59
|
+
A || !x || (V(!0), j.query({
|
|
60
|
+
query: T,
|
|
61
|
+
variables: { filter: K },
|
|
62
|
+
fetchPolicy: "network-only"
|
|
63
|
+
}).then((e) => {
|
|
64
|
+
let t = e.data;
|
|
65
|
+
z(t ?? null), U(null);
|
|
66
|
+
}).catch((e) => U({ message: e.message })).finally(() => V(!1)));
|
|
67
|
+
}, [
|
|
68
|
+
j,
|
|
69
|
+
K,
|
|
70
|
+
A,
|
|
71
|
+
x,
|
|
72
|
+
W
|
|
73
|
+
]);
|
|
74
|
+
let J = d(() => R?.waitlist ?? [], [R]), Y = d(() => {
|
|
75
|
+
if (!P) return J;
|
|
76
|
+
let e = P.toLowerCase();
|
|
77
|
+
return J.filter((t) => t.email.toLowerCase().includes(e) || t.name && t.name.toLowerCase().includes(e) || t.company && t.company.toLowerCase().includes(e));
|
|
78
|
+
}, [J, P]), X = Y.length, Z = Math.ceil(X / C), Q = Y.slice((M - 1) * C, M * C), $ = l(async (e) => {
|
|
79
|
+
await j.mutate({
|
|
80
|
+
mutation: E,
|
|
81
|
+
variables: { input: { id: e } }
|
|
82
|
+
}), q();
|
|
83
|
+
}, [j, q]), ee = l(async (e) => {
|
|
84
|
+
let t = window.prompt("Rejection reason (optional):");
|
|
85
|
+
await j.mutate({
|
|
86
|
+
mutation: D,
|
|
87
|
+
variables: { input: {
|
|
88
|
+
id: e,
|
|
89
|
+
reason: t
|
|
90
|
+
} }
|
|
91
|
+
}), q();
|
|
92
|
+
}, [j, q]), te = l(async (e) => {
|
|
93
|
+
window.confirm("Remove this waitlist entry?") && (await j.mutate({
|
|
94
|
+
mutation: O,
|
|
95
|
+
variables: { id: e }
|
|
96
|
+
}), q());
|
|
97
|
+
}, [j, q]), ne = [
|
|
98
|
+
{
|
|
99
|
+
key: "email",
|
|
100
|
+
header: "Email",
|
|
101
|
+
render: (e) => /* @__PURE__ */ b("div", {
|
|
102
|
+
className: "min-w-0",
|
|
103
|
+
children: [/* @__PURE__ */ y("div", {
|
|
104
|
+
className: "font-medium text-foreground",
|
|
105
|
+
children: e.email
|
|
106
|
+
}), e.name && /* @__PURE__ */ y("div", {
|
|
107
|
+
className: "text-xs text-muted-foreground",
|
|
108
|
+
children: e.name
|
|
109
|
+
})]
|
|
110
|
+
})
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
key: "company",
|
|
114
|
+
header: "Company",
|
|
115
|
+
width: "140px",
|
|
116
|
+
render: (e) => /* @__PURE__ */ y("span", {
|
|
117
|
+
className: "text-sm text-muted-foreground",
|
|
118
|
+
children: e.company || "-"
|
|
119
|
+
})
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
key: "status",
|
|
123
|
+
header: "Status",
|
|
124
|
+
width: "100px",
|
|
125
|
+
render: (e) => /* @__PURE__ */ y(t, {
|
|
126
|
+
variant: w[e.status] ?? "outline",
|
|
127
|
+
className: "text-xs capitalize",
|
|
128
|
+
children: e.status.toLowerCase()
|
|
129
|
+
})
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
key: "createdAt",
|
|
133
|
+
header: "Joined",
|
|
134
|
+
width: "110px",
|
|
135
|
+
render: (e) => a(e.createdAt)
|
|
136
|
+
},
|
|
137
|
+
...k ? [{
|
|
138
|
+
key: "actions",
|
|
139
|
+
header: "Actions",
|
|
140
|
+
width: "140px",
|
|
141
|
+
render: (e) => /* @__PURE__ */ b("div", {
|
|
142
|
+
className: "flex items-center gap-1",
|
|
143
|
+
children: [e.status === "PENDING" && /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y("button", {
|
|
144
|
+
onClick: () => $(e.id),
|
|
145
|
+
className: "rounded p-1 text-green-500 hover:bg-green-500/10",
|
|
146
|
+
title: "Approve",
|
|
147
|
+
children: /* @__PURE__ */ y(p, { className: "h-4 w-4" })
|
|
148
|
+
}), /* @__PURE__ */ y("button", {
|
|
149
|
+
onClick: () => ee(e.id),
|
|
150
|
+
className: "rounded p-1 text-red-500 hover:bg-red-500/10",
|
|
151
|
+
title: "Reject",
|
|
152
|
+
children: /* @__PURE__ */ y(_, { className: "h-4 w-4" })
|
|
153
|
+
})] }), /* @__PURE__ */ y("button", {
|
|
154
|
+
onClick: () => te(e.id),
|
|
155
|
+
className: "rounded p-1 text-muted-foreground hover:bg-muted",
|
|
156
|
+
title: "Remove",
|
|
157
|
+
children: /* @__PURE__ */ y(g, { className: "h-4 w-4" })
|
|
158
|
+
})]
|
|
159
|
+
})
|
|
160
|
+
}] : []
|
|
161
|
+
];
|
|
162
|
+
return /* @__PURE__ */ y(c, {
|
|
163
|
+
allowed: x,
|
|
164
|
+
isLoading: A,
|
|
165
|
+
pageTitle: "Waitlist",
|
|
166
|
+
denyMessage: "You don't have permission to view the waitlist.",
|
|
167
|
+
children: /* @__PURE__ */ y(i, {
|
|
168
|
+
title: "Waitlist Management",
|
|
169
|
+
description: `Product waitlist entries${X ? ` \u00b7 ${X} total` : ""}`,
|
|
170
|
+
children: /* @__PURE__ */ b("div", {
|
|
171
|
+
className: "space-y-4",
|
|
172
|
+
children: [
|
|
173
|
+
/* @__PURE__ */ b("div", {
|
|
174
|
+
className: "flex flex-wrap items-center gap-3",
|
|
175
|
+
children: [/* @__PURE__ */ b("div", {
|
|
176
|
+
className: "relative max-w-sm flex-1",
|
|
177
|
+
children: [/* @__PURE__ */ y(h, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), /* @__PURE__ */ y(r, {
|
|
178
|
+
placeholder: "Search by email, name, or company...",
|
|
179
|
+
value: P,
|
|
180
|
+
onChange: (e) => {
|
|
181
|
+
N(1), F(e.target.value);
|
|
182
|
+
},
|
|
183
|
+
className: "pl-9"
|
|
184
|
+
})]
|
|
185
|
+
}), /* @__PURE__ */ b("select", {
|
|
186
|
+
value: I,
|
|
187
|
+
onChange: (e) => {
|
|
188
|
+
N(1), L(e.target.value);
|
|
189
|
+
},
|
|
190
|
+
className: "rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
191
|
+
children: [
|
|
192
|
+
/* @__PURE__ */ y("option", {
|
|
193
|
+
value: "",
|
|
194
|
+
children: "All statuses"
|
|
195
|
+
}),
|
|
196
|
+
/* @__PURE__ */ y("option", {
|
|
197
|
+
value: "PENDING",
|
|
198
|
+
children: "Pending"
|
|
199
|
+
}),
|
|
200
|
+
/* @__PURE__ */ y("option", {
|
|
201
|
+
value: "APPROVED",
|
|
202
|
+
children: "Approved"
|
|
203
|
+
}),
|
|
204
|
+
/* @__PURE__ */ y("option", {
|
|
205
|
+
value: "REJECTED",
|
|
206
|
+
children: "Rejected"
|
|
207
|
+
})
|
|
208
|
+
]
|
|
209
|
+
})]
|
|
210
|
+
}),
|
|
211
|
+
H && /* @__PURE__ */ b("div", {
|
|
212
|
+
className: "rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive",
|
|
213
|
+
children: ["Failed to load waitlist: ", H.message]
|
|
214
|
+
}),
|
|
215
|
+
/* @__PURE__ */ y(o, {
|
|
216
|
+
columns: ne,
|
|
217
|
+
data: Q,
|
|
218
|
+
keyExtractor: (e) => e.id,
|
|
219
|
+
loading: B,
|
|
220
|
+
emptyState: /* @__PURE__ */ y(n, {
|
|
221
|
+
icon: /* @__PURE__ */ y(m, { className: "h-8 w-8" }),
|
|
222
|
+
title: "No waitlist entries",
|
|
223
|
+
description: "No entries match your current filters"
|
|
224
|
+
})
|
|
225
|
+
}),
|
|
226
|
+
X > C && /* @__PURE__ */ y(s, {
|
|
227
|
+
page: M,
|
|
228
|
+
totalPages: Z,
|
|
229
|
+
totalItems: X,
|
|
230
|
+
pageSize: C,
|
|
231
|
+
onPageChange: N
|
|
232
|
+
})
|
|
233
|
+
]
|
|
234
|
+
})
|
|
235
|
+
})
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
//#endregion
|
|
239
|
+
export { k as WaitlistPage };
|
|
240
|
+
|
|
241
|
+
//# sourceMappingURL=WaitlistPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WaitlistPage.js","names":[],"sources":["../../../src/admin/pages/WaitlistPage.tsx"],"sourcesContent":["import { useState, useMemo, useCallback, useEffect } from 'react';\nimport { ClipboardList, Search, Check, X, Trash2 } from 'lucide-react';\nimport { useAdminPermissions } from '../hooks/useAdminPermissions';\nimport {\n PageLayout,\n Input,\n DataTable,\n Pagination,\n EmptyState,\n Badge,\n PermissionGuard,\n} from '../components';\nimport { formatDate } from '../utils/formatters';\nimport { useGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\nimport { gql } from '@apollo/client';\n\nconst PAGE_SIZE = 20;\n\ntype WaitlistStatus = 'PENDING' | 'APPROVED' | 'REJECTED';\n\nconst STATUS_VARIANT: Record<WaitlistStatus, 'default' | 'secondary' | 'outline' | 'destructive'> =\n {\n PENDING: 'outline',\n APPROVED: 'default',\n REJECTED: 'destructive',\n };\n\nconst GET_WAITLIST = gql`\n query GetWaitlist($filter: WaitlistFilterInput) {\n waitlist(filter: $filter) {\n id\n email\n name\n company\n platformProductId\n status\n reason\n rejectionReason\n processedAt\n processedBy\n createdAt\n }\n }\n`;\n\nconst APPROVE_WAITLIST = gql`\n mutation ApproveWaitlist($input: ApproveWaitlistInput!) {\n approveWaitlist(input: $input) {\n id\n status\n }\n }\n`;\n\nconst REJECT_WAITLIST = gql`\n mutation RejectWaitlist($input: RejectWaitlistInput!) {\n rejectWaitlist(input: $input) {\n id\n status\n }\n }\n`;\n\nconst REMOVE_WAITLIST = gql`\n mutation RemoveFromWaitlist($id: ID!) {\n removeFromWaitlist(id: $id)\n }\n`;\n\ntype WaitlistItem = {\n id: string;\n email: string;\n name: string | null;\n company: string | null;\n platformProductId: string;\n status: WaitlistStatus;\n reason: string | null;\n rejectionReason: string | null;\n processedAt: string | null;\n processedBy: string | null;\n createdAt: string;\n};\n\nexport function WaitlistPage() {\n const {\n canViewWaitlist,\n canManageWaitlist,\n isLoading: permissionsLoading,\n } = useAdminPermissions();\n const globalClient = useGatewayClient('global');\n\n const [page, setPage] = useState(1);\n const [search, setSearch] = useState('');\n const [statusFilter, setStatusFilter] = useState<WaitlistStatus | ''>('');\n const [data, setData] = useState<{ waitlist?: WaitlistItem[] } | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<{ message: string } | null>(null);\n const [fetchCount, setFetchCount] = useState(0);\n\n const filter = useMemo(() => {\n const f: Record<string, unknown> = {};\n if (statusFilter) f.status = statusFilter;\n return Object.keys(f).length > 0 ? f : undefined;\n }, [statusFilter]);\n\n const refetch = useCallback(() => setFetchCount((c) => c + 1), []);\n\n useEffect(() => {\n if (permissionsLoading || !canViewWaitlist) return;\n setLoading(true);\n globalClient\n .query({ query: GET_WAITLIST, variables: { filter }, fetchPolicy: 'network-only' })\n .then((result) => {\n const d = result.data as { waitlist?: WaitlistItem[] } | undefined;\n setData(d ?? null);\n setError(null);\n })\n .catch((err: Error) => setError({ message: err.message }))\n .finally(() => setLoading(false));\n }, [globalClient, filter, permissionsLoading, canViewWaitlist, fetchCount]);\n\n const allEntries: WaitlistItem[] = useMemo(\n () => (data?.waitlist ?? []) as WaitlistItem[],\n [data]\n );\n\n // Client-side search filter (email, name, company)\n const filtered = useMemo(() => {\n if (!search) return allEntries;\n const q = search.toLowerCase();\n return allEntries.filter(\n (e) =>\n e.email.toLowerCase().includes(q) ||\n (e.name && e.name.toLowerCase().includes(q)) ||\n (e.company && e.company.toLowerCase().includes(q))\n );\n }, [allEntries, search]);\n\n const total = filtered.length;\n const totalPages = Math.ceil(total / PAGE_SIZE);\n const paged = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);\n\n const handleApprove = useCallback(\n async (id: string) => {\n await globalClient.mutate({ mutation: APPROVE_WAITLIST, variables: { input: { id } } });\n refetch();\n },\n [globalClient, refetch]\n );\n\n const handleReject = useCallback(\n async (id: string) => {\n const reason = window.prompt('Rejection reason (optional):');\n await globalClient.mutate({\n mutation: REJECT_WAITLIST,\n variables: { input: { id, reason } },\n });\n refetch();\n },\n [globalClient, refetch]\n );\n\n const handleRemove = useCallback(\n async (id: string) => {\n if (!window.confirm('Remove this waitlist entry?')) return;\n await globalClient.mutate({ mutation: REMOVE_WAITLIST, variables: { id } });\n refetch();\n },\n [globalClient, refetch]\n );\n\n const columns = [\n {\n key: 'email',\n header: 'Email',\n render: (e: WaitlistItem) => (\n <div className=\"min-w-0\">\n <div className=\"font-medium text-foreground\">{e.email}</div>\n {e.name && <div className=\"text-xs text-muted-foreground\">{e.name}</div>}\n </div>\n ),\n },\n {\n key: 'company',\n header: 'Company',\n width: '140px',\n render: (e: WaitlistItem) => (\n <span className=\"text-sm text-muted-foreground\">{e.company || '-'}</span>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n width: '100px',\n render: (e: WaitlistItem) => (\n <Badge variant={STATUS_VARIANT[e.status] ?? 'outline'} className=\"text-xs capitalize\">\n {e.status.toLowerCase()}\n </Badge>\n ),\n },\n {\n key: 'createdAt',\n header: 'Joined',\n width: '110px',\n render: (e: WaitlistItem) => formatDate(e.createdAt),\n },\n ...(canManageWaitlist\n ? [\n {\n key: 'actions',\n header: 'Actions',\n width: '140px',\n render: (e: WaitlistItem) => (\n <div className=\"flex items-center gap-1\">\n {e.status === 'PENDING' && (\n <>\n <button\n onClick={() => handleApprove(e.id)}\n className=\"rounded p-1 text-green-500 hover:bg-green-500/10\"\n title=\"Approve\"\n >\n <Check className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => handleReject(e.id)}\n className=\"rounded p-1 text-red-500 hover:bg-red-500/10\"\n title=\"Reject\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </>\n )}\n <button\n onClick={() => handleRemove(e.id)}\n className=\"rounded p-1 text-muted-foreground hover:bg-muted\"\n title=\"Remove\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </button>\n </div>\n ),\n },\n ]\n : []),\n ];\n\n return (\n <PermissionGuard\n allowed={canViewWaitlist}\n isLoading={permissionsLoading}\n pageTitle=\"Waitlist\"\n denyMessage=\"You don't have permission to view the waitlist.\"\n >\n <PageLayout\n title=\"Waitlist Management\"\n description={`Product waitlist entries${total ? ` \\u00b7 ${total} total` : ''}`}\n >\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"relative max-w-sm flex-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n placeholder=\"Search by email, name, or company...\"\n value={search}\n onChange={(e) => {\n setPage(1);\n setSearch(e.target.value);\n }}\n className=\"pl-9\"\n />\n </div>\n <select\n value={statusFilter}\n onChange={(e) => {\n setPage(1);\n setStatusFilter(e.target.value as WaitlistStatus | '');\n }}\n className=\"rounded-md border border-input bg-background px-3 py-2 text-sm\"\n >\n <option value=\"\">All statuses</option>\n <option value=\"PENDING\">Pending</option>\n <option value=\"APPROVED\">Approved</option>\n <option value=\"REJECTED\">Rejected</option>\n </select>\n </div>\n\n {error && (\n <div className=\"rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive\">\n Failed to load waitlist: {error.message}\n </div>\n )}\n\n <DataTable\n columns={columns}\n data={paged}\n keyExtractor={(e) => e.id}\n loading={loading}\n emptyState={\n <EmptyState\n icon={<ClipboardList className=\"h-8 w-8\" />}\n title=\"No waitlist entries\"\n description=\"No entries match your current filters\"\n />\n }\n />\n\n {total > PAGE_SIZE && (\n <Pagination\n page={page}\n totalPages={totalPages}\n totalItems={total}\n pageSize={PAGE_SIZE}\n onPageChange={setPage}\n />\n )}\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,IAAM,IAAY,IAIZ,IACJ;CACE,SAAS;CACT,UAAU;CACV,UAAU;CACX,EAEG,IAAe,CAAG;;;;;;;;;;;;;;;;GAkBlB,IAAmB,CAAG;;;;;;;GAStB,IAAkB,CAAG;;;;;;;GASrB,IAAkB,CAAG;;;;;AAoB3B,SAAgB,IAAe;CAC7B,IAAM,EACJ,oBACA,sBACA,WAAW,MACT,GAAqB,EACnB,IAAe,EAAiB,SAAS,EAEzC,CAAC,GAAM,KAAW,EAAS,EAAE,EAC7B,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAc,KAAmB,EAA8B,GAAG,EACnE,CAAC,GAAM,KAAW,EAA+C,KAAK,EACtE,CAAC,GAAS,KAAc,EAAS,GAAM,EACvC,CAAC,GAAO,KAAY,EAAqC,KAAK,EAC9D,CAAC,GAAY,KAAiB,EAAS,EAAE,EAEzC,IAAS,QAAc;EAC3B,IAAM,IAA6B,EAAE;AAErC,SADI,MAAc,EAAE,SAAS,IACtB,OAAO,KAAK,EAAE,CAAC,SAAS,IAAI,IAAI,KAAA;IACtC,CAAC,EAAa,CAAC,EAEZ,IAAU,QAAkB,GAAe,MAAM,IAAI,EAAE,EAAE,EAAE,CAAC;AAElE,SAAgB;AACV,OAAsB,CAAC,MAC3B,EAAW,GAAK,EAChB,EACG,MAAM;GAAE,OAAO;GAAc,WAAW,EAAE,WAAQ;GAAE,aAAa;GAAgB,CAAC,CAClF,MAAM,MAAW;GAChB,IAAM,IAAI,EAAO;AAEjB,GADA,EAAQ,KAAK,KAAK,EAClB,EAAS,KAAK;IACd,CACD,OAAO,MAAe,EAAS,EAAE,SAAS,EAAI,SAAS,CAAC,CAAC,CACzD,cAAc,EAAW,GAAM,CAAC;IAClC;EAAC;EAAc;EAAQ;EAAoB;EAAiB;EAAW,CAAC;CAE3E,IAAM,IAA6B,QAC1B,GAAM,YAAY,EAAE,EAC3B,CAAC,EAAK,CACP,EAGK,IAAW,QAAc;AAC7B,MAAI,CAAC,EAAQ,QAAO;EACpB,IAAM,IAAI,EAAO,aAAa;AAC9B,SAAO,EAAW,QACf,MACC,EAAE,MAAM,aAAa,CAAC,SAAS,EAAE,IAChC,EAAE,QAAQ,EAAE,KAAK,aAAa,CAAC,SAAS,EAAE,IAC1C,EAAE,WAAW,EAAE,QAAQ,aAAa,CAAC,SAAS,EAAE,CACpD;IACA,CAAC,GAAY,EAAO,CAAC,EAElB,IAAQ,EAAS,QACjB,IAAa,KAAK,KAAK,IAAQ,EAAU,EACzC,IAAQ,EAAS,OAAO,IAAO,KAAK,GAAW,IAAO,EAAU,EAEhE,IAAgB,EACpB,OAAO,MAAe;AAEpB,EADA,MAAM,EAAa,OAAO;GAAE,UAAU;GAAkB,WAAW,EAAE,OAAO,EAAE,OAAI,EAAE;GAAE,CAAC,EACvF,GAAS;IAEX,CAAC,GAAc,EAAQ,CACxB,EAEK,KAAe,EACnB,OAAO,MAAe;EACpB,IAAM,IAAS,OAAO,OAAO,+BAA+B;AAK5D,EAJA,MAAM,EAAa,OAAO;GACxB,UAAU;GACV,WAAW,EAAE,OAAO;IAAE;IAAI;IAAQ,EAAE;GACrC,CAAC,EACF,GAAS;IAEX,CAAC,GAAc,EAAQ,CACxB,EAEK,KAAe,EACnB,OAAO,MAAe;AACf,SAAO,QAAQ,8BAA8B,KAClD,MAAM,EAAa,OAAO;GAAE,UAAU;GAAiB,WAAW,EAAE,OAAI;GAAE,CAAC,EAC3E,GAAS;IAEX,CAAC,GAAc,EAAQ,CACxB,EAEK,KAAU;EACd;GACE,KAAK;GACL,QAAQ;GACR,SAAS,MACP,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAA+B,EAAE;KAAY,CAAA,EAC3D,EAAE,QAAQ,kBAAC,OAAD;KAAK,WAAU;eAAiC,EAAE;KAAW,CAAA,CACpE;;GAET;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,SAAS,MACP,kBAAC,QAAD;IAAM,WAAU;cAAiC,EAAE,WAAW;IAAW,CAAA;GAE5E;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,SAAS,MACP,kBAAC,GAAD;IAAO,SAAS,EAAe,EAAE,WAAW;IAAW,WAAU;cAC9D,EAAE,OAAO,aAAa;IACjB,CAAA;GAEX;EACD;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,SAAS,MAAoB,EAAW,EAAE,UAAU;GACrD;EACD,GAAI,IACA,CACE;GACE,KAAK;GACL,QAAQ;GACR,OAAO;GACP,SAAS,MACP,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,EAAE,WAAW,aACZ,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,UAAD;KACE,eAAe,EAAc,EAAE,GAAG;KAClC,WAAU;KACV,OAAM;eAEN,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACtB,CAAA,EACT,kBAAC,UAAD;KACE,eAAe,GAAa,EAAE,GAAG;KACjC,WAAU;KACV,OAAM;eAEN,kBAAC,GAAD,EAAG,WAAU,WAAY,CAAA;KAClB,CAAA,CACR,EAAA,CAAA,EAEL,kBAAC,UAAD;KACE,eAAe,GAAa,EAAE,GAAG;KACjC,WAAU;KACV,OAAM;eAEN,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;KACvB,CAAA,CACL;;GAET,CACF,GACD,EAAE;EACP;AAED,QACE,kBAAC,GAAD;EACE,SAAS;EACT,WAAW;EACX,WAAU;EACV,aAAY;YAEZ,kBAAC,GAAD;GACE,OAAM;GACN,aAAa,2BAA2B,IAAQ,WAAW,EAAM,UAAU;aAE3E,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,0EAA2E,CAAA,EAC7F,kBAAC,GAAD;QACE,aAAY;QACZ,OAAO;QACP,WAAW,MAAM;AAEf,SADA,EAAQ,EAAE,EACV,EAAU,EAAE,OAAO,MAAM;;QAE3B,WAAU;QACV,CAAA,CACE;UACN,kBAAC,UAAD;OACE,OAAO;OACP,WAAW,MAAM;AAEf,QADA,EAAQ,EAAE,EACV,EAAgB,EAAE,OAAO,MAA6B;;OAExD,WAAU;iBANZ;QAQE,kBAAC,UAAD;SAAQ,OAAM;mBAAG;SAAqB,CAAA;QACtC,kBAAC,UAAD;SAAQ,OAAM;mBAAU;SAAgB,CAAA;QACxC,kBAAC,UAAD;SAAQ,OAAM;mBAAW;SAAiB,CAAA;QAC1C,kBAAC,UAAD;SAAQ,OAAM;mBAAW;SAAiB,CAAA;QACnC;SACL;;KAEL,KACC,kBAAC,OAAD;MAAK,WAAU;gBAAf,CAAwG,6BAC5E,EAAM,QAC5B;;KAGR,kBAAC,GAAD;MACW;MACT,MAAM;MACN,eAAe,MAAM,EAAE;MACd;MACT,YACE,kBAAC,GAAD;OACE,MAAM,kBAAC,GAAD,EAAe,WAAU,WAAY,CAAA;OAC3C,OAAM;OACN,aAAY;OACZ,CAAA;MAEJ,CAAA;KAED,IAAQ,KACP,kBAAC,GAAD;MACQ;MACM;MACZ,YAAY;MACZ,UAAU;MACV,cAAc;MACd,CAAA;KAEA;;GACK,CAAA;EACG,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowsPage.d.ts","sourceRoot":"","sources":["../../../src/admin/pages/WorkflowsPage.tsx"],"names":[],"mappings":"AAiBA,wBAAgB,aAAa,4CAwH5B"}
|