Merge branch 'dev-anang' of https://gitlab.com/hanifsalafi/mediahub_redesign
This commit is contained in:
commit
ac2bba1e02
|
|
@ -5,7 +5,7 @@ export default function PerformancePolda() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
<p className="font-semibold">PERFORMANCE KUMULATIF PER POLDA</p>
|
<p className="font-semibold">PERFORMANCE KUMULATIF PER POLRES</p>
|
||||||
<PerformancePolresViz />
|
<PerformancePolresViz />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
|
import PerformancePolresViz from "@/components/visualization/performance-polres";
|
||||||
|
import PerformanceSatkerViz from "@/components/visualization/performance-satker";
|
||||||
|
|
||||||
|
export default function PerformanceSatker() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SiteBreadcrumb />
|
||||||
|
<p className="font-semibold">PERFORMANCE KUMULATIF PER SATKER</p>
|
||||||
|
<PerformanceSatkerViz />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -14,9 +14,7 @@ export default function AdminBanner() {
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
{selectedTab === "content"
|
{selectedTab === "content" ? "List Media" : " List Banner"}
|
||||||
? "Daftar List Media"
|
|
||||||
: "Table List Banner"}
|
|
||||||
|
|
||||||
<div className="flex flex-row gap-1 border-2 rounded-md w-fit mb-5">
|
<div className="flex flex-row gap-1 border-2 rounded-md w-fit mb-5">
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import Image from "next/image";
|
||||||
import { Upload } from "tus-js-client";
|
import { Upload } from "tus-js-client";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
title: z.string({
|
title: z.string({
|
||||||
|
|
@ -109,7 +110,7 @@ export default function CreateCategoryModal() {
|
||||||
const levelNumber = getCookiesDecrypt("ulne");
|
const levelNumber = getCookiesDecrypt("ulne");
|
||||||
const userLevelId = getCookiesDecrypt("ulie");
|
const userLevelId = getCookiesDecrypt("ulie");
|
||||||
const poldaState = Cookies.get("state");
|
const poldaState = Cookies.get("state");
|
||||||
|
const t = useTranslations("Menu");
|
||||||
const [files, setFiles] = useState<File[]>([]);
|
const [files, setFiles] = useState<File[]>([]);
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [satkerData, setSatkerData] = useState<string[]>([]);
|
const [satkerData, setSatkerData] = useState<string[]>([]);
|
||||||
|
|
@ -239,12 +240,12 @@ export default function CreateCategoryModal() {
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button color="primary" size="md">
|
<Button color="primary" size="md">
|
||||||
Tambah Kategori
|
{t("add-category")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent size="md">
|
<DialogContent size="md">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Tambah Kategori</DialogTitle>
|
<DialogTitle> {t("add-category")}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,12 @@ import {
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import CreateCategoryModal from "./create";
|
import CreateCategoryModal from "./create";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const AdminCategoryTable = () => {
|
const AdminCategoryTable = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
const t = useTranslations("Menu");
|
||||||
const dataChange = searchParams?.get("dataChange");
|
const dataChange = searchParams?.get("dataChange");
|
||||||
const [openModal, setOpenModal] = React.useState(false);
|
const [openModal, setOpenModal] = React.useState(false);
|
||||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||||
|
|
@ -127,7 +129,7 @@ const AdminCategoryTable = () => {
|
||||||
return (
|
return (
|
||||||
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
||||||
<div className="flex justify-between mb-10 items-center">
|
<div className="flex justify-between mb-10 items-center">
|
||||||
<p className="text-xl font-medium text-default-900">Kategori</p>
|
<p className="text-xl font-medium text-default-900">{t("category")}</p>
|
||||||
<CreateCategoryModal />
|
<CreateCategoryModal />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import { useDropzone } from "react-dropzone";
|
||||||
import { CloudUpload } from "lucide-react";
|
import { CloudUpload } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { Upload } from "tus-js-client";
|
import { Upload } from "tus-js-client";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
answer: z.string({
|
answer: z.string({
|
||||||
|
|
@ -79,7 +80,7 @@ const publishToList = [
|
||||||
export default function CreateFAQModal() {
|
export default function CreateFAQModal() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
const t = useTranslations("Menu");
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [satkerData, setSatkerData] = useState<string[]>([]);
|
const [satkerData, setSatkerData] = useState<string[]>([]);
|
||||||
const [unitData, setUnitData] = useState<string[]>([]);
|
const [unitData, setUnitData] = useState<string[]>([]);
|
||||||
|
|
@ -120,12 +121,12 @@ export default function CreateFAQModal() {
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button color="primary" size="md">
|
<Button color="primary" size="md">
|
||||||
Tambah FAQ
|
{t("add")} FAQ
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent size="md">
|
<DialogContent size="md">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Tambah FAQ</DialogTitle>
|
<DialogTitle>{t("add")} FAQ</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import { useDropzone } from "react-dropzone";
|
||||||
import { CloudUpload } from "lucide-react";
|
import { CloudUpload } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { Upload } from "tus-js-client";
|
import { Upload } from "tus-js-client";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
question: z.string({
|
question: z.string({
|
||||||
|
|
@ -77,7 +78,7 @@ const publishToList = [
|
||||||
export default function CreateFAQModal() {
|
export default function CreateFAQModal() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
const t = useTranslations("Menu");
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof FormSchema>>({
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
|
|
@ -110,12 +111,12 @@ export default function CreateFAQModal() {
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button color="primary" size="md">
|
<Button color="primary" size="md">
|
||||||
Tambah Feedback
|
{t("add")} Feedback
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent size="md">
|
<DialogContent size="md">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Tambah Feedback</DialogTitle>
|
<DialogTitle>{t("add")} Feedback</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,13 @@ import {
|
||||||
} from "@/service/settings/settings";
|
} from "@/service/settings/settings";
|
||||||
|
|
||||||
import CreateFAQModal from "./create";
|
import CreateFAQModal from "./create";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const AdminFeedbackTable = () => {
|
const AdminFeedbackTable = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const dataChange = searchParams?.get("dataChange");
|
const dataChange = searchParams?.get("dataChange");
|
||||||
|
|
||||||
const [openModal, setOpenModal] = React.useState(false);
|
const [openModal, setOpenModal] = React.useState(false);
|
||||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ import {
|
||||||
CommandList,
|
CommandList,
|
||||||
} from "@/components/ui/command";
|
} from "@/components/ui/command";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
name: z.string({
|
name: z.string({
|
||||||
|
|
@ -55,6 +56,7 @@ const FormSchema = z.object({
|
||||||
export default function CreateTagModal() {
|
export default function CreateTagModal() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
const t = useTranslations("Menu");
|
||||||
const [categoryList, setCategoryList] = useState<
|
const [categoryList, setCategoryList] = useState<
|
||||||
{ id: number; label: string; value: string }[]
|
{ id: number; label: string; value: string }[]
|
||||||
>([]);
|
>([]);
|
||||||
|
|
@ -107,12 +109,12 @@ export default function CreateTagModal() {
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button color="primary" size="md">
|
<Button color="primary" size="md">
|
||||||
Tambah Tag
|
{t("add-tags")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent size="md">
|
<DialogContent size="md">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Tambah Tag</DialogTitle>
|
<DialogTitle> {t("add-tags")}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,12 @@ import {
|
||||||
} from "@/service/settings/settings";
|
} from "@/service/settings/settings";
|
||||||
|
|
||||||
import CreateFAQModal from "./create";
|
import CreateFAQModal from "./create";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const AdminTagTable = () => {
|
const AdminTagTable = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
const t = useTranslations("Menu");
|
||||||
const dataChange = searchParams?.get("dataChange");
|
const dataChange = searchParams?.get("dataChange");
|
||||||
const [openModal, setOpenModal] = React.useState(false);
|
const [openModal, setOpenModal] = React.useState(false);
|
||||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||||
|
|
@ -124,7 +126,7 @@ const AdminTagTable = () => {
|
||||||
return (
|
return (
|
||||||
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
||||||
<div className="flex justify-between mb-10 items-center">
|
<div className="flex justify-between mb-10 items-center">
|
||||||
<p className="text-xl font-medium text-default-900">Tag</p>
|
<p className="text-xl font-medium text-default-900">{t("tags")}</p>
|
||||||
<CreateFAQModal />
|
<CreateFAQModal />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ export default function ExecutiveDashboard() {
|
||||||
|
|
||||||
const response3 = await generateTicket();
|
const response3 = await generateTicket();
|
||||||
setTicket3(response3?.data?.data);
|
setTicket3(response3?.data?.data);
|
||||||
|
|
||||||
const response4 = await generateTicket();
|
const response4 = await generateTicket();
|
||||||
setTicket4(response4?.data?.data);
|
setTicket4(response4?.data?.data);
|
||||||
|
|
||||||
|
|
@ -250,35 +250,6 @@ export default function ExecutiveDashboard() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
<Dialog>
|
|
||||||
<DialogTrigger asChild>
|
|
||||||
<Button variant="outline">Download Report</Button>
|
|
||||||
</DialogTrigger>
|
|
||||||
<DialogContent className="sm:max-w-[425px]">
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Download Report</DialogTitle>
|
|
||||||
</DialogHeader>
|
|
||||||
<div className="grid gap-4 py-4">
|
|
||||||
<div className="w-full">
|
|
||||||
<Label>Date</Label>
|
|
||||||
<Input
|
|
||||||
type="date"
|
|
||||||
// value={dateFilter}
|
|
||||||
// onChange={(e) => setDateFilter(e.target.value)}
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<DialogFooter>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
// onClick={downloadReport}
|
|
||||||
>
|
|
||||||
Download
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
<div className="mt-3 flex flex-row gap-3 justify-center">
|
<div className="mt-3 flex flex-row gap-3 justify-center">
|
||||||
<Card className="rounded-sm w-4/12 p-3">
|
<Card className="rounded-sm w-4/12 p-3">
|
||||||
<div className="flex flex-row justify-between">
|
<div className="flex flex-row justify-between">
|
||||||
|
|
@ -412,7 +383,7 @@ export default function ExecutiveDashboard() {
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full mt-3">
|
<div className="w-full mt-3">
|
||||||
<Card className="rounded-sm p-3 h-[300px]">
|
<Card className="rounded-sm p-3 h-auto">
|
||||||
<div className="flex flex-row justify-between">
|
<div className="flex flex-row justify-between">
|
||||||
<p className="text-base font-semibold">Emergency Issue</p>
|
<p className="text-base font-semibold">Emergency Issue</p>
|
||||||
<LucideBoxSelect />
|
<LucideBoxSelect />
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,19 @@ import AudioSliderPage from "./giat-routine/audio/audio";
|
||||||
import ImageSliderPage from "./giat-routine/image/image";
|
import ImageSliderPage from "./giat-routine/image/image";
|
||||||
import TeksSliderPage from "./giat-routine/document/teks";
|
import TeksSliderPage from "./giat-routine/document/teks";
|
||||||
import ContestTable from "../contest/components/contest-table";
|
import ContestTable from "../contest/components/contest-table";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const CuratedContentPage = () => {
|
const CuratedContentPage = () => {
|
||||||
|
const t = useTranslations("Curation");
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
<div className="my-3">
|
<div className="my-3">
|
||||||
<Tabs defaultValue="giat-routine" className="w-full">
|
<Tabs defaultValue="giat-routine" className="w-full">
|
||||||
<Card className="py-3 px-2 my-4">
|
<Card className="py-3 px-2 my-4">
|
||||||
<p className="text-lg font-semibold ml-2">Kurasi Konten</p>
|
<p className="text-lg font-semibold ml-2">
|
||||||
|
{t("content-curation")}
|
||||||
|
</p>
|
||||||
<TabsList className="flex-wrap">
|
<TabsList className="flex-wrap">
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="giat-routine"
|
value="giat-routine"
|
||||||
|
|
|
||||||
|
|
@ -442,7 +442,22 @@ export default function FormAudio() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestData = {
|
let requestData: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
htmlDescription: string;
|
||||||
|
fileTypeId: string;
|
||||||
|
categoryId: any;
|
||||||
|
subCategoryId: any;
|
||||||
|
uploadedBy: string;
|
||||||
|
statusId: string;
|
||||||
|
publishedFor: string;
|
||||||
|
creatorName: string;
|
||||||
|
tags: string;
|
||||||
|
isYoutube: boolean;
|
||||||
|
isInternationalMedia: boolean;
|
||||||
|
attachFromScheduleId?: number; // ✅ Tambahkan properti ini
|
||||||
|
} = {
|
||||||
...data,
|
...data,
|
||||||
title: finalTitle,
|
title: finalTitle,
|
||||||
description: finalDescription,
|
description: finalDescription,
|
||||||
|
|
@ -461,6 +476,10 @@ export default function FormAudio() {
|
||||||
|
|
||||||
let id = Cookies.get("idCreate");
|
let id = Cookies.get("idCreate");
|
||||||
|
|
||||||
|
if (scheduleId !== undefined) {
|
||||||
|
requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini
|
||||||
|
}
|
||||||
|
|
||||||
if (id == undefined) {
|
if (id == undefined) {
|
||||||
const response = await createMedia(requestData);
|
const response = await createMedia(requestData);
|
||||||
console.log("Form Data Submitted:", requestData);
|
console.log("Form Data Submitted:", requestData);
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ import { options } from "@fullcalendar/core/preact.js";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { getCsrfToken } from "@/service/auth";
|
import { getCsrfToken } from "@/service/auth";
|
||||||
import { Link } from "@/i18n/routing";
|
import { Link } from "@/i18n/routing";
|
||||||
|
import { request } from "http";
|
||||||
|
|
||||||
interface FileWithPreview extends File {
|
interface FileWithPreview extends File {
|
||||||
preview: string;
|
preview: string;
|
||||||
|
|
@ -443,11 +444,28 @@ export default function FormImage() {
|
||||||
const finalTags = tags.join(", ");
|
const finalTags = tags.join(", ");
|
||||||
const finalTitle = isSwitchOn ? title : data.title;
|
const finalTitle = isSwitchOn ? title : data.title;
|
||||||
const finalDescription = articleBody || data.description;
|
const finalDescription = articleBody || data.description;
|
||||||
|
|
||||||
if (!finalDescription.trim()) {
|
if (!finalDescription.trim()) {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const requestData = {
|
|
||||||
|
let requestData: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
htmlDescription: string;
|
||||||
|
fileTypeId: string;
|
||||||
|
categoryId: any;
|
||||||
|
subCategoryId: any;
|
||||||
|
uploadedBy: string;
|
||||||
|
statusId: string;
|
||||||
|
publishedFor: string;
|
||||||
|
creatorName: string;
|
||||||
|
tags: string;
|
||||||
|
isYoutube: boolean;
|
||||||
|
isInternationalMedia: boolean;
|
||||||
|
attachFromScheduleId?: number; // ✅ Tambahkan properti ini
|
||||||
|
} = {
|
||||||
...data,
|
...data,
|
||||||
title: finalTitle,
|
title: finalTitle,
|
||||||
description: finalDescription,
|
description: finalDescription,
|
||||||
|
|
@ -466,14 +484,14 @@ export default function FormImage() {
|
||||||
|
|
||||||
let id = Cookies.get("idCreate");
|
let id = Cookies.get("idCreate");
|
||||||
|
|
||||||
|
if (scheduleId !== undefined) {
|
||||||
|
requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini
|
||||||
|
}
|
||||||
|
|
||||||
if (id == undefined) {
|
if (id == undefined) {
|
||||||
const response = await createMedia(requestData);
|
const response = await createMedia(requestData);
|
||||||
console.log("Form Data Submitted:", requestData);
|
console.log("Form Data Submitted:", requestData);
|
||||||
|
|
||||||
// if (response?.error) {
|
|
||||||
// MySwal.fire("Error", response?.message, "error");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
Cookies.set("idCreate", response?.data?.data, { expires: 1 });
|
Cookies.set("idCreate", response?.data?.data, { expires: 1 });
|
||||||
id = response?.data?.data;
|
id = response?.data?.data;
|
||||||
|
|
||||||
|
|
@ -489,16 +507,15 @@ export default function FormImage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload File
|
// Upload File
|
||||||
const progressInfoArr = [];
|
const progressInfoArr = files.map((item) => ({
|
||||||
for (const item of files) {
|
percentage: 0,
|
||||||
progressInfoArr.push({ percentage: 0, fileName: item.name });
|
fileName: item.name,
|
||||||
}
|
}));
|
||||||
progressInfo = progressInfoArr;
|
progressInfo = progressInfoArr;
|
||||||
setIsStartUpload(true);
|
setIsStartUpload(true);
|
||||||
setProgressList(progressInfoArr);
|
setProgressList(progressInfoArr);
|
||||||
|
|
||||||
close();
|
close();
|
||||||
// showProgress();
|
|
||||||
files.map(async (item: any, index: number) => {
|
files.map(async (item: any, index: number) => {
|
||||||
await uploadResumableFile(
|
await uploadResumableFile(
|
||||||
index,
|
index,
|
||||||
|
|
@ -509,8 +526,6 @@ export default function FormImage() {
|
||||||
});
|
});
|
||||||
|
|
||||||
Cookies.remove("idCreate");
|
Cookies.remove("idCreate");
|
||||||
|
|
||||||
// MySwal.fire("Sukses", "Data berhasil disimpan.", "success");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSubmit = (data: ImageSchema) => {
|
const onSubmit = (data: ImageSchema) => {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -441,7 +441,22 @@ export default function FormTeks() {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const requestData = {
|
let requestData: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
htmlDescription: string;
|
||||||
|
fileTypeId: string;
|
||||||
|
categoryId: any;
|
||||||
|
subCategoryId: any;
|
||||||
|
uploadedBy: string;
|
||||||
|
statusId: string;
|
||||||
|
publishedFor: string;
|
||||||
|
creatorName: string;
|
||||||
|
tags: string;
|
||||||
|
isYoutube: boolean;
|
||||||
|
isInternationalMedia: boolean;
|
||||||
|
attachFromScheduleId?: number; // ✅ Tambahkan properti ini
|
||||||
|
} = {
|
||||||
...data,
|
...data,
|
||||||
title: finalTitle,
|
title: finalTitle,
|
||||||
description: finalDescription,
|
description: finalDescription,
|
||||||
|
|
@ -460,6 +475,10 @@ export default function FormTeks() {
|
||||||
|
|
||||||
let id = Cookies.get("idCreate");
|
let id = Cookies.get("idCreate");
|
||||||
|
|
||||||
|
if (scheduleId !== undefined) {
|
||||||
|
requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini
|
||||||
|
}
|
||||||
|
|
||||||
if (id == undefined) {
|
if (id == undefined) {
|
||||||
const response = await createMedia(requestData);
|
const response = await createMedia(requestData);
|
||||||
console.log("Form Data Submitted:", requestData);
|
console.log("Form Data Submitted:", requestData);
|
||||||
|
|
|
||||||
|
|
@ -441,7 +441,22 @@ export default function FormVideo() {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const requestData = {
|
let requestData: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
htmlDescription: string;
|
||||||
|
fileTypeId: string;
|
||||||
|
categoryId: any;
|
||||||
|
subCategoryId: any;
|
||||||
|
uploadedBy: string;
|
||||||
|
statusId: string;
|
||||||
|
publishedFor: string;
|
||||||
|
creatorName: string;
|
||||||
|
tags: string;
|
||||||
|
isYoutube: boolean;
|
||||||
|
isInternationalMedia: boolean;
|
||||||
|
attachFromScheduleId?: number; // ✅ Tambahkan properti ini
|
||||||
|
} = {
|
||||||
...data,
|
...data,
|
||||||
title: finalTitle,
|
title: finalTitle,
|
||||||
description: finalDescription,
|
description: finalDescription,
|
||||||
|
|
@ -460,6 +475,10 @@ export default function FormVideo() {
|
||||||
|
|
||||||
let id = Cookies.get("idCreate");
|
let id = Cookies.get("idCreate");
|
||||||
|
|
||||||
|
if (scheduleId !== undefined) {
|
||||||
|
requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini
|
||||||
|
}
|
||||||
|
|
||||||
if (id == undefined) {
|
if (id == undefined) {
|
||||||
const response = await createMedia(requestData);
|
const response = await createMedia(requestData);
|
||||||
console.log("Form Data Submitted:", requestData);
|
console.log("Form Data Submitted:", requestData);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import {
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { CalendarIcon, Clock1, MapPin, Plus, User2 } from "lucide-react";
|
import { CalendarIcon, Clock1, Eye, MapPin, Plus, User2 } from "lucide-react";
|
||||||
import { Calendar } from "@/components/ui/calendar";
|
import { Calendar } from "@/components/ui/calendar";
|
||||||
import { addDays, format, parseISO, setDate } from "date-fns";
|
import { addDays, format, parseISO, setDate } from "date-fns";
|
||||||
import { DateRange } from "react-day-picker";
|
import { DateRange } from "react-day-picker";
|
||||||
|
|
@ -30,6 +30,7 @@ import { error, loading } from "@/lib/swal";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import {
|
import {
|
||||||
detailSchedule,
|
detailSchedule,
|
||||||
|
getListScheduleAttachment,
|
||||||
listScheduleNext,
|
listScheduleNext,
|
||||||
listScheduleToday,
|
listScheduleToday,
|
||||||
postSchedule,
|
postSchedule,
|
||||||
|
|
@ -61,6 +62,14 @@ interface Detail {
|
||||||
addressLong: number;
|
addressLong: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Attachment {
|
||||||
|
id: any;
|
||||||
|
title: string;
|
||||||
|
fileTypeId: number;
|
||||||
|
type: number;
|
||||||
|
fileTypeName: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default function FormEventDetail() {
|
export default function FormEventDetail() {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const { id } = useParams() as { id: string };
|
const { id } = useParams() as { id: string };
|
||||||
|
|
@ -89,6 +98,14 @@ export default function FormEventDetail() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [lampiran, setDataLampiran] = useState<Attachment[]>([]);
|
||||||
|
|
||||||
|
async function getDataAttachment() {
|
||||||
|
const response = await getListScheduleAttachment(id);
|
||||||
|
console.log("data attach", response?.data?.data?.content);
|
||||||
|
setDataLampiran(response?.data?.data?.content);
|
||||||
|
}
|
||||||
|
|
||||||
async function getDataByDate() {
|
async function getDataByDate() {
|
||||||
const resToday = await listScheduleToday();
|
const resToday = await listScheduleToday();
|
||||||
const today = resToday?.data?.data;
|
const today = resToday?.data?.data;
|
||||||
|
|
@ -120,6 +137,7 @@ export default function FormEventDetail() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initState();
|
initState();
|
||||||
|
getDataAttachment();
|
||||||
}, [refresh, setValue]);
|
}, [refresh, setValue]);
|
||||||
|
|
||||||
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
|
@ -130,6 +148,29 @@ export default function FormEventDetail() {
|
||||||
setEndTime(e.target.value);
|
setEndTime(e.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDestinationUpload = (
|
||||||
|
type: number,
|
||||||
|
id: string | number,
|
||||||
|
setOpen: (open: boolean) => void,
|
||||||
|
router: any
|
||||||
|
) => {
|
||||||
|
setOpen(false); // Tutup modal dialog
|
||||||
|
|
||||||
|
if (id !== undefined) {
|
||||||
|
Cookies.set("scheduleId", id.toString(), { expires: 1 });
|
||||||
|
Cookies.set("scheduleType", "3", { expires: 1 });
|
||||||
|
|
||||||
|
const routes: Record<number, string> = {
|
||||||
|
1: "/in/contributor/schedule/media/image/create",
|
||||||
|
2: "/in/contributor/schedule/media/video/create",
|
||||||
|
3: "/in/contributor/schedule/media/text/create",
|
||||||
|
4: "/in/contributor/schedule/media/audio/create",
|
||||||
|
};
|
||||||
|
|
||||||
|
router.push(routes[type] || "/admin/schedule/media/audio/create");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col lg:flex-row gap-2">
|
<div className="flex flex-col lg:flex-row gap-2">
|
||||||
<Card className="w-full lg:w-9/12">
|
<Card className="w-full lg:w-9/12">
|
||||||
|
|
@ -336,92 +377,67 @@ export default function FormEventDetail() {
|
||||||
<Button color="primary" size="sm" type="button">
|
<Button color="primary" size="sm" type="button">
|
||||||
<Plus /> Tambah Lampiran
|
<Plus /> Tambah Lampiran
|
||||||
</Button>
|
</Button>
|
||||||
<p>0 Lampiran</p>
|
<p>{lampiran?.length || 0} Lampiran</p>
|
||||||
</div>
|
</div>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="max-w-md p-6 bg-white rounded-lg shadow-lg h-[420px] w-[700px]">
|
<DialogContent className="max-w-md p-6 bg-white rounded-lg shadow-lg h-[420px] w-[700px]">
|
||||||
<h2 className="text-lg font-semibold">
|
<h2 className="text-lg font-semibold">
|
||||||
Pilih Jenis Lampiran
|
Pilih Jenis Lampiran
|
||||||
</h2>
|
</h2>
|
||||||
<div className=" space-y-4 gap-y-4">
|
<div className="space-y-4 gap-y-4">
|
||||||
<Link href={"/contributor/schedule/media/video/create"}>
|
{[
|
||||||
<div className="flex flex-row items-center space-x-4">
|
{
|
||||||
<div className="flex flex-col w-4/12 items-center">
|
type: 2,
|
||||||
<img
|
img: "/assets/img/upload-video.png",
|
||||||
src={"/assets/img/upload-video.png"}
|
label: "Audio Visual",
|
||||||
alt={"item.label"}
|
},
|
||||||
className="w-12 h-12"
|
{
|
||||||
/>
|
type: 1,
|
||||||
<h3 className="text-base font-semibold">
|
img: "/assets/img/upload-image.png",
|
||||||
Audio Visual
|
label: "Foto",
|
||||||
</h3>
|
},
|
||||||
|
{
|
||||||
|
type: 3,
|
||||||
|
img: "/assets/img/upload-text.png",
|
||||||
|
label: "Teks",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 4,
|
||||||
|
img: "/assets/img/upload-audio.png",
|
||||||
|
label: "Audio",
|
||||||
|
},
|
||||||
|
].map((item) => (
|
||||||
|
<a
|
||||||
|
key={item.type}
|
||||||
|
onClick={() =>
|
||||||
|
handleDestinationUpload(
|
||||||
|
item.type,
|
||||||
|
id,
|
||||||
|
setOpen,
|
||||||
|
router
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="flex flex-row items-center space-x-4">
|
||||||
|
<div className="flex flex-col w-4/12 items-center">
|
||||||
|
<img
|
||||||
|
src={item.img}
|
||||||
|
alt={item.label}
|
||||||
|
className="w-12 h-12"
|
||||||
|
/>
|
||||||
|
<h3 className="text-base font-semibold">
|
||||||
|
{item.label}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div className="w-8/12">
|
||||||
|
<p className="text-sm text-gray-600">
|
||||||
|
Unggah media berupa {item.label.toLowerCase()}{" "}
|
||||||
|
dengan format sesuai yang didukung.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-8/12">
|
</a>
|
||||||
<p className="text-sm text-gray-600">
|
))}
|
||||||
Unggah media berupa video dengan format avi, wmv,
|
|
||||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
|
||||||
500mb.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
<Link href={"/contributor/schedule/media/image/create"}>
|
|
||||||
<div className="flex flex-row items-center space-x-4">
|
|
||||||
<div className="flex flex-col w-4/12 items-center">
|
|
||||||
<img
|
|
||||||
src={"/assets/img/upload-image.png"}
|
|
||||||
alt={"item.label"}
|
|
||||||
className="w-12 h-12"
|
|
||||||
/>
|
|
||||||
<h3 className="text-base font-semibold">Foto</h3>
|
|
||||||
</div>
|
|
||||||
<div className="w-8/12">
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
Unggah media berupa video dengan format avi, wmv,
|
|
||||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
|
||||||
500mb.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
<Link href={"/contributor/schedule/media/text/create"}>
|
|
||||||
<div className="flex flex-row items-center space-x-4">
|
|
||||||
<div className="flex flex-col w-4/12 items-center">
|
|
||||||
<img
|
|
||||||
src={"/assets/img/upload-text.png"}
|
|
||||||
alt={"item.label"}
|
|
||||||
className="w-12 h-12"
|
|
||||||
/>
|
|
||||||
<h3 className="text-base font-semibold">Teks</h3>
|
|
||||||
</div>
|
|
||||||
<div className="w-8/12">
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
Unggah media berupa video dengan format avi, wmv,
|
|
||||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
|
||||||
500mb.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
<Link href={"/contributor/schedule/media/audio/create"}>
|
|
||||||
<div className="flex flex-row items-center space-x-4">
|
|
||||||
<div className="flex flex-col w-4/12 items-center">
|
|
||||||
<img
|
|
||||||
src={"/assets/img/upload-audio.png"}
|
|
||||||
alt={"item.label"}
|
|
||||||
className="w-12 h-12"
|
|
||||||
/>
|
|
||||||
<h3 className="text-base font-semibold">Audio</h3>
|
|
||||||
</div>
|
|
||||||
<div className="w-8/12">
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
Unggah media berupa video dengan format avi, wmv,
|
|
||||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
|
||||||
500mb.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
@ -430,7 +446,52 @@ export default function FormEventDetail() {
|
||||||
""
|
""
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 flex justify-end">
|
<div className="mt-6 mx-6">
|
||||||
|
<table className="w-full border border-gray-300 rounded-lg">
|
||||||
|
<thead className="bg-gray-200 text-left">
|
||||||
|
<tr>
|
||||||
|
<th className="p-3 font-semibold">Judul Konten</th>
|
||||||
|
<th className="p-3 font-semibold">Konten</th>
|
||||||
|
<th className="p-3 font-semibold">Tindakan</th>
|
||||||
|
<th className="p-3 font-semibold">Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{lampiran.map((item, index) => (
|
||||||
|
<tr key={index} className="border-t border-gray-300">
|
||||||
|
<td className="p-3 text-blue-600 cursor-pointer">
|
||||||
|
{item.title}
|
||||||
|
</td>
|
||||||
|
<td className="p-3">{item.fileTypeName}</td>
|
||||||
|
<td className="p-3 text-blue-600">Konfersi Ai</td>
|
||||||
|
<td className="p-3">
|
||||||
|
<Link
|
||||||
|
href={
|
||||||
|
Number(item.fileTypeId) == 1
|
||||||
|
? `/contributor/content/image/detail/${item.id}`
|
||||||
|
: Number(item.fileTypeId) == 2
|
||||||
|
? `/contributor/content/video/detail/${item.id}`
|
||||||
|
: Number(item.fileTypeId) == 3
|
||||||
|
? `/contributor/content/teks/detail/${item.id}`
|
||||||
|
: `/contributor/content/audio/detail/${item.id}`
|
||||||
|
}
|
||||||
|
target="_blank"
|
||||||
|
className="btn"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<Eye
|
||||||
|
className={
|
||||||
|
item.type === 1 ? "text-blue-600" : "text-black"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div className="my-4 mr-6 flex justify-end">
|
||||||
<Button type="submit" color="primary">
|
<Button type="submit" color="primary">
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import {
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { CalendarIcon, Clock1, MapPin, Plus, User2 } from "lucide-react";
|
import { CalendarIcon, Clock1, Eye, MapPin, Plus, User2 } from "lucide-react";
|
||||||
import { Calendar } from "@/components/ui/calendar";
|
import { Calendar } from "@/components/ui/calendar";
|
||||||
import { addDays, format, parseISO, setDate } from "date-fns";
|
import { addDays, format, parseISO, setDate } from "date-fns";
|
||||||
import { DateRange } from "react-day-picker";
|
import { DateRange } from "react-day-picker";
|
||||||
|
|
@ -30,6 +30,7 @@ import { error, loading } from "@/lib/swal";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import {
|
import {
|
||||||
detailSchedule,
|
detailSchedule,
|
||||||
|
getListScheduleAttachment,
|
||||||
listScheduleNext,
|
listScheduleNext,
|
||||||
listScheduleToday,
|
listScheduleToday,
|
||||||
postSchedule,
|
postSchedule,
|
||||||
|
|
@ -50,6 +51,7 @@ import {
|
||||||
import { formatDate } from "@fullcalendar/core/index.js";
|
import { formatDate } from "@fullcalendar/core/index.js";
|
||||||
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
|
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
|
||||||
import { Link } from "@/i18n/routing";
|
import { Link } from "@/i18n/routing";
|
||||||
|
import $ from "jquery";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -68,6 +70,14 @@ interface Detail {
|
||||||
addressLong: number;
|
addressLong: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Attachment {
|
||||||
|
id: any;
|
||||||
|
title: string;
|
||||||
|
fileTypeId: number;
|
||||||
|
type: number;
|
||||||
|
fileTypeName: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default function FormDetailPressRillis() {
|
export default function FormDetailPressRillis() {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const { id } = useParams() as { id: string };
|
const { id } = useParams() as { id: string };
|
||||||
|
|
@ -98,6 +108,14 @@ export default function FormDetailPressRillis() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [lampiran, setDataLampiran] = useState<Attachment[]>([]);
|
||||||
|
|
||||||
|
async function getDataAttachment() {
|
||||||
|
const response = await getListScheduleAttachment(id);
|
||||||
|
console.log("data attach", response?.data?.data?.content);
|
||||||
|
setDataLampiran(response?.data?.data?.content);
|
||||||
|
}
|
||||||
|
|
||||||
async function getDataByDate() {
|
async function getDataByDate() {
|
||||||
const resToday = await listScheduleToday();
|
const resToday = await listScheduleToday();
|
||||||
const today = resToday?.data?.data;
|
const today = resToday?.data?.data;
|
||||||
|
|
@ -129,6 +147,7 @@ export default function FormDetailPressRillis() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initState();
|
initState();
|
||||||
|
getDataAttachment();
|
||||||
}, [refresh, setValue]);
|
}, [refresh, setValue]);
|
||||||
|
|
||||||
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
|
@ -139,20 +158,26 @@ export default function FormDetailPressRillis() {
|
||||||
setEndTime(e.target.value);
|
setEndTime(e.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUploadAttachment = () => {
|
const handleDestinationUpload = (
|
||||||
const scheduleId = Cookies.get("scheduleId");
|
type: number,
|
||||||
|
id: string | number,
|
||||||
|
setOpen: (open: boolean) => void,
|
||||||
|
router: any
|
||||||
|
) => {
|
||||||
|
setOpen(false); // Tutup modal dialog
|
||||||
|
|
||||||
if (scheduleId == undefined) {
|
if (id !== undefined) {
|
||||||
MySwal.fire({
|
Cookies.set("scheduleId", id.toString(), { expires: 1 });
|
||||||
title: "Simpan Jadwal Terlebih Dahulu",
|
Cookies.set("scheduleType", "3", { expires: 1 });
|
||||||
icon: "info",
|
|
||||||
confirmButtonColor: "#3085d6",
|
const routes: Record<number, string> = {
|
||||||
confirmButtonText: "Ok",
|
1: "/in/contributor/schedule/media/image/create",
|
||||||
}).then((result) => {
|
2: "/in/contributor/schedule/media/video/create",
|
||||||
if (result.isConfirmed) {
|
3: "/in/contributor/schedule/media/text/create",
|
||||||
return true;
|
4: "/in/contributor/schedule/media/audio/create",
|
||||||
}
|
};
|
||||||
});
|
|
||||||
|
router.push(routes[type] || "/admin/schedule/media/audio/create");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -379,92 +404,67 @@ export default function FormDetailPressRillis() {
|
||||||
<Button color="primary" size="sm" type="button">
|
<Button color="primary" size="sm" type="button">
|
||||||
<Plus /> Tambah Lampiran
|
<Plus /> Tambah Lampiran
|
||||||
</Button>
|
</Button>
|
||||||
<p>0 Lampiran</p>
|
<p>{lampiran?.length || 0} Lampiran</p>
|
||||||
</div>
|
</div>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="max-w-md p-6 bg-white rounded-lg shadow-lg h-[420px] w-[700px]">
|
<DialogContent className="max-w-md p-6 bg-white rounded-lg shadow-lg h-[420px] w-[700px]">
|
||||||
<h2 className="text-lg font-semibold">
|
<h2 className="text-lg font-semibold">
|
||||||
Pilih Jenis Lampiran
|
Pilih Jenis Lampiran
|
||||||
</h2>
|
</h2>
|
||||||
<div className=" space-y-4 gap-y-4">
|
<div className="space-y-4 gap-y-4">
|
||||||
<Link href={"/contributor/schedule/media/video/create"}>
|
{[
|
||||||
<div className="flex flex-row items-center space-x-4">
|
{
|
||||||
<div className="flex flex-col w-4/12 items-center">
|
type: 2,
|
||||||
<img
|
img: "/assets/img/upload-video.png",
|
||||||
src={"/assets/img/upload-video.png"}
|
label: "Audio Visual",
|
||||||
alt={"item.label"}
|
},
|
||||||
className="w-12 h-12"
|
{
|
||||||
/>
|
type: 1,
|
||||||
<h3 className="text-base font-semibold">
|
img: "/assets/img/upload-image.png",
|
||||||
Audio Visual
|
label: "Foto",
|
||||||
</h3>
|
},
|
||||||
|
{
|
||||||
|
type: 3,
|
||||||
|
img: "/assets/img/upload-text.png",
|
||||||
|
label: "Teks",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 4,
|
||||||
|
img: "/assets/img/upload-audio.png",
|
||||||
|
label: "Audio",
|
||||||
|
},
|
||||||
|
].map((item) => (
|
||||||
|
<a
|
||||||
|
key={item.type}
|
||||||
|
onClick={() =>
|
||||||
|
handleDestinationUpload(
|
||||||
|
item.type,
|
||||||
|
id,
|
||||||
|
setOpen,
|
||||||
|
router
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="flex flex-row items-center space-x-4">
|
||||||
|
<div className="flex flex-col w-4/12 items-center">
|
||||||
|
<img
|
||||||
|
src={item.img}
|
||||||
|
alt={item.label}
|
||||||
|
className="w-12 h-12"
|
||||||
|
/>
|
||||||
|
<h3 className="text-base font-semibold">
|
||||||
|
{item.label}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div className="w-8/12">
|
||||||
|
<p className="text-sm text-gray-600">
|
||||||
|
Unggah media berupa {item.label.toLowerCase()}{" "}
|
||||||
|
dengan format sesuai yang didukung.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-8/12">
|
</a>
|
||||||
<p className="text-sm text-gray-600">
|
))}
|
||||||
Unggah media berupa video dengan format avi, wmv,
|
|
||||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
|
||||||
500mb.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
<Link href={"/contributor/schedule/media/image/create"}>
|
|
||||||
<div className="flex flex-row items-center space-x-4">
|
|
||||||
<div className="flex flex-col w-4/12 items-center">
|
|
||||||
<img
|
|
||||||
src={"/assets/img/upload-image.png"}
|
|
||||||
alt={"item.label"}
|
|
||||||
className="w-12 h-12"
|
|
||||||
/>
|
|
||||||
<h3 className="text-base font-semibold">Foto</h3>
|
|
||||||
</div>
|
|
||||||
<div className="w-8/12">
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
Unggah media berupa video dengan format avi, wmv,
|
|
||||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
|
||||||
500mb.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
<Link href={"/contributor/schedule/media/text/create"}>
|
|
||||||
<div className="flex flex-row items-center space-x-4">
|
|
||||||
<div className="flex flex-col w-4/12 items-center">
|
|
||||||
<img
|
|
||||||
src={"/assets/img/upload-text.png"}
|
|
||||||
alt={"item.label"}
|
|
||||||
className="w-12 h-12"
|
|
||||||
/>
|
|
||||||
<h3 className="text-base font-semibold">Teks</h3>
|
|
||||||
</div>
|
|
||||||
<div className="w-8/12">
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
Unggah media berupa video dengan format avi, wmv,
|
|
||||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
|
||||||
500mb.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
<Link href={"/contributor/schedule/media/audio/create"}>
|
|
||||||
<div className="flex flex-row items-center space-x-4">
|
|
||||||
<div className="flex flex-col w-4/12 items-center">
|
|
||||||
<img
|
|
||||||
src={"/assets/img/upload-audio.png"}
|
|
||||||
alt={"item.label"}
|
|
||||||
className="w-12 h-12"
|
|
||||||
/>
|
|
||||||
<h3 className="text-base font-semibold">Audio</h3>
|
|
||||||
</div>
|
|
||||||
<div className="w-8/12">
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
Unggah media berupa video dengan format avi, wmv,
|
|
||||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
|
||||||
500mb.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
@ -472,6 +472,51 @@ export default function FormDetailPressRillis() {
|
||||||
) : (
|
) : (
|
||||||
""
|
""
|
||||||
)}
|
)}
|
||||||
|
<div className="mt-6">
|
||||||
|
<table className="w-full border border-gray-300 rounded-lg">
|
||||||
|
<thead className="bg-gray-200 text-left">
|
||||||
|
<tr>
|
||||||
|
<th className="p-3 font-semibold">Judul Konten</th>
|
||||||
|
<th className="p-3 font-semibold">Konten</th>
|
||||||
|
<th className="p-3 font-semibold">Tindakan</th>
|
||||||
|
<th className="p-3 font-semibold">Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{lampiran.map((item, index) => (
|
||||||
|
<tr key={index} className="border-t border-gray-300">
|
||||||
|
<td className="p-3 text-blue-600 cursor-pointer">
|
||||||
|
{item.title}
|
||||||
|
</td>
|
||||||
|
<td className="p-3">{item.fileTypeName}</td>
|
||||||
|
<td className="p-3 text-blue-600">Konfersi Ai</td>
|
||||||
|
<td className="p-3">
|
||||||
|
<Link
|
||||||
|
href={
|
||||||
|
Number(item.fileTypeId) == 1
|
||||||
|
? `/contributor/content/image/detail/${item.id}`
|
||||||
|
: Number(item.fileTypeId) == 2
|
||||||
|
? `/contributor/content/video/detail/${item.id}`
|
||||||
|
: Number(item.fileTypeId) == 3
|
||||||
|
? `/contributor/content/teks/detail/${item.id}`
|
||||||
|
: `/contributor/content/audio/detail/${item.id}`
|
||||||
|
}
|
||||||
|
target="_blank"
|
||||||
|
className="btn"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<Eye
|
||||||
|
className={
|
||||||
|
item.type === 1 ? "text-blue-600" : "text-black"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
<div className="mt-4 flex justify-end">
|
<div className="mt-4 flex justify-end">
|
||||||
<Button type="submit" color="primary">
|
<Button type="submit" color="primary">
|
||||||
Submit
|
Submit
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,17 @@ import React, { useEffect } from "react";
|
||||||
import DateRangePicker from "@/components/date-range-picker";
|
import DateRangePicker from "@/components/date-range-picker";
|
||||||
import { usePathname } from "@/components/navigation";
|
import { usePathname } from "@/components/navigation";
|
||||||
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "./ui/dialog";
|
||||||
|
import { Button } from "./ui/button";
|
||||||
|
import { Label } from "./ui/label";
|
||||||
|
import { Input } from "./ui/input";
|
||||||
|
|
||||||
const PageTitle = ({
|
const PageTitle = ({
|
||||||
title,
|
title,
|
||||||
|
|
@ -30,7 +41,35 @@ const PageTitle = ({
|
||||||
<div className="text-2xl font-medium text-default-800 capitalize">
|
<div className="text-2xl font-medium text-default-800 capitalize">
|
||||||
Dashboard
|
Dashboard
|
||||||
</div>
|
</div>
|
||||||
<DateRangePicker />
|
<Dialog>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<Button variant="outline">Download Report</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-[425px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Download Report</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="grid gap-4 py-4">
|
||||||
|
<div className="w-full">
|
||||||
|
<Label>Date</Label>
|
||||||
|
<Input
|
||||||
|
type="date"
|
||||||
|
// value={dateFilter}
|
||||||
|
// onChange={(e) => setDateFilter(e.target.value)}
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
// onClick={downloadReport}
|
||||||
|
>
|
||||||
|
Download
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
"use client";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
|
import { generateTicket } from "@/service/tableau/tableau-service";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
|
export default function PerformanceSatkerViz() {
|
||||||
|
const [hasMounted, setHasMounted] = useState(false);
|
||||||
|
const t = useTranslations("AnalyticsDashboard");
|
||||||
|
const levelName = getCookiesDecrypt("ulnae");
|
||||||
|
const poldaState = Cookies.get("state");
|
||||||
|
const provState = Cookies.get("state-prov");
|
||||||
|
|
||||||
|
const [ticket1, setTicket1] = useState("");
|
||||||
|
const [ticket2, setTicket2] = useState("");
|
||||||
|
const [ticket3, setTicket3] = useState("");
|
||||||
|
const [ticket4, setTicket4] = useState("");
|
||||||
|
const [isInternational, setIsInternational] = useState([false, false, false]);
|
||||||
|
|
||||||
|
const baseUrl = "https://db-mediahub.polri.go.id/";
|
||||||
|
const url = "https://db-mediahub.polri.go.id/trusted/";
|
||||||
|
|
||||||
|
const view1 =
|
||||||
|
levelName == "MABES POLRI"
|
||||||
|
? isInternational[0]
|
||||||
|
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-konten-top10?"
|
||||||
|
: "views/2023_04_MediaHUB-Viz-POLDA_Rev201/db-konten-top10?"
|
||||||
|
: `/views/2023_09_db-ranking-polres-by-polda_rev100/db-ranking-by-polda?polda-selected=${provState}&`;
|
||||||
|
|
||||||
|
const param = ":embed=yes&:toolbar=yes&:iframeSizedToWindow=true";
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function initState() {
|
||||||
|
const response1 = await generateTicket();
|
||||||
|
setTicket1(response1?.data?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
initState();
|
||||||
|
}, [isInternational]);
|
||||||
|
|
||||||
|
// Hooks
|
||||||
|
useEffect(() => {
|
||||||
|
setHasMounted(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Render
|
||||||
|
if (!hasMounted) return null;
|
||||||
|
|
||||||
|
const handleInternational = (index: number, val: boolean) => {
|
||||||
|
const updatedIsInternational = [...isInternational];
|
||||||
|
|
||||||
|
updatedIsInternational[index] = val;
|
||||||
|
setIsInternational(updatedIsInternational);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-2 bg-white rounded-lg p-3">
|
||||||
|
<p className="text-lg">
|
||||||
|
<b>
|
||||||
|
{isInternational[0] ? "SATKER PERFORMANCE" : "POLFORMANCE SATKER"}
|
||||||
|
</b>
|
||||||
|
</p>
|
||||||
|
<div className="my-5">
|
||||||
|
{ticket1 == "" ? (
|
||||||
|
<iframe
|
||||||
|
src={`${baseUrl + view1 + param}`}
|
||||||
|
width="100%"
|
||||||
|
height="750"
|
||||||
|
frameBorder="0"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<iframe
|
||||||
|
src={`${`${url + ticket1}/${view1}${param}`}`}
|
||||||
|
width="100%"
|
||||||
|
height="750"
|
||||||
|
frameBorder="0"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
129
lib/menus.ts
129
lib/menus.ts
|
|
@ -1591,21 +1591,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
submenus: [
|
submenus: [
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/press-conference",
|
href: "/contributor/schedule/press-conference",
|
||||||
label: "konferensi pers",
|
label: t("press-conference"),
|
||||||
active: pathname.includes("/schedule/press-conference"),
|
active: pathname.includes("/schedule/press-conference"),
|
||||||
icon: "heroicons:arrow-trending-up",
|
icon: "heroicons:arrow-trending-up",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/event",
|
href: "/contributor/schedule/event",
|
||||||
label: "event",
|
label: t("event"),
|
||||||
active: pathname.includes("/schedule/event"),
|
active: pathname.includes("/schedule/event"),
|
||||||
icon: "heroicons:shopping-cart",
|
icon: "heroicons:shopping-cart",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/press-release",
|
href: "/contributor/schedule/press-release",
|
||||||
label: "pers rilis",
|
label: t("press-release"),
|
||||||
active: pathname.includes("/schedule/press-release"),
|
active: pathname.includes("/schedule/press-release"),
|
||||||
icon: "heroicons:shopping-cart",
|
icon: "heroicons:shopping-cart",
|
||||||
children: [],
|
children: [],
|
||||||
|
|
@ -1789,21 +1789,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
submenus: [
|
submenus: [
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/press-conference",
|
href: "/contributor/schedule/press-conference",
|
||||||
label: "konferensi pers",
|
label: t("press-conference"),
|
||||||
active: pathname.includes("/schedule/press-conference"),
|
active: pathname.includes("/schedule/press-conference"),
|
||||||
icon: "heroicons:arrow-trending-up",
|
icon: "heroicons:arrow-trending-up",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/event",
|
href: "/contributor/schedule/event",
|
||||||
label: "event",
|
label: t("event"),
|
||||||
active: pathname.includes("/schedule/event"),
|
active: pathname.includes("/schedule/event"),
|
||||||
icon: "heroicons:shopping-cart",
|
icon: "heroicons:shopping-cart",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/press-release",
|
href: "/contributor/schedule/press-release",
|
||||||
label: "pers rilis",
|
label: t("press-release"),
|
||||||
active: pathname.includes("/schedule/press-release"),
|
active: pathname.includes("/schedule/press-release"),
|
||||||
icon: "heroicons:shopping-cart",
|
icon: "heroicons:shopping-cart",
|
||||||
children: [],
|
children: [],
|
||||||
|
|
@ -2019,7 +2019,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
submenus: [
|
submenus: [
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/press-conference",
|
href: "/contributor/schedule/press-conference",
|
||||||
label: "konferensi pers",
|
label: t("press-conference"),
|
||||||
active: pathname.includes("/schedule/press-conference"),
|
active: pathname.includes("/schedule/press-conference"),
|
||||||
icon: "heroicons:arrow-trending-up",
|
icon: "heroicons:arrow-trending-up",
|
||||||
children: [],
|
children: [],
|
||||||
|
|
@ -2033,7 +2033,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/press-release",
|
href: "/contributor/schedule/press-release",
|
||||||
label: "pers rilis",
|
label: t("press-release"),
|
||||||
active: pathname.includes("/schedule/press-release"),
|
active: pathname.includes("/schedule/press-release"),
|
||||||
icon: "heroicons:shopping-cart",
|
icon: "heroicons:shopping-cart",
|
||||||
children: [],
|
children: [],
|
||||||
|
|
@ -2233,21 +2233,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
submenus: [
|
submenus: [
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/press-conference",
|
href: "/contributor/schedule/press-conference",
|
||||||
label: "konferensi pers",
|
label: t("press-conference"),
|
||||||
active: pathname.includes("/schedule/press-conference"),
|
active: pathname.includes("/schedule/press-conference"),
|
||||||
icon: "heroicons:arrow-trending-up",
|
icon: "heroicons:arrow-trending-up",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/event",
|
href: "/contributor/schedule/event",
|
||||||
label: "event",
|
label: t("event"),
|
||||||
active: pathname.includes("/schedule/event"),
|
active: pathname.includes("/schedule/event"),
|
||||||
icon: "heroicons:shopping-cart",
|
icon: "heroicons:shopping-cart",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/press-release",
|
href: "/contributor/schedule/press-release",
|
||||||
label: "pers rilis",
|
label: t("press-release"),
|
||||||
active: pathname.includes("/schedule/press-release"),
|
active: pathname.includes("/schedule/press-release"),
|
||||||
icon: "heroicons:shopping-cart",
|
icon: "heroicons:shopping-cart",
|
||||||
children: [],
|
children: [],
|
||||||
|
|
@ -2442,21 +2442,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
submenus: [
|
submenus: [
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/press-conference",
|
href: "/contributor/schedule/press-conference",
|
||||||
label: "konferensi pers",
|
label: t("press-conference"),
|
||||||
active: pathname.includes("/schedule/press-conference"),
|
active: pathname.includes("/schedule/press-conference"),
|
||||||
icon: "heroicons:arrow-trending-up",
|
icon: "heroicons:arrow-trending-up",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/event",
|
href: "/contributor/schedule/event",
|
||||||
label: "event",
|
label: t("event"),
|
||||||
active: pathname.includes("/schedule/event"),
|
active: pathname.includes("/schedule/event"),
|
||||||
icon: "heroicons:shopping-cart",
|
icon: "heroicons:shopping-cart",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/contributor/schedule/press-release",
|
href: "/contributor/schedule/press-release",
|
||||||
label: "pers rilis",
|
label: t("press-release"),
|
||||||
active: pathname.includes("/schedule/press-release"),
|
active: pathname.includes("/schedule/press-release"),
|
||||||
icon: "heroicons:shopping-cart",
|
icon: "heroicons:shopping-cart",
|
||||||
children: [],
|
children: [],
|
||||||
|
|
@ -3202,20 +3202,20 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
groupLabel: "",
|
// groupLabel: "",
|
||||||
id: "agenda-setting",
|
// id: "agenda-setting",
|
||||||
menus: [
|
// menus: [
|
||||||
{
|
// {
|
||||||
id: "agenda-setting",
|
// id: "agenda-setting",
|
||||||
href: "/contributor/agenda-setting",
|
// href: "/contributor/agenda-setting",
|
||||||
label: t("agenda-setting"),
|
// label: t("agenda-setting"),
|
||||||
active: pathname.includes("/agenda-setting"),
|
// active: pathname.includes("/agenda-setting"),
|
||||||
icon: "iconoir:journal-page",
|
// icon: "iconoir:journal-page",
|
||||||
submenus: [],
|
// submenus: [],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
groupLabel: "",
|
groupLabel: "",
|
||||||
id: "performance-polres",
|
id: "performance-polres",
|
||||||
|
|
@ -3364,11 +3364,39 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
label: t("dashboard"),
|
label: t("dashboard"),
|
||||||
active: pathname.includes("/dashboard"),
|
active: pathname.includes("/dashboard"),
|
||||||
icon: "material-symbols:dashboard",
|
icon: "material-symbols:dashboard",
|
||||||
|
submenus: [
|
||||||
|
{
|
||||||
|
href: "/dashboard/executive",
|
||||||
|
label: "Executive",
|
||||||
|
active: pathname === "/dashboard/executive",
|
||||||
|
icon: "heroicons:arrow-trending-up",
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/dashboard",
|
||||||
|
label: "Breakdown",
|
||||||
|
active: pathname === "/dashboard",
|
||||||
|
icon: "heroicons:arrow-trending-up",
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupLabel: "",
|
||||||
|
id: "management-user",
|
||||||
|
menus: [
|
||||||
|
{
|
||||||
|
id: "management-user-menu",
|
||||||
|
href: "/admin/management-user",
|
||||||
|
label: "Management User",
|
||||||
|
active: pathname.includes("/management-user"),
|
||||||
|
icon: "clarity:users-solid",
|
||||||
submenus: [],
|
submenus: [],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
groupLabel: "",
|
groupLabel: "",
|
||||||
id: "content-production",
|
id: "content-production",
|
||||||
|
|
@ -3397,6 +3425,49 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
groupLabel: "",
|
||||||
|
id: "performance-polres",
|
||||||
|
menus: [
|
||||||
|
{
|
||||||
|
id: "performance-polres",
|
||||||
|
href: "/admin/performance-satker",
|
||||||
|
label: t("performance-satker"),
|
||||||
|
active: pathname.includes("/admin/performance-satker"),
|
||||||
|
icon: "ant-design:signal-filled",
|
||||||
|
submenus: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupLabel: "",
|
||||||
|
id: "media-tracking",
|
||||||
|
menus: [
|
||||||
|
{
|
||||||
|
id: "media-tracking",
|
||||||
|
href: "/curator/media-tracking",
|
||||||
|
label: t("media-tracking"),
|
||||||
|
active: pathname.includes("/media-tracking"),
|
||||||
|
icon: "material-symbols:map-search-outline",
|
||||||
|
submenus: [
|
||||||
|
{
|
||||||
|
href: "/admin/media-tracking/media-online",
|
||||||
|
label: "Media Online",
|
||||||
|
active: pathname === "/media-tracking/media-online",
|
||||||
|
icon: "heroicons:arrow-trending-up",
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "/admin/media-tracking/tb-news",
|
||||||
|
label: "Tracking Beritra Hari Ini",
|
||||||
|
active: pathname === "/media-tracking/news",
|
||||||
|
icon: "heroicons:arrow-trending-up",
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
groupLabel: "",
|
groupLabel: "",
|
||||||
id: "communication",
|
id: "communication",
|
||||||
|
|
|
||||||
|
|
@ -325,10 +325,15 @@
|
||||||
"colors": "Colors",
|
"colors": "Colors",
|
||||||
"performance-polda": "Performance Polda",
|
"performance-polda": "Performance Polda",
|
||||||
"performance-polres": "Performance Polres",
|
"performance-polres": "Performance Polres",
|
||||||
|
"performance-satker": "Performance Satker",
|
||||||
"analysis": "Analysis",
|
"analysis": "Analysis",
|
||||||
"management-content": "Content Management ",
|
"management-content": "Content Management ",
|
||||||
"add-experts": "Add Experts",
|
"add-experts": "Add Experts",
|
||||||
"category": "Category",
|
"category": "Category",
|
||||||
|
"add-category": "Add Category",
|
||||||
|
"tags": "Tags",
|
||||||
|
"add-tags": "Add Tags",
|
||||||
|
"add": "Add",
|
||||||
"privacy": "Privacy Policy"
|
"privacy": "Privacy Policy"
|
||||||
},
|
},
|
||||||
"Changelog": {
|
"Changelog": {
|
||||||
|
|
@ -580,7 +585,8 @@
|
||||||
"schedule": "Schedule",
|
"schedule": "Schedule",
|
||||||
"press-conference": "Press Conference",
|
"press-conference": "Press Conference",
|
||||||
"press-release": "Press Release",
|
"press-release": "Press Release",
|
||||||
"create-schedule": "Create Schedule"
|
"create-schedule": "Create Schedule",
|
||||||
|
"event": "event"
|
||||||
},
|
},
|
||||||
"Blog": {
|
"Blog": {
|
||||||
"table": "Table",
|
"table": "Table",
|
||||||
|
|
@ -599,5 +605,37 @@
|
||||||
"table": "Table",
|
"table": "Table",
|
||||||
"contest": "Lomba",
|
"contest": "Lomba",
|
||||||
"create-contest": "Create Contest"
|
"create-contest": "Create Contest"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -326,10 +326,15 @@
|
||||||
"colors": "Colors",
|
"colors": "Colors",
|
||||||
"performance-polda": "Performa Polda",
|
"performance-polda": "Performa Polda",
|
||||||
"performance-polres": "Performa Polres",
|
"performance-polres": "Performa Polres",
|
||||||
|
"performance-satker": "Performa Satker",
|
||||||
"analysis": "Analisa",
|
"analysis": "Analisa",
|
||||||
"management-content": "Manajemen Konten",
|
"management-content": "Manajemen Konten",
|
||||||
"add-experts": "Tambah Tenaga Ahli",
|
"add-experts": "Tambah Tenaga Ahli",
|
||||||
"category": "Kategori",
|
"category": "Kategori",
|
||||||
|
"add-category": "Tambah Kategori",
|
||||||
|
"tags": "Tag",
|
||||||
|
"add-tags": "Tambah Tag",
|
||||||
|
"add": "Tambah",
|
||||||
"privacy": "Kebijakan Privacy"
|
"privacy": "Kebijakan Privacy"
|
||||||
},
|
},
|
||||||
"Changelog": {
|
"Changelog": {
|
||||||
|
|
@ -581,7 +586,8 @@
|
||||||
"schedule": "Jadwal",
|
"schedule": "Jadwal",
|
||||||
"press-conference": "Konferensi Pers",
|
"press-conference": "Konferensi Pers",
|
||||||
"press-release": "Pers Rilis",
|
"press-release": "Pers Rilis",
|
||||||
"create-schedule": "Buat Jadwal"
|
"create-schedule": "Buat Jadwal",
|
||||||
|
"event": "event"
|
||||||
},
|
},
|
||||||
"Blog": {
|
"Blog": {
|
||||||
"table": "Tabel",
|
"table": "Tabel",
|
||||||
|
|
@ -600,5 +606,37 @@
|
||||||
"table": "Tabel",
|
"table": "Tabel",
|
||||||
"contest": "Lomba",
|
"contest": "Lomba",
|
||||||
"create-contest": "Buat Lomba"
|
"create-contest": "Buat Lomba"
|
||||||
|
},
|
||||||
|
"Curation": {
|
||||||
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,15 @@ import {
|
||||||
import { httpGet } from "../http-config/http-base-service";
|
import { httpGet } from "../http-config/http-base-service";
|
||||||
import { any } from "zod";
|
import { any } from "zod";
|
||||||
|
|
||||||
export async function paginationSchedule(size: number, page: number, type: any, title: string = "") {
|
export async function paginationSchedule(
|
||||||
return await httpGetInterceptor(`schedule/pagination?enablePage=1&scheduleTypeId=${type}&page=${page}&size=${size}&title=${title}`);
|
size: number,
|
||||||
|
page: number,
|
||||||
|
type: any,
|
||||||
|
title: string = ""
|
||||||
|
) {
|
||||||
|
return await httpGetInterceptor(
|
||||||
|
`schedule/pagination?enablePage=1&scheduleTypeId=${type}&page=${page}&size=${size}&title=${title}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function postSchedule(data: any) {
|
export async function postSchedule(data: any) {
|
||||||
|
|
@ -49,6 +56,11 @@ export async function listScheduleToday() {
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getListScheduleAttachment(scheduleId: any) {
|
||||||
|
const url = `media/list?&enablePage=0&scheduleId=${scheduleId}`;
|
||||||
|
return httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function listScheduleNext() {
|
export async function listScheduleNext() {
|
||||||
const url = "schedule/next-activity";
|
const url = "schedule/next-activity";
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue