212 lines
6.5 KiB
TypeScript
212 lines
6.5 KiB
TypeScript
"use client";
|
|
import * as React from "react";
|
|
import { ColumnDef } from "@tanstack/react-table";
|
|
|
|
import { Eye, MoreVertical, CheckCircle, Clock } from "lucide-react";
|
|
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuTrigger,
|
|
DropdownMenuItem,
|
|
} from "@/components/ui/dropdown-menu";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { format } from "date-fns";
|
|
import { useRouter } from "next/navigation";
|
|
import Link from "next/link";
|
|
import { PendingApprovalData } from "@/service/content/content";
|
|
|
|
const usePendingApprovalColumns = () => {
|
|
const router = useRouter();
|
|
const userLevelId = getCookiesDecrypt("ulie");
|
|
|
|
const columns: ColumnDef<PendingApprovalData>[] = [
|
|
{
|
|
accessorKey: "id",
|
|
header: "No",
|
|
cell: ({ row, table }) => {
|
|
const pageIndex = table.getState().pagination.pageIndex;
|
|
const pageSize = table.getState().pagination.pageSize;
|
|
const rowIndex = row.index;
|
|
return (
|
|
<div className="flex items-center gap-5">
|
|
<div className="flex-1 text-start">
|
|
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
|
{pageIndex * pageSize + rowIndex + 1}
|
|
</h4>
|
|
</div>
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "title",
|
|
header: "Title",
|
|
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
|
const title: string = row.getValue("title");
|
|
return (
|
|
<span className="whitespace-nowrap">
|
|
{title.length > 50 ? `${title.slice(0, 30)}...` : title}
|
|
</span>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "categoryName",
|
|
header: "Category",
|
|
cell: ({ row }) => {
|
|
const categoryName = row.getValue("categoryName") as string;
|
|
return (
|
|
<span className="whitespace-nowrap">
|
|
{categoryName || "-"}
|
|
</span>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "authorName",
|
|
header: "Author",
|
|
cell: ({ row }) => (
|
|
<span className="whitespace-nowrap">
|
|
{row.getValue("authorName")}
|
|
</span>
|
|
),
|
|
},
|
|
{
|
|
accessorKey: "submittedAt",
|
|
header: "Submitted Date",
|
|
cell: ({ row }) => {
|
|
const submittedAt = row.getValue("submittedAt") as string;
|
|
const formattedDate = submittedAt
|
|
? format(new Date(submittedAt), "dd-MM-yyyy HH:mm:ss")
|
|
: "-";
|
|
return <span className="whitespace-nowrap">{formattedDate}</span>;
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "priority",
|
|
header: "Priority",
|
|
cell: ({ row }) => {
|
|
const priority = row.getValue("priority") as string;
|
|
const colors: Record<string, string> = {
|
|
high: "bg-red-100 text-red-600",
|
|
medium: "bg-yellow-100 text-yellow-600",
|
|
low: "bg-green-100 text-green-600",
|
|
};
|
|
const priorityStyles = colors[priority] || "bg-gray-100 text-gray-600";
|
|
|
|
return (
|
|
<Badge
|
|
className={cn(
|
|
"rounded-full px-3 py-1 text-xs font-medium",
|
|
priorityStyles
|
|
)}
|
|
>
|
|
{priority?.toUpperCase() || "N/A"}
|
|
</Badge>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "currentStep",
|
|
header: "Progress",
|
|
cell: ({ row }) => {
|
|
const currentStep = row.getValue("currentStep") as number;
|
|
const totalSteps = row.original.totalSteps;
|
|
const progress = totalSteps > 0 ? (currentStep / totalSteps) * 100 : 0;
|
|
|
|
return (
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-16 bg-gray-200 rounded-full h-2">
|
|
<div
|
|
className="bg-blue-600 h-2 rounded-full transition-all duration-300"
|
|
style={{ width: `${progress}%` }}
|
|
/>
|
|
</div>
|
|
<span className="text-xs text-gray-600">
|
|
{currentStep}/{totalSteps}
|
|
</span>
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "daysInQueue",
|
|
header: "Days in Queue",
|
|
cell: ({ row }) => {
|
|
const days = row.getValue("daysInQueue") as number;
|
|
const colorClass = days > 7 ? "text-red-600" : days > 3 ? "text-yellow-600" : "text-green-600";
|
|
|
|
return (
|
|
<div className="flex items-center gap-1">
|
|
<Clock className="h-4 w-4" />
|
|
<span className={`text-sm font-medium ${colorClass}`}>
|
|
{days} days
|
|
</span>
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "estimatedTime",
|
|
header: "Est. Time",
|
|
cell: ({ row }) => (
|
|
<span className="whitespace-nowrap text-sm text-gray-600">
|
|
{row.getValue("estimatedTime") || "-"}
|
|
</span>
|
|
),
|
|
},
|
|
{
|
|
id: "actions",
|
|
accessorKey: "action",
|
|
header: "Action",
|
|
enableHiding: false,
|
|
cell: ({ row }) => {
|
|
const canApprove = row.original.canApprove;
|
|
|
|
return (
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button
|
|
size="icon"
|
|
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
|
|
>
|
|
<span className="sr-only">Open menu</span>
|
|
<MoreVertical className="h-4 w-4 text-default-800" />
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent className="p-0 hover:text-black" align="end">
|
|
<Link
|
|
href={`/admin/content/document/detail/${row.original.id}`}
|
|
className="hover:text-black"
|
|
>
|
|
<DropdownMenuItem className="p-2 border-b text-default-700 group rounded-none">
|
|
<Eye className="w-4 h-4 me-1.5" />
|
|
View
|
|
</DropdownMenuItem>
|
|
</Link>
|
|
{/* {canApprove && (
|
|
<DropdownMenuItem
|
|
className="p-2 border-b text-green-700 bg-green-50 group rounded-none"
|
|
onClick={() => {
|
|
// Handle approval logic here
|
|
console.log("Approve item:", row.original.id);
|
|
}}
|
|
>
|
|
<CheckCircle className="w-4 h-4 me-1.5" />
|
|
Approve
|
|
</DropdownMenuItem>
|
|
)} */}
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
);
|
|
},
|
|
},
|
|
];
|
|
|
|
return columns;
|
|
};
|
|
|
|
export default usePendingApprovalColumns;
|