@udhuong/admin-core 0.1.0 → 0.1.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/dist/client/auth/AuthContext.d.ts +19 -0
- package/dist/client/auth/AuthContext.d.ts.map +1 -0
- package/dist/client/auth/AuthContext.js +115 -0
- package/dist/client/auth/AuthContext.js.map +1 -0
- package/dist/client/auth/PermissionGuard.d.ts +12 -0
- package/dist/client/auth/PermissionGuard.d.ts.map +1 -0
- package/dist/client/auth/PermissionGuard.js +23 -0
- package/dist/client/auth/PermissionGuard.js.map +1 -0
- package/dist/client/auth/ProtectedPage.d.ts +9 -0
- package/dist/client/auth/ProtectedPage.d.ts.map +1 -0
- package/dist/client/auth/ProtectedPage.js +57 -0
- package/dist/client/auth/ProtectedPage.js.map +1 -0
- package/dist/client/auth/ProtectedRoute.d.ts +4 -0
- package/dist/client/auth/ProtectedRoute.d.ts.map +1 -0
- package/dist/client/auth/ProtectedRoute.js +25 -0
- package/dist/client/auth/ProtectedRoute.js.map +1 -0
- package/dist/client/auth/api-client.d.ts +4 -0
- package/dist/client/auth/api-client.d.ts.map +1 -0
- package/dist/client/auth/api-client.js +83 -0
- package/dist/client/auth/api-client.js.map +1 -0
- package/dist/client/auth/auth.service.d.ts +7 -0
- package/dist/client/auth/auth.service.d.ts.map +1 -0
- package/dist/client/auth/auth.service.js +19 -0
- package/dist/client/auth/auth.service.js.map +1 -0
- package/dist/client/auth/index.d.ts +7 -0
- package/dist/client/auth/index.d.ts.map +1 -0
- package/dist/client/auth/index.js +7 -0
- package/dist/client/auth/index.js.map +1 -0
- package/dist/client/components/PageHeader.d.ts +19 -0
- package/dist/client/components/PageHeader.d.ts.map +1 -0
- package/dist/client/components/PageHeader.js +7 -0
- package/dist/client/components/PageHeader.js.map +1 -0
- package/dist/client/components/Providers.d.ts +9 -0
- package/dist/client/components/Providers.d.ts.map +1 -0
- package/dist/client/components/Providers.js +52 -0
- package/dist/client/components/Providers.js.map +1 -0
- package/dist/client/components/ThemeToggle.d.ts +6 -0
- package/dist/client/components/ThemeToggle.d.ts.map +1 -0
- package/dist/client/components/ThemeToggle.js +22 -0
- package/dist/client/components/ThemeToggle.js.map +1 -0
- package/dist/client/components/index.d.ts +4 -0
- package/dist/client/components/index.d.ts.map +1 -0
- package/dist/client/components/index.js +4 -0
- package/dist/client/components/index.js.map +1 -0
- package/dist/client/config/AdminConfigContext.d.ts +12 -0
- package/dist/client/config/AdminConfigContext.d.ts.map +1 -0
- package/dist/client/config/AdminConfigContext.js +29 -0
- package/dist/client/config/AdminConfigContext.js.map +1 -0
- package/dist/client/config/defaults.d.ts +4 -0
- package/dist/client/config/defaults.d.ts.map +1 -0
- package/dist/client/config/defaults.js +86 -0
- package/dist/client/config/defaults.js.map +1 -0
- package/dist/client/config/types.d.ts +61 -0
- package/dist/client/config/types.d.ts.map +1 -0
- package/dist/client/config/types.js +2 -0
- package/dist/client/config/types.js.map +1 -0
- package/dist/client/constants/api-routes.d.ts +104 -0
- package/dist/client/constants/api-routes.d.ts.map +1 -0
- package/dist/client/constants/api-routes.js +91 -0
- package/dist/client/constants/api-routes.js.map +1 -0
- package/dist/client/constants/permissions.d.ts +38 -0
- package/dist/client/constants/permissions.d.ts.map +1 -0
- package/dist/client/constants/permissions.js +37 -0
- package/dist/client/constants/permissions.js.map +1 -0
- package/dist/client/contexts/ThemeContext.d.ts +3 -0
- package/dist/client/contexts/ThemeContext.d.ts.map +1 -0
- package/dist/client/contexts/ThemeContext.js +8 -0
- package/dist/client/contexts/ThemeContext.js.map +1 -0
- package/dist/client/hooks/useToast.d.ts +14 -0
- package/dist/client/hooks/useToast.d.ts.map +1 -0
- package/dist/client/hooks/useToast.js +90 -0
- package/dist/client/hooks/useToast.js.map +1 -0
- package/dist/client/index.d.ts +25 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +33 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/layouts/AdminLayout.d.ts +4 -0
- package/dist/client/layouts/AdminLayout.d.ts.map +1 -0
- package/dist/client/layouts/AdminLayout.js +72 -0
- package/dist/client/layouts/AdminLayout.js.map +1 -0
- package/dist/client/layouts/Sidebar.d.ts +6 -0
- package/dist/client/layouts/Sidebar.d.ts.map +1 -0
- package/dist/client/layouts/Sidebar.js +86 -0
- package/dist/client/layouts/Sidebar.js.map +1 -0
- package/dist/client/layouts/index.d.ts +3 -0
- package/dist/client/layouts/index.d.ts.map +1 -0
- package/dist/client/layouts/index.js +3 -0
- package/dist/client/layouts/index.js.map +1 -0
- package/dist/client/lib/utils.d.ts +5 -0
- package/dist/client/lib/utils.d.ts.map +1 -0
- package/dist/client/lib/utils.js +22 -0
- package/dist/client/lib/utils.js.map +1 -0
- package/dist/client/pages/ChangePasswordPage.d.ts +2 -0
- package/dist/client/pages/ChangePasswordPage.d.ts.map +1 -0
- package/dist/client/pages/ChangePasswordPage.js +58 -0
- package/dist/client/pages/ChangePasswordPage.js.map +1 -0
- package/dist/client/pages/ForgotPasswordPage.d.ts +2 -0
- package/dist/client/pages/ForgotPasswordPage.d.ts.map +1 -0
- package/dist/client/pages/ForgotPasswordPage.js +30 -0
- package/dist/client/pages/ForgotPasswordPage.js.map +1 -0
- package/dist/client/pages/LoginPage.d.ts +2 -0
- package/dist/client/pages/LoginPage.d.ts.map +1 -0
- package/dist/client/pages/LoginPage.js +52 -0
- package/dist/client/pages/LoginPage.js.map +1 -0
- package/dist/client/pages/PermissionsPage.d.ts +2 -0
- package/dist/client/pages/PermissionsPage.d.ts.map +1 -0
- package/dist/client/pages/PermissionsPage.js +42 -0
- package/dist/client/pages/PermissionsPage.js.map +1 -0
- package/dist/client/pages/ProfilePage.d.ts +2 -0
- package/dist/client/pages/ProfilePage.d.ts.map +1 -0
- package/dist/client/pages/ProfilePage.js +107 -0
- package/dist/client/pages/ProfilePage.js.map +1 -0
- package/dist/client/pages/ResetPasswordPage.d.ts +2 -0
- package/dist/client/pages/ResetPasswordPage.d.ts.map +1 -0
- package/dist/client/pages/ResetPasswordPage.js +68 -0
- package/dist/client/pages/ResetPasswordPage.js.map +1 -0
- package/dist/client/pages/RolesPage.d.ts +2 -0
- package/dist/client/pages/RolesPage.d.ts.map +1 -0
- package/dist/client/pages/RolesPage.js +82 -0
- package/dist/client/pages/RolesPage.js.map +1 -0
- package/dist/client/pages/UnauthorizedPage.d.ts +2 -0
- package/dist/client/pages/UnauthorizedPage.d.ts.map +1 -0
- package/dist/client/pages/UnauthorizedPage.js +9 -0
- package/dist/client/pages/UnauthorizedPage.js.map +1 -0
- package/dist/client/pages/UserDetailPage.d.ts +6 -0
- package/dist/client/pages/UserDetailPage.d.ts.map +1 -0
- package/dist/client/pages/UserDetailPage.js +220 -0
- package/dist/client/pages/UserDetailPage.js.map +1 -0
- package/dist/client/pages/UserPreferencesPage.d.ts +2 -0
- package/dist/client/pages/UserPreferencesPage.d.ts.map +1 -0
- package/dist/client/pages/UserPreferencesPage.js +152 -0
- package/dist/client/pages/UserPreferencesPage.js.map +1 -0
- package/dist/client/pages/UsersPage.d.ts +2 -0
- package/dist/client/pages/UsersPage.d.ts.map +1 -0
- package/dist/client/pages/UsersPage.js +228 -0
- package/dist/client/pages/UsersPage.js.map +1 -0
- package/dist/client/pages/VerifyEmailPage.d.ts +2 -0
- package/dist/client/pages/VerifyEmailPage.d.ts.map +1 -0
- package/dist/client/pages/VerifyEmailPage.js +43 -0
- package/dist/client/pages/VerifyEmailPage.js.map +1 -0
- package/dist/client/pages/index.d.ts +13 -0
- package/dist/client/pages/index.d.ts.map +1 -0
- package/dist/client/pages/index.js +13 -0
- package/dist/client/pages/index.js.map +1 -0
- package/dist/client/pages/roles/RoleModal.d.ts +10 -0
- package/dist/client/pages/roles/RoleModal.d.ts.map +1 -0
- package/dist/client/pages/roles/RoleModal.js +123 -0
- package/dist/client/pages/roles/RoleModal.js.map +1 -0
- package/dist/client/pages/users/DangerZone.d.ts +10 -0
- package/dist/client/pages/users/DangerZone.d.ts.map +1 -0
- package/dist/client/pages/users/DangerZone.js +8 -0
- package/dist/client/pages/users/DangerZone.js.map +1 -0
- package/dist/client/pages/users/ProfileCard.d.ts +14 -0
- package/dist/client/pages/users/ProfileCard.d.ts.map +1 -0
- package/dist/client/pages/users/ProfileCard.js +8 -0
- package/dist/client/pages/users/ProfileCard.js.map +1 -0
- package/dist/client/pages/users/SecuritySection.d.ts +14 -0
- package/dist/client/pages/users/SecuritySection.d.ts.map +1 -0
- package/dist/client/pages/users/SecuritySection.js +16 -0
- package/dist/client/pages/users/SecuritySection.js.map +1 -0
- package/dist/client/pages/users/SessionsSection.d.ts +25 -0
- package/dist/client/pages/users/SessionsSection.d.ts.map +1 -0
- package/dist/client/pages/users/SessionsSection.js +93 -0
- package/dist/client/pages/users/SessionsSection.js.map +1 -0
- package/dist/client/pages/users/SocialAccountsSection.d.ts +29 -0
- package/dist/client/pages/users/SocialAccountsSection.d.ts.map +1 -0
- package/dist/client/pages/users/SocialAccountsSection.js +72 -0
- package/dist/client/pages/users/SocialAccountsSection.js.map +1 -0
- package/dist/client/pages/users/UserDetailModal.d.ts +24 -0
- package/dist/client/pages/users/UserDetailModal.d.ts.map +1 -0
- package/dist/client/pages/users/UserDetailModal.js +42 -0
- package/dist/client/pages/users/UserDetailModal.js.map +1 -0
- package/dist/client/pages/users/UserFilters.d.ts +14 -0
- package/dist/client/pages/users/UserFilters.d.ts.map +1 -0
- package/dist/client/pages/users/UserFilters.js +22 -0
- package/dist/client/pages/users/UserFilters.js.map +1 -0
- package/dist/client/pages/users/UserStats.d.ts +9 -0
- package/dist/client/pages/users/UserStats.d.ts.map +1 -0
- package/dist/client/pages/users/UserStats.js +37 -0
- package/dist/client/pages/users/UserStats.js.map +1 -0
- package/dist/client/pages/users/UserTable.d.ts +24 -0
- package/dist/client/pages/users/UserTable.d.ts.map +1 -0
- package/dist/client/pages/users/UserTable.js +39 -0
- package/dist/client/pages/users/UserTable.js.map +1 -0
- package/dist/client/pages/users/VerificationSection.d.ts +9 -0
- package/dist/client/pages/users/VerificationSection.d.ts.map +1 -0
- package/dist/client/pages/users/VerificationSection.js +8 -0
- package/dist/client/pages/users/VerificationSection.js.map +1 -0
- package/dist/client/types/auth.d.ts +29 -0
- package/dist/client/types/auth.d.ts.map +1 -0
- package/dist/client/types/auth.js +2 -0
- package/dist/client/types/auth.js.map +1 -0
- package/dist/client/types/rbac.d.ts +39 -0
- package/dist/client/types/rbac.d.ts.map +1 -0
- package/dist/client/types/rbac.js +5 -0
- package/dist/client/types/rbac.js.map +1 -0
- package/dist/client/types/status.d.ts +12 -0
- package/dist/client/types/status.d.ts.map +1 -0
- package/dist/client/types/status.js +14 -0
- package/dist/client/types/status.js.map +1 -0
- package/dist/client/ui/Badge.d.ts +14 -0
- package/dist/client/ui/Badge.d.ts.map +1 -0
- package/dist/client/ui/Badge.js +32 -0
- package/dist/client/ui/Badge.js.map +1 -0
- package/dist/client/ui/Button.d.ts +18 -0
- package/dist/client/ui/Button.d.ts.map +1 -0
- package/dist/client/ui/Button.js +33 -0
- package/dist/client/ui/Button.js.map +1 -0
- package/dist/client/ui/Checkbox.d.ts +14 -0
- package/dist/client/ui/Checkbox.d.ts.map +1 -0
- package/dist/client/ui/Checkbox.js +35 -0
- package/dist/client/ui/Checkbox.js.map +1 -0
- package/dist/client/ui/ConfirmModal.d.ts +14 -0
- package/dist/client/ui/ConfirmModal.d.ts.map +1 -0
- package/dist/client/ui/ConfirmModal.js +43 -0
- package/dist/client/ui/ConfirmModal.js.map +1 -0
- package/dist/client/ui/DataTable.d.ts +69 -0
- package/dist/client/ui/DataTable.d.ts.map +1 -0
- package/dist/client/ui/DataTable.js +133 -0
- package/dist/client/ui/DataTable.js.map +1 -0
- package/dist/client/ui/Dropdown.d.ts +11 -0
- package/dist/client/ui/Dropdown.d.ts.map +1 -0
- package/dist/client/ui/Dropdown.js +65 -0
- package/dist/client/ui/Dropdown.js.map +1 -0
- package/dist/client/ui/FileInput.d.ts +16 -0
- package/dist/client/ui/FileInput.d.ts.map +1 -0
- package/dist/client/ui/FileInput.js +45 -0
- package/dist/client/ui/FileInput.js.map +1 -0
- package/dist/client/ui/Input.d.ts +16 -0
- package/dist/client/ui/Input.d.ts.map +1 -0
- package/dist/client/ui/Input.js +33 -0
- package/dist/client/ui/Input.js.map +1 -0
- package/dist/client/ui/LoadingSpinner.d.ts +7 -0
- package/dist/client/ui/LoadingSpinner.d.ts.map +1 -0
- package/dist/client/ui/LoadingSpinner.js +12 -0
- package/dist/client/ui/LoadingSpinner.js.map +1 -0
- package/dist/client/ui/Modal.d.ts +14 -0
- package/dist/client/ui/Modal.d.ts.map +1 -0
- package/dist/client/ui/Modal.js +46 -0
- package/dist/client/ui/Modal.js.map +1 -0
- package/dist/client/ui/Pagination.d.ts +14 -0
- package/dist/client/ui/Pagination.d.ts.map +1 -0
- package/dist/client/ui/Pagination.js +50 -0
- package/dist/client/ui/Pagination.js.map +1 -0
- package/dist/client/ui/Radio.d.ts +34 -0
- package/dist/client/ui/Radio.d.ts.map +1 -0
- package/dist/client/ui/Radio.js +44 -0
- package/dist/client/ui/Radio.js.map +1 -0
- package/dist/client/ui/Range.d.ts +17 -0
- package/dist/client/ui/Range.d.ts.map +1 -0
- package/dist/client/ui/Range.js +28 -0
- package/dist/client/ui/Range.js.map +1 -0
- package/dist/client/ui/Rating.d.ts +18 -0
- package/dist/client/ui/Rating.d.ts.map +1 -0
- package/dist/client/ui/Rating.js +64 -0
- package/dist/client/ui/Rating.js.map +1 -0
- package/dist/client/ui/Select.d.ts +20 -0
- package/dist/client/ui/Select.d.ts.map +1 -0
- package/dist/client/ui/Select.js +30 -0
- package/dist/client/ui/Select.js.map +1 -0
- package/dist/client/ui/Textarea.d.ts +14 -0
- package/dist/client/ui/Textarea.d.ts.map +1 -0
- package/dist/client/ui/Textarea.js +20 -0
- package/dist/client/ui/Textarea.js.map +1 -0
- package/dist/client/ui/Toggle.d.ts +13 -0
- package/dist/client/ui/Toggle.d.ts.map +1 -0
- package/dist/client/ui/Toggle.js +29 -0
- package/dist/client/ui/Toggle.js.map +1 -0
- package/dist/client/ui/index.d.ts +31 -0
- package/dist/client/ui/index.d.ts.map +1 -0
- package/dist/client/ui/index.js +35 -0
- package/dist/client/ui/index.js.map +1 -0
- package/dist/tailwind.preset.d.ts +10 -0
- package/dist/tailwind.preset.js +12 -0
- package/package.json +46 -17
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface SecuritySectionProps {
|
|
2
|
+
isEditing: boolean;
|
|
3
|
+
passwordMethod: 'SET_PASSWORD' | 'SEND_LINK';
|
|
4
|
+
onPasswordMethodChange: (method: 'SET_PASSWORD' | 'SEND_LINK') => void;
|
|
5
|
+
newPassword: string;
|
|
6
|
+
onNewPasswordChange: (value: string) => void;
|
|
7
|
+
onResetPassword: () => void;
|
|
8
|
+
onGeneratePassword: () => void;
|
|
9
|
+
twoFactorEnabled?: boolean;
|
|
10
|
+
onDisable2FA: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare const SecuritySection: ({ isEditing, passwordMethod, onPasswordMethodChange, newPassword, onNewPasswordChange, onResetPassword, onGeneratePassword, twoFactorEnabled, onDisable2FA, }: SecuritySectionProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=SecuritySection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecuritySection.d.ts","sourceRoot":"","sources":["../../../../src/client/pages/users/SecuritySection.tsx"],"names":[],"mappings":"AAKA,UAAU,oBAAoB;IAC5B,SAAS,EAAE,OAAO,CAAA;IAClB,cAAc,EAAE,cAAc,GAAG,WAAW,CAAA;IAC5C,sBAAsB,EAAE,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,KAAK,IAAI,CAAA;IACtE,WAAW,EAAE,MAAM,CAAA;IACnB,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5C,eAAe,EAAE,MAAM,IAAI,CAAA;IAC3B,kBAAkB,EAAE,MAAM,IAAI,CAAA;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB;AAED,eAAO,MAAM,eAAe,GAAI,+JAU7B,oBAAoB,4CA4JtB,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Key, Eye, EyeOff, RefreshCw, Lock, Unlock, Shield } from 'lucide-react';
|
|
5
|
+
export const SecuritySection = ({ isEditing, passwordMethod, onPasswordMethodChange, newPassword, onNewPasswordChange, onResetPassword, onGeneratePassword, twoFactorEnabled, onDisable2FA, }) => {
|
|
6
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
7
|
+
// Use the passed password prop for both edit and create modes
|
|
8
|
+
const currentPassword = newPassword;
|
|
9
|
+
// const handlePasswordChange = isEditing ? onNewPasswordChange : setLocalPassword
|
|
10
|
+
return (_jsxs("div", { className: "bg-white rounded-2xl border border-gray-200 overflow-hidden", children: [_jsx("div", { className: "p-6 border-b border-gray-100 bg-gray-50/50", children: _jsxs("h3", { className: "font-semibold text-gray-900 flex items-center gap-2", children: [_jsx(Shield, { className: "w-5 h-5 text-gray-500" }), "B\u1EA3o m\u1EADt & \u0110\u0103ng nh\u1EADp"] }) }), _jsxs("div", { className: "p-6 space-y-6", children: [isEditing ? (
|
|
11
|
+
/* Edit Mode: Reset Password Options */
|
|
12
|
+
_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex gap-6", children: [_jsxs("label", { className: "flex items-center gap-2.5 cursor-pointer group", children: [_jsx("div", { className: `w-5 h-5 rounded-full border flex items-center justify-center transition-all ${passwordMethod === 'SET_PASSWORD' ? 'border-primary' : 'border-gray-300 group-hover:border-primary/50'}`, children: passwordMethod === 'SET_PASSWORD' && _jsx("div", { className: "w-2.5 h-2.5 rounded-full bg-primary" }) }), _jsx("input", { type: "radio", checked: passwordMethod === 'SET_PASSWORD', onChange: () => onPasswordMethodChange('SET_PASSWORD'), className: "hidden" }), _jsx("span", { className: "font-medium text-gray-700", children: "\u0110\u1EB7t m\u1EADt kh\u1EA9u m\u1EDBi" })] }), _jsxs("label", { className: "flex items-center gap-2.5 cursor-pointer group", children: [_jsx("div", { className: `w-5 h-5 rounded-full border flex items-center justify-center transition-all ${passwordMethod === 'SEND_LINK' ? 'border-primary' : 'border-gray-300 group-hover:border-primary/50'}`, children: passwordMethod === 'SEND_LINK' && _jsx("div", { className: "w-2.5 h-2.5 rounded-full bg-primary" }) }), _jsx("input", { type: "radio", checked: passwordMethod === 'SEND_LINK', onChange: () => onPasswordMethodChange('SEND_LINK'), className: "hidden" }), _jsx("span", { className: "font-medium text-gray-700", children: "G\u1EEDi link qua email" })] })] }), passwordMethod === 'SET_PASSWORD' && (_jsxs("div", { className: "flex gap-2", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(Key, { className: "absolute left-3.5 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" }), _jsx("input", { type: "text", value: newPassword, onChange: (e) => onNewPasswordChange(e.target.value), placeholder: "Nh\u1EADp m\u1EADt kh\u1EA9u m\u1EDBi...", className: "w-full pl-10 pr-4 py-2.5 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all" })] }), _jsx("button", { type: "button", onClick: onResetPassword, disabled: !newPassword, className: "px-5 py-2.5 bg-primary text-white rounded-xl hover:bg-primary/90 font-medium disabled:opacity-50 disabled:cursor-not-allowed", children: "L\u01B0u" })] })), passwordMethod === 'SEND_LINK' && (_jsx("button", { type: "button", onClick: onResetPassword, className: "w-full sm:w-auto px-6 py-2.5 bg-primary text-white rounded-xl hover:bg-primary/90 font-medium", children: "G\u1EEDi link reset password ngay" })), _jsx("div", { className: "pt-4 border-t border-gray-50", children: _jsxs("button", { type: "button", onClick: onGeneratePassword, className: "text-sm font-medium text-primary hover:text-primary/80 flex items-center gap-1.5 transition-colors", children: [_jsx(RefreshCw, { className: "w-3.5 h-3.5" }), "T\u1EA1o m\u1EADt kh\u1EA9u ng\u1EABu nhi\u00EAn an to\u00E0n"] }) })] })) : (
|
|
13
|
+
/* Create Mode: Initial Password */
|
|
14
|
+
_jsxs("div", { children: [_jsx("label", { className: "block text-xs font-medium text-gray-500 mb-1.5 uppercase", children: "M\u1EADt kh\u1EA9u kh\u1EDFi t\u1EA1o" }), _jsxs("div", { className: "flex gap-2", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(Key, { className: "absolute left-3.5 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" }), _jsx("input", { type: showPassword ? 'text' : 'password', required: true, value: currentPassword, onChange: (e) => onNewPasswordChange(e.target.value), className: "w-full pl-10 pr-10 py-2.5 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all", placeholder: "M\u1EADt kh\u1EA9u \u00EDt nh\u1EA5t 6 k\u00FD t\u1EF1" }), _jsx("button", { type: "button", onClick: () => setShowPassword(!showPassword), className: "absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600", children: showPassword ? _jsx(EyeOff, { className: "w-4 h-4" }) : _jsx(Eye, { className: "w-4 h-4" }) })] }), _jsxs("button", { type: "button", onClick: onGeneratePassword, className: "px-4 py-2.5 bg-gray-50 text-gray-700 border border-gray-200 rounded-xl hover:bg-gray-100 font-medium flex items-center gap-2", children: [_jsx(RefreshCw, { className: "w-4 h-4" }), _jsx("span", { className: "hidden sm:inline", children: "Random" })] })] })] })), isEditing && twoFactorEnabled !== undefined && (_jsx("div", { className: "pt-6 border-t border-gray-100", children: _jsxs("div", { className: "flex items-center justify-between p-4 bg-gray-50 rounded-xl border border-gray-100", children: [_jsxs("div", { children: [_jsxs("h4", { className: "font-medium text-gray-900 flex items-center gap-2", children: [twoFactorEnabled ? _jsx(Lock, { className: "w-4 h-4 text-purple-600" }) : _jsx(Unlock, { className: "w-4 h-4 text-gray-400" }), "X\u00E1c th\u1EF1c 2 b\u01B0\u1EDBc (2FA)"] }), _jsx("p", { className: "text-sm text-gray-500 mt-0.5", children: twoFactorEnabled ? 'Người dùng đang bật bảo mật 2 lớp.' : 'Người dùng chưa kích hoạt bảo mật 2 lớp.' })] }), twoFactorEnabled && (_jsx("button", { type: "button", onClick: onDisable2FA, className: "px-4 py-2 bg-white border border-gray-200 text-red-600 rounded-lg hover:bg-red-50 hover:border-red-100 text-sm font-medium transition-colors", children: "T\u1EAFt 2FA" }))] }) }))] })] }));
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=SecuritySection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecuritySection.js","sourceRoot":"","sources":["../../../../src/client/pages/users/SecuritySection.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface UserSession {
|
|
2
|
+
id: number;
|
|
3
|
+
userId: number;
|
|
4
|
+
sessionToken: string;
|
|
5
|
+
deviceName: string;
|
|
6
|
+
deviceFingerprint?: string;
|
|
7
|
+
ipAddress: string;
|
|
8
|
+
userAgent?: string;
|
|
9
|
+
clientId?: number;
|
|
10
|
+
isCurrent: boolean;
|
|
11
|
+
expiresAt: string;
|
|
12
|
+
lastActiveAt?: string;
|
|
13
|
+
revokedAt?: string;
|
|
14
|
+
revokedReason?: string;
|
|
15
|
+
createdAt: string;
|
|
16
|
+
updatedAt: string;
|
|
17
|
+
}
|
|
18
|
+
interface SessionsSectionProps {
|
|
19
|
+
userId: string;
|
|
20
|
+
sessions: UserSession[];
|
|
21
|
+
onRefresh: () => void;
|
|
22
|
+
}
|
|
23
|
+
export declare function SessionsSection({ userId, sessions, onRefresh }: SessionsSectionProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=SessionsSection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionsSection.d.ts","sourceRoot":"","sources":["../../../../src/client/pages/users/SessionsSection.tsx"],"names":[],"mappings":"AAQA,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,UAAU,oBAAoB;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,SAAS,EAAE,MAAM,IAAI,CAAA;CACtB;AAED,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,oBAAoB,2CA4KpF"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Smartphone, Monitor, Globe, Clock, Shield, Trash2 } from 'lucide-react';
|
|
5
|
+
import toast from 'react-hot-toast';
|
|
6
|
+
import { getApiClient } from '../../auth/api-client';
|
|
7
|
+
import { CORE_API_ROUTES } from '../../constants/api-routes';
|
|
8
|
+
export function SessionsSection({ userId, sessions, onRefresh }) {
|
|
9
|
+
const apiClient = getApiClient();
|
|
10
|
+
const [revoking, setRevoking] = useState(null);
|
|
11
|
+
const [revokingAll, setRevokingAll] = useState(false);
|
|
12
|
+
const handleRevokeSession = async (sessionId) => {
|
|
13
|
+
if (!confirm('Bạn có chắc chắn muốn thu hồi session này?'))
|
|
14
|
+
return;
|
|
15
|
+
setRevoking(sessionId);
|
|
16
|
+
try {
|
|
17
|
+
await apiClient.delete(CORE_API_ROUTES.ADMIN_USERS.REVOKE_SESSION(userId, sessionId));
|
|
18
|
+
toast.success('Đã thu hồi session');
|
|
19
|
+
onRefresh();
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
toast.error(error.response?.data?.message || 'Không thể thu hồi session');
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
setRevoking(null);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const handleRevokeAllSessions = async () => {
|
|
29
|
+
if (!confirm('Bạn có chắc chắn muốn thu hồi TẤT CẢ các session của user này?'))
|
|
30
|
+
return;
|
|
31
|
+
setRevokingAll(true);
|
|
32
|
+
try {
|
|
33
|
+
const response = await apiClient.post(CORE_API_ROUTES.ADMIN_USERS.REVOKE_ALL_SESSIONS(userId));
|
|
34
|
+
toast.success(response.data?.message || 'Đã thu hồi tất cả sessions');
|
|
35
|
+
onRefresh();
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
toast.error(error.response?.data?.message || 'Không thể thu hồi sessions');
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
setRevokingAll(false);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const getDeviceIcon = (deviceName, userAgent) => {
|
|
45
|
+
const ua = (userAgent || deviceName || '').toLowerCase();
|
|
46
|
+
if (ua.includes('mobile') || ua.includes('android') || ua.includes('iphone')) {
|
|
47
|
+
return _jsx(Smartphone, { className: "w-5 h-5" });
|
|
48
|
+
}
|
|
49
|
+
return _jsx(Monitor, { className: "w-5 h-5" });
|
|
50
|
+
};
|
|
51
|
+
const getBrowserInfo = (userAgent) => {
|
|
52
|
+
if (!userAgent)
|
|
53
|
+
return 'Unknown Browser';
|
|
54
|
+
const ua = userAgent.toLowerCase();
|
|
55
|
+
if (ua.includes('chrome'))
|
|
56
|
+
return 'Chrome';
|
|
57
|
+
if (ua.includes('firefox'))
|
|
58
|
+
return 'Firefox';
|
|
59
|
+
if (ua.includes('safari'))
|
|
60
|
+
return 'Safari';
|
|
61
|
+
if (ua.includes('edge'))
|
|
62
|
+
return 'Edge';
|
|
63
|
+
return 'Unknown Browser';
|
|
64
|
+
};
|
|
65
|
+
const formatDate = (date) => {
|
|
66
|
+
return new Date(date).toLocaleString('vi-VN', {
|
|
67
|
+
year: 'numeric',
|
|
68
|
+
month: '2-digit',
|
|
69
|
+
day: '2-digit',
|
|
70
|
+
hour: '2-digit',
|
|
71
|
+
minute: '2-digit',
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
const formatRelativeTime = (date) => {
|
|
75
|
+
const now = new Date();
|
|
76
|
+
const then = new Date(date);
|
|
77
|
+
const diffMs = now.getTime() - then.getTime();
|
|
78
|
+
const diffMins = Math.floor(diffMs / 60000);
|
|
79
|
+
const diffHours = Math.floor(diffMins / 60);
|
|
80
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
81
|
+
if (diffMins < 1)
|
|
82
|
+
return 'Vừa xong';
|
|
83
|
+
if (diffMins < 60)
|
|
84
|
+
return `${diffMins} phút trước`;
|
|
85
|
+
if (diffHours < 24)
|
|
86
|
+
return `${diffHours} giờ trước`;
|
|
87
|
+
if (diffDays < 7)
|
|
88
|
+
return `${diffDays} ngày trước`;
|
|
89
|
+
return formatDate(date);
|
|
90
|
+
};
|
|
91
|
+
return (_jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-gray-200", children: [_jsx("div", { className: "p-6 border-b border-gray-200", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center", children: _jsx(Shield, { className: "w-5 h-5 text-blue-600" }) }), _jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "Phi\u00EAn \u0111\u0103ng nh\u1EADp" }), _jsxs("p", { className: "text-sm text-gray-500", children: [sessions.length, " phi\u00EAn \u0111ang ho\u1EA1t \u0111\u1ED9ng"] })] })] }), sessions.length > 0 && (_jsx("button", { onClick: handleRevokeAllSessions, disabled: revokingAll, className: "px-4 py-2 text-sm font-medium text-red-600 hover:bg-red-50 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed", children: revokingAll ? 'Đang thu hồi...' : 'Thu hồi tất cả' }))] }) }), _jsx("div", { className: "divide-y divide-gray-200", children: sessions.length === 0 ? (_jsxs("div", { className: "p-12 text-center", children: [_jsx(Shield, { className: "w-12 h-12 text-gray-300 mx-auto mb-3" }), _jsx("p", { className: "text-gray-500", children: "Kh\u00F4ng c\u00F3 phi\u00EAn \u0111\u0103ng nh\u1EADp n\u00E0o" })] })) : (sessions.map((session) => (_jsx("div", { className: "p-6 hover:bg-gray-50 transition-colors", children: _jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "flex items-start gap-4 flex-1", children: [_jsx("div", { className: "w-12 h-12 bg-gray-100 rounded-lg flex items-center justify-center flex-shrink-0", children: getDeviceIcon(session.deviceName, session.userAgent) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2 mb-1", children: [_jsx("h3", { className: "text-base font-semibold text-gray-900", children: session.deviceName || 'Unknown Device' }), session.isCurrent && (_jsx("span", { className: "px-2 py-0.5 text-xs font-medium bg-green-100 text-green-700 rounded-full", children: "Hi\u1EC7n t\u1EA1i" }))] }), _jsxs("div", { className: "space-y-1.5 mt-2", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-600", children: [_jsx(Globe, { className: "w-4 h-4" }), _jsx("span", { children: session.ipAddress }), _jsx("span", { className: "text-gray-400", children: "\u2022" }), _jsx("span", { children: getBrowserInfo(session.userAgent) })] }), session.lastActiveAt && (_jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-600", children: [_jsx(Clock, { className: "w-4 h-4" }), _jsxs("span", { children: ["Ho\u1EA1t \u0111\u1ED9ng: ", formatRelativeTime(session.lastActiveAt)] })] })), _jsxs("div", { className: "text-xs text-gray-500", children: ["T\u1EA1o l\u00FAc: ", formatDate(session.createdAt)] })] })] })] }), _jsxs("button", { onClick: () => handleRevokeSession(session.id), disabled: revoking === session.id, className: "px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2", children: [_jsx(Trash2, { className: "w-4 h-4" }), revoking === session.id ? 'Đang xóa...' : 'Thu hồi'] })] }) }, session.id)))) })] }));
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=SessionsSection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionsSection.js","sourceRoot":"","sources":["../../../../src/client/pages/users/SessionsSection.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
declare enum SocialProvider {
|
|
2
|
+
DEFAULT = 0,
|
|
3
|
+
GOOGLE = 1,
|
|
4
|
+
FACEBOOK = 2,
|
|
5
|
+
GITHUB = 3
|
|
6
|
+
}
|
|
7
|
+
interface SocialAccount {
|
|
8
|
+
id: number;
|
|
9
|
+
userId: number;
|
|
10
|
+
provider: SocialProvider;
|
|
11
|
+
providerUserId: string;
|
|
12
|
+
email?: string;
|
|
13
|
+
displayName?: string;
|
|
14
|
+
avatar?: string;
|
|
15
|
+
accessToken?: string;
|
|
16
|
+
refreshToken?: string;
|
|
17
|
+
tokenExpiresAt?: string;
|
|
18
|
+
profileData?: any;
|
|
19
|
+
createdAt: string;
|
|
20
|
+
updatedAt: string;
|
|
21
|
+
}
|
|
22
|
+
interface SocialAccountsSectionProps {
|
|
23
|
+
userId: string;
|
|
24
|
+
accounts: SocialAccount[];
|
|
25
|
+
onRefresh: () => void;
|
|
26
|
+
}
|
|
27
|
+
export declare function SocialAccountsSection({ userId, accounts, onRefresh }: SocialAccountsSectionProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=SocialAccountsSection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SocialAccountsSection.d.ts","sourceRoot":"","sources":["../../../../src/client/pages/users/SocialAccountsSection.tsx"],"names":[],"mappings":"AAQA,aAAK,cAAc;IACjB,OAAO,IAAI;IACX,MAAM,IAAI;IACV,QAAQ,IAAI;IACZ,MAAM,IAAI;CACX;AAED,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,cAAc,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,GAAG,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,UAAU,0BAA0B;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,SAAS,EAAE,MAAM,IAAI,CAAA;CACtB;AA6BD,wBAAgB,qBAAqB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,0BAA0B,2CA+GhG"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Link2, Trash2, Mail, Calendar } from 'lucide-react';
|
|
5
|
+
import toast from 'react-hot-toast';
|
|
6
|
+
import { getApiClient } from '../../auth/api-client';
|
|
7
|
+
import { CORE_API_ROUTES } from '../../constants/api-routes';
|
|
8
|
+
var SocialProvider;
|
|
9
|
+
(function (SocialProvider) {
|
|
10
|
+
SocialProvider[SocialProvider["DEFAULT"] = 0] = "DEFAULT";
|
|
11
|
+
SocialProvider[SocialProvider["GOOGLE"] = 1] = "GOOGLE";
|
|
12
|
+
SocialProvider[SocialProvider["FACEBOOK"] = 2] = "FACEBOOK";
|
|
13
|
+
SocialProvider[SocialProvider["GITHUB"] = 3] = "GITHUB";
|
|
14
|
+
})(SocialProvider || (SocialProvider = {}));
|
|
15
|
+
const PROVIDER_CONFIG = {
|
|
16
|
+
[SocialProvider.GOOGLE]: {
|
|
17
|
+
name: 'Google',
|
|
18
|
+
icon: '',
|
|
19
|
+
bgColor: 'bg-blue-50',
|
|
20
|
+
textColor: 'text-blue-700',
|
|
21
|
+
},
|
|
22
|
+
[SocialProvider.FACEBOOK]: {
|
|
23
|
+
name: 'Facebook',
|
|
24
|
+
icon: '',
|
|
25
|
+
bgColor: 'bg-blue-50',
|
|
26
|
+
textColor: 'text-blue-600',
|
|
27
|
+
},
|
|
28
|
+
[SocialProvider.GITHUB]: {
|
|
29
|
+
name: 'GitHub',
|
|
30
|
+
icon: '',
|
|
31
|
+
bgColor: 'bg-gray-50',
|
|
32
|
+
textColor: 'text-gray-900',
|
|
33
|
+
},
|
|
34
|
+
[SocialProvider.DEFAULT]: {
|
|
35
|
+
name: 'Unknown',
|
|
36
|
+
icon: '?',
|
|
37
|
+
bgColor: 'bg-gray-50',
|
|
38
|
+
textColor: 'text-gray-600',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
export function SocialAccountsSection({ userId, accounts, onRefresh }) {
|
|
42
|
+
const apiClient = getApiClient();
|
|
43
|
+
const [unlinking, setUnlinking] = useState(null);
|
|
44
|
+
const handleUnlinkAccount = async (accountId, providerName) => {
|
|
45
|
+
if (!confirm(`Bạn có chắc chắn muốn hủy liên kết tài khoản ${providerName}?`))
|
|
46
|
+
return;
|
|
47
|
+
setUnlinking(accountId);
|
|
48
|
+
try {
|
|
49
|
+
await apiClient.delete(CORE_API_ROUTES.ADMIN_USERS.UNLINK_SOCIAL_ACCOUNT(userId, accountId));
|
|
50
|
+
toast.success('Đã hủy liên kết tài khoản');
|
|
51
|
+
onRefresh();
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
toast.error(error.response?.data?.message || 'Không thể hủy liên kết tài khoản');
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
setUnlinking(null);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const formatDate = (date) => {
|
|
61
|
+
return new Date(date).toLocaleDateString('vi-VN', {
|
|
62
|
+
year: 'numeric',
|
|
63
|
+
month: 'long',
|
|
64
|
+
day: 'numeric',
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
return (_jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-gray-200", children: [_jsx("div", { className: "p-6 border-b border-gray-200", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "w-10 h-10 bg-purple-100 rounded-lg flex items-center justify-center", children: _jsx(Link2, { className: "w-5 h-5 text-purple-600" }) }), _jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "T\u00E0i kho\u1EA3n li\u00EAn k\u1EBFt" }), _jsxs("p", { className: "text-sm text-gray-500", children: [accounts.length, " t\u00E0i kho\u1EA3n m\u1EA1ng x\u00E3 h\u1ED9i"] })] })] }) }), _jsx("div", { className: "divide-y divide-gray-200", children: accounts.length === 0 ? (_jsxs("div", { className: "p-12 text-center", children: [_jsx(Link2, { className: "w-12 h-12 text-gray-300 mx-auto mb-3" }), _jsx("p", { className: "text-gray-500", children: "Ch\u01B0a li\u00EAn k\u1EBFt t\u00E0i kho\u1EA3n n\u00E0o" }), _jsx("p", { className: "text-sm text-gray-400 mt-1", children: "User ch\u01B0a \u0111\u0103ng nh\u1EADp qua m\u1EA1ng x\u00E3 h\u1ED9i" })] })) : (accounts.map((account) => {
|
|
68
|
+
const config = PROVIDER_CONFIG[account.provider] || PROVIDER_CONFIG[SocialProvider.DEFAULT];
|
|
69
|
+
return (_jsx("div", { className: "p-6 hover:bg-gray-50 transition-colors", children: _jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "flex items-start gap-4 flex-1", children: [_jsx("div", { className: `w-12 h-12 ${config.bgColor} rounded-lg flex items-center justify-center text-2xl flex-shrink-0`, children: config.icon }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "flex items-center gap-2 mb-1", children: _jsx("h3", { className: `text-base font-semibold ${config.textColor}`, children: config.name }) }), _jsxs("div", { className: "space-y-1.5 mt-2", children: [account.displayName && (_jsx("div", { className: "text-sm text-gray-900", children: account.displayName })), account.email && (_jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-600", children: [_jsx(Mail, { className: "w-4 h-4" }), _jsx("span", { children: account.email })] })), _jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-500", children: [_jsx(Calendar, { className: "w-4 h-4" }), _jsxs("span", { children: ["Li\u00EAn k\u1EBFt l\u00FAc: ", formatDate(account.createdAt)] })] })] })] })] }), _jsxs("button", { onClick: () => handleUnlinkAccount(account.id, config.name), disabled: unlinking === account.id, className: "px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2", children: [_jsx(Trash2, { className: "w-4 h-4" }), unlinking === account.id ? 'Đang xóa...' : 'Hủy liên kết'] })] }) }, account.id));
|
|
70
|
+
})) })] }));
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=SocialAccountsSection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SocialAccountsSection.js","sourceRoot":"","sources":["../../../../src/client/pages/users/SocialAccountsSection.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
interface User {
|
|
2
|
+
id: number;
|
|
3
|
+
email: string;
|
|
4
|
+
name: string;
|
|
5
|
+
role: string;
|
|
6
|
+
isActive: boolean;
|
|
7
|
+
createdAt: string;
|
|
8
|
+
avatar?: string;
|
|
9
|
+
emailVerified?: boolean;
|
|
10
|
+
emailVerifiedAt?: string;
|
|
11
|
+
twoFactorEnabled?: boolean;
|
|
12
|
+
deletedAt?: string;
|
|
13
|
+
lastLoginAt?: string;
|
|
14
|
+
failedLoginAttempts?: number;
|
|
15
|
+
lockedUntil?: string;
|
|
16
|
+
passwordChangedAt?: string;
|
|
17
|
+
}
|
|
18
|
+
interface UserDetailModalProps {
|
|
19
|
+
user: User | null;
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
}
|
|
22
|
+
export declare const UserDetailModal: ({ user, onClose }: UserDetailModalProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=UserDetailModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserDetailModal.d.ts","sourceRoot":"","sources":["../../../../src/client/pages/users/UserDetailModal.tsx"],"names":[],"mappings":"AAGA,UAAU,IAAI;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,UAAU,oBAAoB;IAC5B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IACjB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,eAAO,MAAM,eAAe,GAAI,mBAAmB,oBAAoB,mDAqMtE,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { X, Mail, Shield, Calendar, Clock, CheckCircle, XCircle } from 'lucide-react';
|
|
3
|
+
import Modal from '../../ui/Modal';
|
|
4
|
+
export const UserDetailModal = ({ user, onClose }) => {
|
|
5
|
+
if (!user)
|
|
6
|
+
return null;
|
|
7
|
+
const formatDate = (date) => {
|
|
8
|
+
if (!date)
|
|
9
|
+
return 'Chưa có';
|
|
10
|
+
return new Date(date).toLocaleString('vi-VN', {
|
|
11
|
+
year: 'numeric',
|
|
12
|
+
month: '2-digit',
|
|
13
|
+
day: '2-digit',
|
|
14
|
+
hour: '2-digit',
|
|
15
|
+
minute: '2-digit',
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
const getRoleName = (role) => {
|
|
19
|
+
const roles = {
|
|
20
|
+
viewer: 'Người xem',
|
|
21
|
+
editor: 'Biên tập viên',
|
|
22
|
+
admin: 'Quản trị viên',
|
|
23
|
+
super_admin: 'Quản trị viên cấp cao',
|
|
24
|
+
};
|
|
25
|
+
return roles[role] || role;
|
|
26
|
+
};
|
|
27
|
+
const getRoleBadgeColor = (role) => {
|
|
28
|
+
const colors = {
|
|
29
|
+
viewer: 'bg-base-200 text-base-content',
|
|
30
|
+
editor: 'bg-info/10 text-info',
|
|
31
|
+
admin: 'bg-primary/10 text-primary',
|
|
32
|
+
super_admin: 'bg-warning/10 text-warning',
|
|
33
|
+
};
|
|
34
|
+
return colors[role] || 'bg-base-200 text-base-content';
|
|
35
|
+
};
|
|
36
|
+
return (_jsxs(Modal, { isOpen: !!user, onClose: onClose, title: "", showCloseButton: false, size: "md", className: "max-w-2xl p-0 overflow-hidden", children: [_jsx("div", { className: "p-6 border-b border-base-200 bg-base-200/50", children: _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx("div", { className: "w-16 h-16 rounded-full bg-base-300 flex items-center justify-center overflow-hidden border-2 border-base-100 shadow-sm", children: user.avatar ? (_jsx("img", { src: user.avatar, alt: user.name, className: "w-full h-full object-cover" })) : (_jsx("span", { className: "text-2xl font-semibold text-base-content/50", children: user.name.charAt(0).toUpperCase() })) }), _jsxs("div", { children: [_jsx("h2", { className: "text-xl font-bold text-base-content", children: user.name }), _jsxs("div", { className: "flex items-center gap-2 mt-1", children: [_jsx(Mail, { className: "w-4 h-4 text-base-content/60" }), _jsx("p", { className: "text-sm text-base-content/60", children: user.email })] })] })] }), _jsx("button", { onClick: onClose, className: "p-2 hover:bg-base-200 rounded-lg transition-colors text-base-content/60 hover:text-base-content", children: _jsx(X, { className: "w-5 h-5" }) })] }) }), _jsx("div", { className: "p-6 overflow-y-auto max-h-[calc(90vh-140px)]", children: _jsxs("div", { className: "space-y-6", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-sm font-semibold text-base-content/50 uppercase tracking-wider mb-3", children: "Th\u00F4ng tin c\u01A1 b\u1EA3n" }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(InfoItem, { label: "ID", value: user.id.toString() }), _jsx(InfoItem, { label: "Vai tr\u00F2", value: _jsx("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getRoleBadgeColor(user.role)}`, children: getRoleName(user.role) }) }), _jsx(InfoItem, { label: "Tr\u1EA1ng th\u00E1i t\u00E0i kho\u1EA3n", value: _jsxs("span", { className: `inline-flex items-center gap-1.5 px-2 py-1 rounded-md text-xs font-medium ${user.deletedAt ? 'bg-gray-50 text-gray-600' :
|
|
37
|
+
user.isActive ? 'bg-green-50 text-green-700' : 'bg-red-50 text-red-700'}`, children: [_jsx("div", { className: `w-1.5 h-1.5 rounded-full ${user.deletedAt ? 'bg-gray-400' :
|
|
38
|
+
user.isActive ? 'bg-green-500' : 'bg-red-500'}` }), user.deletedAt ? 'Đã xóa' : user.isActive ? 'Hoạt động' : 'Bị khóa'] }) }), _jsx(InfoItem, { label: "Email x\u00E1c th\u1EF1c", value: _jsx("span", { className: "inline-flex items-center gap-1", children: user.emailVerified ? (_jsxs(_Fragment, { children: [_jsx(CheckCircle, { className: "w-4 h-4 text-green-600" }), _jsx("span", { className: "text-green-700 text-sm font-medium", children: "\u0110\u00E3 x\u00E1c th\u1EF1c" })] })) : (_jsxs(_Fragment, { children: [_jsx(XCircle, { className: "w-4 h-4 text-gray-400" }), _jsx("span", { className: "text-gray-500 text-sm", children: "Ch\u01B0a x\u00E1c th\u1EF1c" })] })) }) })] })] }), _jsxs("div", { className: "pt-4 border-t border-base-200", children: [_jsx("h3", { className: "text-sm font-semibold text-base-content/50 uppercase tracking-wider mb-3", children: "B\u1EA3o m\u1EADt" }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(InfoItem, { label: "X\u00E1c th\u1EF1c 2 b\u01B0\u1EDBc (2FA)", value: _jsx("span", { className: "inline-flex items-center gap-1.5", children: user.twoFactorEnabled ? (_jsxs(_Fragment, { children: [_jsx(Shield, { className: "w-4 h-4 text-purple-600" }), _jsx("span", { className: "text-purple-700 text-sm font-medium", children: "\u0110\u00E3 b\u1EADt" })] })) : (_jsxs(_Fragment, { children: [_jsx(Shield, { className: "w-4 h-4 text-gray-300" }), _jsx("span", { className: "text-gray-500 text-sm", children: "Ch\u01B0a b\u1EADt" })] })) }) }), _jsx(InfoItem, { label: "S\u1ED1 l\u1EA7n \u0111\u0103ng nh\u1EADp sai", value: user.failedLoginAttempts?.toString() || '0' }), _jsx(InfoItem, { label: "Kh\u00F3a \u0111\u1EBFn", value: user.lockedUntil ? formatDate(user.lockedUntil) : 'Không bị khóa' }), _jsx(InfoItem, { label: "M\u1EADt kh\u1EA9u thay \u0111\u1ED5i l\u00FAc", value: formatDate(user.passwordChangedAt) })] })] }), _jsxs("div", { className: "pt-4 border-t border-base-200", children: [_jsx("h3", { className: "text-sm font-semibold text-base-content/50 uppercase tracking-wider mb-3", children: "Ho\u1EA1t \u0111\u1ED9ng" }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(InfoItem, { label: "Ng\u00E0y t\u1EA1o", value: formatDate(user.createdAt), icon: _jsx(Calendar, { className: "w-4 h-4 text-gray-400" }) }), _jsx(InfoItem, { label: "\u0110\u0103ng nh\u1EADp l\u1EA7n cu\u1ED1i", value: formatDate(user.lastLoginAt), icon: _jsx(Clock, { className: "w-4 h-4 text-gray-400" }) }), _jsx(InfoItem, { label: "Email x\u00E1c th\u1EF1c l\u00FAc", value: formatDate(user.emailVerifiedAt) }), _jsx(InfoItem, { label: "Ng\u00E0y x\u00F3a", value: formatDate(user.deletedAt) })] })] })] }) })] }));
|
|
39
|
+
};
|
|
40
|
+
// Helper component for displaying info items
|
|
41
|
+
const InfoItem = ({ label, value, icon }) => (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-1.5 mb-1.5", children: [icon, _jsx("label", { className: "text-xs font-medium text-base-content/50 uppercase tracking-wide", children: label })] }), _jsx("div", { className: "text-sm text-base-content font-medium", children: value || _jsx("span", { className: "text-base-content/40 italic", children: "Ch\u01B0a c\u00F3 d\u1EEF li\u1EC7u" }) })] }));
|
|
42
|
+
//# sourceMappingURL=UserDetailModal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserDetailModal.js","sourceRoot":"","sources":["../../../../src/client/pages/users/UserDetailModal.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface UserFiltersProps {
|
|
2
|
+
searchTerm: string;
|
|
3
|
+
onSearchChange: (value: string) => void;
|
|
4
|
+
roleFilter: string;
|
|
5
|
+
onRoleFilterChange: (value: string) => void;
|
|
6
|
+
statusFilter: string;
|
|
7
|
+
onStatusFilterChange: (value: string) => void;
|
|
8
|
+
showDeleted: boolean;
|
|
9
|
+
onShowDeletedChange: (value: boolean) => void;
|
|
10
|
+
onClearFilters: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare const UserFilters: ({ searchTerm, onSearchChange, roleFilter, onRoleFilterChange, statusFilter, onStatusFilterChange, showDeleted, onShowDeletedChange, onClearFilters, }: UserFiltersProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=UserFilters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserFilters.d.ts","sourceRoot":"","sources":["../../../../src/client/pages/users/UserFilters.tsx"],"names":[],"mappings":"AAKA,UAAU,gBAAgB;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,YAAY,EAAE,MAAM,CAAA;IACpB,oBAAoB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7C,WAAW,EAAE,OAAO,CAAA;IACpB,mBAAmB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAC7C,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B;AAED,eAAO,MAAM,WAAW,GAAI,uJAUzB,gBAAgB,4CAoHlB,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Search, Filter } from 'lucide-react';
|
|
4
|
+
import { useState, useRef, useEffect } from 'react';
|
|
5
|
+
export const UserFilters = ({ searchTerm, onSearchChange, roleFilter, onRoleFilterChange, statusFilter, onStatusFilterChange, showDeleted, onShowDeletedChange, onClearFilters, }) => {
|
|
6
|
+
const [showFilters, setShowFilters] = useState(false);
|
|
7
|
+
const filterRef = useRef(null);
|
|
8
|
+
const activeFiltersCount = [roleFilter, statusFilter].filter(Boolean).length + (showDeleted ? 1 : 0);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const handleClickOutside = (event) => {
|
|
11
|
+
if (filterRef.current && !filterRef.current.contains(event.target)) {
|
|
12
|
+
setShowFilters(false);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
16
|
+
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
17
|
+
}, []);
|
|
18
|
+
return (_jsxs("div", { className: "flex flex-col sm:flex-row gap-4 mb-6", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" }), _jsx("input", { type: "text", placeholder: "T\u00ECm ki\u1EBFm theo t\u00EAn, email...", value: searchTerm, onChange: (e) => onSearchChange(e.target.value), className: "w-full pl-10 pr-4 py-2.5 bg-white rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary shadow-sm transition-all" })] }), _jsxs("div", { className: "relative", ref: filterRef, children: [_jsxs("button", { onClick: () => setShowFilters(!showFilters), className: `flex items-center gap-2 px-4 py-2.5 rounded-lg border transition-all ${activeFiltersCount > 0
|
|
19
|
+
? 'bg-primary/5 border-primary/20 text-primary'
|
|
20
|
+
: 'bg-white border-gray-200 text-gray-700 hover:bg-gray-50'}`, children: [_jsx(Filter, { className: "w-4 h-4" }), _jsx("span", { className: "font-medium", children: "B\u1ED9 l\u1ECDc" }), activeFiltersCount > 0 && (_jsx("span", { className: "flex items-center justify-center w-5 h-5 bg-primary text-white text-xs rounded-full ml-1", children: activeFiltersCount }))] }), showFilters && (_jsxs("div", { className: "absolute right-0 mt-2 w-72 bg-white rounded-xl border border-gray-200 shadow-lg z-30 animate-in fade-in zoom-in-95 duration-200 p-4", children: [_jsxs("div", { className: "flex justify-between items-center mb-4", children: [_jsx("h3", { className: "font-semibold text-gray-900", children: "B\u1ED9 l\u1ECDc t\u00ECm ki\u1EBFm" }), activeFiltersCount > 0 && (_jsx("button", { onClick: onClearFilters, className: "text-xs text-red-600 hover:text-red-700 font-medium", children: "X\u00F3a b\u1ED9 l\u1ECDc" }))] }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-xs font-medium text-gray-500 mb-1.5 uppercase", children: "Vai tr\u00F2" }), _jsxs("select", { value: roleFilter, onChange: (e) => onRoleFilterChange(e.target.value), className: "w-full px-3 py-2 rounded-lg border border-gray-200 text-sm focus:outline-none focus:border-primary", children: [_jsx("option", { value: "", children: "T\u1EA5t c\u1EA3 vai tr\u00F2" }), _jsx("option", { value: "viewer", children: "Viewer" }), _jsx("option", { value: "editor", children: "Editor" }), _jsx("option", { value: "admin", children: "Admin" }), _jsx("option", { value: "super_admin", children: "Super Admin" })] })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-xs font-medium text-gray-500 mb-1.5 uppercase", children: "Tr\u1EA1ng th\u00E1i" }), _jsxs("select", { value: statusFilter, onChange: (e) => onStatusFilterChange(e.target.value), className: "w-full px-3 py-2 rounded-lg border border-gray-200 text-sm focus:outline-none focus:border-primary", children: [_jsx("option", { value: "", children: "T\u1EA5t c\u1EA3 tr\u1EA1ng th\u00E1i" }), _jsx("option", { value: "ACTIVE", children: "Ho\u1EA1t \u0111\u1ED9ng" }), _jsx("option", { value: "INACTIVE", children: "Kh\u00F4ng ho\u1EA1t \u0111\u1ED9ng/B\u1ECB kh\u00F3a" })] })] }), _jsx("div", { className: "pt-2 border-t border-gray-50", children: _jsxs("label", { className: "flex items-center gap-2 cursor-pointer group", children: [_jsx("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${showDeleted ? 'bg-primary border-primary' : 'border-gray-300 bg-white'}`, children: showDeleted && _jsx("div", { className: "w-2 h-2 bg-white rounded-sm" }) }), _jsx("input", { type: "checkbox", checked: showDeleted, onChange: (e) => onShowDeletedChange(e.target.checked), className: "hidden" }), _jsx("span", { className: "text-sm text-gray-700 group-hover:text-gray-900", children: "Hi\u1EC3n th\u1ECB \u0111\u00E3 x\u00F3a" })] }) })] })] }))] })] }));
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=UserFilters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserFilters.js","sourceRoot":"","sources":["../../../../src/client/pages/users/UserFilters.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface UserStatsProps {
|
|
2
|
+
total: number;
|
|
3
|
+
activeCount: number;
|
|
4
|
+
verifiedCount: number;
|
|
5
|
+
newUsersCount: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const UserStats: ({ total, activeCount, verifiedCount, newUsersCount }: Partial<UserStatsProps>) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=UserStats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserStats.d.ts","sourceRoot":"","sources":["../../../../src/client/pages/users/UserStats.tsx"],"names":[],"mappings":"AAGA,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,eAAO,MAAM,SAAS,GAAI,sDAAsE,OAAO,CAAC,cAAc,CAAC,4CAiDtH,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Users, UserCheck, UserPlus, ShieldAlert } from 'lucide-react';
|
|
3
|
+
export const UserStats = ({ total = 0, activeCount = 0, verifiedCount = 0, newUsersCount = 0 }) => {
|
|
4
|
+
const stats = [
|
|
5
|
+
{
|
|
6
|
+
label: 'Tổng người dùng',
|
|
7
|
+
value: total,
|
|
8
|
+
icon: Users,
|
|
9
|
+
color: 'text-blue-600',
|
|
10
|
+
bgCallback: 'bg-blue-50',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
label: 'Đang hoạt động',
|
|
14
|
+
value: activeCount,
|
|
15
|
+
icon: UserCheck,
|
|
16
|
+
color: 'text-green-600',
|
|
17
|
+
bgCallback: 'bg-green-50',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
label: 'Đã xác thực',
|
|
21
|
+
value: verifiedCount,
|
|
22
|
+
icon: ShieldAlert,
|
|
23
|
+
color: 'text-purple-600',
|
|
24
|
+
bgCallback: 'bg-purple-50',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
label: 'Người dùng mới',
|
|
28
|
+
value: newUsersCount,
|
|
29
|
+
icon: UserPlus,
|
|
30
|
+
color: 'text-orange-600',
|
|
31
|
+
bgCallback: 'bg-orange-50',
|
|
32
|
+
subtext: '7 ngày qua'
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
return (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6", children: stats.map((stat, index) => (_jsxs("div", { className: "bg-base-100 p-4 rounded-xl border border-base-200 flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-base-content/60 mb-1", children: stat.label }), _jsx("h3", { className: "text-2xl font-bold text-base-content", children: stat.value.toLocaleString() }), stat.subtext && _jsx("p", { className: "text-xs text-base-content/40 mt-1", children: stat.subtext })] }), _jsx("div", { className: `p-3 rounded-lg ${stat.bgCallback}`, children: _jsx(stat.icon, { className: `w-6 h-6 ${stat.color}` }) })] }, index))) }));
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=UserStats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserStats.js","sourceRoot":"","sources":["../../../../src/client/pages/users/UserStats.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAStE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,WAAW,GAAG,CAAC,EAAE,aAAa,GAAG,CAAC,EAAE,aAAa,GAAG,CAAC,EAA2B,EAAE,EAAE;IACzH,MAAM,KAAK,GAAG;QACZ;YACE,KAAK,EAAE,iBAAiB;YACxB,KAAK,EAAE,KAAK;YACZ,IAAI,EAAE,KAAK;YACX,KAAK,EAAE,eAAe;YACtB,UAAU,EAAE,YAAY;SACzB;QACD;YACE,KAAK,EAAE,gBAAgB;YACvB,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,gBAAgB;YACvB,UAAU,EAAE,aAAa;SAC1B;QACD;YACE,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,iBAAiB;YACxB,UAAU,EAAE,cAAc;SAC3B;QACD;YACE,KAAK,EAAE,gBAAgB;YACvB,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,iBAAiB;YACxB,UAAU,EAAE,cAAc;YAC1B,OAAO,EAAE,YAAY;SACtB;KACF,CAAA;IAED,OAAO,CACL,cAAK,SAAS,EAAC,2DAA2D,YACvE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,eAAiB,SAAS,EAAC,qFAAqF,aAC9G,0BACE,YAAG,SAAS,EAAC,+CAA+C,YAAE,IAAI,CAAC,KAAK,GAAK,EAC7E,aAAI,SAAS,EAAC,sCAAsC,YAAE,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,GAAM,EACtF,IAAI,CAAC,OAAO,IAAI,YAAG,SAAS,EAAC,mCAAmC,YAAE,IAAI,CAAC,OAAO,GAAK,IAChF,EACN,cAAK,SAAS,EAAE,kBAAkB,IAAI,CAAC,UAAU,EAAE,YACjD,KAAC,IAAI,CAAC,IAAI,IAAC,SAAS,EAAE,WAAW,IAAI,CAAC,KAAK,EAAE,GAAI,GAC7C,KARE,KAAK,CAST,CACP,CAAC,GACE,CACP,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { User } from 'lucide-react';
|
|
2
|
+
interface User {
|
|
3
|
+
id: number;
|
|
4
|
+
email: string;
|
|
5
|
+
name: string;
|
|
6
|
+
role: string;
|
|
7
|
+
isActive: boolean;
|
|
8
|
+
createdAt: string;
|
|
9
|
+
avatar?: string;
|
|
10
|
+
emailVerified?: boolean;
|
|
11
|
+
twoFactorEnabled?: boolean;
|
|
12
|
+
deletedAt?: string;
|
|
13
|
+
}
|
|
14
|
+
interface UserTableProps {
|
|
15
|
+
users: User[];
|
|
16
|
+
onDelete: (id: number) => void;
|
|
17
|
+
onRestore: (id: number) => void;
|
|
18
|
+
onUpdateStatus: (id: number, status: string) => void;
|
|
19
|
+
onVerifyEmail: (id: number) => void;
|
|
20
|
+
onUserClick: (user: User) => void;
|
|
21
|
+
}
|
|
22
|
+
export declare const UserTable: ({ users, onDelete, onRestore, onUpdateStatus, onVerifyEmail, onUserClick }: UserTableProps) => import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=UserTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserTable.d.ts","sourceRoot":"","sources":["../../../../src/client/pages/users/UserTable.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAyD,IAAI,EAA4B,MAAM,cAAc,CAAA;AAIpH,UAAU,IAAI;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,UAAU,cAAc;IACtB,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9B,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IACpD,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;CAClC;AAED,eAAO,MAAM,SAAS,GAAI,4EAA4E,cAAc,4CAiMnH,CAAA"}
|