change role
This commit is contained in:
@@ -72,6 +72,7 @@ export default function UserTable() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const response = await apiGetListUser(payload);
|
const response = await apiGetListUser(payload);
|
||||||
|
|
||||||
if (response?.status) {
|
if (response?.status) {
|
||||||
setTableData(response);
|
setTableData(response);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
@theme {
|
@theme {
|
||||||
--font-*: initial;
|
--font-*: initial;
|
||||||
--font-outfit: Outfit, sans-serif;
|
--font-outfit: Outfit, sans-serif;
|
||||||
|
--font-inter: "Inter", ui-sans-serif, system-ui, sans-serif;
|
||||||
|
|
||||||
--breakpoint-*: initial;
|
--breakpoint-*: initial;
|
||||||
--breakpoint-2xsm: 375px;
|
--breakpoint-2xsm: 375px;
|
||||||
@@ -188,7 +189,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
@apply relative font-normal font-outfit z-1 bg-gray-50;
|
@apply relative font-normal font-inter z-1 bg-gray-50;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Outfit } from 'next/font/google';
|
import { Inter } from 'next/font/google';
|
||||||
import './globals.css';
|
import './globals.css';
|
||||||
import "flatpickr/dist/flatpickr.css";
|
import "flatpickr/dist/flatpickr.css";
|
||||||
import { SidebarProvider } from '@/context/SidebarContext';
|
import { SidebarProvider } from '@/context/SidebarContext';
|
||||||
@@ -6,7 +6,7 @@ import { ThemeProvider } from '@/context/ThemeContext';
|
|||||||
import { Toaster } from 'sonner';
|
import { Toaster } from 'sonner';
|
||||||
import StoreProvider from '@/store/StoreProvider';
|
import StoreProvider from '@/store/StoreProvider';
|
||||||
|
|
||||||
const outfit = Outfit({
|
const inter = Inter({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ export default function RootLayout({
|
|||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body className={`${outfit.className} dark:bg-gray-900`}>
|
<body className={`${inter.className} dark:bg-gray-900`}>
|
||||||
<StoreProvider>
|
<StoreProvider>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<SidebarProvider>{children} <Toaster closeButton richColors position="top-right" /> </SidebarProvider>
|
<SidebarProvider>{children} <Toaster closeButton richColors position="top-right" /> </SidebarProvider>
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ interface ChangeRoleModalProps {
|
|||||||
onSuccess: () => void;
|
onSuccess: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_ROLE_NAME = "USER";
|
||||||
|
|
||||||
export default function ChangeRoleModal({ isOpen, onClose, user, onSuccess }: ChangeRoleModalProps) {
|
export default function ChangeRoleModal({ isOpen, onClose, user, onSuccess }: ChangeRoleModalProps) {
|
||||||
const [roles, setRoles] = useState<Role[]>([]);
|
const [roles, setRoles] = useState<Role[]>([]);
|
||||||
const [selectedRoleIds, setSelectedRoleIds] = useState<string[]>([]);
|
const [selectedRoleIds, setSelectedRoleIds] = useState<string[]>([]);
|
||||||
@@ -42,9 +44,13 @@ export default function ChangeRoleModal({ isOpen, onClose, user, onSuccess }: Ch
|
|||||||
}
|
}
|
||||||
}, [isOpen, user]);
|
}, [isOpen, user]);
|
||||||
|
|
||||||
const handleToggleRole = (roleId: string) => {
|
const handleToggleRole = (roleId: string, isDefault: boolean) => {
|
||||||
|
if (isDefault) return;
|
||||||
|
|
||||||
setSelectedRoleIds((prev) =>
|
setSelectedRoleIds((prev) =>
|
||||||
prev.includes(roleId) ? prev.filter((id) => id !== roleId) : [...prev, roleId]
|
prev.includes(roleId)
|
||||||
|
? prev.filter((id) => id !== roleId)
|
||||||
|
: [...prev, roleId]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -54,11 +60,12 @@ export default function ChangeRoleModal({ isOpen, onClose, user, onSuccess }: Ch
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
role_ids: selectedRoleIds,
|
role_ids: selectedRoleIds,
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
};
|
};
|
||||||
console.log("Payload gửi lên API:", payload);
|
|
||||||
await apiChangeRole(user.id, payload);
|
await apiChangeRole(user.id, payload);
|
||||||
toast.success("Cập nhật vai trò thành công!");
|
toast.success("Cập nhật vai trò thành công!");
|
||||||
onSuccess();
|
onSuccess();
|
||||||
@@ -95,20 +102,42 @@ export default function ChangeRoleModal({ isOpen, onClose, user, onSuccess }: Ch
|
|||||||
<div className="flex flex-col space-y-1 max-h-[300px] overflow-y-auto custom-scrollbar -mx-2 px-2">
|
<div className="flex flex-col space-y-1 max-h-[300px] overflow-y-auto custom-scrollbar -mx-2 px-2">
|
||||||
{roles.map((role) => {
|
{roles.map((role) => {
|
||||||
const isSelected = selectedRoleIds.includes(role.id);
|
const isSelected = selectedRoleIds.includes(role.id);
|
||||||
|
const isDefault = role.name === DEFAULT_ROLE_NAME;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
key={role.id}
|
key={role.id}
|
||||||
className="flex items-center gap-3 p-2.5 rounded-lg cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors"
|
className={`flex items-center gap-3 p-2.5 rounded-lg transition-colors ${
|
||||||
|
isDefault
|
||||||
|
? "opacity-40 cursor-not-allowed bg-gray-50 dark:bg-gray-800/30"
|
||||||
|
: "cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={isSelected}
|
checked={isDefault ? true : isSelected}
|
||||||
onChange={() => handleToggleRole(role.id)}
|
onChange={() => handleToggleRole(role.id, isDefault)}
|
||||||
className="w-4 h-4 text-brand-500 border-gray-300 rounded focus:ring-brand-500 dark:border-gray-600 dark:bg-gray-700"
|
disabled={isDefault}
|
||||||
|
className={`w-4 h-4 rounded border-gray-300 focus:ring-brand-500 dark:border-gray-600 dark:bg-gray-700 ${
|
||||||
|
isDefault ? "text-gray-400" : "text-brand-500"
|
||||||
|
}`}
|
||||||
/>
|
/>
|
||||||
<span className={`text-sm ${isSelected ? "text-gray-900 dark:text-white font-medium" : "text-gray-700 dark:text-gray-300"}`}>
|
<div className="flex flex-col">
|
||||||
{role.name}
|
<span className={`text-sm ${
|
||||||
</span>
|
isDefault
|
||||||
|
? "text-gray-500 font-normal"
|
||||||
|
: isSelected
|
||||||
|
? "text-gray-900 dark:text-white font-medium"
|
||||||
|
: "text-gray-700 dark:text-gray-300"
|
||||||
|
}`}>
|
||||||
|
{role.name}
|
||||||
|
</span>
|
||||||
|
{isDefault && (
|
||||||
|
<span className="text-[10px] text-gray-400 italic">
|
||||||
|
Mặc định không thể xóa
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export default function UserMetaCard({ data }: { data: UserMetaCardProps }) {
|
|||||||
"No roles available"}
|
"No roles available"}
|
||||||
</p>
|
</p>
|
||||||
<div className="hidden h-3.5 w-px bg-gray-300 dark:bg-gray-700 xl:block"></div>
|
<div className="hidden h-3.5 w-px bg-gray-300 dark:bg-gray-700 xl:block"></div>
|
||||||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
<p className="text-sm text-gray-500 dark:text-gray-400 max-w-[450px] truncate">
|
||||||
{data.data?.profile?.bio || "No bio available"}
|
{data.data?.profile?.bio || "No bio available"}
|
||||||
</p>
|
</p>
|
||||||
<div className="hidden h-3.5 w-px bg-gray-300 dark:bg-gray-700 xl:block"></div>
|
<div className="hidden h-3.5 w-px bg-gray-300 dark:bg-gray-700 xl:block"></div>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const apiGetListUser = async (payload: getUserDto) => {
|
|||||||
|
|
||||||
export const apiChangeRole = async (id: string, payload: any) => {
|
export const apiChangeRole = async (id: string, payload: any) => {
|
||||||
const response = await api.patch(API.Admin.CHANGE_ROLE(id), payload);
|
const response = await api.patch(API.Admin.CHANGE_ROLE(id), payload);
|
||||||
console.log("Response từ API sau khi đổi role:", response);
|
// console.log("Response từ API sau khi đổi role:", response);
|
||||||
return response?.data;
|
return response?.data;
|
||||||
};
|
};
|
||||||
export const apiDeleteUser = async (id: string) => {
|
export const apiDeleteUser = async (id: string) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user