feat:language table approver

This commit is contained in:
Anang Yusman 2025-03-06 16:18:31 +08:00
parent dbf0edb58e
commit b842c63998
35 changed files with 2545 additions and 2323 deletions

View File

@ -45,6 +45,7 @@ import { listEnableCategory } from "@/service/content/content";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { CardHeader, CardTitle } from "@/components/ui/card"; import { CardHeader, CardTitle } from "@/components/ui/card";
import { Link } from "@/i18n/routing"; import { Link } from "@/i18n/routing";
import useTableColumns from "./columns";
const BlogTable = () => { const BlogTable = () => {
const router = useRouter(); const router = useRouter();
@ -73,7 +74,7 @@ const BlogTable = () => {
); );
const [categoryFilter, setCategoryFilter] = React.useState<string>(""); const [categoryFilter, setCategoryFilter] = React.useState<string>("");
const [statusFilter, setStatusFilter] = React.useState<any[]>([]); const [statusFilter, setStatusFilter] = React.useState<any[]>([]);
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -17,155 +17,162 @@ import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import { deleteBlog } from "@/service/blog/blog"; import { deleteBlog } from "@/service/blog/blog";
import { error, loading } from "@/lib/swal"; import { error, loading } from "@/lib/swal";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no",
header: "No",
cell: ({ row }) => <span>{row.getValue("no")}</span>,
},
{
accessorKey: "title",
header: "Title",
cell: ({ row }) => (
<span className="whitespace-normal">{row.getValue("title")}</span>
),
},
{
accessorKey: "categoryName",
header: "Category",
cell: ({ row }) => <span>{row.getValue("categoryName")}</span>,
},
{
accessorKey: "createdAt",
header: "Upload Date",
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate = const columns: ColumnDef<any>[] = [
createdAt && !isNaN(new Date(createdAt).getTime()) {
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") accessorKey: "no",
: "-"; header: t("no"),
return <span className="whitespace-nowrap">{formattedDate}</span>; cell: ({ row }) => <span>{row.getValue("no")}</span>,
}, },
}, {
{ accessorKey: "title",
accessorKey: "tags", header: t("title"),
header: "Tag", cell: ({ row }) => (
cell: ({ row }) => <span className="">{row.getValue("tags")}</span>, <span className="whitespace-normal">{row.getValue("title")}</span>
}, ),
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
};
// Mengambil `statusName` dari data API
const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil
// Gunakan `statusName` untuk pencocokan
const statusStyles =
statusColors[statusName] || "bg-gray-100 text-gray-600";
return (
<Badge className={cn("rounded-full px-5", statusStyles)}>
{status} {/* Tetap tampilkan nilai asli */}
</Badge>
);
}, },
}, {
accessorKey: "categoryName",
header: t("category"),
cell: ({ row }) => <span>{row.getValue("categoryName")}</span>,
},
{
accessorKey: "createdAt",
header: t("upload-date"),
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
{ const formattedDate =
id: "actions", createdAt && !isNaN(new Date(createdAt).getTime())
accessorKey: "action", ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
header: "Actions", : "-";
enableHiding: false, return <span className="whitespace-nowrap">{formattedDate}</span>;
cell: ({ row }) => { },
const router = useRouter(); },
const MySwal = withReactContent(Swal); {
accessorKey: "tags",
header: t("tag"),
cell: ({ row }) => <span className="">{row.getValue("tags")}</span>,
},
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
};
async function deleteProcess(id: any) { // Mengambil `statusName` dari data API
loading(); const status = row.getValue("statusName") as string;
const resDelete = await deleteBlog(id); const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil
if (resDelete?.error) { // Gunakan `statusName` untuk pencocokan
error(resDelete.message); const statusStyles =
return false; statusColors[statusName] || "bg-gray-100 text-gray-600";
return (
<Badge className={cn("rounded-full px-5", statusStyles)}>
{status} {/* Tetap tampilkan nilai asli */}
</Badge>
);
},
},
{
id: "actions",
accessorKey: "action",
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
const router = useRouter();
const MySwal = withReactContent(Swal);
async function deleteProcess(id: any) {
loading();
const resDelete = await deleteBlog(id);
if (resDelete?.error) {
error(resDelete.message);
return false;
}
success();
} }
success();
}
function success() { function success() {
MySwal.fire({ MySwal.fire({
title: "Sukses", title: "Sukses",
icon: "success", icon: "success",
confirmButtonColor: "#3085d6", confirmButtonColor: "#3085d6",
confirmButtonText: "OK", confirmButtonText: "OK",
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
window.location.reload(); window.location.reload();
} }
}); });
} }
const handleDeleteBlog = (id: any) => { const handleDeleteBlog = (id: any) => {
MySwal.fire({ MySwal.fire({
title: "Hapus Data", title: "Hapus Data",
text: "", text: "",
icon: "warning", icon: "warning",
showCancelButton: true, showCancelButton: true,
cancelButtonColor: "#3085d6", cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33", confirmButtonColor: "#d33",
confirmButtonText: "Hapus", confirmButtonText: "Hapus",
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
deleteProcess(id); deleteProcess(id);
} }
}); });
}; };
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button <Button
size="icon" size="icon"
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent" className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
> >
<span className="sr-only">Open menu</span> <span className="sr-only">Open menu</span>
<MoreVertical className="h-4 w-4 text-default-800" /> <MoreVertical className="h-4 w-4 text-default-800" />
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end"> <DropdownMenuContent className="p-0" align="end">
<Link href={`/contributor/blog/detail/${row.original.id}`}> <Link href={`/contributor/blog/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"> <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" /> <Eye className="w-4 h-4 me-1.5" />
View View
</DropdownMenuItem>
</Link>
<Link href={`/contributor/blog/update/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteBlog(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem> </DropdownMenuItem>
</Link> </DropdownMenuContent>
<Link href={`/contributor/blog/update/${row.original.id}`}> </DropdownMenu>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"> );
<SquarePen className="w-4 h-4 me-1.5" /> },
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteBlog(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, ];
];
export default columns; return columns;
};
export default useTableColumns;

View File

@ -17,211 +17,224 @@ import withReactContent from "sweetalert2-react-content";
import { deleteMedia } from "@/service/content/content"; import { deleteMedia } from "@/service/content/content";
import { error } from "@/lib/swal"; import { error } from "@/lib/swal";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no", const MySwal = withReactContent(Swal);
header: "No", const columns: ColumnDef<any>[] = [
cell: ({ row }) => ( {
<div className="flex items-center gap-5"> accessorKey: "no",
<div className="flex-1 text-start"> header: t("no"),
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> cell: ({ row }) => (
{row.getValue("no")} <div className="flex items-center gap-5">
</h4> <div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
), },
}, {
{ accessorKey: "title",
accessorKey: "title", header: t("title"),
header: "Title", cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
cell: ({ row }: { row: { getValue: (key: string) => string } }) => { const title: string = row.getValue("title");
const title: string = row.getValue("title"); return (
return ( <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title}
</span>
);
},
},
{
accessorKey: "categoryName",
header: t("category-name"),
cell: ({ row }) => (
<span className="whitespace-nowrap"> <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title} {row.getValue("categoryName")}
</span> </span>
); ),
}, },
}, {
{ accessorKey: "createdAt",
accessorKey: "categoryName", header: t("upload-date"),
header: "Category Name", cell: ({ row }) => {
cell: ({ row }) => ( const createdAt = row.getValue("createdAt") as
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span> | string
), | number
}, | undefined;
{
accessorKey: "createdAt",
header: "Upload Date",
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate = const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime()) createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-"; : "-";
return <span className="whitespace-nowrap">{formattedDate}</span>; return <span className="whitespace-nowrap">{formattedDate}</span>;
},
}, },
}, {
{ accessorKey: "creatorName",
accessorKey: "creatorName", header: t("creator-group"),
header: "Creator Group", cell: ({ row }) => (
cell: ({ row }) => ( <span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span> ),
),
},
{
accessorKey: "creatorGroupLevelName",
header: "Sumber",
cell: ({ row }) => (
<span className="whitespace-nowrap">
{row.getValue("creatorGroupLevelName")}
</span>
),
},
{
accessorKey: "publishedOn",
header: "Published",
cell: ({ row }) => {
const isPublish = row.original.isPublish;
const isPublishOnPolda = row.original.isPublishOnPolda;
let displayText = "-";
if (isPublish && !isPublishOnPolda) {
displayText = "Mabes";
} else if (isPublish && isPublishOnPolda) {
displayText = "Mabes & Polda";
} else if (!isPublish && isPublishOnPolda) {
displayText = "Polda";
}
return (
<div className="text-center whitespace-nowrap" title={displayText}>
{displayText}
</div>
);
}, },
}, {
{ accessorKey: "creatorGroupLevelName",
accessorKey: "statusName", header: t("source"),
header: "Status", cell: ({ row }) => (
cell: ({ row }) => { <span className="whitespace-nowrap">
const statusColors: Record<string, string> = { {row.getValue("creatorGroupLevelName")}
diterima: "bg-green-100 text-green-600", </span>
"menunggu review": "bg-orange-100 text-orange-600", ),
};
// Mengambil `statusName` dari data API
const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil
// Gunakan `statusName` untuk pencocokan
const statusStyles =
statusColors[statusName] || "bg-gray-100 text-gray-600";
return (
<Badge
className={cn(
"rounded-full px-5 w-full whitespace-nowrap",
statusStyles
)}
>
{status} {/* Tetap tampilkan nilai asli */}
</Badge>
);
}, },
}, {
{ accessorKey: "publishedOn",
id: "actions", header: t("published"),
accessorKey: "action", cell: ({ row }) => {
header: "Actions", const isPublish = row.original.isPublish;
enableHiding: false, const isPublishOnPolda = row.original.isPublishOnPolda;
cell: ({ row }) => {
const MySwal = withReactContent(Swal);
async function doDelete(id: any) { let displayText = "-";
// loading(); if (isPublish && !isPublishOnPolda) {
const data = { displayText = "Mabes";
id, } else if (isPublish && isPublishOnPolda) {
displayText = "Mabes & Polda";
} else if (!isPublish && isPublishOnPolda) {
displayText = "Polda";
}
return (
<div className="text-center whitespace-nowrap" title={displayText}>
{displayText}
</div>
);
},
},
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
}; };
const response = await deleteMedia(data); // Mengambil `statusName` dari data API
const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil
if (response?.error) { // Gunakan `statusName` untuk pencocokan
error(response.message); const statusStyles =
return false; statusColors[statusName] || "bg-gray-100 text-gray-600";
}
success();
}
function success() { return (
MySwal.fire({ <Badge
title: "Sukses", className={cn(
icon: "success", "rounded-full px-5 w-full whitespace-nowrap",
confirmButtonColor: "#3085d6", statusStyles
confirmButtonText: "OK", )}
}).then((result) => { >
if (result.isConfirmed) { {status} {/* Tetap tampilkan nilai asli */}
window.location.reload(); </Badge>
} );
}); },
}
const handleDeleteMedia = (id: any) => {
MySwal.fire({
title: "Hapus Data",
text: "",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Hapus",
}).then((result) => {
if (result.isConfirmed) {
doDelete(id);
}
});
};
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" align="end">
<Link href={`/contributor/content/audio/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link href={`/contributor/content/audio/update/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteMedia(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, {
]; id: "actions",
accessorKey: "action",
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
const MySwal = withReactContent(Swal);
export default columns; async function doDelete(id: any) {
// loading();
const data = {
id,
};
const response = await deleteMedia(data);
if (response?.error) {
error(response.message);
return false;
}
success();
}
function success() {
MySwal.fire({
title: "Sukses",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const handleDeleteMedia = (id: any) => {
MySwal.fire({
title: "Hapus Data",
text: "",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Hapus",
}).then((result) => {
if (result.isConfirmed) {
doDelete(id);
}
});
};
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" align="end">
<Link
href={`/contributor/content/audio/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/content/audio/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteMedia(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
return columns;
};
export default useTableColumns;

View File

@ -61,6 +61,7 @@ import {
} from "@/service/content/content"; } from "@/service/content/content";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { format } from "date-fns"; import { format } from "date-fns";
import useTableColumns from "./columns";
const TableAudio = () => { const TableAudio = () => {
const router = useRouter(); const router = useRouter();
@ -99,7 +100,7 @@ const TableAudio = () => {
const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState(""); const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState("");
const roleId = getCookiesDecrypt("urie"); const roleId = getCookiesDecrypt("urie");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -1,3 +1,4 @@
"use client";
import * as React from "react"; import * as React from "react";
import { ColumnDef } from "@tanstack/react-table"; import { ColumnDef } from "@tanstack/react-table";
@ -19,213 +20,224 @@ import { deleteMedia } from "@/service/content/content";
import { error, loading } from "@/lib/swal"; import { error, loading } from "@/lib/swal";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import { useTranslations } from "next-intl";
const MySwal = withReactContent(Swal); const useTableColumns = () => {
const t = useTranslations("Table"); // Panggil di dalam hook
const columns: ColumnDef<any>[] = [ const MySwal = withReactContent(Swal);
{ const columns: ColumnDef<any>[] = [
accessorKey: "no", {
header: "No", accessorKey: "no",
cell: ({ row }) => ( header: t("no"),
<div className="flex items-center gap-5"> cell: ({ row }) => (
<div className="flex-1 text-start"> <div className="flex items-center gap-5">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> <div className="flex-1 text-start">
{row.getValue("no")} <h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
</h4> {row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
), },
}, {
{ accessorKey: "title",
accessorKey: "title", header: t("title"),
header: "Title", cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
cell: ({ row }: { row: { getValue: (key: string) => string } }) => { const title: string = row.getValue("title");
const title: string = row.getValue("title"); return (
return ( <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title}
</span>
);
},
},
{
accessorKey: "categoryName",
header: t("category-name"),
cell: ({ row }) => (
<span className="whitespace-nowrap"> <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title} {row.getValue("categoryName")}
</span> </span>
); ),
}, },
}, {
{ accessorKey: "createdAt",
accessorKey: "categoryName", header: t("upload-date"),
header: "Category Name", cell: ({ row }) => {
cell: ({ row }) => ( const createdAt = row.getValue("createdAt") as
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span> | string
), | number
}, | undefined;
{
accessorKey: "createdAt",
header: "Upload Date",
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate = const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime()) createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-"; : "-";
return <span className="whitespace-nowrap">{formattedDate}</span>; return <span className="whitespace-nowrap">{formattedDate}</span>;
},
}, },
}, {
{ accessorKey: "creatorName",
accessorKey: "creatorName", header: t("creator-group"),
header: "Creator Group", cell: ({ row }) => (
cell: ({ row }) => ( <span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span> ),
),
},
{
accessorKey: "creatorGroupLevelName",
header: "Sumber",
cell: ({ row }) => (
<span className="whitespace-nowrap">
{row.getValue("creatorGroupLevelName")}
</span>
),
},
{
accessorKey: "publishedOn",
header: "Published",
cell: ({ row }) => {
const isPublish = row.original.isPublish;
const isPublishOnPolda = row.original.isPublishOnPolda;
let displayText = "-";
if (isPublish && !isPublishOnPolda) {
displayText = "Mabes";
} else if (isPublish && isPublishOnPolda) {
displayText = "Mabes & Polda";
} else if (!isPublish && isPublishOnPolda) {
displayText = "Polda";
}
return (
<div className="text-center whitespace-nowrap" title={displayText}>
{displayText}
</div>
);
}, },
}, {
// accessorKey: "creatorGroupLevelName",
{ header: t("source"),
accessorKey: "statusName", cell: ({ row }) => (
header: "Status", <span className="whitespace-nowrap">
cell: ({ row }) => { {row.getValue("creatorGroupLevelName")}
const statusColors: Record<string, string> = { </span>
diterima: "bg-green-100 text-green-600", ),
"menunggu review": "bg-orange-100 text-orange-600",
};
const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase();
const statusStyles =
statusColors[statusName] || "bg-red-200 text-red-600";
return (
<Badge
className={cn(
"rounded-full px-5 w-full whitespace-nowrap",
statusStyles
)}
>
{status} {/* Tetap tampilkan nilai asli */}
</Badge>
);
}, },
}, {
accessorKey: "publishedOn",
header: t("published"),
cell: ({ row }) => {
const isPublish = row.original.isPublish;
const isPublishOnPolda = row.original.isPublishOnPolda;
{ let displayText = "-";
id: "actions", if (isPublish && !isPublishOnPolda) {
accessorKey: "action", displayText = "Mabes";
header: "Actions", } else if (isPublish && isPublishOnPolda) {
enableHiding: false, displayText = "Mabes & Polda";
cell: ({ row }) => { } else if (!isPublish && isPublishOnPolda) {
const router = useRouter(); displayText = "Polda";
const MySwal = withReactContent(Swal); }
async function doDelete(id: any) { return (
// loading(); <div className="text-center whitespace-nowrap" title={displayText}>
const data = { {displayText}
id, </div>
);
},
},
//
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
}; };
const response = await deleteMedia(data); const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase();
const statusStyles =
statusColors[statusName] || "bg-red-200 text-red-600";
if (response?.error) { return (
error(response.message); <Badge
return false; className={cn(
} "rounded-full px-5 w-full whitespace-nowrap",
success(); statusStyles
} )}
>
function success() { {status} {/* Tetap tampilkan nilai asli */}
MySwal.fire({ </Badge>
title: "Sukses", );
icon: "success", },
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const handleDeleteMedia = (id: any) => {
MySwal.fire({
title: "Hapus Data",
text: "",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Hapus",
}).then((result) => {
if (result.isConfirmed) {
doDelete(id);
}
});
};
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" align="end">
<Link href={`/contributor/content/image/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link href={`/contributor/content/image/update/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteMedia(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
},
];
export default columns; {
id: "actions",
accessorKey: "action",
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
const router = useRouter();
const MySwal = withReactContent(Swal);
async function doDelete(id: any) {
// loading();
const data = {
id,
};
const response = await deleteMedia(data);
if (response?.error) {
error(response.message);
return false;
}
success();
}
function success() {
MySwal.fire({
title: "Sukses",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const handleDeleteMedia = (id: any) => {
MySwal.fire({
title: "Hapus Data",
text: "",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Hapus",
}).then((result) => {
if (result.isConfirmed) {
doDelete(id);
}
});
};
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" align="end">
<Link
href={`/contributor/content/image/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/content/image/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteMedia(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
return columns;
};
export default useTableColumns;

View File

@ -52,7 +52,7 @@ import { ticketingPagination } from "@/service/ticketing/ticketing";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { useRouter, useSearchParams } from "next/navigation"; import { useRouter, useSearchParams } from "next/navigation";
import TablePagination from "@/components/table/table-pagination"; import TablePagination from "@/components/table/table-pagination";
import columns from "./columns";
import { import {
deleteMedia, deleteMedia,
listDataImage, listDataImage,
@ -66,6 +66,7 @@ import withReactContent from "sweetalert2-react-content";
import { error } from "@/lib/swal"; import { error } from "@/lib/swal";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { format } from "date-fns"; import { format } from "date-fns";
import useTableColumns from "./columns";
const TableImage = () => { const TableImage = () => {
const router = useRouter(); const router = useRouter();
@ -104,7 +105,7 @@ const TableImage = () => {
const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState(""); const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState("");
const roleId = getCookiesDecrypt("urie"); const roleId = getCookiesDecrypt("urie");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -16,137 +16,146 @@ import {
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { format } from "date-fns"; import { format } from "date-fns";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no", const MySwal = withReactContent(Swal);
header: "No", const columns: ColumnDef<any>[] = [
cell: ({ row }) => ( {
<div className="flex items-center gap-5"> accessorKey: "no",
<div className="flex-1 text-start"> header: t("no"),
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> cell: ({ row }) => (
{row.getValue("no")} <div className="flex items-center gap-5">
</h4> <div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
), },
}, {
{ accessorKey: "contentTitle",
accessorKey: "contentTitle", header: t("title"),
header: "Judul", cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
cell: ({ row }: { row: { getValue: (key: string) => string } }) => { const title: string = row.getValue("contentTitle");
const title: string = row.getValue("contentTitle"); return (
return ( <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title}
</span>
);
},
},
{
accessorKey: "contentTag",
header: t("tag"),
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("contentTag")}</span>
),
},
{
accessorKey: "contentType",
header: t("type-content"),
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("contentType")}</span>
),
},
{
accessorKey: "contentCreatedGroupBy",
header: t("source"),
cell: ({ row }) => (
<span className="whitespace-nowrap"> <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title} {row.getValue("contentCreatedGroupBy")}
</span> </span>
); ),
}, },
},
{
accessorKey: "contentTag",
header: "Tag",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("contentTag")}</span>
),
},
{ {
accessorKey: "contentType", accessorKey: "isPublish",
header: "Tipe Konten ", header: "Status",
cell: ({ row }) => ( cell: ({ row }) => {
<span className="whitespace-nowrap">{row.getValue("contentType")}</span> const isPublish = row.getValue<boolean>("isPublish");
), return (
}, <div>
{
accessorKey: "contentCreatedGroupBy",
header: "Sumber ",
cell: ({ row }) => (
<span className="whitespace-nowrap">
{row.getValue("contentCreatedGroupBy")}
</span>
),
},
{
accessorKey: "isPublish",
header: "Status",
cell: ({ row }) => {
const isPublish = row.getValue<boolean>("isPublish");
return (
<div>
<Button
size="sm"
color={isPublish ? "success" : "warning"}
variant="outline"
className={`btn btn-sm ${
isPublish ? "btn-outline-success" : "btn-outline-warning"
} pill-btn ml-1`}
>
{isPublish ? "Diterima" : "Menunggu Review"}
</Button>
</div>
);
},
},
{
accessorKey: "contentCreatedDate",
header: "Tanggal Unggah",
cell: ({ row }) => {
const createdAt = row.getValue("contentCreatedDate") as
| string
| number
| undefined;
const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
},
},
{
id: "actions",
accessorKey: "action",
header: "Actions",
enableHiding: false,
cell: ({ row }) => {
const isDisabled = row.original.isPublish; // Check the isPublish value
return (
<DropdownMenu>
<DropdownMenuTrigger asChild disabled={isDisabled}>
<Button <Button
size="icon" size="sm"
className={`bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent ${ color={isPublish ? "success" : "warning"}
isDisabled ? "cursor-not-allowed opacity-50" : "" variant="outline"
}`} className={`btn btn-sm ${
disabled={isDisabled} // Disable button if isPublish is true isPublish ? "btn-outline-success" : "btn-outline-warning"
} pill-btn ml-1`}
> >
<span className="sr-only">Open menu</span> {isPublish ? "Diterima" : "Menunggu Review"}
<MoreVertical className="h-4 w-4 text-default-800" />
</Button> </Button>
</DropdownMenuTrigger> </div>
<DropdownMenuContent className="p-0" align="end"> );
<Link },
href={`/contributor/content/spit/convert/${row.original.contentId}`} },
>
<DropdownMenuItem {
className={`p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none ${ accessorKey: "contentCreatedDate",
header: t("upload-date"),
cell: ({ row }) => {
const createdAt = row.getValue("contentCreatedDate") as
| string
| number
| undefined;
const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
},
},
{
id: "actions",
accessorKey: "action",
header: "Actions",
enableHiding: false,
cell: ({ row }) => {
const isDisabled = row.original.isPublish; // Check the isPublish value
return (
<DropdownMenu>
<DropdownMenuTrigger asChild disabled={isDisabled}>
<Button
size="icon"
className={`bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent ${
isDisabled ? "cursor-not-allowed opacity-50" : "" isDisabled ? "cursor-not-allowed opacity-50" : ""
}`} }`}
disabled={isDisabled} // Disable dropdown item if isPublish is true disabled={isDisabled} // Disable button if isPublish is true
> >
<MoveDownRight className="w-4 h-4 me-1.5" /> <span className="sr-only">Open menu</span>
Pindah Ke Mediahub <MoreVertical className="h-4 w-4 text-default-800" />
</DropdownMenuItem> </Button>
</Link> </DropdownMenuTrigger>
</DropdownMenuContent> <DropdownMenuContent className="p-0" align="end">
</DropdownMenu> <Link
); href={`/contributor/content/spit/convert/${row.original.contentId}`}
>
<DropdownMenuItem
className={`p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none ${
isDisabled ? "cursor-not-allowed opacity-50" : ""
}`}
disabled={isDisabled} // Disable dropdown item if isPublish is true
>
<MoveDownRight className="w-4 h-4 me-1.5" />
Pindah Ke Mediahub
</DropdownMenuItem>
</Link>
</DropdownMenuContent>
</DropdownMenu>
);
},
}, },
}, ];
];
export default columns; return columns;
};
export default useTableColumns;

