UNPKG

aau-auth-kit-ui

Version:

Plug & play shadcn/ui components for aau-auth-kit with Next.js integration

1,249 lines (1,186 loc) 341 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client"; var _chunkCKHGUCXTcjs = require('./chunk-CKHGUCXT.cjs'); // src/components/admin/admin-page.tsx var _lucidereact = require('lucide-react'); var _react = require('react'); var React = _interopRequireWildcard(_react); var React2 = _interopRequireWildcard(_react); var React3 = _interopRequireWildcard(_react); var React5 = _interopRequireWildcard(_react); // src/hooks/use-admin-users.tsx var ERROR_MESSAGES = { fetchUsers: "Failed to load users. Please try again.", banUser: "Unable to ban user. The operation failed.", unbanUser: "Unable to unban user. The operation failed.", removeUser: "Unable to remove user. The operation failed.", setRole: "Unable to change user role. The operation failed.", revokeSessions: "Unable to revoke user sessions. The operation failed.", invalidResponse: "The server returned an invalid response.", networkError: "Network connection error. Please check your internet connection.", serverError: "The server encountered an error. Please try again later.", unauthorized: "You don't have permission to perform this action.", rateLimited: "Too many requests. Please try again in a moment.", unknown: "An unexpected error occurred. Please try again." }; function useAdminUsers(initialFilters = {}) { const { authClient, toast } = _react.useContext.call(void 0, _chunkCKHGUCXTcjs.AuthUIContext); const [users, setUsers] = _react.useState.call(void 0, []); const [totalUsers, setTotalUsers] = _react.useState.call(void 0, 0); const [isLoading, setIsLoading] = _react.useState.call(void 0, true); const [isRefetching, setIsRefetching] = _react.useState.call(void 0, false); const [isActionPending, setIsActionPending] = _react.useState.call(void 0, false); const [error, setError] = _react.useState.call(void 0, null); const [initialFetchDone, setInitialFetchDone] = _react.useState.call(void 0, false); const [filters, setFilters] = _react.useState.call(void 0, { searchQuery: "", filterRole: null, sortBy: "createdAt", sortDirection: "desc", currentPage: 1, pageSize: 10, ...initialFilters }); const totalPages = Math.ceil(totalUsers / filters.pageSize); const hasError = error !== null; const queryParams = _react.useMemo.call(void 0, () => { const params = { limit: filters.pageSize, offset: (filters.currentPage - 1) * filters.pageSize, sortBy: filters.sortBy, sortDirection: filters.sortDirection, search: "" }; if (filters.searchQuery) { params.search = filters.searchQuery; } return params; }, [filters]); const e = _react.useCallback.call(void 0, (errorMessage, errorCode, action, userId) => { const errorState = { code: errorCode, message: errorMessage, action, userId, timestamp: Date.now() }; setError(errorState); toast({ variant: "error", message: errorMessage }); return errorState; }, [toast] ); const handleError = _react.useCallback.call(void 0, (error2, action, userId) => { let errorCode = _optionalChain([error2, 'optionalAccess', _2 => _2.code]); let errorMessage = error2.message; if (errorCode && errorMessage) return e(errorMessage, errorCode, action, userId); if (error2.code) { errorCode = error2.code; } else if (error2.status) { errorCode = String(error2.status); } switch (errorCode) { case "NETWORK_ERROR": errorMessage = ERROR_MESSAGES.networkError; break; case "RATE_LIMITED": case "429": errorMessage = ERROR_MESSAGES.rateLimited; break; case "401": case "403": errorMessage = ERROR_MESSAGES.unauthorized; break; case "500": case "502": case "503": case "504": errorMessage = ERROR_MESSAGES.serverError; break; default: if (action === "fetchUsers") { errorMessage = ERROR_MESSAGES.fetchUsers; } else if (action === "banUser") { errorMessage = ERROR_MESSAGES.banUser; } else if (action === "unbanUser") { errorMessage = ERROR_MESSAGES.unbanUser; } else if (action === "removeUser") { errorMessage = ERROR_MESSAGES.removeUser; } else if (action === "setRole") { errorMessage = ERROR_MESSAGES.setRole; } else if (action === "revokeSessions") { errorMessage = ERROR_MESSAGES.revokeSessions; } } if (error2.message) { errorMessage = error2.message; } return e(errorMessage, errorCode, action, userId); }, [e] ); const clearError = _react.useCallback.call(void 0, () => { setError(null); }, []); const fetchUsers = _react.useCallback.call(void 0, async (options = {}) => { const { retryCount = 0, silentRefetch = false } = options; if (!initialFetchDone || !silentRefetch) { setIsLoading(true); } else { setIsRefetching(true); } clearError(); try { const response = await authClient.admin.listUsers({ query: queryParams }); if (!response || !response.data || !Array.isArray(response.data.users)) { throw new Error(ERROR_MESSAGES.invalidResponse); } const formattedUsers = response.data.users.map((user) => ({ id: user.id, name: user.name || "N/A", email: user.email || "No email", role: user.role || "user", verified: !!user.emailVerified, status: user.banned ? "banned" : "active", createdAt: user.createdAt ? new Date(user.createdAt).toLocaleDateString() : "Unknown" })); setUsers(formattedUsers); setTotalUsers(formattedUsers.length); setInitialFetchDone(true); } finally { setIsLoading(false); setIsRefetching(false); } }, [authClient, queryParams, handleError, clearError, initialFetchDone] ); const updateFilters = _react.useCallback.call(void 0, (newFilters, silentRefetch = false) => { setFilters((prev) => ({ ...prev, ...newFilters, currentPage: "currentPage" in newFilters ? newFilters.currentPage : 1 })); if (silentRefetch) { return { silentRefetch: true }; } return { silentRefetch: false }; }, [] ); const handleUserAction = _react.useCallback.call(void 0, async (action, userId, data) => { if (isActionPending) return { success: false }; setIsActionPending(true); clearError(); try { if (!userId) { throw new Error("Invalid user ID"); } switch (action) { case "ban": await authClient.admin.banUser( { userId }, { onSuccess() { toast({ variant: "success", message: "User banned successfully" }); }, onError(ctx) { console.log({ ctx }); handleError(_optionalChain([ctx, 'optionalAccess', _3 => _3.error]), `${action}User`, userId); } } ); break; case "unban": await authClient.admin.unbanUser( { userId }, { onSuccess() { toast({ variant: "success", message: "User unbanned successfully" }); }, onError(ctx) { console.log({ ctx }); handleError(_optionalChain([ctx, 'optionalAccess', _4 => _4.error]), `${action}User`, userId); } } ); break; case "remove": await authClient.admin.removeUser( { userId }, { onSuccess() { toast({ variant: "success", message: "User removed successfully" }); }, onError(ctx) { console.log({ ctx }); handleError(_optionalChain([ctx, 'optionalAccess', _5 => _5.error]), `${action}User`, userId); } } ); break; case "setRole": await authClient.admin.setRole( { userId, role: data.role }, { onSuccess() { toast({ variant: "success", message: "User role updated successfully" }); }, onError(ctx) { console.log({ ctx }); handleError(_optionalChain([ctx, 'optionalAccess', _6 => _6.error]), action, userId); } } ); break; case "revokeSessions": await authClient.admin.revokeUserSessions( { userId }, { onSuccess() { toast({ variant: "success", message: "User sessions revoked successfully" }); }, onError(ctx) { console.log({ ctx }); handleError(_optionalChain([ctx, 'optionalAccess', _7 => _7.error]), action, userId); } } ); break; default: throw new Error(`Unsupported action: ${action}`); } fetchUsers({ silentRefetch: true }); return { success: true }; } catch (error2) { return { success: false }; } finally { setIsActionPending(false); } }, [authClient, fetchUsers, isActionPending, toast, handleError, clearError] ); const retry = _react.useCallback.call(void 0, () => { if (!error) return; const { action, userId } = error; clearError(); if (action === "fetchUsers") { fetchUsers({ retryCount: 1 }); } else if (_optionalChain([action, 'optionalAccess', _8 => _8.endsWith, 'call', _9 => _9("User")]) && userId) { const originalAction = action.replace("User", ""); handleUserAction(originalAction, userId); } }, [error, clearError, fetchUsers, handleUserAction]); _react.useEffect.call(void 0, () => { fetchUsers({ silentRefetch: initialFetchDone }); }, [fetchUsers, initialFetchDone]); return { // Data users, totalUsers, totalPages, // State isLoading, isRefetching, // New state for tracking silent refetches isActionPending, error, hasError, // Filters filters, updateFilters, // Actions fetchUsers, handleUserAction, retry, clearError }; } // src/components/ui/card.tsx var _jsxruntime = require('react/jsx-runtime'); function Card({ className, ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "card", className: _chunkCKHGUCXTcjs.cn.call(void 0, "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", className ), ...props } ); } function CardHeader({ className, ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "card-header", className: _chunkCKHGUCXTcjs.cn.call(void 0, "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", className ), ...props } ); } function CardTitle({ className, ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "card-title", className: _chunkCKHGUCXTcjs.cn.call(void 0, "leading-none font-semibold", className), ...props } ); } function CardDescription({ className, ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "card-description", className: _chunkCKHGUCXTcjs.cn.call(void 0, "text-muted-foreground text-sm", className), ...props } ); } function CardContent({ className, ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "card-content", className: _chunkCKHGUCXTcjs.cn.call(void 0, "px-6", className), ...props } ); } function CardFooter({ className, ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "card-footer", className: _chunkCKHGUCXTcjs.cn.call(void 0, "flex items-center px-6 [.border-t]:pt-6", className), ...props } ); } // src/components/admin/create-user-dialog.tsx var _zod = require('@hookform/resolvers/zod'); var _reacthookform = require('react-hook-form'); var _zod3 = require('zod'); var z = _interopRequireWildcard(_zod3); var z2 = _interopRequireWildcard(_zod3); var z3 = _interopRequireWildcard(_zod3); var z4 = _interopRequireWildcard(_zod3); var z5 = _interopRequireWildcard(_zod3); var z6 = _interopRequireWildcard(_zod3); var z7 = _interopRequireWildcard(_zod3); var z8 = _interopRequireWildcard(_zod3); var z9 = _interopRequireWildcard(_zod3); var z10 = _interopRequireWildcard(_zod3); var z11 = _interopRequireWildcard(_zod3); var z12 = _interopRequireWildcard(_zod3); var z13 = _interopRequireWildcard(_zod3); var z14 = _interopRequireWildcard(_zod3); // src/lib/auth-localization.ts var authLocalization = { /** @default "Account" */ account: "Account", /** @default "Accounts" */ accounts: "Accounts", /** @default "Manage your currently signed in accounts." */ accountsDescription: "Switch between your currently signed in accounts.", /** @default "Sign in to an additional account." */ accountsInstructions: "Sign in to an additional account.", /** @default "Add Account" */ addAccount: "Add Account", /** @default "Add Passkey" */ addPasskey: "Add Passkey", /** @default "Already have an account?" */ alreadyHaveAnAccount: "Already have an account?", /** @default "Avatar" */ avatar: "Avatar", /** @default "Click on the avatar to upload a custom one from your files." */ avatarDescription: "Click on the avatar to upload a custom one from your files.", /** @default "An avatar is optional but strongly recommended." */ avatarInstructions: "An avatar is optional but strongly recommended.", /** @default "Backup code is required" */ backupCodeRequired: "Backup code is required", /** @default "Backup Codes" */ backupCodes: "Backup Codes", /** @default "Save these backup codes in a secure place. You can use them to access your account if you lose your two-factor authentication method." */ backupCodesDescription: "Save these backup codes in a secure place. You can use them to access your account if you lose your two-factor authentication method.", /** @default "Enter one of your backup codes. Once used, each code can only be used once and will be invalidated after use." */ backupCodePlaceholder: "Backup Code", /** @default "Backup Code" */ backupCode: "Backup Code", /** @default "Recover account" */ backupCodeAction: "Recover account", /** @default "Cancel" */ cancel: "Cancel", /** @default "Change Password" */ changePassword: "Change Password", /** @default "Enter your current password and a new password." */ changePasswordDescription: "Enter your current password and a new password.", /** @default "Please use 8 characters at minimum." */ changePasswordInstructions: "Please use 8 characters at minimum.", /** @default "Your password has been changed." */ changePasswordSuccess: "Your password has been changed.", /** @default "Confirm Password" */ confirmPassword: "Confirm Password", /** @default "Confirm Password" */ confirmPasswordPlaceholder: "Confirm Password", /** @default "Confirm password is required" */ confirmPasswordRequired: "Confirm password is required", /** @default "Continue with Authenticator" */ continueWithAuthenticator: "Continue with Authenticator", /** @default "Copied to clipboard" */ copiedToClipboard: "Copied to clipboard", /** @default "Copy all codes" */ copyAllCodes: "Copy all codes", /** @default "Continue" */ continue: "Continue", /** @default "Current Password" */ currentPassword: "Current Password", /** @default "Current Password" */ currentPasswordPlaceholder: "Current Password", /** @default "Current Session" */ currentSession: "Current Session", /** @default "Delete" */ delete: "Delete", /** @default "Delete Account" */ deleteAccount: "Delete Account", /** @default "Permanently remove your account and all of its contents. This action is not reversible, so please continue with caution." */ deleteAccountDescription: "Permanently remove your account and all of its contents. This action is not reversible, so please continue with caution.", /** @default "Please confirm the deletion of your account. This action is not reversible, so please continue with caution." */ deleteAccountInstructions: "Please confirm the deletion of your account. This action is not reversible, so please continue with caution.", /** @default "Please check your email to verify the deletion of your account." */ deleteAccountVerify: "Please check your email to verify the deletion of your account.", /** @default "Your account has been deleted." */ deleteAccountSuccess: "Your account has been deleted.", /** @default "You must be recently logged in to delete your account." */ deleteAccountNotFresh: "You must be recently logged in to delete your account.", /** @default "Disable" */ disable: "Disable", /** @default "Choose a provider to login to your account" */ disabledCredentialsDescription: "Choose a provider to login to your account", /** @default "Don't have an account?" */ dontHaveAnAccount: "Don't have an account?", /** @default "Email" */ email: "Email", /** @default "Enter the email address you want to use to log in." */ emailDescription: "Enter the email address you want to use to log in.", /** @default "Please enter a valid email address." */ emailInstructions: "Please enter a valid email address.", /** @default "Email address is invalid" */ emailInvalid: "Email address is invalid", /** @default "Phone" */ phone: "Phone", /** @default "Phone Number" */ phoneNumber: "Phone Number", /** @default "Enter your phone number" */ phonePlaceholder: "+1 (555) 123-4567", /** @default "Please enter a valid phone number" */ phoneInvalid: "Please enter a valid phone number", /** @default "We'll send you a verification code" */ phoneDescription: "We'll send you a verification code", /** @default "Verification code sent successfully" */ otpSent: "Verification code sent successfully", /** @default "Phone number verified successfully" */ phoneVerified: "Phone number verified successfully", /** @default "Verify" */ verifyPhoneNumber: "Verify", /** @default "Enter the verification code sent to" */ enterVerificationCode: "Enter the 6-digit code sent to", /** @default "Verification Code" */ verificationCode: "Verification Code", /** @default "Resend Code" */ resendCode: "Resend Code", /** @default "One Time Password" */ oneTimePassword: "One Time Password", /** @default "Email is the same" */ emailIsTheSame: "Email is the same", /** @default "m@example.com" */ emailPlaceholder: "m@example.com", /** @default "Email address is required" */ emailRequired: "Email address is required", /** @default "Please check your email to verify the change." */ emailVerifyChange: "Please check your email to verify the change.", /** @default "Please check your email for the verification link." */ emailVerification: "Please check your email for the verification link.", /** @default "Enable" */ enable: "Enable", /** @default "Error" */ error: "Error", /** @default "is invalid" */ isInvalid: "is invalid", /** @default "is required" */ isRequired: "is required", /** @default "is the same" */ isTheSame: "is the same", /** @default "Forgot authenticator?" */ forgotAuthenticator: "Forgot authenticator?", /** @default "Forgot Password" */ forgotPassword: "Forgot Password", /** @default "Send reset link" */ forgotPasswordAction: "Send reset link", /** @default "Enter your email to reset your password" */ forgotPasswordDescription: "Enter your email to reset your password", /** @default "Check your email for the password reset link." */ forgotPasswordEmail: "Check your email for the password reset link.", /** @default "Forgot your password?" */ forgotPasswordLink: "Forgot your password?", /** @default "Invalid two factor cookie" */ invalidTwoFactorCookie: "Invalid two factor cookie", /** @default "Link" */ link: "Link", /** @default "Magic Link" */ magicLink: "Magic Link", /** @default "Send magic link" */ magicLinkAction: "Send magic link", /** @default "Enter your email to receive a magic link" */ magicLinkDescription: "Enter your email to receive a magic link", /** @default "Check your email for the magic link" */ magicLinkEmail: "Check your email for the magic link", /** @default "Email Code" */ emailOTP: "Email Code", /** @default "Send code" */ emailOTPSendAction: "Send code", /** @default "Verify code" */ emailOTPVerifyAction: "Verify code", /** @default "Enter your email to receive a code" */ emailOTPDescription: "Enter your email to receive a code", /** @default "Please check your email for the verification code." */ emailOTPVerificationSent: "Please check your email for the verification code.", /** @default "Name" */ name: "Name", /** @default "Please enter your full name, or a display name." */ nameDescription: "Please enter your full name, or a display name.", /** @default "Please use 32 characters at maximum." */ nameInstructions: "Please use 32 characters at maximum.", /** @default "Name" */ namePlaceholder: "Name", /** @default "New Password" */ newPassword: "New Password", /** @default "New Password" */ newPasswordPlaceholder: "New Password", /** @default "New password is required" */ newPasswordRequired: "New password is required", /** @default "Or continue with" */ orContinueWith: "Or continue with", /** @default "Passkey" */ passkey: "Passkey", /** @default "Passkeys" */ passkeys: "Passkeys", /** @default "Manage your passkeys for secure access." */ passkeysDescription: "Manage your passkeys for secure access.", /** @default "Securely access your account without a password." */ passkeysInstructions: "Securely access your account without a password.", /** @default "Password" */ password: "Password", /** @default "Password" */ passwordPlaceholder: "Password", /** @default "Password is required" */ passwordRequired: "Password is required", /** @default "Passwords do not match" */ passwordsDoNotMatch: "Passwords do not match", /** @default "Providers" */ providers: "Providers", /** @default "Connect your account with a third-party service." */ providersDescription: "Connect your account with a third-party service.", /** @default "Recover Account" */ recoverAccount: "Recover Account", /** @default "Recover account" */ recoverAccountAction: "Recover account", /** @default "Please enter a backup code to access your account" */ recoverAccountDescription: "Please enter a backup code to access your account", /** @default "Remember me" */ rememberMe: "Remember me", /** @default "Resend verification email" */ resendVerificationEmail: "Resend Verification Email", /** @default "Reset Password" */ resetPassword: "Reset Password", /** @default "Save new password" */ resetPasswordAction: "Save new password", /** @default "Enter your new password below" */ resetPasswordDescription: "Enter your new password below", /** @default "Invalid reset password link" */ resetPasswordInvalidToken: "Invalid reset password link", /** @default "Password reset successfully" */ resetPasswordSuccess: "Password reset successfully", /** @default "Request failed" */ requestFailed: "Request failed", /** @default "Revoke" */ revoke: "Revoke", /** @default "Sign In" */ signIn: "Sign In", /** @default "Sign In" */ signInPhone: "Sign In", /** @default "Login" */ signInAction: "Login", /** @default "Enter your email below to login to your account" */ signInDescription: "Enter your email below to login to your account", /** @default "Enter your username or email below to login to your account" */ signInUsernameDescription: "Enter your username or email to login to your account", /** @default "Sign in with" */ signInWith: "Sign in with", /** @default "Sign Out" */ signOut: "Sign Out", /** @default "Sign Up" */ signUp: "Sign Up", /** @default "Create an account" */ signUpAction: "Create an account", /** @default "Enter your information to create an account" */ signUpDescription: "Enter your information to create an account", /** @default "Check your email for the verification link." */ signUpEmail: "Check your email for the verification link.", /** @default "Sessions" */ sessions: "Sessions", /** @default "Manage your active sessions and revoke access." */ sessionsDescription: "Manage your active sessions and revoke access.", /** @default "Set Password" */ setPassword: "Set Password", /** @default "Click the button below to receive an email to set up a password for your account." */ setPasswordDescription: "Click the button below to receive an email to set up a password for your account.", /** @default "Settings" */ settings: "Settings", /** @default "Save" */ save: "Save", /** @default "Security" */ security: "Security", /** @default "Switch Account" */ switchAccount: "Switch Account", /** @default "Trust this device" */ trustDevice: "Trust this device", /** @default "Two-Factor" */ twoFactor: "Two-Factor", /** @default "Verify code" */ twoFactorAction: "Verify code", /** @default "Please enter your one-time password to continue" */ twoFactorDescription: "Please enter your one-time password to continue", /** @default "Add an extra layer of security to your account." */ twoFactorCardDescription: "Add an extra layer of security to your account.", /** @default "Please enter your password to disable 2FA." */ twoFactorDisableInstructions: "Please enter your password to disable 2FA.", /** @default "Please enter your password to enable 2FA" */ twoFactorEnableInstructions: "Please enter your password to enable 2FA.", /** @default "Two-factor authentication has been enabled" */ twoFactorEnabled: "Two-factor authentication has been enabled", /** @default "Two-Factor Authentication has been disabled" */ twoFactorDisabled: "Two-Factor Authentication has been disabled", /** @default "Two-Factor Authentication" */ twoFactorPrompt: "Two-Factor Authentication", /** @default "Scan the QR Code with your Authenticator" */ twoFactorTotpLabel: "Scan the QR Code with your Authenticator", /** @default "Send verification code" */ sendVerificationCode: "Send verification code", /** @default "Unlink" */ unlink: "Unlink", /** @default "Updated successfully" */ updatedSuccessfully: "updated successfully", /** @default "Username" */ username: "Username", /** @default "Enter the username you want to use to log in." */ usernameDescription: "Enter the username you want to use to log in.", /** @default "Please use 32 characters at maximum." */ usernameInstructions: "Please use 32 characters at maximum.", /** @default "Username" */ usernamePlaceholder: "Username", /** @default "Username or email" */ signInUsernamePlaceholder: "Username or email", /** @default "Verify Your Email" */ verifyYourEmail: "Verify Your Email", /** @default "Please verify your email address. Check your inbox for the verification email. If you haven't received the email, click the button below to resend." */ verifyYourEmailDescription: "Please verify your email address. Check your inbox for the verification email. If you haven't received the email, click the button below to resend.", /** @default "Go back" */ goBack: "Go back", /** @default "Invalid password" */ invalidPassword: "Invalid password", /** @default "Password too short" */ passwordTooShort: "Password too short", // Admin-related messages /** @default "Admin" */ admin: "Admin", /** @default "Users" */ users: "Users", /** @default "Create User" */ createUser: "Create User", /** @default "Creating..." */ creatingUser: "Creating...", /** @default "User created successfully" */ userCreatedSuccess: "User created successfully", /** @default "Failed to create user" */ userCreatedError: "Failed to create user. Please try again.", // Keep the existing nameRequired property as it's used elsewhere /** @default "Name is required for admin user" */ adminNameRequired: "Name is required", /** @default "Email is required for admin user" */ adminEmailRequired: "Email is required", /** @default "Invalid email address for admin user" */ adminEmailInvalid: "Invalid email address", /** @default "Password must be at least 8 characters" */ passwordMinLength: "Password must be at least 8 characters", /** @default "Role is required" */ adminRoleRequired: "Role is required", /** @default "User banned successfully" */ userBannedSuccess: "User has been banned successfully", /** @default "Failed to ban user" */ userBannedError: "Failed to ban user. Please try again.", /** @default "User unbanned successfully" */ userUnbannedSuccess: "User has been unbanned successfully", /** @default "Failed to unban user" */ userUnbannedError: "Failed to unban user. Please try again.", /** @default "User removed successfully" */ userRemovedSuccess: "User has been removed successfully", /** @default "Failed to remove user" */ userRemovedError: "Failed to remove user. Please try again.", /** @default "Failed to fetch users" */ fetchUsersError: "Failed to fetch users. Please try again." }; // src/components/admin/create-user-dialog.tsx function CreateUserDialog({ open, onOpenChange, onUserCreated, classNames }) { const { authClient, toast: renderToast, phoneNumber: phoneNumberEnabled } = _react.useContext.call(void 0, _chunkCKHGUCXTcjs.AuthUIContext); const localization = { ...authLocalization }; const schemaFields = { name: z.string().min(1, { message: authLocalization.adminNameRequired }), email: z.string().min(1, { message: authLocalization.adminEmailRequired }).email({ message: authLocalization.adminEmailInvalid }), password: z.string().min(8, { message: authLocalization.passwordMinLength }) }; if (phoneNumberEnabled) { schemaFields.phoneNumber = z.string().min(1, { message: `${localization.phoneNumber} ${localization.isRequired}` }).regex(/^\+?[1-9]\d{1,14}$/, { message: localization.phoneInvalid || "Please enter a valid phone number" }); } const formSchema = z.object(schemaFields); const form = _reacthookform.useForm.call(void 0, { resolver: _zod.zodResolver.call(void 0, formSchema), defaultValues: { name: "", email: "", password: "", role: "user" } }); const isSubmitting = form.formState.isSubmitting; _react.useEffect.call(void 0, () => { if (!open) { form.reset(); } }, [open, form]); async function createUser(values) { try { const roleValue = values.role; await authClient.admin.createUser( { name: values.name, email: values.email, password: values.password, role: roleValue, ...values.phoneNumber !== void 0 && { data: { phoneNumber: values.phoneNumber } } }, { onSuccess() { renderToast({ variant: "success", message: authLocalization.userCreatedSuccess }); form.reset(); onOpenChange(false); onUserCreated(); }, onError() { renderToast({ variant: "error", message: authLocalization.userCreatedError }); form.resetField("password"); } } ); } catch (error) { console.error("Failed to create user:", error); renderToast({ variant: "error", message: authLocalization.userCreatedError }); form.resetField("password"); } } return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Dialog, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkCKHGUCXTcjs.DialogContent, { className: "sm:max-w-[425px]", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkCKHGUCXTcjs.DialogHeader, { children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.DialogTitle, { children: authLocalization.createUser }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.DialogDescription, { children: "Fill in the details to create a new user account." }) ] }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Form, { ...form, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit: form.handleSubmit(createUser), className: "space-y-4 py-4", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormField, { control: form.control, name: "name", render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkCKHGUCXTcjs.FormItem, { children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormLabel, { children: "Name" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormControl, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Input, { placeholder: "John Doe", disabled: isSubmitting, ...field } ) }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormMessage, {}) ] }) } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormField, { control: form.control, name: "email", render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkCKHGUCXTcjs.FormItem, { children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormLabel, { children: "Email" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormControl, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Input, { type: "email", placeholder: "john@example.com", disabled: isSubmitting, ...field } ) }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormMessage, {}) ] }) } ), phoneNumberEnabled && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormField, { control: form.control, name: "phoneNumber", render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkCKHGUCXTcjs.FormItem, { children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormLabel, { className: _optionalChain([classNames, 'optionalAccess', _10 => _10.label]), children: localization.phoneNumber }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormControl, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Input, { className: _optionalChain([classNames, 'optionalAccess', _11 => _11.input]), type: "tel", placeholder: localization.phonePlaceholder, disabled: isSubmitting, ...field } ) }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm text-muted-foreground", children: localization.phoneDescription }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormMessage, { className: _optionalChain([classNames, 'optionalAccess', _12 => _12.error]) }) ] }) } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormField, { control: form.control, name: "password", render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkCKHGUCXTcjs.FormItem, { children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormLabel, { children: "Password" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormControl, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Input, { type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", disabled: isSubmitting, ...field } ) }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormMessage, {}) ] }) } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormField, { control: form.control, name: "role", render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkCKHGUCXTcjs.FormItem, { children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormLabel, { children: "Role" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormControl, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Input, { placeholder: "user", disabled: isSubmitting, ...field } ) }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.FormMessage, {}), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-xs text-muted-foreground", children: 'Default is "user".' }) ] }) } ) ] }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkCKHGUCXTcjs.DialogFooter, { children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), disabled: isSubmitting, children: "Cancel" } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), authLocalization.creatingUser ] }) : authLocalization.createUser }) ] }) ] } ) }) ] }) }); } // src/components/admin/pagination.tsx function Pagination({ currentPage, totalPages, totalItems, pageSize, isLoading, isActionPending, className, onPageChange }) { if (totalPages <= 1) return null; const startIndex = (currentPage - 1) * pageSize + 1; const endIndex = Math.min(currentPage * pageSize, totalItems); return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkCKHGUCXTcjs.cn.call(void 0, "flex justify-between items-center mt-4", className), children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [ "Showing ", startIndex, " to ", endIndex, " of ", totalItems, " users" ] }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-2", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Button, { variant: "outline", size: "sm", onClick: () => onPageChange(currentPage - 1), disabled: currentPage === 1 || isLoading || isActionPending, children: "Previous" } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCKHGUCXTcjs.Button, { variant: "outline", size: "sm", onClick: () => onPageChange(currentPage + 1), disabled: currentPage === totalPages || isLoading || isActionPending, children: "Next" } ) ] }) ] }); } // src/components/ui/skeleton.tsx function Skeleton({ className, ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "skeleton", className: _chunkCKHGUCXTcjs.cn.call(void 0, "bg-accent animate-pulse rounded-md", className), ...props } ); } // src/components/ui/table.tsx var Table = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "table", { ref, className: _chunkCKHGUCXTcjs.cn.call(void 0, "w-full caption-bottom text-sm", className), ...props } ) })); Table.displayName = "Table"; var TableHeader = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "thead", { ref, className: _chunkCKHGUCXTcjs.cn.call(void 0, "[&_tr]:border-b", className), ...props })); TableHeader.displayName = "TableHeader"; var TableBody = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { ref, className: _chunkCKHGUCXTcjs.cn.call(void 0, "[&_tr:last-child]:border-0", className), ...props } )); TableBody.displayName = "TableBody"; var TableFooter = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tfoot", { ref, className: _chunkCKHGUCXTcjs.cn.call(void 0, "bg-primary font-medium text-primary-foreground", className), ...props } )); TableFooter.displayName = "TableFooter"; var TableRow = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", { ref, className: _chunkCKHGUCXTcjs.cn.call(void 0, "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className ), ...props } )); TableRow.displayName = "TableRow"; var TableHead = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { ref, className: _chunkCKHGUCXTcjs.cn.call(void 0, "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", className ), ...props } )); TableHead.displayName = "TableHead"; var TableCell = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { ref, className: _chunkCKHGUCXTcjs.cn.call(void 0, "p-4 align-middle [&:has([role=checkbox])]:pr-0", className), ...props } )); TableCell.displayName = "TableCell"; var TableCaption = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "caption", { ref, className: _chunkCKHGUCXTcjs.cn.call(void 0, "mt-4 text-sm text-muted-foreground", className), ...props } )); TableCaption.displayName = "TableCaption"; // src/components/admin/user-action-menu.tsx // src/components/ui/dropdown-menu.tsx var _reactdropdownmenu = require('@radix-ui/react-dropdown-menu'); var DropdownMenuPrimitive = _interopRequireWildcard(_reactdropdownmenu); function DropdownMenu({ ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props }); } function DropdownMenuTrigger({ ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props } ); } function DropdownMenuContent({ className, sideOffset = 4, ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.Content, { "data-slot": "dropdown-menu-content", sideOffset, className: _chunkCKHGUCXTcjs.cn.call(void 0, "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", className ), ...props } ) }); } function DropdownMenuItem({ className, inset, variant = "default", ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.Item, { "data-slot": "dropdown-menu-item", "data-inset": inset, "data-variant": variant, className: _chunkCKHGUCXTcjs.cn.call(void 0, "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className ), ...props } ); } function DropdownMenuSeparator({ className, ...props }) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.Separator, { "data-slot": "dropdown-menu-separator", className: _chunkCKHGUCXTcjs.cn.call(void 0, "bg-border -mx-1 my-1 h-px", className), ...props } ); } // src/components/admin/user-action-menu.tsx function UserActionMenu({ userId, status, role, disabled, onUserAction }) { const [showMenu, setShowMenu] = _react.useState.call(void 0, false); const [showRemoveDialog, setShowRemoveDialog] = _react.useState.call(void 0, false); const [showRoleDialog, setShowRoleDialog] = _react.useState.call(void 0, false); const [showRevokeDialog, setShowRevokeDialog] = _react.useState.call(void 0, false); const [newRole, setNewRole] = _react.useState.call(void 0, Array.isArray(role) ? role.join(", ") : role ); const [isRoleActionPending, setIsRoleActionPending] = _react.useState.call(void 0, false); const [isRevokeActionPending, setIsRevokeActionPending] = _react.useState.call(void 0, false); const [isRemoveActionPending, setIsRemoveActionPending] = _react.useState.call(void 0, false); const handleRoleChange = async () => { if (!newRole.trim()) { return; } setIsRoleActionPending(