Compare commits
1 Commits
a2bab73e50
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| ff70fc78f5 |
@@ -15,6 +15,7 @@ import {
|
|||||||
} from "@/service/projectService";
|
} from "@/service/projectService";
|
||||||
import { Project } from "@/interface/project";
|
import { Project } from "@/interface/project";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
|
import PageBreadcrumb from "@/components/common/PageBreadCrumb";
|
||||||
|
|
||||||
type TabType = "overview" | "members" | "settings";
|
type TabType = "overview" | "members" | "settings";
|
||||||
|
|
||||||
@@ -127,22 +128,54 @@ export default function ProjectDetailsPage() {
|
|||||||
|
|
||||||
const handleUpdateRole = async (userId: string, newRole: string) => {
|
const handleUpdateRole = async (userId: string, newRole: string) => {
|
||||||
try {
|
try {
|
||||||
await updateProjectMemberRole(id, userId, { role: newRole as any });
|
const res = await updateProjectMemberRole(id, userId, {
|
||||||
toast.success("Cập nhật quyền thành công");
|
role: newRole as any,
|
||||||
fetchProject();
|
});
|
||||||
} catch (error) {
|
|
||||||
toast.error("Cập nhật quyền thất bại");
|
if (res?.status) {
|
||||||
|
toast.success("Cập nhật quyền thành công");
|
||||||
|
fetchProject();
|
||||||
|
} else {
|
||||||
|
toast.error(res?.message || "Cập nhật quyền thất bại");
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
const errorMessage =
|
||||||
|
error.response?.data?.message || "Cập nhật quyền thất bại";
|
||||||
|
toast.error(errorMessage);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveMember = async (userId: string) => {
|
const handleRemoveMember = async (userId: string) => {
|
||||||
if (!confirm("Xác nhận xóa thành viên này?")) return;
|
// 1. Hiển thị hộp thoại xác nhận bằng SweetAlert2
|
||||||
|
const result = await Swal.fire({
|
||||||
|
title: "Xác nhận xóa?",
|
||||||
|
text: "Bạn có chắc chắn muốn xóa thành viên này khỏi dự án?",
|
||||||
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: "Đồng ý",
|
||||||
|
cancelButtonText: "Hủy",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.isConfirmed) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await removeProjectMember(id, userId);
|
const res = await removeProjectMember(id, userId);
|
||||||
toast.success("Đã xóa thành viên");
|
|
||||||
|
if (res?.status) {
|
||||||
|
toast.success("Đã xóa thành viên");
|
||||||
|
} else {
|
||||||
|
toast.error(res?.message || "Xóa thành viên thất bại");
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
const errorMessage =
|
||||||
|
error.response?.data?.message || "Xóa thành viên thất bại";
|
||||||
|
toast.error(errorMessage);
|
||||||
|
|
||||||
|
console.error("Remove Member Error:", error);
|
||||||
|
} finally {
|
||||||
fetchProject();
|
fetchProject();
|
||||||
} catch (error) {
|
|
||||||
toast.error("Xóa thành viên thất bại");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -192,7 +225,8 @@ export default function ProjectDetailsPage() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-white dark:bg-[#0d1117] text-gray-900 dark:text-[#c9d1d9] font-sans">
|
<div className="min-h-screen dark:bg-[#0d1117] text-gray-900 dark:text-[#c9d1d9] font-sans">
|
||||||
|
<PageBreadcrumb pageTitle="Chi tiết dự án" />
|
||||||
<div className="pt-8 border-b border-gray-200 dark:border-[#30363d] bg-gray-50 dark:bg-[#0d1117]">
|
<div className="pt-8 border-b border-gray-200 dark:border-[#30363d] bg-gray-50 dark:bg-[#0d1117]">
|
||||||
<div className="px-6">
|
<div className="px-6">
|
||||||
<div className="flex items-center gap-2 text-xl mb-6">
|
<div className="flex items-center gap-2 text-xl mb-6">
|
||||||
|
|||||||
@@ -150,16 +150,16 @@ export default function ProjectsTable({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center max-w-[250px]">
|
<div className="flex items-center max-w-[250px]">
|
||||||
<span className="text-lg font-medium text-gray-700 dark:text-gray-300 truncate">
|
<span className="text-[14px] font-medium text-gray-700 dark:text-gray-300 truncate">
|
||||||
{item.user?.display_name || "Unknown"}
|
{item.user?.display_name || "Unknown"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span className="text-lg text-gray-400 dark:text-gray-600 shrink-0">
|
<span className="text-[14px] text-gray-400 dark:text-gray-600 shrink-0">
|
||||||
/
|
/
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<h3 className="text-lg font-semibold text-blue-600 dark:text-[#58a6ff] truncate max-w-[300px]">
|
<h3 className="text-[14px] font-semibold text-blue-600 dark:text-[#58a6ff] truncate max-w-[300px]">
|
||||||
{item.title}
|
{item.title}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
|||||||
@@ -159,6 +159,9 @@ export default function UserMetaCard({ data }: { data: UserMetaCardProps }) {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<span className="text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
ID: {data.data?.id}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user