View File

@ -49,6 +49,7 @@ import {
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { format } from "date-fns"; import { format } from "date-fns";
import useTableColumns from "./columns";
// export type CompanyData = { // export type CompanyData = {
// no: number; // no: number;
@ -89,7 +90,7 @@ const TableSPIT = () => {
const [statusFilter, setStatusFilter] = React.useState<any[]>([]); const [statusFilter, setStatusFilter] = React.useState<any[]>([]);
const roleId = getCookiesDecrypt("urie"); const roleId = getCookiesDecrypt("urie");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: spitTable, data: spitTable,
columns, columns,

View File

@ -17,212 +17,224 @@ import { error } from "@/lib/swal";
import { deleteMedia } from "@/service/content/content"; import { deleteMedia } from "@/service/content/content";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no", const MySwal = withReactContent(Swal);
header: "No", const columns: ColumnDef<any>[] = [
cell: ({ row }) => ( {
<div className="flex items-center gap-5"> accessorKey: "no",
<div className="flex-1 text-start"> header: t("no"),
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> cell: ({ row }) => (
{row.getValue("no")} <div className="flex items-center gap-5">
</h4> <div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
), },
}, {
{ accessorKey: "title",
accessorKey: "title", header: t("title"),
header: "Title", cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
cell: ({ row }: { row: { getValue: (key: string) => string } }) => { const title: string = row.getValue("title");
const title: string = row.getValue("title"); return (
return ( <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title}
</span>
);
},
},
{
accessorKey: "categoryName",
header: t("category-name"),
cell: ({ row }) => (
<span className="whitespace-nowrap"> <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title} {row.getValue("categoryName")}
</span> </span>
); ),
}, },
}, {
{ accessorKey: "createdAt",
accessorKey: "categoryName", header: t("upload-date"),
header: "Category Name", cell: ({ row }) => {
cell: ({ row }) => ( const createdAt = row.getValue("createdAt") as
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span> | string
), | number
}, | undefined;
{
accessorKey: "createdAt",
header: "Upload Date",
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate = const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime()) createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-"; : "-";
return <span className="whitespace-nowrap">{formattedDate}</span>; return <span className="whitespace-nowrap">{formattedDate}</span>;
},
}, },
}, {
{ accessorKey: "creatorName",
accessorKey: "creatorName", header: t("creator-group"),
header: "Creator Group", cell: ({ row }) => (
cell: ({ row }) => ( <span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span> ),
),
},
{
accessorKey: "creatorGroupLevelName",
header: "Sumber",
cell: ({ row }) => (
<span className="whitespace-nowrap">
{row.getValue("creatorGroupLevelName")}
</span>
),
},
{
accessorKey: "publishedOn",
header: "Published",
cell: ({ row }) => {
const isPublish = row.original.isPublish;
const isPublishOnPolda = row.original.isPublishOnPolda;
let displayText = "-";
if (isPublish && !isPublishOnPolda) {
displayText = "Mabes";
} else if (isPublish && isPublishOnPolda) {
displayText = "Mabes & Polda";
} else if (!isPublish && isPublishOnPolda) {
displayText = "Polda";
}
return (
<div className="text-center whitespace-nowrap" title={displayText}>
{displayText}
</div>
);
}, },
}, {
accessorKey: "creatorGroupLevelName",
{ header: t("source"),
accessorKey: "statusName", cell: ({ row }) => (
header: "Status", <span className="whitespace-nowrap">
cell: ({ row }) => { {row.getValue("creatorGroupLevelName")}
const statusColors: Record<string, string> = { </span>
diterima: "bg-green-100 text-green-600", ),
"menunggu review": "bg-orange-100 text-orange-600",
};
// Mengambil `statusName` dari data API
const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil
// Gunakan `statusName` untuk pencocokan
const statusStyles =
statusColors[statusName] || "bg-gray-100 text-gray-600";
return (
<Badge
className={cn(
"rounded-full px-5 w-full whitespace-nowrap",
statusStyles
)}
>
{status} {/* Tetap tampilkan nilai asli */}
</Badge>
);
}, },
}, {
{ accessorKey: "publishedOn",
id: "actions", header: t("published"),
accessorKey: "action", cell: ({ row }) => {
header: "Actions", const isPublish = row.original.isPublish;
enableHiding: false, const isPublishOnPolda = row.original.isPublishOnPolda;
cell: ({ row }) => {
const MySwal = withReactContent(Swal);
async function doDelete(id: any) { let displayText = "-";
// loading(); if (isPublish && !isPublishOnPolda) {
const data = { displayText = "Mabes";
id, } else if (isPublish && isPublishOnPolda) {
displayText = "Mabes & Polda";
} else if (!isPublish && isPublishOnPolda) {
displayText = "Polda";
}
return (
<div className="text-center whitespace-nowrap" title={displayText}>
{displayText}
</div>
);
},
},
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
}; };
const response = await deleteMedia(data); // Mengambil `statusName` dari data API
const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil
if (response?.error) { // Gunakan `statusName` untuk pencocokan
error(response.message); const statusStyles =
return false; statusColors[statusName] || "bg-gray-100 text-gray-600";
}
success();
}
function success() { return (
MySwal.fire({ <Badge
title: "Sukses", className={cn(
icon: "success", "rounded-full px-5 w-full whitespace-nowrap",
confirmButtonColor: "#3085d6", statusStyles
confirmButtonText: "OK", )}
}).then((result) => { >
if (result.isConfirmed) { {status} {/* Tetap tampilkan nilai asli */}
window.location.reload(); </Badge>
} );
}); },
}
const handleDeleteMedia = (id: any) => {
MySwal.fire({
title: "Hapus Data",
text: "",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Hapus",
}).then((result) => {
if (result.isConfirmed) {
doDelete(id);
}
});
};
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" align="end">
<Link href={`/contributor/content/teks/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link href={`/contributor/content/teks/update/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteMedia(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, {
]; id: "actions",
accessorKey: "action",
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
const MySwal = withReactContent(Swal);
export default columns; async function doDelete(id: any) {
// loading();
const data = {
id,
};
const response = await deleteMedia(data);
if (response?.error) {
error(response.message);
return false;
}
success();
}
function success() {
MySwal.fire({
title: "Sukses",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const handleDeleteMedia = (id: any) => {
MySwal.fire({
title: "Hapus Data",
text: "",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Hapus",
}).then((result) => {
if (result.isConfirmed) {
doDelete(id);
}
});
};
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" align="end">
<Link
href={`/contributor/content/teks/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/content/teks/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteMedia(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
return columns;
};
export default useTableColumns;

View File

@ -60,6 +60,7 @@ import {
} from "@/service/content/content"; } from "@/service/content/content";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { format } from "date-fns"; import { format } from "date-fns";
import useTableColumns from "./columns";
const TableTeks = () => { const TableTeks = () => {
const router = useRouter(); const router = useRouter();
@ -98,7 +99,7 @@ const TableTeks = () => {
const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState(""); const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState("");
const roleId = getCookiesDecrypt("urie"); const roleId = getCookiesDecrypt("urie");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -17,209 +17,223 @@ import { deleteMedia } from "@/service/content/content";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import { error } from "@/lib/swal"; import { error } from "@/lib/swal";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no", const MySwal = withReactContent(Swal);
header: "No",
cell: ({ row }) => ( const columns: ColumnDef<any>[] = [
<div className="flex items-center gap-5"> {
<div className="flex-1 text-start"> accessorKey: "no",
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> header: t("no"),
{row.getValue("no")} cell: ({ row }) => (
</h4> <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">
{row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
), },
}, {
{ accessorKey: "title",
accessorKey: "title", header: t("title"),
header: "Title", cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
cell: ({ row }: { row: { getValue: (key: string) => string } }) => { const title: string = row.getValue("title");
const title: string = row.getValue("title"); return (
return ( <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title}
</span>
);
},
},
{
accessorKey: "categoryName",
header: t("category-name"),
cell: ({ row }) => (
<span className="whitespace-nowrap"> <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title} {row.getValue("categoryName")}
</span> </span>
); ),
}, },
}, {
{ accessorKey: "createdAt",
accessorKey: "categoryName", header: t("upload-date"),
header: "Category Name", cell: ({ row }) => {
cell: ({ row }) => ( const createdAt = row.getValue("createdAt") as
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span> | string
), | number
}, | undefined;
{
accessorKey: "createdAt",
header: "Upload Date",
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate = const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime()) createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-"; : "-";
return <span className="whitespace-nowrap">{formattedDate}</span>; return <span className="whitespace-nowrap">{formattedDate}</span>;
},
}, },
}, {
{ accessorKey: "creatorName",
accessorKey: "creatorName", header: t("creator-group"),
header: "Creator Group", cell: ({ row }) => (
cell: ({ row }) => ( <span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span> ),
),
},
{
accessorKey: "creatorGroupLevelName",
header: "Sumber",
cell: ({ row }) => (
<span className="whitespace-nowrap">
{row.getValue("creatorGroupLevelName")}
</span>
),
},
{
accessorKey: "publishedOn",
header: "Published",
cell: ({ row }) => {
const isPublish = row.original.isPublish;
const isPublishOnPolda = row.original.isPublishOnPolda;
let displayText = "-";
if (isPublish && !isPublishOnPolda) {
displayText = "Mabes";
} else if (isPublish && isPublishOnPolda) {
displayText = "Mabes & Polda";
} else if (!isPublish && isPublishOnPolda) {
displayText = "Polda";
}
return (
<div className="text-center whitespace-nowrap" title={displayText}>
{displayText}
</div>
);
}, },
}, {
accessorKey: "creatorGroupLevelName",
{ header: t("source"),
accessorKey: "statusName", cell: ({ row }) => (
header: "Status", <span className="whitespace-nowrap">
cell: ({ row }) => { {row.getValue("creatorGroupLevelName")}
const statusColors: Record<string, string> = { </span>
diterima: "bg-green-100 text-green-600", ),
"menunggu review": "bg-orange-100 text-orange-600",
};
const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase();
const statusStyles =
statusColors[statusName] || "bg-red-200 text-red-600";
return (
<Badge
className={cn(
"rounded-full px-5 w-full whitespace-nowrap",
statusStyles
)}
>
{status} {/* Tetap tampilkan nilai asli */}
</Badge>
);
}, },
}, {
{ accessorKey: "publishedOn",
id: "actions", header: t("published"),
accessorKey: "action", cell: ({ row }) => {
header: "Actions", const isPublish = row.original.isPublish;
enableHiding: false, const isPublishOnPolda = row.original.isPublishOnPolda;
cell: ({ row }) => {
const MySwal = withReactContent(Swal);
async function doDelete(id: any) { let displayText = "-";
// loading(); if (isPublish && !isPublishOnPolda) {
const data = { displayText = "Mabes";
id, } else if (isPublish && isPublishOnPolda) {
displayText = "Mabes & Polda";
} else if (!isPublish && isPublishOnPolda) {
displayText = "Polda";
}
return (
<div className="text-center whitespace-nowrap" title={displayText}>
{displayText}
</div>
);
},
},
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
}; };
const response = await deleteMedia(data); const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase();
const statusStyles =
statusColors[statusName] || "bg-red-200 text-red-600";
if (response?.error) { return (
error(response.message); <Badge
return false; className={cn(
} "rounded-full px-5 w-full whitespace-nowrap",
success(); statusStyles
} )}
>
function success() { {status} {/* Tetap tampilkan nilai asli */}
MySwal.fire({ </Badge>
title: "Sukses", );
icon: "success", },
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const handleDeleteMedia = (id: any) => {
MySwal.fire({
title: "Hapus Data",
text: "",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Hapus",
}).then((result) => {
if (result.isConfirmed) {
doDelete(id);
}
});
};
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" align="end">
<Link href={`/contributor/content/video/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link href={`/contributor/content/video/update/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteMedia(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, {
]; id: "actions",
accessorKey: "action",
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
const MySwal = withReactContent(Swal);
export default columns; async function doDelete(id: any) {
// loading();
const data = {
id,
};
const response = await deleteMedia(data);
if (response?.error) {
error(response.message);
return false;
}
success();
}
function success() {
MySwal.fire({
title: "Sukses",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const handleDeleteMedia = (id: any) => {
MySwal.fire({
title: "Hapus Data",
text: "",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Hapus",
}).then((result) => {
if (result.isConfirmed) {
doDelete(id);
}
});
};
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" align="end">
<Link
href={`/contributor/content/video/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/content/video/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteMedia(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
return columns;
};
export default useTableColumns;

View File

@ -60,6 +60,7 @@ import {
} from "@/service/content/content"; } from "@/service/content/content";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { format } from "date-fns"; import { format } from "date-fns";
import useTableColumns from "./columns";
const TableVideo = () => { const TableVideo = () => {
const router = useRouter(); const router = useRouter();
@ -98,7 +99,7 @@ const TableVideo = () => {
const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState(""); const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState("");
const roleId = getCookiesDecrypt("urie"); const roleId = getCookiesDecrypt("urie");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -13,105 +13,111 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { format } from "date-fns"; import { format } from "date-fns";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no", const columns: ColumnDef<any>[] = [
header: "No", {
cell: ({ row }) => ( accessorKey: "no",
<div className="flex items-center gap-5"> header: t("no"),
<div className="flex-1 text-start"> cell: ({ row }) => (
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> <div className="flex items-center gap-5">
{row.getValue("no")} <div className="flex-1 text-start">
</h4> <h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
), },
}, {
{ accessorKey: "title",
accessorKey: "title", header: t("title"),
header: "Judul", cell: ({ row }) => (
cell: ({ row }) => ( <div className="flex items-center gap-5">
<div className="flex items-center gap-5"> <div className="flex-1 text-start">
<div className="flex-1 text-start"> <h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> {row.getValue("title")}
{row.getValue("title")} </h4>
</h4> </div>
</div> </div>
</div> ),
), },
}, {
{ accessorKey: "createdAt",
accessorKey: "createdAt", header: t("upload-date"),
header: "Tanggal Unggah ", cell: ({ row }) => {
cell: ({ row }) => { const createdAt = row.getValue("createdAt") as
const createdAt = row.getValue("createdAt") as | string
| string | number
| number | undefined;
| undefined;
const formattedDate = const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime()) createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-"; : "-";
return <span className="whitespace-nowrap">{formattedDate}</span>; return <span className="whitespace-nowrap">{formattedDate}</span>;
},
}, },
}, {
{ accessorKey: "isActive",
accessorKey: "isActive", header: "Status",
header: "Status", cell: ({ row }) => {
cell: ({ row }) => { const isActive = row.getValue<boolean>("isActive");
const isActive = row.getValue<boolean>("isActive"); console.log("isActive value:", isActive); // TypeScript type is inferred correctly
console.log("isActive value:", isActive); // TypeScript type is inferred correctly return (
return ( <div>
<div> {isActive ? (
{isActive ? ( <b className="text-blue-500">Terkirim</b>
<b className="text-blue-500">Terkirim</b> ) : (
) : ( <b className="text-danger">Belum Terkirim</b>
<b className="text-danger">Belum Terkirim</b> )}
)} </div>
</div> );
); },
}, },
}, {
{ id: "actions",
id: "actions", accessorKey: "action",
accessorKey: "action", header: t("action"),
header: "Actions", enableHiding: false,
enableHiding: false, cell: ({ row }) => {
cell: ({ row }) => { return (
return ( <DropdownMenu>
<DropdownMenu> <DropdownMenuTrigger asChild>
<DropdownMenuTrigger asChild> <Button
<Button size="icon"
size="icon" className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent" >
> <span className="sr-only">Open menu</span>
<span className="sr-only">Open menu</span> <MoreVertical className="h-4 w-4 text-default-800" />
<MoreVertical className="h-4 w-4 text-default-800" /> </Button>
</Button> </DropdownMenuTrigger>
</DropdownMenuTrigger> <DropdownMenuContent className="p-0" align="end">
<DropdownMenuContent className="p-0" align="end"> <Link
<Link href={`/contributor/planning/mediahub/publish/${row.original.id}`}
href={`/contributor/planning/mediahub/publish/${row.original.id}`} >
> <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"> <Eye className="w-4 h-4 me-1.5" />
<Eye className="w-4 h-4 me-1.5" /> Publish
Publish </DropdownMenuItem>
</Link>
<DropdownMenuItem
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
// onClick={() => deletePlan(row.id)}
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem> </DropdownMenuItem>
</Link> </DropdownMenuContent>
<DropdownMenuItem </DropdownMenu>
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none" );
// onClick={() => deletePlan(row.id)} },
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, ];
];
export default columns; return columns;
};
export default useTableColumns;

View File

@ -55,6 +55,7 @@ import { getPlanningSentPagination } from "@/service/planning/planning";
import search from "@/app/[locale]/(protected)/app/chat/components/search"; import search from "@/app/[locale]/(protected)/app/chat/components/search";
import { CardHeader, CardTitle } from "@/components/ui/card"; import { CardHeader, CardTitle } from "@/components/ui/card";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import useTableColumns from "./columns";
const MediahubTable = () => { const MediahubTable = () => {
const t = useTranslations("Planning"); const t = useTranslations("Planning");
@ -78,7 +79,7 @@ const MediahubTable = () => {
const [totalPage, setTotalPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10); const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState(""); const [search, setSearch] = React.useState("");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -13,103 +13,109 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { format } from "date-fns"; import { format } from "date-fns";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no", const columns: ColumnDef<any>[] = [
header: "No", {
cell: ({ row }) => ( accessorKey: "no",
<div className="flex items-center gap-5"> header: t("no"),
<div className="flex-1 text-start"> cell: ({ row }) => (
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> <div className="flex items-center gap-5">
{row.getValue("no")} <div className="flex-1 text-start">
</h4> <h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
), },
}, {
{ accessorKey: "title",
accessorKey: "title", header: t("title"),
header: "Judul", cell: ({ row }) => (
cell: ({ row }) => ( <div className="flex items-center gap-5">
<div className="flex items-center gap-5"> <div className="flex-1 text-start">
<div className="flex-1 text-start"> <h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> {row.getValue("title")}
{row.getValue("title")} </h4>
</h4> </div>
</div> </div>
</div> ),
), },
}, {
{ accessorKey: "createdAt",
accessorKey: "createdAt", header: t("upload-date"),
header: "Tanggal Unggah ", cell: ({ row }) => {
cell: ({ row }) => { const createdAt = row.getValue("createdAt") as
const createdAt = row.getValue("createdAt") as | string
| string | number
| number | undefined;
| undefined;
const formattedDate = const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime()) createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-"; : "-";
return <span className="whitespace-nowrap">{formattedDate}</span>; return <span className="whitespace-nowrap">{formattedDate}</span>;
},
}, },
}, {
{ accessorKey: "isActive",
accessorKey: "isActive", header: "Status",
header: "Status", cell: ({ row }) => {
cell: ({ row }) => { const isActive = row.getValue<boolean>("isActive");
const isActive = row.getValue<boolean>("isActive"); console.log("isActive value:", isActive); // TypeScript type is inferred correctly
console.log("isActive value:", isActive); // TypeScript type is inferred correctly return (
return ( <div>
<div> {isActive ? (
{isActive ? ( <b className="text-blue-500">Terkirim</b>
<b className="text-blue-500">Terkirim</b> ) : (
) : ( <b className="text-danger">Belum Terkirim</b>
<b className="text-danger">Belum Terkirim</b> )}
)} </div>
</div> );
); },
}, },
}, {
{ id: "actions",
id: "actions", accessorKey: "action",
accessorKey: "action", header: t("action"),
header: "Actions", enableHiding: false,
enableHiding: false, cell: ({ row }) => {
cell: ({ row }) => { return (
return ( <DropdownMenu>
<DropdownMenu> <DropdownMenuTrigger asChild>
<DropdownMenuTrigger asChild> <Button
<Button size="icon"
size="icon" className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent" >
> <span className="sr-only">Open menu</span>
<span className="sr-only">Open menu</span> <MoreVertical className="h-4 w-4 text-default-800" />
<MoreVertical className="h-4 w-4 text-default-800" /> </Button>
</Button> </DropdownMenuTrigger>
</DropdownMenuTrigger> <DropdownMenuContent className="p-0" align="end">
<DropdownMenuContent className="p-0" align="end"> <Link
<Link href={`/contributor/planning/medsos-mediahub/publish/${row.original.id}`}
href={`/contributor/planning/medsos-mediahub/publish/${row.original.id}`} >
> <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"> <Eye className="w-4 h-4 me-1.5" />
<Eye className="w-4 h-4 me-1.5" /> Publish
Publish </DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem> </DropdownMenuItem>
</Link> </DropdownMenuContent>
</DropdownMenu>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"> );
<Trash2 className="w-4 h-4 me-1.5" /> },
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, ];
];
export default columns; return columns;
};
export default useTableColumns;

View File

@ -54,6 +54,7 @@ import columns from "./columns";
import { getPlanningSentPagination } from "@/service/planning/planning"; import { getPlanningSentPagination } from "@/service/planning/planning";
import { CardHeader, CardTitle } from "@/components/ui/card"; import { CardHeader, CardTitle } from "@/components/ui/card";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import useTableColumns from "./columns";
const MedsosTable = () => { const MedsosTable = () => {
const t = useTranslations("Planning"); const t = useTranslations("Planning");
@ -77,7 +78,7 @@ const MedsosTable = () => {
const [totalPage, setTotalPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10); const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState(""); const [search, setSearch] = React.useState("");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -12,163 +12,171 @@ import {
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no",
header: "No", const columns: ColumnDef<any>[] = [
cell: ({ row }) => ( {
<div className="flex items-center gap-5"> accessorKey: "no",
<div className="flex-1 text-start"> header: t("no"),
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> cell: ({ row }) => (
{row.getValue("no")} <div className="flex items-center gap-5">
</h4> <div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
), },
},
{ {
accessorKey: "title", accessorKey: "title",
header: "Title", header: t("title"),
cell: ({ row }: { row: { getValue: (key: string) => string } }) => { cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const title: string = row.getValue("title"); const title: string = row.getValue("title");
return ( return (
<span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title}
</span>
);
},
},
{
accessorKey: "startDate",
header: t("start-date"),
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startDate")}</span>
),
},
{
accessorKey: "endDate",
header: t("end-date"),
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("endDate")}</span>
),
},
{
accessorKey: "time",
header: t("time"),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
header: t("address"),
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const address: string = row.getValue("address");
return (
<span className="whitespace-nowrap">
{address.length > 50 ? `${address.slice(0, 40)}...` : address}
</span>
);
},
},
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
};
// Mengambil `statusName` dari data API
const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil
// Gunakan `statusName` untuk pencocokan
const statusStyles =
statusColors[statusName] || "bg-gray-100 text-gray-600";
return (
<Badge
className={cn("rounded-full px-5 whitespace-nowrap", statusStyles)}
>
{status} {/* Tetap tampilkan nilai asli */}
</Badge>
);
},
},
{
accessorKey: "speaker",
header: t("speaker"),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { speakerTitle, speakerName } = row.original;
return (
<span className="whitespace-nowrap">
{speakerTitle || ""} {speakerName || ""}
</span>
);
},
},
{
accessorKey: "uploaderName",
header: t("source"),
cell: ({ row }) => (
<span className="whitespace-nowrap"> <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title} {row.getValue("uploaderName")}
</span> </span>
); ),
}, },
},
{
accessorKey: "startDate",
header: "Start Date ",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startDate")}</span>
),
},
{
accessorKey: "endDate",
header: "End Date",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("endDate")}</span>
),
},
{
accessorKey: "time",
header: "Time",
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
header: "Address",
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const address: string = row.getValue("address");
return (
<span className="whitespace-nowrap">
{address.length > 50 ? `${address.slice(0, 40)}...` : address}
</span>
);
},
},
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
};
// Mengambil `statusName` dari data API {
const status = row.getValue("statusName") as string; id: "actions",
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil accessorKey: "action",
header: t("action"),
// Gunakan `statusName` untuk pencocokan enableHiding: false,
const statusStyles = cell: ({ row }) => {
statusColors[statusName] || "bg-gray-100 text-gray-600"; return (
<DropdownMenu>
return ( <DropdownMenuTrigger asChild>
<Badge <Button
className={cn("rounded-full px-5 whitespace-nowrap", statusStyles)} size="icon"
> className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
{status} {/* Tetap tampilkan nilai asli */} >
</Badge> <span className="sr-only">Open menu</span>
); <MoreVertical className="h-4 w-4 text-default-800" />
}, </Button>
}, </DropdownMenuTrigger>
{ <DropdownMenuContent className="p-0" align="end">
accessorKey: "speaker", <Link
header: "Disampaikan oleh", href={`/contributor/schedule/event/detail/${row.original.id}`}
cell: ({ row }: { row: { original: any } }) => { >
console.log("Row Original Data:", row.original); <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
const { speakerTitle, speakerName } = row.original; <Eye className="w-4 h-4 me-1.5" />
return ( View
<span className="whitespace-nowrap"> </DropdownMenuItem>
{speakerTitle || ""} {speakerName || ""} </Link>
</span> <Link
); href={`/contributor/schedule/event/update/${row.original.id}`}
}, >
}, <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
{ <SquarePen className="w-4 h-4 me-1.5" />
accessorKey: "uploaderName", Edit
header: "Sumber ", </DropdownMenuItem>
cell: ({ row }) => ( </Link>
<span className="whitespace-nowrap">{row.getValue("uploaderName")}</span> <DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
), <Trash2 className="w-4 h-4 me-1.5" />
}, Delete
{
id: "actions",
accessorKey: "action",
header: "Actions",
enableHiding: false,
cell: ({ row }) => {
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" align="end">
<Link
href={`/contributor/schedule/event/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem> </DropdownMenuItem>
</Link> </DropdownMenuContent>
<Link </DropdownMenu>
href={`/contributor/schedule/event/update/${row.original.id}`} );
> },
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, ];
]; return columns;
};
export default columns; export default useTableColumns;

View File

@ -33,6 +33,7 @@ import { useTranslations } from "next-intl";
import { CardHeader, CardTitle } from "@/components/ui/card"; import { CardHeader, CardTitle } from "@/components/ui/card";
import { Link } from "@/i18n/routing"; import { Link } from "@/i18n/routing";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import useTableColumns from "./columns";
const EventTable = () => { const EventTable = () => {
const router = useRouter(); const router = useRouter();
@ -55,7 +56,7 @@ const EventTable = () => {
const [totalPage, setTotalPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10); const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState<string>(""); const [search, setSearch] = React.useState<string>("");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -12,163 +12,172 @@ import {
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no",
header: "No", const columns: ColumnDef<any>[] = [
cell: ({ row }) => ( {
<div className="flex items-center gap-5"> accessorKey: "no",
<div className="flex-1 text-start"> header: t("no"),
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> cell: ({ row }) => (
{row.getValue("no")} <div className="flex items-center gap-5">
</h4> <div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
), },
},
{ {
accessorKey: "title", accessorKey: "title",
header: "Title", header: t("title"),
cell: ({ row }: { row: { getValue: (key: string) => string } }) => { cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const title: string = row.getValue("title"); const title: string = row.getValue("title");
return ( return (
<span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title}
</span>
);
},
},
{
accessorKey: "startDate",
header: t("start-date"),
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startDate")}</span>
),
},
{
accessorKey: "endDate",
header: t("end-date"),
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("endDate")}</span>
),
},
{
accessorKey: "time",
header: t("time"),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
header: t("address"),
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const address: string = row.getValue("address");
return (
<span className="whitespace-nowrap">
{address.length > 50 ? `${address.slice(0, 40)}...` : address}
</span>
);
},
},
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
};
// Mengambil `statusName` dari data API
const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil
// Gunakan `statusName` untuk pencocokan
const statusStyles =
statusColors[statusName] || "bg-gray-100 text-gray-600";
return (
<Badge
className={cn("rounded-full px-5 whitespace-nowrap", statusStyles)}
>
{status} {/* Tetap tampilkan nilai asli */}
</Badge>
);
},
},
{
accessorKey: "speaker",
header: t("speaker"),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { speakerTitle, speakerName } = row.original;
return (
<span className="whitespace-nowrap">
{speakerTitle || ""} {speakerName || ""}
</span>
);
},
},
{
accessorKey: "uploaderName",
header: t("source"),
cell: ({ row }) => (
<span className="whitespace-nowrap"> <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title} {row.getValue("uploaderName")}
</span> </span>
); ),
}, },
},
{
accessorKey: "startDate",
header: "Start Date ",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startDate")}</span>
),
},
{
accessorKey: "endDate",
header: "End Date",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("endDate")}</span>
),
},
{
accessorKey: "time",
header: "Time",
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
header: "Address",
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const address: string = row.getValue("address");
return (
<span className="whitespace-nowrap">
{address.length > 50 ? `${address.slice(0, 40)}...` : address}
</span>
);
},
},
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
};
// Mengambil `statusName` dari data API {
const status = row.getValue("statusName") as string; id: "actions",
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil accessorKey: "action",
header: t("action"),
// Gunakan `statusName` untuk pencocokan enableHiding: false,
const statusStyles = cell: ({ row }) => {
statusColors[statusName] || "bg-gray-100 text-gray-600"; return (
<DropdownMenu>
return ( <DropdownMenuTrigger asChild>
<Badge <Button
className={cn("rounded-full px-5 whitespace-nowrap", statusStyles)} size="icon"
> className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
{status} {/* Tetap tampilkan nilai asli */} >
</Badge> <span className="sr-only">Open menu</span>
); <MoreVertical className="h-4 w-4 text-default-800" />
}, </Button>
}, </DropdownMenuTrigger>
{ <DropdownMenuContent className="p-0" align="end">
accessorKey: "speaker", <Link
header: "Disampaikan oleh", href={`/contributor/schedule/press-conference/detail/${row.original.id}`}
cell: ({ row }: { row: { original: any } }) => { >
console.log("Row Original Data:", row.original); <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
const { speakerTitle, speakerName } = row.original; <Eye className="w-4 h-4 me-1.5" />
return ( Detail
<span className="whitespace-nowrap"> </DropdownMenuItem>
{speakerTitle || ""} {speakerName || ""} </Link>
</span> <Link
); href={`/contributor/schedule/press-conference/update/${row.original.id}`}
}, >
}, <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
{ <SquarePen className="w-4 h-4 me-1.5" />
accessorKey: "uploaderName", Edit
header: "Sumber ", </DropdownMenuItem>
cell: ({ row }) => ( </Link>
<span className="whitespace-nowrap">{row.getValue("uploaderName")}</span> <DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
), <Trash2 className="w-4 h-4 me-1.5" />
}, Delete
{
id: "actions",
accessorKey: "action",
header: "Actions",
enableHiding: false,
cell: ({ row }) => {
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" align="end">
<Link
href={`/contributor/schedule/press-conference/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
Detail
</DropdownMenuItem> </DropdownMenuItem>
</Link> </DropdownMenuContent>
<Link </DropdownMenu>
href={`/contributor/schedule/press-conference/update/${row.original.id}`} );
> },
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, ];
];
export default columns; return columns;
};
export default useTableColumns;

View File

@ -46,6 +46,7 @@ import { paginationSchedule } from "@/service/schedule/schedule";
import { CardHeader, CardTitle } from "@/components/ui/card"; import { CardHeader, CardTitle } from "@/components/ui/card";
import { Link } from "@/i18n/routing"; import { Link } from "@/i18n/routing";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import useTableColumns from "./columns";
const PressConferenceTable = () => { const PressConferenceTable = () => {
const router = useRouter(); const router = useRouter();
@ -68,7 +69,7 @@ const PressConferenceTable = () => {
const [totalPage, setTotalPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10); const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState<string>(""); const [search, setSearch] = React.useState<string>("");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -12,163 +12,172 @@ import {
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no",
header: "No", const columns: ColumnDef<any>[] = [
cell: ({ row }) => ( {
<div className="flex items-center gap-5"> accessorKey: "no",
<div className="flex-1 text-start"> header: t("no"),
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> cell: ({ row }) => (
{row.getValue("no")} <div className="flex items-center gap-5">
</h4> <div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
), },
},
{ {
accessorKey: "title", accessorKey: "title",
header: "Title", header: t("title"),
cell: ({ row }: { row: { getValue: (key: string) => string } }) => { cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const title: string = row.getValue("title"); const title: string = row.getValue("title");
return ( return (
<span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title}
</span>
);
},
},
{
accessorKey: "startDate",
header: t("start-date"),
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startDate")}</span>
),
},
{
accessorKey: "endDate",
header: t("end-date"),
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("endDate")}</span>
),
},
{
accessorKey: "time",
header: t("time"),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
header: t("address"),
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const address: string = row.getValue("address");
return (
<span className="whitespace-nowrap">
{address.length > 50 ? `${address.slice(0, 40)}...` : address}
</span>
);
},
},
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
};
// Mengambil `statusName` dari data API
const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil
// Gunakan `statusName` untuk pencocokan
const statusStyles =
statusColors[statusName] || "bg-gray-100 text-gray-600";
return (
<Badge
className={cn("rounded-full px-5 whitespace-nowrap", statusStyles)}
>
{status} {/* Tetap tampilkan nilai asli */}
</Badge>
);
},
},
{
accessorKey: "speaker",
header: t("speaker"),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { speakerTitle, speakerName } = row.original;
return (
<span className="whitespace-nowrap">
{speakerTitle || ""} {speakerName || ""}
</span>
);
},
},
{
accessorKey: "uploaderName",
header: t("source"),
cell: ({ row }) => (
<span className="whitespace-nowrap"> <span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title} {row.getValue("uploaderName")}
</span> </span>
); ),
}, },
},
{
accessorKey: "startDate",
header: "Start Date ",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startDate")}</span>
),
},
{
accessorKey: "endDate",
header: "End Date",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("endDate")}</span>
),
},
{
accessorKey: "time",
header: "Time",
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
header: "Address",
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const address: string = row.getValue("address");
return (
<span className="whitespace-nowrap">
{address.length > 50 ? `${address.slice(0, 40)}...` : address}
</span>
);
},
},
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
diterima: "bg-green-100 text-green-600",
"menunggu review": "bg-orange-100 text-orange-600",
};
// Mengambil `statusName` dari data API {
const status = row.getValue("statusName") as string; id: "actions",
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil accessorKey: "action",
header: t("action"),
// Gunakan `statusName` untuk pencocokan enableHiding: false,
const statusStyles = cell: ({ row }) => {
statusColors[statusName] || "bg-gray-100 text-gray-600"; return (
<DropdownMenu>
return ( <DropdownMenuTrigger asChild>
<Badge <Button
className={cn("rounded-full px-5 whitespace-nowrap", statusStyles)} size="icon"
> className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
{status} {/* Tetap tampilkan nilai asli */} >
</Badge> <span className="sr-only">Open menu</span>
); <MoreVertical className="h-4 w-4 text-default-800" />
}, </Button>
}, </DropdownMenuTrigger>
{ <DropdownMenuContent className="p-0" align="end">
accessorKey: "speaker", <Link
header: "Disampaikan oleh", href={`/contributor/schedule/press-release/detail/${row.original.id}`}
cell: ({ row }: { row: { original: any } }) => { >
console.log("Row Original Data:", row.original); <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
const { speakerTitle, speakerName } = row.original; <Eye className="w-4 h-4 me-1.5" />
return ( View
<span className="whitespace-nowrap"> </DropdownMenuItem>
{speakerTitle || ""} {speakerName || ""} </Link>
</span> <Link
); href={`/contributor/schedule/press-release/update/${row.original.id}`}
}, >
}, <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
{ <SquarePen className="w-4 h-4 me-1.5" />
accessorKey: "uploaderName", Edit
header: "Sumber ", </DropdownMenuItem>
cell: ({ row }) => ( </Link>
<span className="whitespace-nowrap">{row.getValue("uploaderName")}</span> <DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
), <Trash2 className="w-4 h-4 me-1.5" />
}, Delete
{
id: "actions",
accessorKey: "action",
header: "Actions",
enableHiding: false,
cell: ({ row }) => {
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" align="end">
<Link
href={`/contributor/schedule/press-release/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem> </DropdownMenuItem>
</Link> </DropdownMenuContent>
<Link </DropdownMenu>
href={`/contributor/schedule/press-release/update/${row.original.id}`} );
> },
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, ];
];
export default columns; return columns;
};
export default useTableColumns;

View File

@ -47,6 +47,7 @@ import { paginationSchedule } from "@/service/schedule/schedule";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { CardHeader, CardTitle } from "@/components/ui/card"; import { CardHeader, CardTitle } from "@/components/ui/card";
import { Link } from "@/i18n/routing"; import { Link } from "@/i18n/routing";
import useTableColumns from "./columns";
const PressReleaseTable = () => { const PressReleaseTable = () => {
const router = useRouter(); const router = useRouter();
@ -69,7 +70,7 @@ const PressReleaseTable = () => {
const [totalPage, setTotalPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10); const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState<string>(""); const [search, setSearch] = React.useState<string>("");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -20,187 +20,193 @@ import { deleteTask } from "@/service/task";
import { error, loading } from "@/lib/swal"; import { error, loading } from "@/lib/swal";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no", const columns: ColumnDef<any>[] = [
header: "No", {
cell: ({ row }) => <span>{row.getValue("no")}</span>, accessorKey: "no",
}, header: t("no"),
{ cell: ({ row }) => <span>{row.getValue("no")}</span>,
accessorKey: "title",
header: "Title",
cell: ({ row }) => (
<div>
<span>{row.getValue("title")}</span>
{row.original.isForward && (
<Button
variant={"outline"}
color="primary"
size="sm"
className="ml-3 rounded-xl"
>
Forward
</Button>
)}
</div>
),
},
{
accessorKey: "uniqueCode",
header: "Code",
cell: ({ row }) => <span>{row.getValue("uniqueCode")}</span>,
},
{
accessorKey: "assignmentMainType",
header: "Type Task",
cell: ({ row }) => {
const type = row.getValue("assignmentMainType") as { name: string };
return <span>{type?.name}</span>;
}, },
}, {
{ accessorKey: "title",
accessorKey: "assignmentType", header: t("title"),
header: "Category Task", cell: ({ row }) => (
cell: ({ row }) => { <div>
const type = row.getValue("assignmentType") as { name: string }; <span>{row.getValue("title")}</span>
return <span>{type?.name}</span>; {row.original.isForward && (
},
},
{
accessorKey: "createdAt",
header: "Upload Date ",
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
},
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const isActive = row.original.isActive;
const isDone = row.original.isDone;
let statusText = "";
if (isDone) {
statusText = "Selesai";
} else if (isActive) {
statusText = "Aktif";
} else {
statusText = "Nonaktif";
}
const statusColors: Record<string, string> = {
Aktif: "bg-primary/20 text-primary",
Selesai: "bg-success/20 text-success",
Nonaktif: "bg-gray-200 text-gray-500",
};
const statusStyles = statusColors[statusText] || "default";
return (
<Badge className={cn("rounded-full px-5", statusStyles)}>
{statusText}
</Badge>
);
},
},
{
id: "actions",
accessorKey: "action",
header: "Actions",
enableHiding: false,
cell: ({ row }) => {
const router = useRouter();
const MySwal = withReactContent(Swal);
async function deleteProcess(id: any) {
loading();
const resDelete = await deleteTask(id);
if (resDelete?.error) {
error(resDelete.message);
return false;
}
success();
}
function success() {
MySwal.fire({
title: "Sukses",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const TaskDelete = (id: any) => {
MySwal.fire({
title: "Hapus Data",
text: "",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Hapus",
}).then((result) => {
if (result.isConfirmed) {
deleteProcess(id);
}
});
};
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button <Button
size="icon" variant={"outline"}
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent" color="primary"
size="sm"
className="ml-3 rounded-xl"
> >
<span className="sr-only">Open menu</span> Forward
<MoreVertical className="h-4 w-4 text-default-800" />
</Button> </Button>
</DropdownMenuTrigger> )}
<DropdownMenuContent className="p-0" align="end"> </div>
<Link href={`/contributor/task/detail/${row.original.id}`}> ),
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link href={`/contributor/task/update/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => TaskDelete(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
},
];
export default columns; {
accessorKey: "uniqueCode",
header: t("code"),
cell: ({ row }) => <span>{row.getValue("uniqueCode")}</span>,
},
{
accessorKey: "assignmentMainType",
header: t("type-task"),
cell: ({ row }) => {
const type = row.getValue("assignmentMainType") as { name: string };
return <span>{type?.name}</span>;
},
},
{
accessorKey: "assignmentType",
header: t("category-task"),
cell: ({ row }) => {
const type = row.getValue("assignmentType") as { name: string };
return <span>{type?.name}</span>;
},
},
{
accessorKey: "createdAt",
header: t("upload-date"),
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
},
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const isActive = row.original.isActive;
const isDone = row.original.isDone;
let statusText = "";
if (isDone) {
statusText = "Selesai";
} else if (isActive) {
statusText = "Aktif";
} else {
statusText = "Nonaktif";
}
const statusColors: Record<string, string> = {
Aktif: "bg-primary/20 text-primary",
Selesai: "bg-success/20 text-success",
Nonaktif: "bg-gray-200 text-gray-500",
};
const statusStyles = statusColors[statusText] || "default";
return (
<Badge className={cn("rounded-full px-5", statusStyles)}>
{statusText}
</Badge>
);
},
},
{
id: "actions",
accessorKey: "action",
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
const router = useRouter();
const MySwal = withReactContent(Swal);
async function deleteProcess(id: any) {
loading();
const resDelete = await deleteTask(id);
if (resDelete?.error) {
error(resDelete.message);
return false;
}
success();
}
function success() {
MySwal.fire({
title: "Sukses",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const TaskDelete = (id: any) => {
MySwal.fire({
title: "Hapus Data",
text: "",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Hapus",
}).then((result) => {
if (result.isConfirmed) {
deleteProcess(id);
}
});
};
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" align="end">
<Link href={`/contributor/task/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link href={`/contributor/task/update/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => TaskDelete(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
return columns;
};
export default useTableColumns;

View File

@ -56,6 +56,7 @@ import { listTask } from "@/service/task";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { format } from "date-fns"; import { format } from "date-fns";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import useTableColumns from "./columns";
const TaskTable = () => { const TaskTable = () => {
const router = useRouter(); const router = useRouter();
@ -83,7 +84,7 @@ const TaskTable = () => {
const [limit, setLimit] = React.useState(10); const [limit, setLimit] = React.useState(10);
const [isSpecificAttention, setIsSpecificAttention] = React.useState(true); const [isSpecificAttention, setIsSpecificAttention] = React.useState(true);
const [search, setSearch] = React.useState<string>(""); const [search, setSearch] = React.useState<string>("");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -63,6 +63,7 @@ import {
getTicketingEscalationPagination, getTicketingEscalationPagination,
listTicketingInternal, listTicketingInternal,
} from "@/service/communication/communication"; } from "@/service/communication/communication";
import useTableColumns from "./columns";
const CollaborationTable = () => { const CollaborationTable = () => {
const router = useRouter(); const router = useRouter();
@ -88,7 +89,7 @@ const CollaborationTable = () => {
const [search, setSearch] = React.useState<string>(""); const [search, setSearch] = React.useState<string>("");
const roleId = getCookiesDecrypt("urie"); const roleId = getCookiesDecrypt("urie");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -13,102 +13,113 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { format } from "date-fns"; import { format } from "date-fns";
import { Link, useRouter } from "@/i18n/routing"; import { Link, useRouter } from "@/i18n/routing";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no",
header: "No", const columns: ColumnDef<any>[] = [
cell: ({ row }) => <span> {row.getValue("no")}</span>, {
}, accessorKey: "no",
{ header: t("no"),
accessorKey: "title", cell: ({ row }) => <span> {row.getValue("no")}</span>,
header: "Pertanyaan",
cell: ({ row }) => (
<span className="normal-case"> {row.getValue("title")}</span>
),
},
{
accessorKey: "commentFromUserName",
header: "CreateBy",
cell: ({ row }) => (
<span className="normal-case">{row.getValue("commentFromUserName")}</span>
),
},
{
accessorKey: "Type",
header: "Channel",
cell: ({ row }) => {
const type = row.original.type;
return <span className="normal-case">{type?.name || "N/A"}</span>;
}, },
}, {
{ accessorKey: "title",
accessorKey: "createdAt", header: t("question"),
header: "Waktu", cell: ({ row }) => (
cell: ({ row }) => { <span className="normal-case"> {row.getValue("title")}</span>
const createdAt = row.getValue("createdAt") as ),
| string
| number
| undefined;
const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
}, },
}, {
{ accessorKey: "commentFromUserName",
accessorKey: "isActive", header: t("sender"),
header: "Status", cell: ({ row }) => (
cell: ({ row }) => { <span className="normal-case">
const isActive = row.getValue("isActive") as boolean; // Ambil nilai isActive {row.getValue("commentFromUserName")}
const status = isActive ? "Open" : "Closed"; // Tentukan teks berdasarkan isActive </span>
const statusStyles = isActive ),
? "bg-green-100 text-green-600" // Gaya untuk "Open"
: "bg-red-100 text-red-600"; // Gaya untuk "Closed"
return (
<Badge className={`rounded-full px-5 ${statusStyles}`}>{status}</Badge>
);
}, },
}, {
accessorKey: "Type",
{ header: t("type"),
id: "actions", cell: ({ row }) => {
accessorKey: "action", const type = row.original.type;
header: "Actions", return <span className="normal-case">{type?.name || "N/A"}</span>;
enableHiding: false, },
cell: ({ row }) => {
const router = useRouter();
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" align="end">
<DropdownMenuItem
onClick={() =>
router.push(
`/shared/communication/collaboration/detail/${row.original.id}`
)
}
className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none items-center"
>
<Eye className="w-4 h-4 me-1.5" />
Detail
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, {
]; accessorKey: "createdAt",
header: t("time"),
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
export default columns; const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
},
},
{
accessorKey: "isActive",
header: "Status",
cell: ({ row }) => {
const isActive = row.getValue("isActive") as boolean; // Ambil nilai isActive
const status = isActive ? "Open" : "Closed"; // Tentukan teks berdasarkan isActive
const statusStyles = isActive
? "bg-green-100 text-green-600" // Gaya untuk "Open"
: "bg-red-100 text-red-600"; // Gaya untuk "Closed"
return (
<Badge className={`rounded-full px-5 ${statusStyles}`}>
{status}
</Badge>
);
},
},
{
id: "actions",
accessorKey: "action",
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
const router = useRouter();
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" align="end">
<DropdownMenuItem
onClick={() =>
router.push(
`/shared/communication/collaboration/detail/${row.original.id}`
)
}
className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none items-center"
>
<Eye className="w-4 h-4 me-1.5" />
Detail
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
return columns;
};
export default useTableColumns;

View File

@ -13,98 +13,108 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { format } from "date-fns"; import { format } from "date-fns";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no",
header: "No", const columns: ColumnDef<any>[] = [
cell: ({ row }) => <span> {row.getValue("no")}</span>, {
}, accessorKey: "no",
{ header: t("no"),
accessorKey: "title", cell: ({ row }) => <span> {row.getValue("no")}</span>,
header: "Pertanyaan",
cell: ({ row }) => (
<span className="normal-case"> {row.getValue("title")}</span>
),
},
{
accessorKey: "commentFromUserName",
header: "Penerima",
cell: ({ row }) => (
<span className="normal-case">{row.getValue("commentFromUserName")}</span>
),
},
{
accessorKey: "type",
header: "Penerima",
cell: ({ row }) => {
const type = row.original.type; // Akses properti category
return <span className="normal-case">{type?.name || "N/A"}</span>;
}, },
}, {
{ accessorKey: "title",
accessorKey: "createdAt", header: t("question"),
header: "Waktu", cell: ({ row }) => (
cell: ({ row }) => { <span className="normal-case"> {row.getValue("title")}</span>
const createdAt = row.getValue("createdAt") as ),
| string
| number
| undefined;
const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
}, },
}, {
{ accessorKey: "commentFromUserName",
accessorKey: "isActive", header: t("sender"),
header: "Status", cell: ({ row }) => (
cell: ({ row }) => { <span className="normal-case">
const isActive = row.getValue("isActive") as boolean; // Ambil nilai isActive {row.getValue("commentFromUserName")}
const status = isActive ? "Open" : "Closed"; // Tentukan teks berdasarkan isActive </span>
const statusStyles = isActive ),
? "bg-green-100 text-green-600" // Gaya untuk "Open"
: "bg-red-100 text-red-600"; // Gaya untuk "Closed"
return (
<Badge className={`rounded-full px-5 ${statusStyles}`}>{status}</Badge>
);
}, },
}, {
accessorKey: "type",
{ header: t("type"),
id: "actions", cell: ({ row }) => {
accessorKey: "action", const type = row.original.type; // Akses properti category
header: "Actions", return <span className="normal-case">{type?.name || "N/A"}</span>;
enableHiding: false, },
cell: ({ row }) => {
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" align="end">
<Link
href={`/shared/communication/escalation/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, {
]; accessorKey: "createdAt",
header: t("time"),
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
export default columns; const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
},
},
{
accessorKey: "isActive",
header: "Status",
cell: ({ row }) => {
const isActive = row.getValue("isActive") as boolean; // Ambil nilai isActive
const status = isActive ? "Open" : "Closed"; // Tentukan teks berdasarkan isActive
const statusStyles = isActive
? "bg-green-100 text-green-600" // Gaya untuk "Open"
: "bg-red-100 text-red-600"; // Gaya untuk "Closed"
return (
<Badge className={`rounded-full px-5 ${statusStyles}`}>
{status}
</Badge>
);
},
},
{
id: "actions",
accessorKey: "action",
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
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" align="end">
<Link
href={`/shared/communication/escalation/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
return columns;
};
export default useTableColumns;

View File

@ -62,6 +62,7 @@ import {
getTicketingEscalationPagination, getTicketingEscalationPagination,
listTicketingInternal, listTicketingInternal,
} from "@/service/communication/communication"; } from "@/service/communication/communication";
import useTableColumns from "./columns";
const EscalationTable = () => { const EscalationTable = () => {
const router = useRouter(); const router = useRouter();
@ -87,7 +88,7 @@ const EscalationTable = () => {
const [search, setSearch] = React.useState<string>(""); const [search, setSearch] = React.useState<string>("");
const roleId = getCookiesDecrypt("urie"); const roleId = getCookiesDecrypt("urie");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -13,97 +13,104 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { format } from "date-fns"; import { format } from "date-fns";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no",
header: "No",
cell: ({ row }) => <span> {row.getValue("no")}</span>,
},
{
accessorKey: "title",
header: "Pertanyaan",
cell: ({ row }) => (
<span className="normal-case"> {row.getValue("title")}</span>
),
},
{
accessorKey: "createdBy",
header: "Pengirim",
cell: ({ row }) => {
const createdBy = row.original.createdBy; // Akses properti category
return (
<span className="normal-case">{createdBy?.fullname || "N/A"}</span>
);
},
},
{
accessorKey: "sendTo",
header: "Penerima",
cell: ({ row }) => {
const sendTo = row.original.sendTo; // Akses properti category
return <span className="normal-case">{sendTo?.fullname || "N/A"}</span>;
},
},
{
accessorKey: "createdAt",
header: "Waktu",
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate = const columns: ColumnDef<any>[] = [
createdAt && !isNaN(new Date(createdAt).getTime()) {
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") accessorKey: "no",
: "-"; header: t("no"),
return <span className="whitespace-nowrap">{formattedDate}</span>; cell: ({ row }) => <span> {row.getValue("no")}</span>,
}, },
}, {
{ accessorKey: "title",
id: "actions", header: t("question"),
accessorKey: "action", cell: ({ row }) => (
header: "Actions", <span className="normal-case"> {row.getValue("title")}</span>
enableHiding: false, ),
cell: ({ row }) => { },
return ( {
<DropdownMenu> accessorKey: "createdBy",
<DropdownMenuTrigger asChild> header: t("sender"),
<Button cell: ({ row }) => {
size="icon" const createdBy = row.original.createdBy; // Akses properti category
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent" return (
> <span className="normal-case">{createdBy?.fullname || "N/A"}</span>
<span className="sr-only">Open menu</span> );
<MoreVertical className="h-4 w-4 text-default-800" /> },
</Button> },
</DropdownMenuTrigger> {
<DropdownMenuContent className="p-0" align="end"> accessorKey: "sendTo",
<Link header: t("sendto"),
href={`/shared/communication/internal/detail/${row.original.id}`} cell: ({ row }) => {
> const sendTo = row.original.sendTo; // Akses properti category
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"> return <span className="normal-case">{sendTo?.fullname || "N/A"}</span>;
<Eye className="w-4 h-4 me-1.5" /> },
View },
{
accessorKey: "createdAt",
header: t("time"),
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
},
},
{
id: "actions",
accessorKey: "action",
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
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" align="end">
<Link
href={`/shared/communication/internal/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link
href={`/shared/communication/internal/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem> </DropdownMenuItem>
</Link> </DropdownMenuContent>
<Link </DropdownMenu>
href={`/shared/communication/internal/update/${row.original.id}`} );
> },
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}, },
}, ];
];
export default columns; return columns;
};
export default useTableColumns;

View File

@ -61,6 +61,7 @@ import {
} from "@/service/content/content"; } from "@/service/content/content";
import { listTicketingInternal } from "@/service/communication/communication"; import { listTicketingInternal } from "@/service/communication/communication";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import useTableColumns from "./columns";
const InternalTable = () => { const InternalTable = () => {
const router = useRouter(); const router = useRouter();
@ -88,7 +89,7 @@ const InternalTable = () => {
const userLevelId = getCookiesDecrypt("ulie"); const userLevelId = getCookiesDecrypt("ulie");
const roleId = getCookiesDecrypt("urie"); const roleId = getCookiesDecrypt("urie");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -18,200 +18,206 @@ import Swal from "sweetalert2";
import { error } from "@/lib/swal"; import { error } from "@/lib/swal";
import { deleteMedia } from "@/service/content/content"; import { deleteMedia } from "@/service/content/content";
import { publishContest } from "@/service/contest/contest"; import { publishContest } from "@/service/contest/contest";
import { useTranslations } from "next-intl";
const columns: ColumnDef<any>[] = [ const useTableColumns = () => {
{ const t = useTranslations("Table"); // Panggil di dalam hook
accessorKey: "no",
header: "No", const columns: ColumnDef<any>[] = [
cell: ({ row }) => ( {
<div className="flex items-center gap-5"> accessorKey: "no",
<div className="flex-1 text-start"> header: t("no"),
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1"> cell: ({ row }) => (
{row.getValue("no")} <div className="flex items-center gap-5">
</h4> <div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div> </div>
</div> ),
),
},
{
accessorKey: "hastagCode",
header: "Kode",
cell: ({ row }) => (
<div className="flex items-center gap-5">
<div className="flex-1 text-start">
<h4
className="text-sm font-bold
text-default-600 whitespace-nowrap mb-1"
>
{row.getValue("hastagCode")}
</h4>
</div>
</div>
),
},
{
accessorKey: "theme",
header: "Judul",
cell: ({ row }) => (
<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">
{row.getValue("theme")}
</h4>
</div>
</div>
),
},
{
accessorKey: "duration",
header: "Durasi ",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("duration")}</span>
),
},
{
accessorKey: "targetOutput",
header: "Target Output ",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("targetOutput")}</span>
),
},
{
accessorKey: "targetParticipantTopLevel",
header: "Target Participant ",
cell: ({ row }) => (
<span className="whitespace-nowrap">
{row.getValue("targetParticipantTopLevel")}
</span>
),
},
{
accessorKey: "isPublishForAll", // Bisa menggunakan ini untuk membaca default data
header: "Status",
cell: ({
row,
}: {
row: {
original: { isPublishForAll?: boolean; isPublishForMabes?: boolean };
};
}) => {
const userRoleId: number = Number(getCookiesDecrypt("urie"));
const userLevelNumber: number = Number(getCookiesDecrypt("ulne"));
const isPublishForAll: boolean = Boolean(row.original.isPublishForAll);
const isPublishForMabes: boolean = Boolean(
row.original.isPublishForMabes
);
const isPending: boolean =
(userRoleId === 3 && userLevelNumber === 1 && !isPublishForAll) ||
((userRoleId === 11 || userRoleId === 12) && !isPublishForMabes);
const isTerkirim: boolean = isPublishForMabes && !isPublishForAll;
return (
<Badge
className={`whitespace-nowrap px-2 py-1 rounded-full ${
isPending
? "bg-orange-100 text-orange-600" // Warna kuning untuk "Pending"
: isTerkirim
? "bg-blue-100 text-blue-600" // Warna biru untuk "Terkirim"
: "bg-green-100 text-green-600" // Warna hijau untuk "Publish"
}`}
>
{isPending ? "Pending" : isTerkirim ? "Terkirim" : "Publish"}
</Badge>
);
}, },
}, {
accessorKey: "hastagCode",
{ header: t("code"),
id: "actions", cell: ({ row }) => (
accessorKey: "action", <div className="flex items-center gap-5">
header: "Actions", <div className="flex-1 text-start">
enableHiding: false, <h4
cell: ({ row }) => { className="text-sm font-bold
const MySwal = withReactContent(Swal); text-default-600 whitespace-nowrap mb-1"
const userRoleId = Number(getCookiesDecrypt("urie"));
const userLevelId = Number(getCookiesDecrypt("ulie"));
const userLevelNumber = Number(getCookiesDecrypt("ulne"));
async function doPublish(id: any) {
// loading();
// const data = {
// id,
// };
const response = await publishContest(id);
if (response?.error) {
error(response.message);
return false;
}
success();
}
function success() {
MySwal.fire({
title: "Sukses",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const handlePublishContest = (id: any) => {
MySwal.fire({
title: "Apakah anda ingin publish Lomba?",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Ya",
cancelButtonText: "Tidak",
}).then((result) => {
if (result.isConfirmed) {
doPublish(id);
}
});
};
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> {row.getValue("hastagCode")}
<MoreVertical className="h-4 w-4 text-default-800" /> </h4>
</Button> </div>
</DropdownMenuTrigger> </div>
<DropdownMenuContent className="p-0" align="end"> ),
{((userRoleId == 11 || userRoleId == 12) && },
row?.original?.isPublishForMabes != true) || {
(userRoleId == 3 && accessorKey: "theme",
userLevelNumber == 1 && header: t("title"),
row?.original?.isPublishForAll != true) ? ( cell: ({ row }) => (
<DropdownMenuItem <div className="flex items-center gap-5">
className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none" <div className="flex-1 text-start">
onClick={() => handlePublishContest(row.original.id)} <h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("theme")}
</h4>
</div>
</div>
),
},
{
accessorKey: "duration",
header: t("duration"),
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("duration")}</span>
),
},
{
accessorKey: "targetOutput",
header: t("target-output"),
cell: ({ row }) => (
<span className="whitespace-nowrap">
{row.getValue("targetOutput")}
</span>
),
},
{
accessorKey: "targetParticipantTopLevel",
header: t("target-participant"),
cell: ({ row }) => (
<span className="whitespace-nowrap">
{row.getValue("targetParticipantTopLevel")}
</span>
),
},
{
accessorKey: "isPublishForAll", // Bisa menggunakan ini untuk membaca default data
header: "Status",
cell: ({
row,
}: {
row: {
original: { isPublishForAll?: boolean; isPublishForMabes?: boolean };
};
}) => {
const userRoleId: number = Number(getCookiesDecrypt("urie"));
const userLevelNumber: number = Number(getCookiesDecrypt("ulne"));
const isPublishForAll: boolean = Boolean(row.original.isPublishForAll);
const isPublishForMabes: boolean = Boolean(
row.original.isPublishForMabes
);
const isPending: boolean =
(userRoleId === 3 && userLevelNumber === 1 && !isPublishForAll) ||
((userRoleId === 11 || userRoleId === 12) && !isPublishForMabes);
const isTerkirim: boolean = isPublishForMabes && !isPublishForAll;
return (
<Badge
className={`whitespace-nowrap px-2 py-1 rounded-full ${
isPending
? "bg-orange-100 text-orange-600" // Warna kuning untuk "Pending"
: isTerkirim
? "bg-blue-100 text-blue-600" // Warna biru untuk "Terkirim"
: "bg-green-100 text-green-600" // Warna hijau untuk "Publish"
}`}
>
{isPending ? "Pending" : isTerkirim ? "Terkirim" : "Publish"}
</Badge>
);
},
},
{
id: "actions",
accessorKey: "action",
header: t("action"),
enableHiding: false,
cell: ({ row }) => {
const MySwal = withReactContent(Swal);
const userRoleId = Number(getCookiesDecrypt("urie"));
const userLevelId = Number(getCookiesDecrypt("ulie"));
const userLevelNumber = Number(getCookiesDecrypt("ulne"));
async function doPublish(id: any) {
// loading();
// const data = {
// id,
// };
const response = await publishContest(id);
if (response?.error) {
error(response.message);
return false;
}
success();
}
function success() {
MySwal.fire({
title: "Sukses",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
}
const handlePublishContest = (id: any) => {
MySwal.fire({
title: "Apakah anda ingin publish Lomba?",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Ya",
cancelButtonText: "Tidak",
}).then((result) => {
if (result.isConfirmed) {
doPublish(id);
}
});
};
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
size="icon"
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
> >
<Upload className="w-4 h-4 me-1.5" /> <span className="sr-only">Open menu</span>
Publish <MoreVertical className="h-4 w-4 text-default-800" />
</DropdownMenuItem> </Button>
) : ( </DropdownMenuTrigger>
"" <DropdownMenuContent className="p-0" align="end">
)} {((userRoleId == 11 || userRoleId == 12) &&
<Link href={`/shared/contest/detail/${row.original.id}`}> row?.original?.isPublishForMabes != true) ||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"> (userRoleId == 3 &&
<Eye className="w-4 h-4 me-1.5" /> userLevelNumber == 1 &&
View row?.original?.isPublishForAll != true) ? (
</DropdownMenuItem> <DropdownMenuItem
</Link> className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"
{/* <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"> onClick={() => handlePublishContest(row.original.id)}
>
<Upload className="w-4 h-4 me-1.5" />
Publish
</DropdownMenuItem>
) : (
""
)}
<Link href={`/shared/contest/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
{/* <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" /> <SquarePen className="w-4 h-4 me-1.5" />
Edit Edit
</DropdownMenuItem> </DropdownMenuItem>
@ -219,11 +225,14 @@ const columns: ColumnDef<any>[] = [
<Trash2 className="w-4 h-4 me-1.5" /> <Trash2 className="w-4 h-4 me-1.5" />
Delete Delete
</DropdownMenuItem> */} </DropdownMenuItem> */}
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
); );
},
}, },
}, ];
];
export default columns; return columns;
};
export default useTableColumns;

View File

@ -42,6 +42,7 @@ import { useRouter, useSearchParams } from "next/navigation";
import TablePagination from "@/components/table/table-pagination"; import TablePagination from "@/components/table/table-pagination";
import columns from "./columns"; import columns from "./columns";
import { listContest } from "@/service/contest/contest"; import { listContest } from "@/service/contest/contest";
import useTableColumns from "./columns";
const TaskTable = () => { const TaskTable = () => {
const router = useRouter(); const router = useRouter();
@ -63,7 +64,7 @@ const TaskTable = () => {
const [totalPage, setTotalPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10); const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState<string>(""); const [search, setSearch] = React.useState<string>("");
const columns = useTableColumns();
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,

View File

@ -812,7 +812,7 @@ export default function FormConvertSPIT() {
<div className="mt-3"> <div className="mt-3">
<Label className="text-xl">Penempatan file</Label> <Label className="text-xl">Penempatan file</Label>
</div> </div>
{files.length > 1 && ( {files?.length > 1 && (
<div className="flex flex-wrap gap-2 mt-2"> <div className="flex flex-wrap gap-2 mt-2">
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Checkbox <Checkbox

View File

@ -607,5 +607,34 @@
}, },
"Curation": { "Curation": {
"content-curation": "Content Curation" "content-curation": "Content Curation"
},
"Table": {
"no": "No",
"title": "Title",
"category-name": "Category Name",
"upload-date": "Upload Date",
"creator-group": "Creator Group",
"source": "source",
"published": "Published",
"date": "Date",
"category": "Category",
"tag": "Tag",
"type-content": "Content Type",
"type-task": "Task Type",
"category-task": "Category Task",
"code": "Code",
"start-date": "Start Date",
"end-date": "End Date",
"speaker": "Speaker",
"time": "Time",
"address": "Address",
"question": "Question",
"sender": "Created By",
"sendto": "SendTo",
"type": "Type",
"duration": "Duration",
"target-output": "Target Output",
"target-participant": "Target Participant",
"action": "Actions"
} }
} }

View File

@ -608,5 +608,34 @@
}, },
"Curation": { "Curation": {
"content-curation": "Kurasi Konten" "content-curation": "Kurasi Konten"
},
"Table": {
"no": "Nomor",
"title": "Judul",
"category-name": "Nama Kategori",
"upload-date": "Tanggal Upload",
"creator-group": "Pembuat",
"source": "Sumber",
"published": "Diterbitkan",
"date": "Tanggal",
"category": "Kategori",
"tag": "Tag",
"type-content": "Tipe Konten",
"type-task": "Tipen Penugasan",
"category-task": "Kategori Penugasan",
"code": "Kode",
"start-date": "Tanggal Mulai",
"end-date": "Tanggal Selesai",
"speaker": "Disampaikan Oleh",
"time": "Waktu",
"address": "Alamat",
"question": "Pertanyaan",
"sender": "Pengirim",
"sendto": "Penerima",
"type": "Tipe",
"duration": "Durasi",
"target-output": "Target Output",
"target-participant": "Target Peserta",
"action": "Aksi"
} }
} }