feat: page regional content filter
This commit is contained in:
parent
30235c240a
commit
d730cc9cf9
|
|
@ -0,0 +1,942 @@
|
||||||
|
"use client";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
|
import {
|
||||||
|
getPublicCategoryData,
|
||||||
|
getUserLevelListByParent,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import ReactDatePicker from "react-datepicker";
|
||||||
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import { close, loading } from "@/config/swal";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import ImageBlurry from "@/components/ui/image-blurry";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
const columns: ColumnDef<any>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "no",
|
||||||
|
header: "No",
|
||||||
|
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function FilterPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const asPath = usePathname();
|
||||||
|
const params = useParams();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const t = useTranslations("FilterPage");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [audioData, setAudioData] = useState<any[]>([]);
|
||||||
|
const [totalData, setTotalData] = useState<number>(1);
|
||||||
|
const [totalPage, setTotalPage] = useState<number>(1);
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||||
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [totalContent, setTotalContent] = useState(0);
|
||||||
|
const [change, setChange] = useState(false);
|
||||||
|
const sortBy = searchParams?.get("sortBy");
|
||||||
|
const title = searchParams?.get("title");
|
||||||
|
const categorie = searchParams?.get("category");
|
||||||
|
const group = searchParams?.get("group");
|
||||||
|
const [categoryFilter, setCategoryFilter] = useState<any[]>([]);
|
||||||
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
|
const [formatFilter, setFormatFilter] = useState<any[]>([]);
|
||||||
|
const pages = page ? page - 1 : 0;
|
||||||
|
const [startDateString, setStartDateString] = useState<any>();
|
||||||
|
const [endDateString, setEndDateString] = useState<any>();
|
||||||
|
const [dateRange, setDateRange] = useState<any>([null, null]);
|
||||||
|
const [handleClose, setHandleClose] = useState(false);
|
||||||
|
const [categories, setCategories] = useState<any[]>([]);
|
||||||
|
const [isFilterOpen, setIsFilterOpen] = useState(true);
|
||||||
|
|
||||||
|
const poldaName = params?.polda_name;
|
||||||
|
const satkerName = params?.satker_name;
|
||||||
|
|
||||||
|
let prefixPath = poldaName
|
||||||
|
? `/polda/${poldaName}`
|
||||||
|
: satkerName
|
||||||
|
? `/satker/${satkerName}`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
// === INIT ===
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => setIsLoading(false), 1200);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const pageFromUrl = searchParams?.get("page");
|
||||||
|
if (pageFromUrl) setPage(Number(pageFromUrl));
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (categorie) {
|
||||||
|
setCategoryFilter(
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [categorie]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategories(categoryPage);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchCategories = async (pageNumber: number) => {
|
||||||
|
const groupParam =
|
||||||
|
poldaName && poldaName.length > 1
|
||||||
|
? poldaName
|
||||||
|
: satkerName && satkerName.length > 1
|
||||||
|
? "satker-" + satkerName
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const isInt = locale === "en";
|
||||||
|
|
||||||
|
const response = await getPublicCategoryData(
|
||||||
|
groupParam,
|
||||||
|
"",
|
||||||
|
isInt,
|
||||||
|
pageNumber
|
||||||
|
); // halaman 1-based
|
||||||
|
|
||||||
|
const content = response?.data?.data?.content || [];
|
||||||
|
const total = response?.data?.data?.totalPages || 1;
|
||||||
|
|
||||||
|
setCategories(content);
|
||||||
|
setCategoryTotalPages(total);
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (asPath?.includes("/regional")) getDataRegional();
|
||||||
|
else getDataAll();
|
||||||
|
}, [
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
|
async function getDataAll() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listData(
|
||||||
|
"4",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
locale == "en" ? true : false
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setAudioData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataRegional() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listDataRegional(
|
||||||
|
"4",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setAudioData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCategoryFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...categoryFilter];
|
||||||
|
if (e) filter.push(String(id));
|
||||||
|
else filter = filter.filter((item) => item !== String(id));
|
||||||
|
router.push(`?category=${filter.join("&")}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormatFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...formatFilter];
|
||||||
|
if (e) filter.push(id);
|
||||||
|
else filter = filter.filter((item) => item !== id);
|
||||||
|
setFormatFilter(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSorting = (e: any) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setSortByOpt(value === "latest" ? "createdAt" : "clickCount");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteDate = () => {
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setStartDateString("");
|
||||||
|
setEndDateString("");
|
||||||
|
setHandleClose(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyUp = () => {
|
||||||
|
if (!searchTitle) router.push("?title=");
|
||||||
|
else router.push(`?title=${searchTitle.toLowerCase()}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// === REACT TABLE ===
|
||||||
|
const table = useReactTable({
|
||||||
|
data: audioData,
|
||||||
|
columns,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
onRowSelectionChange: setRowSelection,
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
state: {
|
||||||
|
sorting,
|
||||||
|
columnFilters,
|
||||||
|
columnVisibility,
|
||||||
|
rowSelection,
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [calenderState, setCalenderState] = useState(false);
|
||||||
|
const [categoryPage, setCategoryPage] = useState(1);
|
||||||
|
const [categoryTotalPages, setCategoryTotalPages] = useState(1);
|
||||||
|
let typingTimer: any;
|
||||||
|
|
||||||
|
const cleanCheckbox = () => {
|
||||||
|
setCategoryFilter([]);
|
||||||
|
setFormatFilter([]);
|
||||||
|
router.push(`?category=&title=`);
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setMonthYearFilter(null);
|
||||||
|
setChange(!change);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = () => {
|
||||||
|
clearTimeout(typingTimer);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
|
||||||
|
<p>
|
||||||
|
{" "}
|
||||||
|
Audio {">"}{" "}
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("allAudio", { defaultValue: "All Audio" })}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">|</p>
|
||||||
|
{!title ? (
|
||||||
|
<p>
|
||||||
|
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
|
||||||
|
"downloadableImage",
|
||||||
|
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
|
||||||
|
)}`}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
|
||||||
|
<span className="font-bold">"{title}"</span>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">
|
||||||
|
{/* Left */}
|
||||||
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
|
Filter
|
||||||
|
</h2>
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
|
{t("search", { defaultValue: "Search" })}
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
value={searchTitle}
|
||||||
|
onChange={(e) => setSearchTitle(e.target.value)}
|
||||||
|
onKeyUp={handleKeyUp}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
type="text"
|
||||||
|
id="search"
|
||||||
|
placeholder={t("searchTitle", { defaultValue: "Search Title" })}
|
||||||
|
className="mt-1 w-full text-sm border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear", { defaultValue: "Month Year" })}
|
||||||
|
</label>
|
||||||
|
<ReactDatePicker
|
||||||
|
selected={monthYearFilter}
|
||||||
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
onChange={(date) => setMonthYearFilter(date)}
|
||||||
|
dateFormat="MM | yyyy"
|
||||||
|
placeholderText={t("selectYear", {
|
||||||
|
defaultValue: "Select Year",
|
||||||
|
})}
|
||||||
|
showMonthYearPicker
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date", { defaultValue: "Date" })}
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
|
<ReactDatePicker
|
||||||
|
selectsRange
|
||||||
|
className="mt-1 w-full border text-sm rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
startDate={dateRange[0]}
|
||||||
|
endDate={dateRange[1]}
|
||||||
|
onChange={(update) => {
|
||||||
|
setDateRange(update);
|
||||||
|
}}
|
||||||
|
placeholderText={t("searchDate", {
|
||||||
|
defaultValue: "Search Date",
|
||||||
|
})}
|
||||||
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* ⬇️ Pagination kategori (rata sejajar) */}
|
||||||
|
<div className="mt-4 flex justify-center items-center gap-2 flex-wrap">
|
||||||
|
{/* Tombol Prev */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{(() => {
|
||||||
|
const maxVisible = 4;
|
||||||
|
let startPage = Math.max(
|
||||||
|
1,
|
||||||
|
Math.min(
|
||||||
|
categoryPage - Math.floor(maxVisible / 2),
|
||||||
|
categoryTotalPages - maxVisible + 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const endPage = Math.min(
|
||||||
|
categoryTotalPages,
|
||||||
|
startPage + maxVisible - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const visiblePages = [];
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
visiblePages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visiblePages.map((pageNum) => (
|
||||||
|
<button
|
||||||
|
key={pageNum}
|
||||||
|
onClick={() => setCategoryPage(pageNum)}
|
||||||
|
className={`px-3 py-1 border rounded text-sm transition-colors ${
|
||||||
|
categoryPage === pageNum
|
||||||
|
? "bg-[#bb3523] text-white"
|
||||||
|
: "bg-white dark:bg-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pageNum}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{/* Tombol Next */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories?.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
<div className="mt-4 flex gap-2 justify-center items-center">
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{Array.from({ length: categoryTotalPages }, (_, i) => (
|
||||||
|
<button
|
||||||
|
key={i}
|
||||||
|
onClick={() => setCategoryPage(i + 1)}
|
||||||
|
className={`px-3 py-1 border rounded ${
|
||||||
|
categoryPage === i + 1 ? "bg-[#bb3523] text-white" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{i + 1}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</div> */}
|
||||||
|
{/* Garis */}
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
{/* Garis */}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="png"
|
||||||
|
value="png"
|
||||||
|
checked={formatFilter.includes("wav")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "wav")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
WAV
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="jpeg"
|
||||||
|
value="jpeg"
|
||||||
|
checked={formatFilter.includes("mp3")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mp3")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MP3
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
|
<div className="text-center">
|
||||||
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
|
<b>Reset Filter</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* CONTENT */}
|
||||||
|
<div className="w-full pr-4 lg:pr-16 pb-4">
|
||||||
|
<Reveal>
|
||||||
|
<div className="flex flex-col items-end mb-4">
|
||||||
|
<h2 className="text-lg font-semibold">Sort By</h2>
|
||||||
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "popular" : "latest"}
|
||||||
|
onChange={handleSorting}
|
||||||
|
className="border rounded-md py-2 px-3"
|
||||||
|
>
|
||||||
|
<option value="latest">Latest</option>
|
||||||
|
<option value="popular">Most Popular</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
</div>
|
||||||
|
) : audioData?.length > 0 ? (
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{audioData?.map((audio: any) => (
|
||||||
|
<Card
|
||||||
|
key={audio?.id}
|
||||||
|
className="hover:scale-105 transition-transform duration-300"
|
||||||
|
>
|
||||||
|
<CardContent
|
||||||
|
key={audio?.id}
|
||||||
|
className="md:basis-1/2 lg:basis-1/3"
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={`${prefixPath}/audio/detail/${audio?.slug
|
||||||
|
?.split("/")
|
||||||
|
.pop()}`}
|
||||||
|
// href={`${prefixPath}/document/detail/${text?.slug}`}
|
||||||
|
// href={prefixPath + `/document/detail/${text?.slug}`}
|
||||||
|
// onClick={() =>
|
||||||
|
// router.push(prefixPath + `/document/detail/${text?.slug}`)
|
||||||
|
// }
|
||||||
|
className="cursor-pointer rounded-lg shadow-md overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500"
|
||||||
|
>
|
||||||
|
{/* Ikon di tengah dengan latar kuning */}
|
||||||
|
<div className="flex items-center justify-center bg-[#bb3523] w-full h-[180px] text-white">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="150"
|
||||||
|
height="150"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M14.702 2.226A1 1 0 0 1 16 3.18v6.027a5.5 5.5 0 0 0-1-.184V6.18L8 8.368V15.5a2.5 2.5 0 1 1-1-2V5.368a1 1 0 0 1 .702-.955zM8 7.32l7-2.187V3.18L8 5.368zM5.5 14a1.5 1.5 0 1 0 0 3a1.5 1.5 0 0 0 0-3m13.5.5a4.5 4.5 0 1 1-9 0a4.5 4.5 0 0 1 9 0m-2.265-.436l-2.994-1.65a.5.5 0 0 0-.741.438v3.3a.5.5 0 0 0 .741.438l2.994-1.65a.5.5 0 0 0 0-.876"
|
||||||
|
/>
|
||||||
|
</svg>{" "}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Konten bawah */}
|
||||||
|
<div className="p-4 flex flex-col gap-2">
|
||||||
|
{/* Kategori merah */}
|
||||||
|
<div className="text-[12px] font-bold text-red-600 uppercase">
|
||||||
|
{audio?.categoryName?.toUpperCase() ?? "Text"}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Judul */}
|
||||||
|
<div className="font-semibold text-gray-900 dark:text-white text-xl leading-snug line-clamp-4">
|
||||||
|
{audio?.title}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-center items-center py-10">
|
||||||
|
<Image
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{totalPage > 1 && (
|
||||||
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Reveal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// import AllContentPage from "@/components/landing-page/all-content-page";
|
||||||
|
|
||||||
|
// const regions = [
|
||||||
|
// { name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
||||||
|
// { name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bangka Belitung",
|
||||||
|
// slug: "bangka-belitung",
|
||||||
|
// logo: "/logo/polda/polda-bangka-belitung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Banten",
|
||||||
|
// slug: "banten",
|
||||||
|
// logo: "/logo/polda/polda-banten.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bengkulu",
|
||||||
|
// slug: "bengkulu",
|
||||||
|
// logo: "/logo/polda/polda-bengkulu.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda DIY",
|
||||||
|
// slug: "jogja",
|
||||||
|
// logo: "/logo/polda/polda-jogja.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Gorontalo",
|
||||||
|
// slug: "gorontalo",
|
||||||
|
// logo: "/logo/polda/polda-gorontalo.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Barat",
|
||||||
|
// slug: "jawa-barat",
|
||||||
|
// logo: "/logo/polda/polda-jawa-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Tengah",
|
||||||
|
// slug: "jawa-tengah",
|
||||||
|
// logo: "/logo/polda/polda-jawa-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Timur",
|
||||||
|
// slug: "jawa-timur",
|
||||||
|
// logo: "/logo/polda/polda-jawa-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Barat",
|
||||||
|
// slug: "kalimantan-barat",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Selatan",
|
||||||
|
// slug: "kalimantan-selatan",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Tengah",
|
||||||
|
// slug: "kalimantan-tengah",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Timur",
|
||||||
|
// slug: "kalimantan-timur",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Utara",
|
||||||
|
// slug: "kalimantan-utara",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kepulauan Riau",
|
||||||
|
// slug: "kepulauan-riau",
|
||||||
|
// logo: "/logo/polda/polda-kepulauan-riau.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Lampung",
|
||||||
|
// slug: "lampung",
|
||||||
|
// logo: "/logo/polda/polda-lampung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku",
|
||||||
|
// slug: "maluku",
|
||||||
|
// logo: "/logo/polda/polda-maluku.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku Utara",
|
||||||
|
// slug: "maluku-utara",
|
||||||
|
// logo: "/logo/polda/polda-maluku-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Metro Jaya",
|
||||||
|
// slug: "metro-jaya",
|
||||||
|
// logo: "/logo/polda/polda-metro-jaya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTB",
|
||||||
|
// slug: "ntb",
|
||||||
|
// logo: "/logo/polda/polda-ntb.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTT",
|
||||||
|
// slug: "ntt",
|
||||||
|
// logo: "/logo/polda/polda-ntt.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat",
|
||||||
|
// slug: "papua-barat",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat Daya",
|
||||||
|
// slug: "papua-barat-daya",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat-daya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Tengah",
|
||||||
|
// slug: "papua-tengah",
|
||||||
|
// logo: "/logo/polda/polda-papua-tengah.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Barat",
|
||||||
|
// slug: "sulawesi-barat",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Selatan",
|
||||||
|
// slug: "sulawesi-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tengah",
|
||||||
|
// slug: "sulawesi-tengah",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tenggara",
|
||||||
|
// slug: "sulawesi-tenggara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Utara",
|
||||||
|
// slug: "sulawesi-utara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Barat",
|
||||||
|
// slug: "sumatera-barat",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Selatan",
|
||||||
|
// slug: "sumatera-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Utara",
|
||||||
|
// slug: "sumatera-utara",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-utara.png",
|
||||||
|
// },
|
||||||
|
// // {
|
||||||
|
// // name: "Satuan Kerja POLRI",
|
||||||
|
// // slug: "satker-polri",
|
||||||
|
// // logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
||||||
|
// // },
|
||||||
|
// // {
|
||||||
|
// // name: "Internasional",
|
||||||
|
// // slug: "internasional",
|
||||||
|
// // logo: "/assets/polda/internasional.png",
|
||||||
|
// // },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// export default function PoldaAllAudioPage() {
|
||||||
|
// return (
|
||||||
|
// <AllContentPage
|
||||||
|
// typeId="4"
|
||||||
|
// title="Semua Konten Audio per Polda"
|
||||||
|
// basePath="audio"
|
||||||
|
// mode="polda"
|
||||||
|
// dataList={regions}
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
@ -0,0 +1,988 @@
|
||||||
|
"use client";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
|
import {
|
||||||
|
getPublicCategoryData,
|
||||||
|
getUserLevelListByParent,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import ReactDatePicker from "react-datepicker";
|
||||||
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import { close, loading } from "@/config/swal";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import ImageBlurry from "@/components/ui/image-blurry";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
const columns: ColumnDef<any>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "no",
|
||||||
|
header: "No",
|
||||||
|
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function FilterPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const asPath = usePathname();
|
||||||
|
const params = useParams();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const t = useTranslations("FilterPage");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [documentData, setDocumentData] = useState<any[]>([]);
|
||||||
|
const [totalData, setTotalData] = useState<number>(1);
|
||||||
|
const [totalPage, setTotalPage] = useState<number>(1);
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||||
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [totalContent, setTotalContent] = useState(0);
|
||||||
|
const [change, setChange] = useState(false);
|
||||||
|
const sortBy = searchParams?.get("sortBy");
|
||||||
|
const title = searchParams?.get("title");
|
||||||
|
const categorie = searchParams?.get("category");
|
||||||
|
const group = searchParams?.get("group");
|
||||||
|
const [categoryFilter, setCategoryFilter] = useState<any[]>([]);
|
||||||
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
|
const [formatFilter, setFormatFilter] = useState<any[]>([]);
|
||||||
|
const pages = page ? page - 1 : 0;
|
||||||
|
const [startDateString, setStartDateString] = useState<any>();
|
||||||
|
const [endDateString, setEndDateString] = useState<any>();
|
||||||
|
const [dateRange, setDateRange] = useState<any>([null, null]);
|
||||||
|
const [handleClose, setHandleClose] = useState(false);
|
||||||
|
const [categories, setCategories] = useState<any[]>([]);
|
||||||
|
const [isFilterOpen, setIsFilterOpen] = useState(true);
|
||||||
|
|
||||||
|
const poldaName = params?.polda_name;
|
||||||
|
const satkerName = params?.satker_name;
|
||||||
|
|
||||||
|
let prefixPath = poldaName
|
||||||
|
? `/polda/${poldaName}`
|
||||||
|
: satkerName
|
||||||
|
? `/satker/${satkerName}`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
// === INIT ===
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => setIsLoading(false), 1200);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const pageFromUrl = searchParams?.get("page");
|
||||||
|
if (pageFromUrl) setPage(Number(pageFromUrl));
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (categorie) {
|
||||||
|
setCategoryFilter(
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [categorie]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategories(categoryPage);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchCategories = async (pageNumber: number) => {
|
||||||
|
const groupParam =
|
||||||
|
poldaName && poldaName.length > 1
|
||||||
|
? poldaName
|
||||||
|
: satkerName && satkerName.length > 1
|
||||||
|
? "satker-" + satkerName
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const isInt = locale === "en";
|
||||||
|
|
||||||
|
const response = await getPublicCategoryData(
|
||||||
|
groupParam,
|
||||||
|
"",
|
||||||
|
isInt,
|
||||||
|
pageNumber
|
||||||
|
); // halaman 1-based
|
||||||
|
|
||||||
|
const content = response?.data?.data?.content || [];
|
||||||
|
const total = response?.data?.data?.totalPages || 1;
|
||||||
|
|
||||||
|
setCategories(content);
|
||||||
|
setCategoryTotalPages(total);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (asPath?.includes("/regional")) getDataRegional();
|
||||||
|
else getDataAll();
|
||||||
|
}, [
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
|
async function getDataAll() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listData(
|
||||||
|
"3",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
locale == "en" ? true : false
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setDocumentData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataRegional() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listDataRegional(
|
||||||
|
"3",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setDocumentData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCategoryFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...categoryFilter];
|
||||||
|
if (e) filter.push(String(id));
|
||||||
|
else filter = filter.filter((item) => item !== String(id));
|
||||||
|
router.push(`?category=${filter.join("&")}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormatFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...formatFilter];
|
||||||
|
if (e) filter.push(id);
|
||||||
|
else filter = filter.filter((item) => item !== id);
|
||||||
|
setFormatFilter(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSorting = (e: any) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setSortByOpt(value === "latest" ? "createdAt" : "clickCount");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteDate = () => {
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setStartDateString("");
|
||||||
|
setEndDateString("");
|
||||||
|
setHandleClose(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyUp = () => {
|
||||||
|
if (!searchTitle) router.push("?title=");
|
||||||
|
else router.push(`?title=${searchTitle.toLowerCase()}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// === REACT TABLE ===
|
||||||
|
const table = useReactTable({
|
||||||
|
data: documentData,
|
||||||
|
columns,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
onRowSelectionChange: setRowSelection,
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
state: {
|
||||||
|
sorting,
|
||||||
|
columnFilters,
|
||||||
|
columnVisibility,
|
||||||
|
rowSelection,
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [calenderState, setCalenderState] = useState(false);
|
||||||
|
const [categoryPage, setCategoryPage] = useState(1);
|
||||||
|
const [categoryTotalPages, setCategoryTotalPages] = useState(1);
|
||||||
|
let typingTimer: any;
|
||||||
|
|
||||||
|
const cleanCheckbox = () => {
|
||||||
|
setCategoryFilter([]);
|
||||||
|
setFormatFilter([]);
|
||||||
|
router.push(`?category=&title=`);
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setMonthYearFilter(null);
|
||||||
|
setChange(!change);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = () => {
|
||||||
|
clearTimeout(typingTimer);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
|
||||||
|
<p>
|
||||||
|
{" "}
|
||||||
|
{t("text", { defaultValue: "Text" })} {">"}{" "}
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("allText", { defaultValue: "All Text" })}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">|</p>
|
||||||
|
{!title ? (
|
||||||
|
<p>
|
||||||
|
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
|
||||||
|
"downloadableImage",
|
||||||
|
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
|
||||||
|
)}`}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
|
||||||
|
<span className="font-bold">"{title}"</span>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">
|
||||||
|
{/* Left */}
|
||||||
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
|
Filter
|
||||||
|
</h2>
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
|
{t("search", { defaultValue: "Search" })}
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
value={searchTitle}
|
||||||
|
onChange={(e) => setSearchTitle(e.target.value)}
|
||||||
|
onKeyUp={handleKeyUp}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
type="text"
|
||||||
|
id="search"
|
||||||
|
placeholder={t("searchTitle", { defaultValue: "Search Title" })}
|
||||||
|
className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear", { defaultValue: "Month Year" })}
|
||||||
|
</label>
|
||||||
|
<ReactDatePicker
|
||||||
|
selected={monthYearFilter}
|
||||||
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
onChange={(date) => setMonthYearFilter(date)}
|
||||||
|
dateFormat="MM | yyyy"
|
||||||
|
placeholderText={t("selectYear", {
|
||||||
|
defaultValue: "Select Year",
|
||||||
|
})}
|
||||||
|
showMonthYearPicker
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date", { defaultValue: "Date" })}
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
|
<ReactDatePicker
|
||||||
|
selectsRange
|
||||||
|
className="mt-1 w-full border text-sm rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
startDate={dateRange[0]}
|
||||||
|
endDate={dateRange[1]}
|
||||||
|
onChange={(update) => {
|
||||||
|
setDateRange(update);
|
||||||
|
}}
|
||||||
|
placeholderText={t("selectDate", {
|
||||||
|
defaultValue: "Select Date",
|
||||||
|
})}
|
||||||
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* ⬇️ Pagination kategori (rata sejajar) */}
|
||||||
|
<div className="mt-4 flex justify-center items-center gap-2 flex-wrap">
|
||||||
|
{/* Tombol Prev */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{(() => {
|
||||||
|
const maxVisible = 4;
|
||||||
|
let startPage = Math.max(
|
||||||
|
1,
|
||||||
|
Math.min(
|
||||||
|
categoryPage - Math.floor(maxVisible / 2),
|
||||||
|
categoryTotalPages - maxVisible + 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const endPage = Math.min(
|
||||||
|
categoryTotalPages,
|
||||||
|
startPage + maxVisible - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const visiblePages = [];
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
visiblePages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visiblePages.map((pageNum) => (
|
||||||
|
<button
|
||||||
|
key={pageNum}
|
||||||
|
onClick={() => setCategoryPage(pageNum)}
|
||||||
|
className={`px-3 py-1 border rounded text-sm transition-colors ${
|
||||||
|
categoryPage === pageNum
|
||||||
|
? "bg-[#bb3523] text-white"
|
||||||
|
: "bg-white dark:bg-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pageNum}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{/* Tombol Next */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
<div className="mt-4 flex gap-2 justify-center items-center">
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{Array.from({ length: categoryTotalPages }, (_, i) => (
|
||||||
|
<button
|
||||||
|
key={i}
|
||||||
|
onClick={() => setCategoryPage(i + 1)}
|
||||||
|
className={`px-3 py-1 border rounded ${
|
||||||
|
categoryPage === i + 1 ? "bg-[#bb3523] text-white" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{i + 1}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</div> */}
|
||||||
|
{/* Garis */}
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
{/* Garis */}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="doc"
|
||||||
|
value="doc"
|
||||||
|
checked={formatFilter.includes("doc")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "doc")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
DOC
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="docx"
|
||||||
|
value="docx"
|
||||||
|
checked={formatFilter.includes("docx")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "docx")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
DOCX
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="pdf"
|
||||||
|
value="pdf"
|
||||||
|
checked={formatFilter.includes("pdf")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "pdf")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PDF
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="ppt"
|
||||||
|
value="ppt"
|
||||||
|
checked={formatFilter.includes("ppt")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "ppt")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PPT
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="pptx"
|
||||||
|
value="pptx"
|
||||||
|
checked={formatFilter.includes("pptx")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "pptx")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PPTX
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
|
<div className="text-center">
|
||||||
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
|
<b>Reset Filter</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* RIGHT */}
|
||||||
|
<div className="w-full pr-4 lg:pr-16 pb-4">
|
||||||
|
<Reveal>
|
||||||
|
<div className="flex flex-col items-end mb-4">
|
||||||
|
<h2 className="text-lg font-semibold">Sort By</h2>
|
||||||
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "popular" : "latest"}
|
||||||
|
onChange={handleSorting}
|
||||||
|
className="border rounded-md py-2 px-3"
|
||||||
|
>
|
||||||
|
<option value="latest">Latest</option>
|
||||||
|
<option value="popular">Most Popular</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
</div>
|
||||||
|
) : documentData?.length > 0 ? (
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{documentData?.map((document: any) => (
|
||||||
|
<Card
|
||||||
|
key={document?.id}
|
||||||
|
className="hover:scale-105 transition-transform duration-300"
|
||||||
|
>
|
||||||
|
<CardContent
|
||||||
|
key={document?.id}
|
||||||
|
className="md:basis-1/2 lg:basis-1/3"
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={`${prefixPath}/document/detail/${document?.slug
|
||||||
|
?.split("/")
|
||||||
|
.pop()}`}
|
||||||
|
// href={`${prefixPath}/document/detail/${text?.slug}`}
|
||||||
|
// href={prefixPath + `/document/detail/${text?.slug}`}
|
||||||
|
// onClick={() =>
|
||||||
|
// router.push(prefixPath + `/document/detail/${text?.slug}`)
|
||||||
|
// }
|
||||||
|
className="cursor-pointer rounded-lg shadow-md overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500"
|
||||||
|
>
|
||||||
|
{/* Ikon di tengah dengan latar kuning */}
|
||||||
|
<div className="bg-[#e0c350] flex items-center justify-center h-[170px] text-white">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="150"
|
||||||
|
height="150"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M5 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V5.414a1.5 1.5 0 0 0-.44-1.06L9.647 1.439A1.5 1.5 0 0 0 8.586 1zM4 3a1 1 0 0 1 1-1h3v2.5A1.5 1.5 0 0 0 9.5 6H12v7a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1zm7.793 2H9.5a.5.5 0 0 1-.5-.5V2.207zM7 7.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5M7.5 9a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1zM7 11.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5M5.5 8a.5.5 0 1 0 0-1a.5.5 0 0 0 0 1M6 9.5a.5.5 0 1 1-1 0a.5.5 0 0 1 1 0M5.5 12a.5.5 0 1 0 0-1a.5.5 0 0 0 0 1"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Konten bawah */}
|
||||||
|
<div className="p-4 flex flex-col gap-2">
|
||||||
|
{/* Kategori merah */}
|
||||||
|
<div className="text-[12px] font-bold text-red-600 uppercase">
|
||||||
|
{document?.categoryName?.toUpperCase() ?? "Text"}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Judul */}
|
||||||
|
<div className="font-semibold text-gray-900 dark:text-white text-xl leading-snug line-clamp-4">
|
||||||
|
{document?.title}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-center items-center py-10">
|
||||||
|
<Image
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{totalPage > 1 && (
|
||||||
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Reveal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// import AllContentPage from "@/components/landing-page/all-content-page";
|
||||||
|
|
||||||
|
// const regions = [
|
||||||
|
// { name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
||||||
|
// { name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bangka Belitung",
|
||||||
|
// slug: "bangka-belitung",
|
||||||
|
// logo: "/logo/polda/polda-bangka-belitung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Banten",
|
||||||
|
// slug: "banten",
|
||||||
|
// logo: "/logo/polda/polda-banten.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bengkulu",
|
||||||
|
// slug: "bengkulu",
|
||||||
|
// logo: "/logo/polda/polda-bengkulu.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda DIY",
|
||||||
|
// slug: "jogja",
|
||||||
|
// logo: "/logo/polda/polda-jogja.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Gorontalo",
|
||||||
|
// slug: "gorontalo",
|
||||||
|
// logo: "/logo/polda/polda-gorontalo.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Barat",
|
||||||
|
// slug: "jawa-barat",
|
||||||
|
// logo: "/logo/polda/polda-jawa-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Tengah",
|
||||||
|
// slug: "jawa-tengah",
|
||||||
|
// logo: "/logo/polda/polda-jawa-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Timur",
|
||||||
|
// slug: "jawa-timur",
|
||||||
|
// logo: "/logo/polda/polda-jawa-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Barat",
|
||||||
|
// slug: "kalimantan-barat",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Selatan",
|
||||||
|
// slug: "kalimantan-selatan",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Tengah",
|
||||||
|
// slug: "kalimantan-tengah",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Timur",
|
||||||
|
// slug: "kalimantan-timur",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Utara",
|
||||||
|
// slug: "kalimantan-utara",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kepulauan Riau",
|
||||||
|
// slug: "kepulauan-riau",
|
||||||
|
// logo: "/logo/polda/polda-kepulauan-riau.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Lampung",
|
||||||
|
// slug: "lampung",
|
||||||
|
// logo: "/logo/polda/polda-lampung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku",
|
||||||
|
// slug: "maluku",
|
||||||
|
// logo: "/logo/polda/polda-maluku.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku Utara",
|
||||||
|
// slug: "maluku-utara",
|
||||||
|
// logo: "/logo/polda/polda-maluku-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Metro Jaya",
|
||||||
|
// slug: "metro-jaya",
|
||||||
|
// logo: "/logo/polda/polda-metro-jaya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTB",
|
||||||
|
// slug: "ntb",
|
||||||
|
// logo: "/logo/polda/polda-ntb.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTT",
|
||||||
|
// slug: "ntt",
|
||||||
|
// logo: "/logo/polda/polda-ntt.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat",
|
||||||
|
// slug: "papua-barat",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat Daya",
|
||||||
|
// slug: "papua-barat-daya",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat-daya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Tengah",
|
||||||
|
// slug: "papua-tengah",
|
||||||
|
// logo: "/logo/polda/polda-papua-tengah.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Barat",
|
||||||
|
// slug: "sulawesi-barat",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Selatan",
|
||||||
|
// slug: "sulawesi-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tengah",
|
||||||
|
// slug: "sulawesi-tengah",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tenggara",
|
||||||
|
// slug: "sulawesi-tenggara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Utara",
|
||||||
|
// slug: "sulawesi-utara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Barat",
|
||||||
|
// slug: "sumatera-barat",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Selatan",
|
||||||
|
// slug: "sumatera-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Utara",
|
||||||
|
// slug: "sumatera-utara",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-utara.png",
|
||||||
|
// },
|
||||||
|
// // {
|
||||||
|
// // name: "Satuan Kerja POLRI",
|
||||||
|
// // slug: "satker-polri",
|
||||||
|
// // logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
||||||
|
// // },
|
||||||
|
// // {
|
||||||
|
// // name: "Internasional",
|
||||||
|
// // slug: "internasional",
|
||||||
|
// // logo: "/assets/polda/internasional.png",
|
||||||
|
// // },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// export default function PoldaAllDocumentPage() {
|
||||||
|
// return (
|
||||||
|
// <AllContentPage
|
||||||
|
// typeId="3"
|
||||||
|
// title="Semua Konten Teks per Polda"
|
||||||
|
// basePath="document"
|
||||||
|
// mode="polda"
|
||||||
|
// dataList={regions}
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
@ -0,0 +1,895 @@
|
||||||
|
"use client";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
|
import {
|
||||||
|
getPublicCategoryData,
|
||||||
|
getUserLevelListByParent,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import ReactDatePicker from "react-datepicker";
|
||||||
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import { close, loading } from "@/config/swal";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import ImageBlurry from "@/components/ui/image-blurry";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
const columns: ColumnDef<any>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "no",
|
||||||
|
header: "No",
|
||||||
|
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function FilterPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const asPath = usePathname();
|
||||||
|
const params = useParams();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const t = useTranslations("FilterPage");
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [imageData, setImageData] = useState<any[]>([]);
|
||||||
|
const [totalData, setTotalData] = useState<number>(1);
|
||||||
|
const [totalPage, setTotalPage] = useState<number>(1);
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||||
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [totalContent, setTotalContent] = useState(0);
|
||||||
|
const [change, setChange] = useState(false);
|
||||||
|
const sortBy = searchParams?.get("sortBy");
|
||||||
|
const title = searchParams?.get("title");
|
||||||
|
const categorie = searchParams?.get("category");
|
||||||
|
const group = searchParams?.get("group");
|
||||||
|
const [categoryFilter, setCategoryFilter] = useState<any[]>([]);
|
||||||
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
|
const [formatFilter, setFormatFilter] = useState<any[]>([]);
|
||||||
|
const pages = page ? page - 1 : 0;
|
||||||
|
const [startDateString, setStartDateString] = useState<any>();
|
||||||
|
const [endDateString, setEndDateString] = useState<any>();
|
||||||
|
const [dateRange, setDateRange] = useState<any>([null, null]);
|
||||||
|
const [handleClose, setHandleClose] = useState(false);
|
||||||
|
const [categories, setCategories] = useState<any[]>([]);
|
||||||
|
const [isFilterOpen, setIsFilterOpen] = useState(true);
|
||||||
|
|
||||||
|
const poldaName = params?.polda_name;
|
||||||
|
const satkerName = params?.satker_name;
|
||||||
|
|
||||||
|
let prefixPath = poldaName
|
||||||
|
? `/polda/${poldaName}`
|
||||||
|
: satkerName
|
||||||
|
? `/satker/${satkerName}`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
// === INIT ===
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => setIsLoading(false), 1200);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const pageFromUrl = searchParams?.get("page");
|
||||||
|
if (pageFromUrl) setPage(Number(pageFromUrl));
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (categorie) {
|
||||||
|
setCategoryFilter(
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [categorie]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategories(categoryPage);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchCategories = async (pageNumber: number) => {
|
||||||
|
const groupParam =
|
||||||
|
poldaName && poldaName.length > 1
|
||||||
|
? poldaName
|
||||||
|
: satkerName && satkerName.length > 1
|
||||||
|
? "satker-" + satkerName
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const isInt = locale === "en";
|
||||||
|
|
||||||
|
const response = await getPublicCategoryData(
|
||||||
|
groupParam,
|
||||||
|
"",
|
||||||
|
isInt,
|
||||||
|
pageNumber
|
||||||
|
); // halaman 1-based
|
||||||
|
|
||||||
|
const content = response?.data?.data?.content || [];
|
||||||
|
const total = response?.data?.data?.totalPages || 1;
|
||||||
|
|
||||||
|
setCategories(content);
|
||||||
|
setCategoryTotalPages(total);
|
||||||
|
};
|
||||||
|
|
||||||
|
// async function fetchCategories() {
|
||||||
|
// const response = await getPublicCategoryData("", "", locale === "en");
|
||||||
|
// setCategories(response?.data?.data?.content || []);
|
||||||
|
// }
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (asPath?.includes("/regional")) getDataRegional();
|
||||||
|
else getDataAll();
|
||||||
|
}, [
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
|
async function getDataAll() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listData(
|
||||||
|
"1",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
locale == "en" ? true : false
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setImageData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataRegional() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listDataRegional(
|
||||||
|
"1",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setImageData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCategoryFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...categoryFilter];
|
||||||
|
if (e) filter.push(String(id));
|
||||||
|
else filter = filter.filter((item) => item !== String(id));
|
||||||
|
router.push(`?category=${filter.join("&")}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormatFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...formatFilter];
|
||||||
|
if (e) filter.push(id);
|
||||||
|
else filter = filter.filter((item) => item !== id);
|
||||||
|
setFormatFilter(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSorting = (e: any) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setSortByOpt(value === "latest" ? "createdAt" : "clickCount");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteDate = () => {
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setStartDateString("");
|
||||||
|
setEndDateString("");
|
||||||
|
setHandleClose(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyUp = () => {
|
||||||
|
if (!searchTitle) router.push("?title=");
|
||||||
|
else router.push(`?title=${searchTitle.toLowerCase()}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// === REACT TABLE ===
|
||||||
|
const table = useReactTable({
|
||||||
|
data: imageData,
|
||||||
|
columns,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
onRowSelectionChange: setRowSelection,
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
state: {
|
||||||
|
sorting,
|
||||||
|
columnFilters,
|
||||||
|
columnVisibility,
|
||||||
|
rowSelection,
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [calenderState, setCalenderState] = useState(false);
|
||||||
|
const [categoryPage, setCategoryPage] = useState(1);
|
||||||
|
const [categoryTotalPages, setCategoryTotalPages] = useState(1);
|
||||||
|
let typingTimer: any;
|
||||||
|
|
||||||
|
const cleanCheckbox = () => {
|
||||||
|
setCategoryFilter([]);
|
||||||
|
setFormatFilter([]);
|
||||||
|
router.push(`?category=&title=`);
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setMonthYearFilter(null);
|
||||||
|
setChange(!change);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = () => {
|
||||||
|
clearTimeout(typingTimer);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
|
||||||
|
<p>{t("image", { defaultValue: "Image" })}</p> {">"}
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("allImage", { defaultValue: "All Image" })}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">|</p>
|
||||||
|
{!title ? (
|
||||||
|
<p>
|
||||||
|
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
|
||||||
|
"downloadableImage",
|
||||||
|
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
|
||||||
|
)}`}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
|
||||||
|
<span className="font-bold">"{title}"</span>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">
|
||||||
|
{/* Left */}
|
||||||
|
<div className="lg:hidden flex justify-end mb-2">
|
||||||
|
<button
|
||||||
|
onClick={() => setIsFilterOpen(!isFilterOpen)}
|
||||||
|
className="text-sm text-white bg-[#bb3523] px-4 py-1 rounded-md shadow"
|
||||||
|
>
|
||||||
|
{isFilterOpen ? "Hide Filter" : "Show Filter"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isFilterOpen && (
|
||||||
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
|
Filter
|
||||||
|
</h2>
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
|
{t("search", { defaultValue: "Search" })}
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
value={searchTitle}
|
||||||
|
onChange={(e) => setSearchTitle(e.target.value)}
|
||||||
|
onKeyUp={handleKeyUp}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
type="text"
|
||||||
|
id="search"
|
||||||
|
placeholder={t("searchTitle", {
|
||||||
|
defaultValue: "Search Title",
|
||||||
|
})}
|
||||||
|
className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear", { defaultValue: "Month Year" })}
|
||||||
|
</label>
|
||||||
|
<ReactDatePicker
|
||||||
|
selected={monthYearFilter}
|
||||||
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
onChange={(date) => setMonthYearFilter(date)}
|
||||||
|
dateFormat="MM | yyyy"
|
||||||
|
placeholderText={t("selectYear", {
|
||||||
|
defaultValue: "Select Year",
|
||||||
|
})}
|
||||||
|
showMonthYearPicker
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date", { defaultValue: "Date" })}
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
|
<ReactDatePicker
|
||||||
|
selectsRange
|
||||||
|
className="mt-1 w-full border text-sm rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
startDate={dateRange[0]}
|
||||||
|
endDate={dateRange[1]}
|
||||||
|
onChange={(update) => {
|
||||||
|
setDateRange(update);
|
||||||
|
}}
|
||||||
|
placeholderText={t("selectDate", {
|
||||||
|
defaultValue: "Select Date",
|
||||||
|
})}
|
||||||
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* ⬇️ Pagination kategori (rata sejajar) */}
|
||||||
|
<div className="mt-4 flex justify-center items-center gap-2 flex-wrap">
|
||||||
|
{/* Tombol Prev */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{(() => {
|
||||||
|
const maxVisible = 4;
|
||||||
|
let startPage = Math.max(
|
||||||
|
1,
|
||||||
|
Math.min(
|
||||||
|
categoryPage - Math.floor(maxVisible / 2),
|
||||||
|
categoryTotalPages - maxVisible + 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const endPage = Math.min(
|
||||||
|
categoryTotalPages,
|
||||||
|
startPage + maxVisible - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const visiblePages = [];
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
visiblePages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visiblePages.map((pageNum) => (
|
||||||
|
<button
|
||||||
|
key={pageNum}
|
||||||
|
onClick={() => setCategoryPage(pageNum)}
|
||||||
|
className={`px-3 py-1 border rounded text-sm transition-colors ${
|
||||||
|
categoryPage === pageNum
|
||||||
|
? "bg-[#bb3523] text-white"
|
||||||
|
: "bg-white dark:bg-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pageNum}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{/* Tombol Next */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Garis */}
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
{/* Garis */}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="png"
|
||||||
|
value="png"
|
||||||
|
checked={formatFilter.includes("png")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "png")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PNG
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="jpeg"
|
||||||
|
value="jpeg"
|
||||||
|
checked={formatFilter.includes("jpeg")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "jpeg")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
JPEG
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="jpg"
|
||||||
|
value="jpg"
|
||||||
|
checked={formatFilter.includes("jpg")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "jpg")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
JPG
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
|
<div className="text-center">
|
||||||
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
|
<b>Reset Filter</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* CONTENT */}
|
||||||
|
<div className="w-full pr-4 lg:pr-16 pb-4">
|
||||||
|
<Reveal>
|
||||||
|
<div className="flex flex-col items-end mb-4">
|
||||||
|
<h2 className="text-lg font-semibold">Sort By</h2>
|
||||||
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "popular" : "latest"}
|
||||||
|
onChange={handleSorting}
|
||||||
|
className="border rounded-md py-2 px-3"
|
||||||
|
>
|
||||||
|
<option value="latest">Latest</option>
|
||||||
|
<option value="popular">Most Popular</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
</div>
|
||||||
|
) : imageData?.length > 0 ? (
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{imageData.map((image: any) => (
|
||||||
|
<Card
|
||||||
|
key={image?.id}
|
||||||
|
className="hover:scale-105 transition-transform duration-300"
|
||||||
|
>
|
||||||
|
<CardContent className="flex flex-col p-0">
|
||||||
|
<Link
|
||||||
|
href={`${prefixPath}/image/detail/${image?.slug
|
||||||
|
?.split("/")
|
||||||
|
.pop()}`}
|
||||||
|
// href={`/image/detail/${image?.slug}`}
|
||||||
|
>
|
||||||
|
<div className="h-60 bg-[#e9e9e9]">
|
||||||
|
<ImageBlurry
|
||||||
|
src={
|
||||||
|
image?.smallThumbnailLink || image?.thumbnailLink
|
||||||
|
}
|
||||||
|
alt={image?.title}
|
||||||
|
style={{
|
||||||
|
objectFit: "cover",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="flex flex-row justify-between mb-1">
|
||||||
|
<p className="text-[9px] font-bold text-[#bb3523]">
|
||||||
|
{image?.categoryName?.toUpperCase() ??
|
||||||
|
"Giat Pimpinan"}
|
||||||
|
</p>
|
||||||
|
<p className="flex flex-row items-center text-[9px] gap-1 text-gray-600">
|
||||||
|
{formatDateToIndonesian(
|
||||||
|
new Date(image?.createdAt)
|
||||||
|
)}{" "}
|
||||||
|
{image?.timezone ?? "WIB"} |
|
||||||
|
<Icon
|
||||||
|
icon="formkit:eye"
|
||||||
|
width="15"
|
||||||
|
height="15"
|
||||||
|
/>{" "}
|
||||||
|
{image.clickCount}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm lg:text-base font-semibold text-black dark:text-white line-clamp-3">
|
||||||
|
{image?.title}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-center items-center py-10">
|
||||||
|
<Image
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{totalPage > 1 && (
|
||||||
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Reveal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// import AllContentPage from "@/components/landing-page/all-content-page";
|
||||||
|
|
||||||
|
// const regions = [
|
||||||
|
// { name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
||||||
|
// { name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bangka Belitung",
|
||||||
|
// slug: "bangka-belitung",
|
||||||
|
// logo: "/logo/polda/polda-bangka-belitung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Banten",
|
||||||
|
// slug: "banten",
|
||||||
|
// logo: "/logo/polda/polda-banten.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bengkulu",
|
||||||
|
// slug: "bengkulu",
|
||||||
|
// logo: "/logo/polda/polda-bengkulu.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda DIY",
|
||||||
|
// slug: "jogja",
|
||||||
|
// logo: "/logo/polda/polda-jogja.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Gorontalo",
|
||||||
|
// slug: "gorontalo",
|
||||||
|
// logo: "/logo/polda/polda-gorontalo.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Barat",
|
||||||
|
// slug: "jawa-barat",
|
||||||
|
// logo: "/logo/polda/polda-jawa-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Tengah",
|
||||||
|
// slug: "jawa-tengah",
|
||||||
|
// logo: "/logo/polda/polda-jawa-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Timur",
|
||||||
|
// slug: "jawa-timur",
|
||||||
|
// logo: "/logo/polda/polda-jawa-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Barat",
|
||||||
|
// slug: "kalimantan-barat",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Selatan",
|
||||||
|
// slug: "kalimantan-selatan",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Tengah",
|
||||||
|
// slug: "kalimantan-tengah",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Timur",
|
||||||
|
// slug: "kalimantan-timur",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Utara",
|
||||||
|
// slug: "kalimantan-utara",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kepulauan Riau",
|
||||||
|
// slug: "kepulauan-riau",
|
||||||
|
// logo: "/logo/polda/polda-kepulauan-riau.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Lampung",
|
||||||
|
// slug: "lampung",
|
||||||
|
// logo: "/logo/polda/polda-lampung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku",
|
||||||
|
// slug: "maluku",
|
||||||
|
// logo: "/logo/polda/polda-maluku.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku Utara",
|
||||||
|
// slug: "maluku-utara",
|
||||||
|
// logo: "/logo/polda/polda-maluku-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Metro Jaya",
|
||||||
|
// slug: "metro-jaya",
|
||||||
|
// logo: "/logo/polda/polda-metro-jaya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTB",
|
||||||
|
// slug: "ntb",
|
||||||
|
// logo: "/logo/polda/polda-ntb.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTT",
|
||||||
|
// slug: "ntt",
|
||||||
|
// logo: "/logo/polda/polda-ntt.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat",
|
||||||
|
// slug: "papua-barat",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat Daya",
|
||||||
|
// slug: "papua-barat-daya",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat-daya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Tengah",
|
||||||
|
// slug: "papua-tengah",
|
||||||
|
// logo: "/logo/polda/polda-papua-tengah.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Barat",
|
||||||
|
// slug: "sulawesi-barat",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Selatan",
|
||||||
|
// slug: "sulawesi-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tengah",
|
||||||
|
// slug: "sulawesi-tengah",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tenggara",
|
||||||
|
// slug: "sulawesi-tenggara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Utara",
|
||||||
|
// slug: "sulawesi-utara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Barat",
|
||||||
|
// slug: "sumatera-barat",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Selatan",
|
||||||
|
// slug: "sumatera-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Utara",
|
||||||
|
// slug: "sumatera-utara",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-utara.png",
|
||||||
|
// },
|
||||||
|
// // {
|
||||||
|
// // name: "Satuan Kerja POLRI",
|
||||||
|
// // slug: "satker-polri",
|
||||||
|
// // logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
||||||
|
// // },
|
||||||
|
// // {
|
||||||
|
// // name: "Internasional",
|
||||||
|
// // slug: "internasional",
|
||||||
|
// // logo: "/assets/polda/internasional.png",
|
||||||
|
// // },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// export default function PoldaAllImagePage() {
|
||||||
|
// return (
|
||||||
|
// <AllContentPage
|
||||||
|
// typeId="1"
|
||||||
|
// title="Semua Foto per Polda"
|
||||||
|
// basePath="image"
|
||||||
|
// mode="polda"
|
||||||
|
// dataList={regions}
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
@ -0,0 +1,987 @@
|
||||||
|
"use client";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
|
import {
|
||||||
|
getPublicCategoryData,
|
||||||
|
getUserLevelListByParent,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import ReactDatePicker from "react-datepicker";
|
||||||
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import { close, loading } from "@/config/swal";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import ImageBlurry from "@/components/ui/image-blurry";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
const columns: ColumnDef<any>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "no",
|
||||||
|
header: "No",
|
||||||
|
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function FilterPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const asPath = usePathname();
|
||||||
|
const params = useParams();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const t = useTranslations("FilterPage");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [videoData, setVideoData] = useState<any[]>([]);
|
||||||
|
const [totalData, setTotalData] = useState<number>(1);
|
||||||
|
const [totalPage, setTotalPage] = useState<number>(1);
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||||
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [totalContent, setTotalContent] = useState(0);
|
||||||
|
const [change, setChange] = useState(false);
|
||||||
|
const sortBy = searchParams?.get("sortBy");
|
||||||
|
const title = searchParams?.get("title");
|
||||||
|
const categorie = searchParams?.get("category");
|
||||||
|
const group = searchParams?.get("group");
|
||||||
|
const [categoryFilter, setCategoryFilter] = useState<any[]>([]);
|
||||||
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
|
const [formatFilter, setFormatFilter] = useState<any[]>([]);
|
||||||
|
const pages = page ? page - 1 : 0;
|
||||||
|
const [startDateString, setStartDateString] = useState<any>();
|
||||||
|
const [endDateString, setEndDateString] = useState<any>();
|
||||||
|
const [dateRange, setDateRange] = useState<any>([null, null]);
|
||||||
|
const [handleClose, setHandleClose] = useState(false);
|
||||||
|
const [categories, setCategories] = useState<any[]>([]);
|
||||||
|
const [isFilterOpen, setIsFilterOpen] = useState(true);
|
||||||
|
|
||||||
|
const poldaName = params?.polda_name;
|
||||||
|
const satkerName = params?.satker_name;
|
||||||
|
|
||||||
|
let prefixPath = poldaName
|
||||||
|
? `/polda/${poldaName}`
|
||||||
|
: satkerName
|
||||||
|
? `/satker/${satkerName}`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
// === INIT ===
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => setIsLoading(false), 1200);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const pageFromUrl = searchParams?.get("page");
|
||||||
|
if (pageFromUrl) setPage(Number(pageFromUrl));
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (categorie) {
|
||||||
|
setCategoryFilter(
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [categorie]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategories(categoryPage);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchCategories = async (pageNumber: number) => {
|
||||||
|
const groupParam =
|
||||||
|
poldaName && poldaName.length > 1
|
||||||
|
? poldaName
|
||||||
|
: satkerName && satkerName.length > 1
|
||||||
|
? "satker-" + satkerName
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const isInt = locale === "en";
|
||||||
|
|
||||||
|
const response = await getPublicCategoryData(
|
||||||
|
groupParam,
|
||||||
|
"",
|
||||||
|
isInt,
|
||||||
|
pageNumber
|
||||||
|
); // halaman 1-based
|
||||||
|
|
||||||
|
const content = response?.data?.data?.content || [];
|
||||||
|
const total = response?.data?.data?.totalPages || 1;
|
||||||
|
|
||||||
|
setCategories(content);
|
||||||
|
setCategoryTotalPages(total);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (asPath?.includes("/regional")) getDataRegional();
|
||||||
|
else getDataAll();
|
||||||
|
}, [
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
|
async function getDataAll() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listData(
|
||||||
|
"2",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
locale == "en" ? true : false
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setVideoData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataRegional() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listDataRegional(
|
||||||
|
"2",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setVideoData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCategoryFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...categoryFilter];
|
||||||
|
if (e) filter.push(String(id));
|
||||||
|
else filter = filter.filter((item) => item !== String(id));
|
||||||
|
router.push(`?category=${filter.join("&")}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormatFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...formatFilter];
|
||||||
|
if (e) filter.push(id);
|
||||||
|
else filter = filter.filter((item) => item !== id);
|
||||||
|
setFormatFilter(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSorting = (e: any) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setSortByOpt(value === "latest" ? "createdAt" : "clickCount");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteDate = () => {
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setStartDateString("");
|
||||||
|
setEndDateString("");
|
||||||
|
setHandleClose(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyUp = () => {
|
||||||
|
if (!searchTitle) router.push("?title=");
|
||||||
|
else router.push(`?title=${searchTitle.toLowerCase()}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// === REACT TABLE ===
|
||||||
|
const table = useReactTable({
|
||||||
|
data: videoData,
|
||||||
|
columns,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
onRowSelectionChange: setRowSelection,
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
state: {
|
||||||
|
sorting,
|
||||||
|
columnFilters,
|
||||||
|
columnVisibility,
|
||||||
|
rowSelection,
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [calenderState, setCalenderState] = useState(false);
|
||||||
|
const [categoryPage, setCategoryPage] = useState(1);
|
||||||
|
const [categoryTotalPages, setCategoryTotalPages] = useState(1);
|
||||||
|
let typingTimer: any;
|
||||||
|
|
||||||
|
const cleanCheckbox = () => {
|
||||||
|
setCategoryFilter([]);
|
||||||
|
setFormatFilter([]);
|
||||||
|
router.push(`?category=&title=`);
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setMonthYearFilter(null);
|
||||||
|
setChange(!change);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = () => {
|
||||||
|
clearTimeout(typingTimer);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
|
||||||
|
<p>{t("video", { defaultValue: "Video" })}</p> {">"}
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("allVideo", { defaultValue: "All Video" })}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">|</p>
|
||||||
|
{!title ? (
|
||||||
|
<p>
|
||||||
|
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
|
||||||
|
"downloadablevideo",
|
||||||
|
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
|
||||||
|
)}`}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
|
||||||
|
<span className="font-bold">"{title}"</span>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">
|
||||||
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
|
Filter
|
||||||
|
</h2>
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
|
{t("search", { defaultValue: "Search" })}
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
value={searchTitle}
|
||||||
|
onChange={(e) => setSearchTitle(e.target.value)}
|
||||||
|
onKeyUp={handleKeyUp}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
type="text"
|
||||||
|
id="search"
|
||||||
|
placeholder={t("searchTitle", { defaultValue: "Search Title" })}
|
||||||
|
className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear", { defaultValue: "Month Year" })}
|
||||||
|
</label>
|
||||||
|
<ReactDatePicker
|
||||||
|
selected={monthYearFilter}
|
||||||
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
onChange={(date) => setMonthYearFilter(date)}
|
||||||
|
dateFormat="MM | yyyy"
|
||||||
|
placeholderText={t("selectYear", {
|
||||||
|
defaultValue: "Select Year",
|
||||||
|
})}
|
||||||
|
showMonthYearPicker
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date", { defaultValue: "Date" })}
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
|
<ReactDatePicker
|
||||||
|
selectsRange
|
||||||
|
className="mt-1 w-full text-sm border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
startDate={dateRange[0]}
|
||||||
|
endDate={dateRange[1]}
|
||||||
|
onChange={(update) => {
|
||||||
|
setDateRange(update);
|
||||||
|
}}
|
||||||
|
placeholderText={t("selectDate", {
|
||||||
|
defaultValue: "Select Date",
|
||||||
|
})}
|
||||||
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* ⬇️ Pagination kategori (rata sejajar) */}
|
||||||
|
<div className="mt-4 flex justify-center items-center gap-2 flex-wrap">
|
||||||
|
{/* Tombol Prev */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{(() => {
|
||||||
|
const maxVisible = 4;
|
||||||
|
let startPage = Math.max(
|
||||||
|
1,
|
||||||
|
Math.min(
|
||||||
|
categoryPage - Math.floor(maxVisible / 2),
|
||||||
|
categoryTotalPages - maxVisible + 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const endPage = Math.min(
|
||||||
|
categoryTotalPages,
|
||||||
|
startPage + maxVisible - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const visiblePages = [];
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
visiblePages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visiblePages.map((pageNum) => (
|
||||||
|
<button
|
||||||
|
key={pageNum}
|
||||||
|
onClick={() => setCategoryPage(pageNum)}
|
||||||
|
className={`px-3 py-1 border rounded text-sm transition-colors ${
|
||||||
|
categoryPage === pageNum
|
||||||
|
? "bg-[#bb3523] text-white"
|
||||||
|
: "bg-white dark:bg-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pageNum}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{/* Tombol Next */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
<div className="mt-4 flex gap-2 justify-center items-center">
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{Array.from({ length: categoryTotalPages }, (_, i) => (
|
||||||
|
<button
|
||||||
|
key={i}
|
||||||
|
onClick={() => setCategoryPage(i + 1)}
|
||||||
|
className={`px-3 py-1 border rounded ${
|
||||||
|
categoryPage === i + 1 ? "bg-[#bb3523] text-white" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{i + 1}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</div> */}
|
||||||
|
{/* Garis */}
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
{/* Garis */}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="mk4"
|
||||||
|
value="mk4"
|
||||||
|
checked={formatFilter.includes("mk4")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mk4")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MK4
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="mov"
|
||||||
|
value="mov"
|
||||||
|
checked={formatFilter.includes("mov")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mov")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MOV
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="mp4"
|
||||||
|
value="mp4"
|
||||||
|
checked={formatFilter.includes("mp4")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mp4")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MP4
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="avi"
|
||||||
|
value="avi"
|
||||||
|
checked={formatFilter.includes("avi")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "avi")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
AVI
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="wmv"
|
||||||
|
value="wmv"
|
||||||
|
checked={formatFilter.includes("wmv")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "wmv")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
WMV
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
|
<div className="text-center">
|
||||||
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
|
<b>Reset Filter</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* CONTENT */}
|
||||||
|
<div className="w-full pr-4 lg:pr-16 pb-4">
|
||||||
|
<Reveal>
|
||||||
|
<div className="flex flex-col items-end mb-4">
|
||||||
|
<h2 className="text-lg font-semibold">Sort By</h2>
|
||||||
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "popular" : "latest"}
|
||||||
|
onChange={handleSorting}
|
||||||
|
className="border rounded-md py-2 px-3"
|
||||||
|
>
|
||||||
|
<option value="latest">Latest</option>
|
||||||
|
<option value="popular">Most Popular</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
</div>
|
||||||
|
) : videoData?.length > 0 ? (
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{videoData.map((video: any) => (
|
||||||
|
<Card
|
||||||
|
key={video?.id}
|
||||||
|
className="hover:scale-105 transition-transform duration-300"
|
||||||
|
>
|
||||||
|
<CardContent className="flex flex-col p-0">
|
||||||
|
<Link
|
||||||
|
href={`${prefixPath}/video/detail/${video?.slug
|
||||||
|
?.split("/")
|
||||||
|
.pop()}`}
|
||||||
|
// href={`/video/detail/${video?.slug}`}
|
||||||
|
>
|
||||||
|
<div className="h-60 bg-[#e9e9e9]">
|
||||||
|
<ImageBlurry
|
||||||
|
src={
|
||||||
|
video?.smallThumbnailLink || video?.thumbnailLink
|
||||||
|
}
|
||||||
|
alt={video?.title}
|
||||||
|
style={{
|
||||||
|
objectFit: "cover",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="flex flex-row justify-between mb-1">
|
||||||
|
<p className="text-[9px] font-bold text-[#bb3523]">
|
||||||
|
{video?.categoryName?.toUpperCase() ??
|
||||||
|
"Giat Pimpinan"}
|
||||||
|
</p>
|
||||||
|
<p className="flex flex-row items-center text-[9px] gap-1 text-gray-600">
|
||||||
|
{formatDateToIndonesian(
|
||||||
|
new Date(video?.createdAt)
|
||||||
|
)}{" "}
|
||||||
|
{video?.timezone ?? "WIB"} |
|
||||||
|
<Icon
|
||||||
|
icon="formkit:eye"
|
||||||
|
width="15"
|
||||||
|
height="15"
|
||||||
|
/>{" "}
|
||||||
|
{video.clickCount}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm lg:text-base font-semibold text-black dark:text-white line-clamp-3">
|
||||||
|
{video?.title}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-center items-center py-10">
|
||||||
|
<Image
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{totalPage > 1 && (
|
||||||
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Reveal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// import AllContentPage from "@/components/landing-page/all-content-page";
|
||||||
|
|
||||||
|
// const regions = [
|
||||||
|
// { name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
||||||
|
// { name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bangka Belitung",
|
||||||
|
// slug: "bangka-belitung",
|
||||||
|
// logo: "/logo/polda/polda-bangka-belitung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Banten",
|
||||||
|
// slug: "banten",
|
||||||
|
// logo: "/logo/polda/polda-banten.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bengkulu",
|
||||||
|
// slug: "bengkulu",
|
||||||
|
// logo: "/logo/polda/polda-bengkulu.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda DIY",
|
||||||
|
// slug: "jogja",
|
||||||
|
// logo: "/logo/polda/polda-jogja.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Gorontalo",
|
||||||
|
// slug: "gorontalo",
|
||||||
|
// logo: "/logo/polda/polda-gorontalo.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Barat",
|
||||||
|
// slug: "jawa-barat",
|
||||||
|
// logo: "/logo/polda/polda-jawa-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Tengah",
|
||||||
|
// slug: "jawa-tengah",
|
||||||
|
// logo: "/logo/polda/polda-jawa-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Timur",
|
||||||
|
// slug: "jawa-timur",
|
||||||
|
// logo: "/logo/polda/polda-jawa-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Barat",
|
||||||
|
// slug: "kalimantan-barat",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Selatan",
|
||||||
|
// slug: "kalimantan-selatan",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Tengah",
|
||||||
|
// slug: "kalimantan-tengah",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Timur",
|
||||||
|
// slug: "kalimantan-timur",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Utara",
|
||||||
|
// slug: "kalimantan-utara",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kepulauan Riau",
|
||||||
|
// slug: "kepulauan-riau",
|
||||||
|
// logo: "/logo/polda/polda-kepulauan-riau.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Lampung",
|
||||||
|
// slug: "lampung",
|
||||||
|
// logo: "/logo/polda/polda-lampung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku",
|
||||||
|
// slug: "maluku",
|
||||||
|
// logo: "/logo/polda/polda-maluku.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku Utara",
|
||||||
|
// slug: "maluku-utara",
|
||||||
|
// logo: "/logo/polda/polda-maluku-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Metro Jaya",
|
||||||
|
// slug: "metro-jaya",
|
||||||
|
// logo: "/logo/polda/polda-metro-jaya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTB",
|
||||||
|
// slug: "ntb",
|
||||||
|
// logo: "/logo/polda/polda-ntb.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTT",
|
||||||
|
// slug: "ntt",
|
||||||
|
// logo: "/logo/polda/polda-ntt.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat",
|
||||||
|
// slug: "papua-barat",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat Daya",
|
||||||
|
// slug: "papua-barat-daya",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat-daya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Tengah",
|
||||||
|
// slug: "papua-tengah",
|
||||||
|
// logo: "/logo/polda/polda-papua-tengah.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Barat",
|
||||||
|
// slug: "sulawesi-barat",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Selatan",
|
||||||
|
// slug: "sulawesi-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tengah",
|
||||||
|
// slug: "sulawesi-tengah",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tenggara",
|
||||||
|
// slug: "sulawesi-tenggara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Utara",
|
||||||
|
// slug: "sulawesi-utara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Barat",
|
||||||
|
// slug: "sumatera-barat",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Selatan",
|
||||||
|
// slug: "sumatera-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Utara",
|
||||||
|
// slug: "sumatera-utara",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-utara.png",
|
||||||
|
// },
|
||||||
|
// // {
|
||||||
|
// // name: "Satuan Kerja POLRI",
|
||||||
|
// // slug: "satker-polri",
|
||||||
|
// // logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
||||||
|
// // },
|
||||||
|
// // {
|
||||||
|
// // name: "Internasional",
|
||||||
|
// // slug: "internasional",
|
||||||
|
// // logo: "/assets/polda/internasional.png",
|
||||||
|
// // },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// export default function PoldaAllVideoPage() {
|
||||||
|
// return (
|
||||||
|
// <AllContentPage
|
||||||
|
// typeId="2"
|
||||||
|
// title="Semua Konten Audio Visual per Polda"
|
||||||
|
// basePath="video"
|
||||||
|
// mode="polda"
|
||||||
|
// dataList={regions}
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
@ -511,8 +511,8 @@ const FilterPage = () => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Left */}
|
|
||||||
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">
|
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">
|
||||||
|
{/* Left */}
|
||||||
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
<Icon icon="stash:filter-light" fontSize={30} />
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
|
|
|
||||||
|
|
@ -500,7 +500,6 @@ const FilterPage = () => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
|
|
||||||
<div className="flex flex-col md:flex-row items-start gap-5 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
|
<div className="flex flex-col md:flex-row items-start gap-5 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
|
||||||
<p>
|
<p>
|
||||||
{" "}
|
{" "}
|
||||||
|
|
@ -527,8 +526,8 @@ const FilterPage = () => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Left */}
|
|
||||||
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4 ">
|
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4 ">
|
||||||
|
{/* Left */}
|
||||||
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
<Icon icon="stash:filter-light" fontSize={30} />
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
|
|
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
import AllContentPage from "@/components/landing-page/all-content-page";
|
|
||||||
|
|
||||||
const regions = [
|
|
||||||
{ name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
|
||||||
{ name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Bangka Belitung",
|
|
||||||
slug: "bangka-belitung",
|
|
||||||
logo: "/logo/polda/polda-bangka-belitung.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Banten",
|
|
||||||
slug: "banten",
|
|
||||||
logo: "/logo/polda/polda-banten.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Bengkulu",
|
|
||||||
slug: "bengkulu",
|
|
||||||
logo: "/logo/polda/polda-bengkulu.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda DIY",
|
|
||||||
slug: "jogja",
|
|
||||||
logo: "/logo/polda/polda-jogja.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Gorontalo",
|
|
||||||
slug: "gorontalo",
|
|
||||||
logo: "/logo/polda/polda-gorontalo.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Barat",
|
|
||||||
slug: "jawa-barat",
|
|
||||||
logo: "/logo/polda/polda-jawa-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Tengah",
|
|
||||||
slug: "jawa-tengah",
|
|
||||||
logo: "/logo/polda/polda-jawa-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Timur",
|
|
||||||
slug: "jawa-timur",
|
|
||||||
logo: "/logo/polda/polda-jawa-timur.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Barat",
|
|
||||||
slug: "kalimantan-barat",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Selatan",
|
|
||||||
slug: "kalimantan-selatan",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Tengah",
|
|
||||||
slug: "kalimantan-tengah",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Timur",
|
|
||||||
slug: "kalimantan-timur",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-timur.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Utara",
|
|
||||||
slug: "kalimantan-utara",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kepulauan Riau",
|
|
||||||
slug: "kepulauan-riau",
|
|
||||||
logo: "/logo/polda/polda-kepulauan-riau.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Lampung",
|
|
||||||
slug: "lampung",
|
|
||||||
logo: "/logo/polda/polda-lampung.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Maluku",
|
|
||||||
slug: "maluku",
|
|
||||||
logo: "/logo/polda/polda-maluku.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Maluku Utara",
|
|
||||||
slug: "maluku-utara",
|
|
||||||
logo: "/logo/polda/polda-maluku-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Metro Jaya",
|
|
||||||
slug: "metro-jaya",
|
|
||||||
logo: "/logo/polda/polda-metro-jaya.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda NTB",
|
|
||||||
slug: "ntb",
|
|
||||||
logo: "/logo/polda/polda-ntb.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda NTT",
|
|
||||||
slug: "ntt",
|
|
||||||
logo: "/logo/polda/polda-ntt.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Papua Barat",
|
|
||||||
slug: "papua-barat",
|
|
||||||
logo: "/logo/polda/polda-papua-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Papua Barat Daya",
|
|
||||||
slug: "papua-barat-daya",
|
|
||||||
logo: "/logo/polda/polda-papua-barat-daya.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Papua Tengah",
|
|
||||||
slug: "papua-tengah",
|
|
||||||
logo: "/logo/polda/polda-papua-tengah.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Barat",
|
|
||||||
slug: "sulawesi-barat",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Selatan",
|
|
||||||
slug: "sulawesi-selatan",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Tengah",
|
|
||||||
slug: "sulawesi-tengah",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Tenggara",
|
|
||||||
slug: "sulawesi-tenggara",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Utara",
|
|
||||||
slug: "sulawesi-utara",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Barat",
|
|
||||||
slug: "sumatera-barat",
|
|
||||||
logo: "/logo/polda/polda-sumatera-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Selatan",
|
|
||||||
slug: "sumatera-selatan",
|
|
||||||
logo: "/logo/polda/polda-sumatera-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Utara",
|
|
||||||
slug: "sumatera-utara",
|
|
||||||
logo: "/logo/polda/polda-sumatera-utara.png",
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// name: "Satuan Kerja POLRI",
|
|
||||||
// slug: "satker-polri",
|
|
||||||
// logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: "Internasional",
|
|
||||||
// slug: "internasional",
|
|
||||||
// logo: "/assets/polda/internasional.png",
|
|
||||||
// },
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function PoldaAllAudioPage() {
|
|
||||||
return (
|
|
||||||
<AllContentPage
|
|
||||||
typeId="4"
|
|
||||||
title="Semua Konten Audio per Polda"
|
|
||||||
basePath="audio"
|
|
||||||
mode="polda"
|
|
||||||
dataList={regions}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,942 @@
|
||||||
|
"use client";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
|
import {
|
||||||
|
getPublicCategoryData,
|
||||||
|
getUserLevelListByParent,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import ReactDatePicker from "react-datepicker";
|
||||||
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import { close, loading } from "@/config/swal";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import ImageBlurry from "@/components/ui/image-blurry";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
const columns: ColumnDef<any>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "no",
|
||||||
|
header: "No",
|
||||||
|
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function FilterPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const asPath = usePathname();
|
||||||
|
const params = useParams();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const t = useTranslations("FilterPage");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [audioData, setAudioData] = useState<any[]>([]);
|
||||||
|
const [totalData, setTotalData] = useState<number>(1);
|
||||||
|
const [totalPage, setTotalPage] = useState<number>(1);
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||||
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [totalContent, setTotalContent] = useState(0);
|
||||||
|
const [change, setChange] = useState(false);
|
||||||
|
const sortBy = searchParams?.get("sortBy");
|
||||||
|
const title = searchParams?.get("title");
|
||||||
|
const categorie = searchParams?.get("category");
|
||||||
|
const group = searchParams?.get("group");
|
||||||
|
const [categoryFilter, setCategoryFilter] = useState<any[]>([]);
|
||||||
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
|
const [formatFilter, setFormatFilter] = useState<any[]>([]);
|
||||||
|
const pages = page ? page - 1 : 0;
|
||||||
|
const [startDateString, setStartDateString] = useState<any>();
|
||||||
|
const [endDateString, setEndDateString] = useState<any>();
|
||||||
|
const [dateRange, setDateRange] = useState<any>([null, null]);
|
||||||
|
const [handleClose, setHandleClose] = useState(false);
|
||||||
|
const [categories, setCategories] = useState<any[]>([]);
|
||||||
|
const [isFilterOpen, setIsFilterOpen] = useState(true);
|
||||||
|
|
||||||
|
const poldaName = params?.polda_name;
|
||||||
|
const satkerName = params?.satker_name;
|
||||||
|
|
||||||
|
let prefixPath = poldaName
|
||||||
|
? `/polda/${poldaName}`
|
||||||
|
: satkerName
|
||||||
|
? `/satker/${satkerName}`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
// === INIT ===
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => setIsLoading(false), 1200);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const pageFromUrl = searchParams?.get("page");
|
||||||
|
if (pageFromUrl) setPage(Number(pageFromUrl));
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (categorie) {
|
||||||
|
setCategoryFilter(
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [categorie]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategories(categoryPage);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchCategories = async (pageNumber: number) => {
|
||||||
|
const groupParam =
|
||||||
|
poldaName && poldaName.length > 1
|
||||||
|
? poldaName
|
||||||
|
: satkerName && satkerName.length > 1
|
||||||
|
? "satker-" + satkerName
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const isInt = locale === "en";
|
||||||
|
|
||||||
|
const response = await getPublicCategoryData(
|
||||||
|
groupParam,
|
||||||
|
"",
|
||||||
|
isInt,
|
||||||
|
pageNumber
|
||||||
|
); // halaman 1-based
|
||||||
|
|
||||||
|
const content = response?.data?.data?.content || [];
|
||||||
|
const total = response?.data?.data?.totalPages || 1;
|
||||||
|
|
||||||
|
setCategories(content);
|
||||||
|
setCategoryTotalPages(total);
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (asPath?.includes("/regional")) getDataRegional();
|
||||||
|
else getDataAll();
|
||||||
|
}, [
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
|
async function getDataAll() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listData(
|
||||||
|
"4",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
locale == "en" ? true : false
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setAudioData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataRegional() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listDataRegional(
|
||||||
|
"4",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setAudioData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCategoryFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...categoryFilter];
|
||||||
|
if (e) filter.push(String(id));
|
||||||
|
else filter = filter.filter((item) => item !== String(id));
|
||||||
|
router.push(`?category=${filter.join("&")}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormatFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...formatFilter];
|
||||||
|
if (e) filter.push(id);
|
||||||
|
else filter = filter.filter((item) => item !== id);
|
||||||
|
setFormatFilter(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSorting = (e: any) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setSortByOpt(value === "latest" ? "createdAt" : "clickCount");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteDate = () => {
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setStartDateString("");
|
||||||
|
setEndDateString("");
|
||||||
|
setHandleClose(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyUp = () => {
|
||||||
|
if (!searchTitle) router.push("?title=");
|
||||||
|
else router.push(`?title=${searchTitle.toLowerCase()}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// === REACT TABLE ===
|
||||||
|
const table = useReactTable({
|
||||||
|
data: audioData,
|
||||||
|
columns,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
onRowSelectionChange: setRowSelection,
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
state: {
|
||||||
|
sorting,
|
||||||
|
columnFilters,
|
||||||
|
columnVisibility,
|
||||||
|
rowSelection,
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [calenderState, setCalenderState] = useState(false);
|
||||||
|
const [categoryPage, setCategoryPage] = useState(1);
|
||||||
|
const [categoryTotalPages, setCategoryTotalPages] = useState(1);
|
||||||
|
let typingTimer: any;
|
||||||
|
|
||||||
|
const cleanCheckbox = () => {
|
||||||
|
setCategoryFilter([]);
|
||||||
|
setFormatFilter([]);
|
||||||
|
router.push(`?category=&title=`);
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setMonthYearFilter(null);
|
||||||
|
setChange(!change);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = () => {
|
||||||
|
clearTimeout(typingTimer);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
|
||||||
|
<p>
|
||||||
|
{" "}
|
||||||
|
Audio {">"}{" "}
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("allAudio", { defaultValue: "All Audio" })}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">|</p>
|
||||||
|
{!title ? (
|
||||||
|
<p>
|
||||||
|
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
|
||||||
|
"downloadableImage",
|
||||||
|
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
|
||||||
|
)}`}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
|
||||||
|
<span className="font-bold">"{title}"</span>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">
|
||||||
|
{/* Left */}
|
||||||
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
|
Filter
|
||||||
|
</h2>
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
|
{t("search", { defaultValue: "Search" })}
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
value={searchTitle}
|
||||||
|
onChange={(e) => setSearchTitle(e.target.value)}
|
||||||
|
onKeyUp={handleKeyUp}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
type="text"
|
||||||
|
id="search"
|
||||||
|
placeholder={t("searchTitle", { defaultValue: "Search Title" })}
|
||||||
|
className="mt-1 w-full text-sm border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear", { defaultValue: "Month Year" })}
|
||||||
|
</label>
|
||||||
|
<ReactDatePicker
|
||||||
|
selected={monthYearFilter}
|
||||||
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
onChange={(date) => setMonthYearFilter(date)}
|
||||||
|
dateFormat="MM | yyyy"
|
||||||
|
placeholderText={t("selectYear", {
|
||||||
|
defaultValue: "Select Year",
|
||||||
|
})}
|
||||||
|
showMonthYearPicker
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date", { defaultValue: "Date" })}
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
|
<ReactDatePicker
|
||||||
|
selectsRange
|
||||||
|
className="mt-1 w-full border text-sm rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
startDate={dateRange[0]}
|
||||||
|
endDate={dateRange[1]}
|
||||||
|
onChange={(update) => {
|
||||||
|
setDateRange(update);
|
||||||
|
}}
|
||||||
|
placeholderText={t("searchDate", {
|
||||||
|
defaultValue: "Search Date",
|
||||||
|
})}
|
||||||
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* ⬇️ Pagination kategori (rata sejajar) */}
|
||||||
|
<div className="mt-4 flex justify-center items-center gap-2 flex-wrap">
|
||||||
|
{/* Tombol Prev */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{(() => {
|
||||||
|
const maxVisible = 4;
|
||||||
|
let startPage = Math.max(
|
||||||
|
1,
|
||||||
|
Math.min(
|
||||||
|
categoryPage - Math.floor(maxVisible / 2),
|
||||||
|
categoryTotalPages - maxVisible + 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const endPage = Math.min(
|
||||||
|
categoryTotalPages,
|
||||||
|
startPage + maxVisible - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const visiblePages = [];
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
visiblePages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visiblePages.map((pageNum) => (
|
||||||
|
<button
|
||||||
|
key={pageNum}
|
||||||
|
onClick={() => setCategoryPage(pageNum)}
|
||||||
|
className={`px-3 py-1 border rounded text-sm transition-colors ${
|
||||||
|
categoryPage === pageNum
|
||||||
|
? "bg-[#bb3523] text-white"
|
||||||
|
: "bg-white dark:bg-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pageNum}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{/* Tombol Next */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories?.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
<div className="mt-4 flex gap-2 justify-center items-center">
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{Array.from({ length: categoryTotalPages }, (_, i) => (
|
||||||
|
<button
|
||||||
|
key={i}
|
||||||
|
onClick={() => setCategoryPage(i + 1)}
|
||||||
|
className={`px-3 py-1 border rounded ${
|
||||||
|
categoryPage === i + 1 ? "bg-[#bb3523] text-white" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{i + 1}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</div> */}
|
||||||
|
{/* Garis */}
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
{/* Garis */}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="png"
|
||||||
|
value="png"
|
||||||
|
checked={formatFilter.includes("wav")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "wav")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
WAV
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="jpeg"
|
||||||
|
value="jpeg"
|
||||||
|
checked={formatFilter.includes("mp3")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mp3")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MP3
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
|
<div className="text-center">
|
||||||
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
|
<b>Reset Filter</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* CONTENT */}
|
||||||
|
<div className="w-full pr-4 lg:pr-16 pb-4">
|
||||||
|
<Reveal>
|
||||||
|
<div className="flex flex-col items-end mb-4">
|
||||||
|
<h2 className="text-lg font-semibold">Sort By</h2>
|
||||||
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "popular" : "latest"}
|
||||||
|
onChange={handleSorting}
|
||||||
|
className="border rounded-md py-2 px-3"
|
||||||
|
>
|
||||||
|
<option value="latest">Latest</option>
|
||||||
|
<option value="popular">Most Popular</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
</div>
|
||||||
|
) : audioData?.length > 0 ? (
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{audioData?.map((audio: any) => (
|
||||||
|
<Card
|
||||||
|
key={audio?.id}
|
||||||
|
className="hover:scale-105 transition-transform duration-300"
|
||||||
|
>
|
||||||
|
<CardContent
|
||||||
|
key={audio?.id}
|
||||||
|
className="md:basis-1/2 lg:basis-1/3"
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={`${prefixPath}/audio/detail/${audio?.slug
|
||||||
|
?.split("/")
|
||||||
|
.pop()}`}
|
||||||
|
// href={`${prefixPath}/document/detail/${text?.slug}`}
|
||||||
|
// href={prefixPath + `/document/detail/${text?.slug}`}
|
||||||
|
// onClick={() =>
|
||||||
|
// router.push(prefixPath + `/document/detail/${text?.slug}`)
|
||||||
|
// }
|
||||||
|
className="cursor-pointer rounded-lg shadow-md overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500"
|
||||||
|
>
|
||||||
|
{/* Ikon di tengah dengan latar kuning */}
|
||||||
|
<div className="flex items-center justify-center bg-[#bb3523] w-full h-[180px] text-white">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="150"
|
||||||
|
height="150"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M14.702 2.226A1 1 0 0 1 16 3.18v6.027a5.5 5.5 0 0 0-1-.184V6.18L8 8.368V15.5a2.5 2.5 0 1 1-1-2V5.368a1 1 0 0 1 .702-.955zM8 7.32l7-2.187V3.18L8 5.368zM5.5 14a1.5 1.5 0 1 0 0 3a1.5 1.5 0 0 0 0-3m13.5.5a4.5 4.5 0 1 1-9 0a4.5 4.5 0 0 1 9 0m-2.265-.436l-2.994-1.65a.5.5 0 0 0-.741.438v3.3a.5.5 0 0 0 .741.438l2.994-1.65a.5.5 0 0 0 0-.876"
|
||||||
|
/>
|
||||||
|
</svg>{" "}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Konten bawah */}
|
||||||
|
<div className="p-4 flex flex-col gap-2">
|
||||||
|
{/* Kategori merah */}
|
||||||
|
<div className="text-[12px] font-bold text-red-600 uppercase">
|
||||||
|
{audio?.categoryName?.toUpperCase() ?? "Text"}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Judul */}
|
||||||
|
<div className="font-semibold text-gray-900 dark:text-white text-xl leading-snug line-clamp-4">
|
||||||
|
{audio?.title}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-center items-center py-10">
|
||||||
|
<Image
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{totalPage > 1 && (
|
||||||
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Reveal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// import AllContentPage from "@/components/landing-page/all-content-page";
|
||||||
|
|
||||||
|
// const regions = [
|
||||||
|
// { name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
||||||
|
// { name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bangka Belitung",
|
||||||
|
// slug: "bangka-belitung",
|
||||||
|
// logo: "/logo/polda/polda-bangka-belitung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Banten",
|
||||||
|
// slug: "banten",
|
||||||
|
// logo: "/logo/polda/polda-banten.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bengkulu",
|
||||||
|
// slug: "bengkulu",
|
||||||
|
// logo: "/logo/polda/polda-bengkulu.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda DIY",
|
||||||
|
// slug: "jogja",
|
||||||
|
// logo: "/logo/polda/polda-jogja.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Gorontalo",
|
||||||
|
// slug: "gorontalo",
|
||||||
|
// logo: "/logo/polda/polda-gorontalo.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Barat",
|
||||||
|
// slug: "jawa-barat",
|
||||||
|
// logo: "/logo/polda/polda-jawa-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Tengah",
|
||||||
|
// slug: "jawa-tengah",
|
||||||
|
// logo: "/logo/polda/polda-jawa-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Timur",
|
||||||
|
// slug: "jawa-timur",
|
||||||
|
// logo: "/logo/polda/polda-jawa-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Barat",
|
||||||
|
// slug: "kalimantan-barat",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Selatan",
|
||||||
|
// slug: "kalimantan-selatan",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Tengah",
|
||||||
|
// slug: "kalimantan-tengah",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Timur",
|
||||||
|
// slug: "kalimantan-timur",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Utara",
|
||||||
|
// slug: "kalimantan-utara",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kepulauan Riau",
|
||||||
|
// slug: "kepulauan-riau",
|
||||||
|
// logo: "/logo/polda/polda-kepulauan-riau.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Lampung",
|
||||||
|
// slug: "lampung",
|
||||||
|
// logo: "/logo/polda/polda-lampung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku",
|
||||||
|
// slug: "maluku",
|
||||||
|
// logo: "/logo/polda/polda-maluku.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku Utara",
|
||||||
|
// slug: "maluku-utara",
|
||||||
|
// logo: "/logo/polda/polda-maluku-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Metro Jaya",
|
||||||
|
// slug: "metro-jaya",
|
||||||
|
// logo: "/logo/polda/polda-metro-jaya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTB",
|
||||||
|
// slug: "ntb",
|
||||||
|
// logo: "/logo/polda/polda-ntb.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTT",
|
||||||
|
// slug: "ntt",
|
||||||
|
// logo: "/logo/polda/polda-ntt.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat",
|
||||||
|
// slug: "papua-barat",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat Daya",
|
||||||
|
// slug: "papua-barat-daya",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat-daya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Tengah",
|
||||||
|
// slug: "papua-tengah",
|
||||||
|
// logo: "/logo/polda/polda-papua-tengah.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Barat",
|
||||||
|
// slug: "sulawesi-barat",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Selatan",
|
||||||
|
// slug: "sulawesi-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tengah",
|
||||||
|
// slug: "sulawesi-tengah",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tenggara",
|
||||||
|
// slug: "sulawesi-tenggara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Utara",
|
||||||
|
// slug: "sulawesi-utara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Barat",
|
||||||
|
// slug: "sumatera-barat",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Selatan",
|
||||||
|
// slug: "sumatera-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Utara",
|
||||||
|
// slug: "sumatera-utara",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-utara.png",
|
||||||
|
// },
|
||||||
|
// // {
|
||||||
|
// // name: "Satuan Kerja POLRI",
|
||||||
|
// // slug: "satker-polri",
|
||||||
|
// // logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
||||||
|
// // },
|
||||||
|
// // {
|
||||||
|
// // name: "Internasional",
|
||||||
|
// // slug: "internasional",
|
||||||
|
// // logo: "/assets/polda/internasional.png",
|
||||||
|
// // },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// export default function PoldaAllAudioPage() {
|
||||||
|
// return (
|
||||||
|
// <AllContentPage
|
||||||
|
// typeId="4"
|
||||||
|
// title="Semua Konten Audio per Polda"
|
||||||
|
// basePath="audio"
|
||||||
|
// mode="polda"
|
||||||
|
// dataList={regions}
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
import AllContentPage from "@/components/landing-page/all-content-page";
|
|
||||||
|
|
||||||
const regions = [
|
|
||||||
{ name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
|
||||||
{ name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Bangka Belitung",
|
|
||||||
slug: "bangka-belitung",
|
|
||||||
logo: "/logo/polda/polda-bangka-belitung.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Banten",
|
|
||||||
slug: "banten",
|
|
||||||
logo: "/logo/polda/polda-banten.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Bengkulu",
|
|
||||||
slug: "bengkulu",
|
|
||||||
logo: "/logo/polda/polda-bengkulu.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda DIY",
|
|
||||||
slug: "jogja",
|
|
||||||
logo: "/logo/polda/polda-jogja.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Gorontalo",
|
|
||||||
slug: "gorontalo",
|
|
||||||
logo: "/logo/polda/polda-gorontalo.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Barat",
|
|
||||||
slug: "jawa-barat",
|
|
||||||
logo: "/logo/polda/polda-jawa-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Tengah",
|
|
||||||
slug: "jawa-tengah",
|
|
||||||
logo: "/logo/polda/polda-jawa-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Timur",
|
|
||||||
slug: "jawa-timur",
|
|
||||||
logo: "/logo/polda/polda-jawa-timur.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Barat",
|
|
||||||
slug: "kalimantan-barat",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Selatan",
|
|
||||||
slug: "kalimantan-selatan",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Tengah",
|
|
||||||
slug: "kalimantan-tengah",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Timur",
|
|
||||||
slug: "kalimantan-timur",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-timur.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Utara",
|
|
||||||
slug: "kalimantan-utara",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kepulauan Riau",
|
|
||||||
slug: "kepulauan-riau",
|
|
||||||
logo: "/logo/polda/polda-kepulauan-riau.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Lampung",
|
|
||||||
slug: "lampung",
|
|
||||||
logo: "/logo/polda/polda-lampung.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Maluku",
|
|
||||||
slug: "maluku",
|
|
||||||
logo: "/logo/polda/polda-maluku.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Maluku Utara",
|
|
||||||
slug: "maluku-utara",
|
|
||||||
logo: "/logo/polda/polda-maluku-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Metro Jaya",
|
|
||||||
slug: "metro-jaya",
|
|
||||||
logo: "/logo/polda/polda-metro-jaya.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda NTB",
|
|
||||||
slug: "ntb",
|
|
||||||
logo: "/logo/polda/polda-ntb.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda NTT",
|
|
||||||
slug: "ntt",
|
|
||||||
logo: "/logo/polda/polda-ntt.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Papua Barat",
|
|
||||||
slug: "papua-barat",
|
|
||||||
logo: "/logo/polda/polda-papua-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Papua Barat Daya",
|
|
||||||
slug: "papua-barat-daya",
|
|
||||||
logo: "/logo/polda/polda-papua-barat-daya.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Papua Tengah",
|
|
||||||
slug: "papua-tengah",
|
|
||||||
logo: "/logo/polda/polda-papua-tengah.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Barat",
|
|
||||||
slug: "sulawesi-barat",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Selatan",
|
|
||||||
slug: "sulawesi-selatan",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Tengah",
|
|
||||||
slug: "sulawesi-tengah",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Tenggara",
|
|
||||||
slug: "sulawesi-tenggara",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Utara",
|
|
||||||
slug: "sulawesi-utara",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Barat",
|
|
||||||
slug: "sumatera-barat",
|
|
||||||
logo: "/logo/polda/polda-sumatera-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Selatan",
|
|
||||||
slug: "sumatera-selatan",
|
|
||||||
logo: "/logo/polda/polda-sumatera-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Utara",
|
|
||||||
slug: "sumatera-utara",
|
|
||||||
logo: "/logo/polda/polda-sumatera-utara.png",
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// name: "Satuan Kerja POLRI",
|
|
||||||
// slug: "satker-polri",
|
|
||||||
// logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: "Internasional",
|
|
||||||
// slug: "internasional",
|
|
||||||
// logo: "/assets/polda/internasional.png",
|
|
||||||
// },
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function PoldaAllDocumentPage() {
|
|
||||||
return (
|
|
||||||
<AllContentPage
|
|
||||||
typeId="3"
|
|
||||||
title="Semua Konten Teks per Polda"
|
|
||||||
basePath="document"
|
|
||||||
mode="polda"
|
|
||||||
dataList={regions}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,988 @@
|
||||||
|
"use client";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
|
import {
|
||||||
|
getPublicCategoryData,
|
||||||
|
getUserLevelListByParent,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import ReactDatePicker from "react-datepicker";
|
||||||
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import { close, loading } from "@/config/swal";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import ImageBlurry from "@/components/ui/image-blurry";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
const columns: ColumnDef<any>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "no",
|
||||||
|
header: "No",
|
||||||
|
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function FilterPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const asPath = usePathname();
|
||||||
|
const params = useParams();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const t = useTranslations("FilterPage");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [documentData, setDocumentData] = useState<any[]>([]);
|
||||||
|
const [totalData, setTotalData] = useState<number>(1);
|
||||||
|
const [totalPage, setTotalPage] = useState<number>(1);
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||||
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [totalContent, setTotalContent] = useState(0);
|
||||||
|
const [change, setChange] = useState(false);
|
||||||
|
const sortBy = searchParams?.get("sortBy");
|
||||||
|
const title = searchParams?.get("title");
|
||||||
|
const categorie = searchParams?.get("category");
|
||||||
|
const group = searchParams?.get("group");
|
||||||
|
const [categoryFilter, setCategoryFilter] = useState<any[]>([]);
|
||||||
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
|
const [formatFilter, setFormatFilter] = useState<any[]>([]);
|
||||||
|
const pages = page ? page - 1 : 0;
|
||||||
|
const [startDateString, setStartDateString] = useState<any>();
|
||||||
|
const [endDateString, setEndDateString] = useState<any>();
|
||||||
|
const [dateRange, setDateRange] = useState<any>([null, null]);
|
||||||
|
const [handleClose, setHandleClose] = useState(false);
|
||||||
|
const [categories, setCategories] = useState<any[]>([]);
|
||||||
|
const [isFilterOpen, setIsFilterOpen] = useState(true);
|
||||||
|
|
||||||
|
const poldaName = params?.polda_name;
|
||||||
|
const satkerName = params?.satker_name;
|
||||||
|
|
||||||
|
let prefixPath = poldaName
|
||||||
|
? `/polda/${poldaName}`
|
||||||
|
: satkerName
|
||||||
|
? `/satker/${satkerName}`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
// === INIT ===
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => setIsLoading(false), 1200);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const pageFromUrl = searchParams?.get("page");
|
||||||
|
if (pageFromUrl) setPage(Number(pageFromUrl));
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (categorie) {
|
||||||
|
setCategoryFilter(
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [categorie]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategories(categoryPage);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchCategories = async (pageNumber: number) => {
|
||||||
|
const groupParam =
|
||||||
|
poldaName && poldaName.length > 1
|
||||||
|
? poldaName
|
||||||
|
: satkerName && satkerName.length > 1
|
||||||
|
? "satker-" + satkerName
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const isInt = locale === "en";
|
||||||
|
|
||||||
|
const response = await getPublicCategoryData(
|
||||||
|
groupParam,
|
||||||
|
"",
|
||||||
|
isInt,
|
||||||
|
pageNumber
|
||||||
|
); // halaman 1-based
|
||||||
|
|
||||||
|
const content = response?.data?.data?.content || [];
|
||||||
|
const total = response?.data?.data?.totalPages || 1;
|
||||||
|
|
||||||
|
setCategories(content);
|
||||||
|
setCategoryTotalPages(total);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (asPath?.includes("/regional")) getDataRegional();
|
||||||
|
else getDataAll();
|
||||||
|
}, [
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
|
async function getDataAll() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listData(
|
||||||
|
"3",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
locale == "en" ? true : false
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setDocumentData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataRegional() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listDataRegional(
|
||||||
|
"3",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setDocumentData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCategoryFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...categoryFilter];
|
||||||
|
if (e) filter.push(String(id));
|
||||||
|
else filter = filter.filter((item) => item !== String(id));
|
||||||
|
router.push(`?category=${filter.join("&")}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormatFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...formatFilter];
|
||||||
|
if (e) filter.push(id);
|
||||||
|
else filter = filter.filter((item) => item !== id);
|
||||||
|
setFormatFilter(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSorting = (e: any) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setSortByOpt(value === "latest" ? "createdAt" : "clickCount");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteDate = () => {
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setStartDateString("");
|
||||||
|
setEndDateString("");
|
||||||
|
setHandleClose(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyUp = () => {
|
||||||
|
if (!searchTitle) router.push("?title=");
|
||||||
|
else router.push(`?title=${searchTitle.toLowerCase()}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// === REACT TABLE ===
|
||||||
|
const table = useReactTable({
|
||||||
|
data: documentData,
|
||||||
|
columns,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
onRowSelectionChange: setRowSelection,
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
state: {
|
||||||
|
sorting,
|
||||||
|
columnFilters,
|
||||||
|
columnVisibility,
|
||||||
|
rowSelection,
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [calenderState, setCalenderState] = useState(false);
|
||||||
|
const [categoryPage, setCategoryPage] = useState(1);
|
||||||
|
const [categoryTotalPages, setCategoryTotalPages] = useState(1);
|
||||||
|
let typingTimer: any;
|
||||||
|
|
||||||
|
const cleanCheckbox = () => {
|
||||||
|
setCategoryFilter([]);
|
||||||
|
setFormatFilter([]);
|
||||||
|
router.push(`?category=&title=`);
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setMonthYearFilter(null);
|
||||||
|
setChange(!change);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = () => {
|
||||||
|
clearTimeout(typingTimer);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
|
||||||
|
<p>
|
||||||
|
{" "}
|
||||||
|
{t("text", { defaultValue: "Text" })} {">"}{" "}
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("allText", { defaultValue: "All Text" })}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">|</p>
|
||||||
|
{!title ? (
|
||||||
|
<p>
|
||||||
|
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
|
||||||
|
"downloadableImage",
|
||||||
|
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
|
||||||
|
)}`}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
|
||||||
|
<span className="font-bold">"{title}"</span>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">
|
||||||
|
{/* Left */}
|
||||||
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
|
Filter
|
||||||
|
</h2>
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
|
{t("search", { defaultValue: "Search" })}
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
value={searchTitle}
|
||||||
|
onChange={(e) => setSearchTitle(e.target.value)}
|
||||||
|
onKeyUp={handleKeyUp}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
type="text"
|
||||||
|
id="search"
|
||||||
|
placeholder={t("searchTitle", { defaultValue: "Search Title" })}
|
||||||
|
className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear", { defaultValue: "Month Year" })}
|
||||||
|
</label>
|
||||||
|
<ReactDatePicker
|
||||||
|
selected={monthYearFilter}
|
||||||
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
onChange={(date) => setMonthYearFilter(date)}
|
||||||
|
dateFormat="MM | yyyy"
|
||||||
|
placeholderText={t("selectYear", {
|
||||||
|
defaultValue: "Select Year",
|
||||||
|
})}
|
||||||
|
showMonthYearPicker
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date", { defaultValue: "Date" })}
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
|
<ReactDatePicker
|
||||||
|
selectsRange
|
||||||
|
className="mt-1 w-full border text-sm rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
startDate={dateRange[0]}
|
||||||
|
endDate={dateRange[1]}
|
||||||
|
onChange={(update) => {
|
||||||
|
setDateRange(update);
|
||||||
|
}}
|
||||||
|
placeholderText={t("selectDate", {
|
||||||
|
defaultValue: "Select Date",
|
||||||
|
})}
|
||||||
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* ⬇️ Pagination kategori (rata sejajar) */}
|
||||||
|
<div className="mt-4 flex justify-center items-center gap-2 flex-wrap">
|
||||||
|
{/* Tombol Prev */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{(() => {
|
||||||
|
const maxVisible = 4;
|
||||||
|
let startPage = Math.max(
|
||||||
|
1,
|
||||||
|
Math.min(
|
||||||
|
categoryPage - Math.floor(maxVisible / 2),
|
||||||
|
categoryTotalPages - maxVisible + 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const endPage = Math.min(
|
||||||
|
categoryTotalPages,
|
||||||
|
startPage + maxVisible - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const visiblePages = [];
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
visiblePages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visiblePages.map((pageNum) => (
|
||||||
|
<button
|
||||||
|
key={pageNum}
|
||||||
|
onClick={() => setCategoryPage(pageNum)}
|
||||||
|
className={`px-3 py-1 border rounded text-sm transition-colors ${
|
||||||
|
categoryPage === pageNum
|
||||||
|
? "bg-[#bb3523] text-white"
|
||||||
|
: "bg-white dark:bg-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pageNum}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{/* Tombol Next */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
<div className="mt-4 flex gap-2 justify-center items-center">
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{Array.from({ length: categoryTotalPages }, (_, i) => (
|
||||||
|
<button
|
||||||
|
key={i}
|
||||||
|
onClick={() => setCategoryPage(i + 1)}
|
||||||
|
className={`px-3 py-1 border rounded ${
|
||||||
|
categoryPage === i + 1 ? "bg-[#bb3523] text-white" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{i + 1}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</div> */}
|
||||||
|
{/* Garis */}
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
{/* Garis */}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="doc"
|
||||||
|
value="doc"
|
||||||
|
checked={formatFilter.includes("doc")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "doc")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
DOC
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="docx"
|
||||||
|
value="docx"
|
||||||
|
checked={formatFilter.includes("docx")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "docx")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
DOCX
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="pdf"
|
||||||
|
value="pdf"
|
||||||
|
checked={formatFilter.includes("pdf")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "pdf")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PDF
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="ppt"
|
||||||
|
value="ppt"
|
||||||
|
checked={formatFilter.includes("ppt")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "ppt")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PPT
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="pptx"
|
||||||
|
value="pptx"
|
||||||
|
checked={formatFilter.includes("pptx")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "pptx")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PPTX
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
|
<div className="text-center">
|
||||||
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
|
<b>Reset Filter</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* RIGHT */}
|
||||||
|
<div className="w-full pr-4 lg:pr-16 pb-4">
|
||||||
|
<Reveal>
|
||||||
|
<div className="flex flex-col items-end mb-4">
|
||||||
|
<h2 className="text-lg font-semibold">Sort By</h2>
|
||||||
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "popular" : "latest"}
|
||||||
|
onChange={handleSorting}
|
||||||
|
className="border rounded-md py-2 px-3"
|
||||||
|
>
|
||||||
|
<option value="latest">Latest</option>
|
||||||
|
<option value="popular">Most Popular</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
</div>
|
||||||
|
) : documentData?.length > 0 ? (
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{documentData?.map((document: any) => (
|
||||||
|
<Card
|
||||||
|
key={document?.id}
|
||||||
|
className="hover:scale-105 transition-transform duration-300"
|
||||||
|
>
|
||||||
|
<CardContent
|
||||||
|
key={document?.id}
|
||||||
|
className="md:basis-1/2 lg:basis-1/3"
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={`${prefixPath}/document/detail/${document?.slug
|
||||||
|
?.split("/")
|
||||||
|
.pop()}`}
|
||||||
|
// href={`${prefixPath}/document/detail/${text?.slug}`}
|
||||||
|
// href={prefixPath + `/document/detail/${text?.slug}`}
|
||||||
|
// onClick={() =>
|
||||||
|
// router.push(prefixPath + `/document/detail/${text?.slug}`)
|
||||||
|
// }
|
||||||
|
className="cursor-pointer rounded-lg shadow-md overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500"
|
||||||
|
>
|
||||||
|
{/* Ikon di tengah dengan latar kuning */}
|
||||||
|
<div className="bg-[#e0c350] flex items-center justify-center h-[170px] text-white">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="150"
|
||||||
|
height="150"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M5 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V5.414a1.5 1.5 0 0 0-.44-1.06L9.647 1.439A1.5 1.5 0 0 0 8.586 1zM4 3a1 1 0 0 1 1-1h3v2.5A1.5 1.5 0 0 0 9.5 6H12v7a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1zm7.793 2H9.5a.5.5 0 0 1-.5-.5V2.207zM7 7.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5M7.5 9a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1zM7 11.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5M5.5 8a.5.5 0 1 0 0-1a.5.5 0 0 0 0 1M6 9.5a.5.5 0 1 1-1 0a.5.5 0 0 1 1 0M5.5 12a.5.5 0 1 0 0-1a.5.5 0 0 0 0 1"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Konten bawah */}
|
||||||
|
<div className="p-4 flex flex-col gap-2">
|
||||||
|
{/* Kategori merah */}
|
||||||
|
<div className="text-[12px] font-bold text-red-600 uppercase">
|
||||||
|
{document?.categoryName?.toUpperCase() ?? "Text"}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Judul */}
|
||||||
|
<div className="font-semibold text-gray-900 dark:text-white text-xl leading-snug line-clamp-4">
|
||||||
|
{document?.title}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-center items-center py-10">
|
||||||
|
<Image
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{totalPage > 1 && (
|
||||||
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Reveal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// import AllContentPage from "@/components/landing-page/all-content-page";
|
||||||
|
|
||||||
|
// const regions = [
|
||||||
|
// { name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
||||||
|
// { name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bangka Belitung",
|
||||||
|
// slug: "bangka-belitung",
|
||||||
|
// logo: "/logo/polda/polda-bangka-belitung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Banten",
|
||||||
|
// slug: "banten",
|
||||||
|
// logo: "/logo/polda/polda-banten.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bengkulu",
|
||||||
|
// slug: "bengkulu",
|
||||||
|
// logo: "/logo/polda/polda-bengkulu.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda DIY",
|
||||||
|
// slug: "jogja",
|
||||||
|
// logo: "/logo/polda/polda-jogja.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Gorontalo",
|
||||||
|
// slug: "gorontalo",
|
||||||
|
// logo: "/logo/polda/polda-gorontalo.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Barat",
|
||||||
|
// slug: "jawa-barat",
|
||||||
|
// logo: "/logo/polda/polda-jawa-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Tengah",
|
||||||
|
// slug: "jawa-tengah",
|
||||||
|
// logo: "/logo/polda/polda-jawa-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Timur",
|
||||||
|
// slug: "jawa-timur",
|
||||||
|
// logo: "/logo/polda/polda-jawa-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Barat",
|
||||||
|
// slug: "kalimantan-barat",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Selatan",
|
||||||
|
// slug: "kalimantan-selatan",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Tengah",
|
||||||
|
// slug: "kalimantan-tengah",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Timur",
|
||||||
|
// slug: "kalimantan-timur",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Utara",
|
||||||
|
// slug: "kalimantan-utara",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kepulauan Riau",
|
||||||
|
// slug: "kepulauan-riau",
|
||||||
|
// logo: "/logo/polda/polda-kepulauan-riau.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Lampung",
|
||||||
|
// slug: "lampung",
|
||||||
|
// logo: "/logo/polda/polda-lampung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku",
|
||||||
|
// slug: "maluku",
|
||||||
|
// logo: "/logo/polda/polda-maluku.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku Utara",
|
||||||
|
// slug: "maluku-utara",
|
||||||
|
// logo: "/logo/polda/polda-maluku-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Metro Jaya",
|
||||||
|
// slug: "metro-jaya",
|
||||||
|
// logo: "/logo/polda/polda-metro-jaya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTB",
|
||||||
|
// slug: "ntb",
|
||||||
|
// logo: "/logo/polda/polda-ntb.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTT",
|
||||||
|
// slug: "ntt",
|
||||||
|
// logo: "/logo/polda/polda-ntt.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat",
|
||||||
|
// slug: "papua-barat",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat Daya",
|
||||||
|
// slug: "papua-barat-daya",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat-daya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Tengah",
|
||||||
|
// slug: "papua-tengah",
|
||||||
|
// logo: "/logo/polda/polda-papua-tengah.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Barat",
|
||||||
|
// slug: "sulawesi-barat",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Selatan",
|
||||||
|
// slug: "sulawesi-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tengah",
|
||||||
|
// slug: "sulawesi-tengah",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tenggara",
|
||||||
|
// slug: "sulawesi-tenggara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Utara",
|
||||||
|
// slug: "sulawesi-utara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Barat",
|
||||||
|
// slug: "sumatera-barat",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Selatan",
|
||||||
|
// slug: "sumatera-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Utara",
|
||||||
|
// slug: "sumatera-utara",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-utara.png",
|
||||||
|
// },
|
||||||
|
// // {
|
||||||
|
// // name: "Satuan Kerja POLRI",
|
||||||
|
// // slug: "satker-polri",
|
||||||
|
// // logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
||||||
|
// // },
|
||||||
|
// // {
|
||||||
|
// // name: "Internasional",
|
||||||
|
// // slug: "internasional",
|
||||||
|
// // logo: "/assets/polda/internasional.png",
|
||||||
|
// // },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// export default function PoldaAllDocumentPage() {
|
||||||
|
// return (
|
||||||
|
// <AllContentPage
|
||||||
|
// typeId="3"
|
||||||
|
// title="Semua Konten Teks per Polda"
|
||||||
|
// basePath="document"
|
||||||
|
// mode="polda"
|
||||||
|
// dataList={regions}
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
import AllContentPage from "@/components/landing-page/all-content-page";
|
|
||||||
|
|
||||||
const regions = [
|
|
||||||
{ name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
|
||||||
{ name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Bangka Belitung",
|
|
||||||
slug: "bangka-belitung",
|
|
||||||
logo: "/logo/polda/polda-bangka-belitung.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Banten",
|
|
||||||
slug: "banten",
|
|
||||||
logo: "/logo/polda/polda-banten.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Bengkulu",
|
|
||||||
slug: "bengkulu",
|
|
||||||
logo: "/logo/polda/polda-bengkulu.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda DIY",
|
|
||||||
slug: "jogja",
|
|
||||||
logo: "/logo/polda/polda-jogja.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Gorontalo",
|
|
||||||
slug: "gorontalo",
|
|
||||||
logo: "/logo/polda/polda-gorontalo.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Barat",
|
|
||||||
slug: "jawa-barat",
|
|
||||||
logo: "/logo/polda/polda-jawa-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Tengah",
|
|
||||||
slug: "jawa-tengah",
|
|
||||||
logo: "/logo/polda/polda-jawa-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Timur",
|
|
||||||
slug: "jawa-timur",
|
|
||||||
logo: "/logo/polda/polda-jawa-timur.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Barat",
|
|
||||||
slug: "kalimantan-barat",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Selatan",
|
|
||||||
slug: "kalimantan-selatan",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Tengah",
|
|
||||||
slug: "kalimantan-tengah",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Timur",
|
|
||||||
slug: "kalimantan-timur",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-timur.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Utara",
|
|
||||||
slug: "kalimantan-utara",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kepulauan Riau",
|
|
||||||
slug: "kepulauan-riau",
|
|
||||||
logo: "/logo/polda/polda-kepulauan-riau.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Lampung",
|
|
||||||
slug: "lampung",
|
|
||||||
logo: "/logo/polda/polda-lampung.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Maluku",
|
|
||||||
slug: "maluku",
|
|
||||||
logo: "/logo/polda/polda-maluku.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Maluku Utara",
|
|
||||||
slug: "maluku-utara",
|
|
||||||
logo: "/logo/polda/polda-maluku-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Metro Jaya",
|
|
||||||
slug: "metro-jaya",
|
|
||||||
logo: "/logo/polda/polda-metro-jaya.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda NTB",
|
|
||||||
slug: "ntb",
|
|
||||||
logo: "/logo/polda/polda-ntb.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda NTT",
|
|
||||||
slug: "ntt",
|
|
||||||
logo: "/logo/polda/polda-ntt.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Papua Barat",
|
|
||||||
slug: "papua-barat",
|
|
||||||
logo: "/logo/polda/polda-papua-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Papua Barat Daya",
|
|
||||||
slug: "papua-barat-daya",
|
|
||||||
logo: "/logo/polda/polda-papua-barat-daya.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Papua Tengah",
|
|
||||||
slug: "papua-tengah",
|
|
||||||
logo: "/logo/polda/polda-papua-tengah.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Barat",
|
|
||||||
slug: "sulawesi-barat",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Selatan",
|
|
||||||
slug: "sulawesi-selatan",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Tengah",
|
|
||||||
slug: "sulawesi-tengah",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Tenggara",
|
|
||||||
slug: "sulawesi-tenggara",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Utara",
|
|
||||||
slug: "sulawesi-utara",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Barat",
|
|
||||||
slug: "sumatera-barat",
|
|
||||||
logo: "/logo/polda/polda-sumatera-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Selatan",
|
|
||||||
slug: "sumatera-selatan",
|
|
||||||
logo: "/logo/polda/polda-sumatera-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Utara",
|
|
||||||
slug: "sumatera-utara",
|
|
||||||
logo: "/logo/polda/polda-sumatera-utara.png",
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// name: "Satuan Kerja POLRI",
|
|
||||||
// slug: "satker-polri",
|
|
||||||
// logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: "Internasional",
|
|
||||||
// slug: "internasional",
|
|
||||||
// logo: "/assets/polda/internasional.png",
|
|
||||||
// },
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function PoldaAllImagePage() {
|
|
||||||
return (
|
|
||||||
<AllContentPage
|
|
||||||
typeId="1"
|
|
||||||
title="Semua Foto per Polda"
|
|
||||||
basePath="image"
|
|
||||||
mode="polda"
|
|
||||||
dataList={regions}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,895 @@
|
||||||
|
"use client";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
|
import {
|
||||||
|
getPublicCategoryData,
|
||||||
|
getUserLevelListByParent,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import ReactDatePicker from "react-datepicker";
|
||||||
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import { close, loading } from "@/config/swal";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import ImageBlurry from "@/components/ui/image-blurry";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
const columns: ColumnDef<any>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "no",
|
||||||
|
header: "No",
|
||||||
|
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function FilterPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const asPath = usePathname();
|
||||||
|
const params = useParams();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const t = useTranslations("FilterPage");
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [imageData, setImageData] = useState<any[]>([]);
|
||||||
|
const [totalData, setTotalData] = useState<number>(1);
|
||||||
|
const [totalPage, setTotalPage] = useState<number>(1);
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||||
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [totalContent, setTotalContent] = useState(0);
|
||||||
|
const [change, setChange] = useState(false);
|
||||||
|
const sortBy = searchParams?.get("sortBy");
|
||||||
|
const title = searchParams?.get("title");
|
||||||
|
const categorie = searchParams?.get("category");
|
||||||
|
const group = searchParams?.get("group");
|
||||||
|
const [categoryFilter, setCategoryFilter] = useState<any[]>([]);
|
||||||
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
|
const [formatFilter, setFormatFilter] = useState<any[]>([]);
|
||||||
|
const pages = page ? page - 1 : 0;
|
||||||
|
const [startDateString, setStartDateString] = useState<any>();
|
||||||
|
const [endDateString, setEndDateString] = useState<any>();
|
||||||
|
const [dateRange, setDateRange] = useState<any>([null, null]);
|
||||||
|
const [handleClose, setHandleClose] = useState(false);
|
||||||
|
const [categories, setCategories] = useState<any[]>([]);
|
||||||
|
const [isFilterOpen, setIsFilterOpen] = useState(true);
|
||||||
|
|
||||||
|
const poldaName = params?.polda_name;
|
||||||
|
const satkerName = params?.satker_name;
|
||||||
|
|
||||||
|
let prefixPath = poldaName
|
||||||
|
? `/polda/${poldaName}`
|
||||||
|
: satkerName
|
||||||
|
? `/satker/${satkerName}`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
// === INIT ===
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => setIsLoading(false), 1200);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const pageFromUrl = searchParams?.get("page");
|
||||||
|
if (pageFromUrl) setPage(Number(pageFromUrl));
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (categorie) {
|
||||||
|
setCategoryFilter(
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [categorie]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategories(categoryPage);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchCategories = async (pageNumber: number) => {
|
||||||
|
const groupParam =
|
||||||
|
poldaName && poldaName.length > 1
|
||||||
|
? poldaName
|
||||||
|
: satkerName && satkerName.length > 1
|
||||||
|
? "satker-" + satkerName
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const isInt = locale === "en";
|
||||||
|
|
||||||
|
const response = await getPublicCategoryData(
|
||||||
|
groupParam,
|
||||||
|
"",
|
||||||
|
isInt,
|
||||||
|
pageNumber
|
||||||
|
); // halaman 1-based
|
||||||
|
|
||||||
|
const content = response?.data?.data?.content || [];
|
||||||
|
const total = response?.data?.data?.totalPages || 1;
|
||||||
|
|
||||||
|
setCategories(content);
|
||||||
|
setCategoryTotalPages(total);
|
||||||
|
};
|
||||||
|
|
||||||
|
// async function fetchCategories() {
|
||||||
|
// const response = await getPublicCategoryData("", "", locale === "en");
|
||||||
|
// setCategories(response?.data?.data?.content || []);
|
||||||
|
// }
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (asPath?.includes("/regional")) getDataRegional();
|
||||||
|
else getDataAll();
|
||||||
|
}, [
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
|
async function getDataAll() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listData(
|
||||||
|
"1",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
locale == "en" ? true : false
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setImageData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataRegional() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listDataRegional(
|
||||||
|
"1",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setImageData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCategoryFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...categoryFilter];
|
||||||
|
if (e) filter.push(String(id));
|
||||||
|
else filter = filter.filter((item) => item !== String(id));
|
||||||
|
router.push(`?category=${filter.join("&")}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormatFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...formatFilter];
|
||||||
|
if (e) filter.push(id);
|
||||||
|
else filter = filter.filter((item) => item !== id);
|
||||||
|
setFormatFilter(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSorting = (e: any) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setSortByOpt(value === "latest" ? "createdAt" : "clickCount");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteDate = () => {
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setStartDateString("");
|
||||||
|
setEndDateString("");
|
||||||
|
setHandleClose(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyUp = () => {
|
||||||
|
if (!searchTitle) router.push("?title=");
|
||||||
|
else router.push(`?title=${searchTitle.toLowerCase()}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// === REACT TABLE ===
|
||||||
|
const table = useReactTable({
|
||||||
|
data: imageData,
|
||||||
|
columns,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
onRowSelectionChange: setRowSelection,
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
state: {
|
||||||
|
sorting,
|
||||||
|
columnFilters,
|
||||||
|
columnVisibility,
|
||||||
|
rowSelection,
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [calenderState, setCalenderState] = useState(false);
|
||||||
|
const [categoryPage, setCategoryPage] = useState(1);
|
||||||
|
const [categoryTotalPages, setCategoryTotalPages] = useState(1);
|
||||||
|
let typingTimer: any;
|
||||||
|
|
||||||
|
const cleanCheckbox = () => {
|
||||||
|
setCategoryFilter([]);
|
||||||
|
setFormatFilter([]);
|
||||||
|
router.push(`?category=&title=`);
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setMonthYearFilter(null);
|
||||||
|
setChange(!change);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = () => {
|
||||||
|
clearTimeout(typingTimer);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
|
||||||
|
<p>{t("image", { defaultValue: "Image" })}</p> {">"}
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("allImage", { defaultValue: "All Image" })}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">|</p>
|
||||||
|
{!title ? (
|
||||||
|
<p>
|
||||||
|
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
|
||||||
|
"downloadableImage",
|
||||||
|
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
|
||||||
|
)}`}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
|
||||||
|
<span className="font-bold">"{title}"</span>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">
|
||||||
|
{/* Left */}
|
||||||
|
<div className="lg:hidden flex justify-end mb-2">
|
||||||
|
<button
|
||||||
|
onClick={() => setIsFilterOpen(!isFilterOpen)}
|
||||||
|
className="text-sm text-white bg-[#bb3523] px-4 py-1 rounded-md shadow"
|
||||||
|
>
|
||||||
|
{isFilterOpen ? "Hide Filter" : "Show Filter"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isFilterOpen && (
|
||||||
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
|
Filter
|
||||||
|
</h2>
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
|
{t("search", { defaultValue: "Search" })}
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
value={searchTitle}
|
||||||
|
onChange={(e) => setSearchTitle(e.target.value)}
|
||||||
|
onKeyUp={handleKeyUp}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
type="text"
|
||||||
|
id="search"
|
||||||
|
placeholder={t("searchTitle", {
|
||||||
|
defaultValue: "Search Title",
|
||||||
|
})}
|
||||||
|
className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear", { defaultValue: "Month Year" })}
|
||||||
|
</label>
|
||||||
|
<ReactDatePicker
|
||||||
|
selected={monthYearFilter}
|
||||||
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
onChange={(date) => setMonthYearFilter(date)}
|
||||||
|
dateFormat="MM | yyyy"
|
||||||
|
placeholderText={t("selectYear", {
|
||||||
|
defaultValue: "Select Year",
|
||||||
|
})}
|
||||||
|
showMonthYearPicker
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date", { defaultValue: "Date" })}
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
|
<ReactDatePicker
|
||||||
|
selectsRange
|
||||||
|
className="mt-1 w-full border text-sm rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
startDate={dateRange[0]}
|
||||||
|
endDate={dateRange[1]}
|
||||||
|
onChange={(update) => {
|
||||||
|
setDateRange(update);
|
||||||
|
}}
|
||||||
|
placeholderText={t("selectDate", {
|
||||||
|
defaultValue: "Select Date",
|
||||||
|
})}
|
||||||
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* ⬇️ Pagination kategori (rata sejajar) */}
|
||||||
|
<div className="mt-4 flex justify-center items-center gap-2 flex-wrap">
|
||||||
|
{/* Tombol Prev */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{(() => {
|
||||||
|
const maxVisible = 4;
|
||||||
|
let startPage = Math.max(
|
||||||
|
1,
|
||||||
|
Math.min(
|
||||||
|
categoryPage - Math.floor(maxVisible / 2),
|
||||||
|
categoryTotalPages - maxVisible + 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const endPage = Math.min(
|
||||||
|
categoryTotalPages,
|
||||||
|
startPage + maxVisible - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const visiblePages = [];
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
visiblePages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visiblePages.map((pageNum) => (
|
||||||
|
<button
|
||||||
|
key={pageNum}
|
||||||
|
onClick={() => setCategoryPage(pageNum)}
|
||||||
|
className={`px-3 py-1 border rounded text-sm transition-colors ${
|
||||||
|
categoryPage === pageNum
|
||||||
|
? "bg-[#bb3523] text-white"
|
||||||
|
: "bg-white dark:bg-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pageNum}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{/* Tombol Next */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Garis */}
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
{/* Garis */}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="png"
|
||||||
|
value="png"
|
||||||
|
checked={formatFilter.includes("png")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "png")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PNG
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="jpeg"
|
||||||
|
value="jpeg"
|
||||||
|
checked={formatFilter.includes("jpeg")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "jpeg")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
JPEG
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="jpg"
|
||||||
|
value="jpg"
|
||||||
|
checked={formatFilter.includes("jpg")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "jpg")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
JPG
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
|
<div className="text-center">
|
||||||
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
|
<b>Reset Filter</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* CONTENT */}
|
||||||
|
<div className="w-full pr-4 lg:pr-16 pb-4">
|
||||||
|
<Reveal>
|
||||||
|
<div className="flex flex-col items-end mb-4">
|
||||||
|
<h2 className="text-lg font-semibold">Sort By</h2>
|
||||||
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "popular" : "latest"}
|
||||||
|
onChange={handleSorting}
|
||||||
|
className="border rounded-md py-2 px-3"
|
||||||
|
>
|
||||||
|
<option value="latest">Latest</option>
|
||||||
|
<option value="popular">Most Popular</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
</div>
|
||||||
|
) : imageData?.length > 0 ? (
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{imageData.map((image: any) => (
|
||||||
|
<Card
|
||||||
|
key={image?.id}
|
||||||
|
className="hover:scale-105 transition-transform duration-300"
|
||||||
|
>
|
||||||
|
<CardContent className="flex flex-col p-0">
|
||||||
|
<Link
|
||||||
|
href={`${prefixPath}/image/detail/${image?.slug
|
||||||
|
?.split("/")
|
||||||
|
.pop()}`}
|
||||||
|
// href={`/image/detail/${image?.slug}`}
|
||||||
|
>
|
||||||
|
<div className="h-60 bg-[#e9e9e9]">
|
||||||
|
<ImageBlurry
|
||||||
|
src={
|
||||||
|
image?.smallThumbnailLink || image?.thumbnailLink
|
||||||
|
}
|
||||||
|
alt={image?.title}
|
||||||
|
style={{
|
||||||
|
objectFit: "cover",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="flex flex-row justify-between mb-1">
|
||||||
|
<p className="text-[9px] font-bold text-[#bb3523]">
|
||||||
|
{image?.categoryName?.toUpperCase() ??
|
||||||
|
"Giat Pimpinan"}
|
||||||
|
</p>
|
||||||
|
<p className="flex flex-row items-center text-[9px] gap-1 text-gray-600">
|
||||||
|
{formatDateToIndonesian(
|
||||||
|
new Date(image?.createdAt)
|
||||||
|
)}{" "}
|
||||||
|
{image?.timezone ?? "WIB"} |
|
||||||
|
<Icon
|
||||||
|
icon="formkit:eye"
|
||||||
|
width="15"
|
||||||
|
height="15"
|
||||||
|
/>{" "}
|
||||||
|
{image.clickCount}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm lg:text-base font-semibold text-black dark:text-white line-clamp-3">
|
||||||
|
{image?.title}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-center items-center py-10">
|
||||||
|
<Image
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{totalPage > 1 && (
|
||||||
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Reveal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// import AllContentPage from "@/components/landing-page/all-content-page";
|
||||||
|
|
||||||
|
// const regions = [
|
||||||
|
// { name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
||||||
|
// { name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bangka Belitung",
|
||||||
|
// slug: "bangka-belitung",
|
||||||
|
// logo: "/logo/polda/polda-bangka-belitung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Banten",
|
||||||
|
// slug: "banten",
|
||||||
|
// logo: "/logo/polda/polda-banten.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bengkulu",
|
||||||
|
// slug: "bengkulu",
|
||||||
|
// logo: "/logo/polda/polda-bengkulu.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda DIY",
|
||||||
|
// slug: "jogja",
|
||||||
|
// logo: "/logo/polda/polda-jogja.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Gorontalo",
|
||||||
|
// slug: "gorontalo",
|
||||||
|
// logo: "/logo/polda/polda-gorontalo.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Barat",
|
||||||
|
// slug: "jawa-barat",
|
||||||
|
// logo: "/logo/polda/polda-jawa-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Tengah",
|
||||||
|
// slug: "jawa-tengah",
|
||||||
|
// logo: "/logo/polda/polda-jawa-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Timur",
|
||||||
|
// slug: "jawa-timur",
|
||||||
|
// logo: "/logo/polda/polda-jawa-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Barat",
|
||||||
|
// slug: "kalimantan-barat",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Selatan",
|
||||||
|
// slug: "kalimantan-selatan",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Tengah",
|
||||||
|
// slug: "kalimantan-tengah",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Timur",
|
||||||
|
// slug: "kalimantan-timur",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Utara",
|
||||||
|
// slug: "kalimantan-utara",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kepulauan Riau",
|
||||||
|
// slug: "kepulauan-riau",
|
||||||
|
// logo: "/logo/polda/polda-kepulauan-riau.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Lampung",
|
||||||
|
// slug: "lampung",
|
||||||
|
// logo: "/logo/polda/polda-lampung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku",
|
||||||
|
// slug: "maluku",
|
||||||
|
// logo: "/logo/polda/polda-maluku.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku Utara",
|
||||||
|
// slug: "maluku-utara",
|
||||||
|
// logo: "/logo/polda/polda-maluku-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Metro Jaya",
|
||||||
|
// slug: "metro-jaya",
|
||||||
|
// logo: "/logo/polda/polda-metro-jaya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTB",
|
||||||
|
// slug: "ntb",
|
||||||
|
// logo: "/logo/polda/polda-ntb.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTT",
|
||||||
|
// slug: "ntt",
|
||||||
|
// logo: "/logo/polda/polda-ntt.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat",
|
||||||
|
// slug: "papua-barat",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat Daya",
|
||||||
|
// slug: "papua-barat-daya",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat-daya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Tengah",
|
||||||
|
// slug: "papua-tengah",
|
||||||
|
// logo: "/logo/polda/polda-papua-tengah.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Barat",
|
||||||
|
// slug: "sulawesi-barat",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Selatan",
|
||||||
|
// slug: "sulawesi-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tengah",
|
||||||
|
// slug: "sulawesi-tengah",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tenggara",
|
||||||
|
// slug: "sulawesi-tenggara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Utara",
|
||||||
|
// slug: "sulawesi-utara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Barat",
|
||||||
|
// slug: "sumatera-barat",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Selatan",
|
||||||
|
// slug: "sumatera-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Utara",
|
||||||
|
// slug: "sumatera-utara",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-utara.png",
|
||||||
|
// },
|
||||||
|
// // {
|
||||||
|
// // name: "Satuan Kerja POLRI",
|
||||||
|
// // slug: "satker-polri",
|
||||||
|
// // logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
||||||
|
// // },
|
||||||
|
// // {
|
||||||
|
// // name: "Internasional",
|
||||||
|
// // slug: "internasional",
|
||||||
|
// // logo: "/assets/polda/internasional.png",
|
||||||
|
// // },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// export default function PoldaAllImagePage() {
|
||||||
|
// return (
|
||||||
|
// <AllContentPage
|
||||||
|
// typeId="1"
|
||||||
|
// title="Semua Foto per Polda"
|
||||||
|
// basePath="image"
|
||||||
|
// mode="polda"
|
||||||
|
// dataList={regions}
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
import AllContentPage from "@/components/landing-page/all-content-page";
|
|
||||||
|
|
||||||
const regions = [
|
|
||||||
{ name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
|
||||||
{ name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Bangka Belitung",
|
|
||||||
slug: "bangka-belitung",
|
|
||||||
logo: "/logo/polda/polda-bangka-belitung.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Banten",
|
|
||||||
slug: "banten",
|
|
||||||
logo: "/logo/polda/polda-banten.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Bengkulu",
|
|
||||||
slug: "bengkulu",
|
|
||||||
logo: "/logo/polda/polda-bengkulu.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda DIY",
|
|
||||||
slug: "jogja",
|
|
||||||
logo: "/logo/polda/polda-jogja.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Gorontalo",
|
|
||||||
slug: "gorontalo",
|
|
||||||
logo: "/logo/polda/polda-gorontalo.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Barat",
|
|
||||||
slug: "jawa-barat",
|
|
||||||
logo: "/logo/polda/polda-jawa-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Tengah",
|
|
||||||
slug: "jawa-tengah",
|
|
||||||
logo: "/logo/polda/polda-jawa-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Jawa Timur",
|
|
||||||
slug: "jawa-timur",
|
|
||||||
logo: "/logo/polda/polda-jawa-timur.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Barat",
|
|
||||||
slug: "kalimantan-barat",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Selatan",
|
|
||||||
slug: "kalimantan-selatan",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Tengah",
|
|
||||||
slug: "kalimantan-tengah",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Timur",
|
|
||||||
slug: "kalimantan-timur",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-timur.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kalimantan Utara",
|
|
||||||
slug: "kalimantan-utara",
|
|
||||||
logo: "/logo/polda/polda-kalimantan-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Kepulauan Riau",
|
|
||||||
slug: "kepulauan-riau",
|
|
||||||
logo: "/logo/polda/polda-kepulauan-riau.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Lampung",
|
|
||||||
slug: "lampung",
|
|
||||||
logo: "/logo/polda/polda-lampung.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Maluku",
|
|
||||||
slug: "maluku",
|
|
||||||
logo: "/logo/polda/polda-maluku.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Maluku Utara",
|
|
||||||
slug: "maluku-utara",
|
|
||||||
logo: "/logo/polda/polda-maluku-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Metro Jaya",
|
|
||||||
slug: "metro-jaya",
|
|
||||||
logo: "/logo/polda/polda-metro-jaya.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda NTB",
|
|
||||||
slug: "ntb",
|
|
||||||
logo: "/logo/polda/polda-ntb.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda NTT",
|
|
||||||
slug: "ntt",
|
|
||||||
logo: "/logo/polda/polda-ntt.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Papua Barat",
|
|
||||||
slug: "papua-barat",
|
|
||||||
logo: "/logo/polda/polda-papua-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Papua Barat Daya",
|
|
||||||
slug: "papua-barat-daya",
|
|
||||||
logo: "/logo/polda/polda-papua-barat-daya.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Papua Tengah",
|
|
||||||
slug: "papua-tengah",
|
|
||||||
logo: "/logo/polda/polda-papua-tengah.png",
|
|
||||||
},
|
|
||||||
{ name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Barat",
|
|
||||||
slug: "sulawesi-barat",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Selatan",
|
|
||||||
slug: "sulawesi-selatan",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Tengah",
|
|
||||||
slug: "sulawesi-tengah",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-tengah.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Tenggara",
|
|
||||||
slug: "sulawesi-tenggara",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sulawesi Utara",
|
|
||||||
slug: "sulawesi-utara",
|
|
||||||
logo: "/logo/polda/polda-sulawesi-utara.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Barat",
|
|
||||||
slug: "sumatera-barat",
|
|
||||||
logo: "/logo/polda/polda-sumatera-barat.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Selatan",
|
|
||||||
slug: "sumatera-selatan",
|
|
||||||
logo: "/logo/polda/polda-sumatera-selatan.png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Polda Sumatera Utara",
|
|
||||||
slug: "sumatera-utara",
|
|
||||||
logo: "/logo/polda/polda-sumatera-utara.png",
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// name: "Satuan Kerja POLRI",
|
|
||||||
// slug: "satker-polri",
|
|
||||||
// logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: "Internasional",
|
|
||||||
// slug: "internasional",
|
|
||||||
// logo: "/assets/polda/internasional.png",
|
|
||||||
// },
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function PoldaAllVideoPage() {
|
|
||||||
return (
|
|
||||||
<AllContentPage
|
|
||||||
typeId="2"
|
|
||||||
title="Semua Konten Audio Visual per Polda"
|
|
||||||
basePath="video"
|
|
||||||
mode="polda"
|
|
||||||
dataList={regions}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,987 @@
|
||||||
|
"use client";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
|
import {
|
||||||
|
getPublicCategoryData,
|
||||||
|
getUserLevelListByParent,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import ReactDatePicker from "react-datepicker";
|
||||||
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import { close, loading } from "@/config/swal";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import ImageBlurry from "@/components/ui/image-blurry";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
const columns: ColumnDef<any>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "no",
|
||||||
|
header: "No",
|
||||||
|
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function FilterPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const asPath = usePathname();
|
||||||
|
const params = useParams();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const t = useTranslations("FilterPage");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [videoData, setVideoData] = useState<any[]>([]);
|
||||||
|
const [totalData, setTotalData] = useState<number>(1);
|
||||||
|
const [totalPage, setTotalPage] = useState<number>(1);
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||||
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [totalContent, setTotalContent] = useState(0);
|
||||||
|
const [change, setChange] = useState(false);
|
||||||
|
const sortBy = searchParams?.get("sortBy");
|
||||||
|
const title = searchParams?.get("title");
|
||||||
|
const categorie = searchParams?.get("category");
|
||||||
|
const group = searchParams?.get("group");
|
||||||
|
const [categoryFilter, setCategoryFilter] = useState<any[]>([]);
|
||||||
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
|
const [formatFilter, setFormatFilter] = useState<any[]>([]);
|
||||||
|
const pages = page ? page - 1 : 0;
|
||||||
|
const [startDateString, setStartDateString] = useState<any>();
|
||||||
|
const [endDateString, setEndDateString] = useState<any>();
|
||||||
|
const [dateRange, setDateRange] = useState<any>([null, null]);
|
||||||
|
const [handleClose, setHandleClose] = useState(false);
|
||||||
|
const [categories, setCategories] = useState<any[]>([]);
|
||||||
|
const [isFilterOpen, setIsFilterOpen] = useState(true);
|
||||||
|
|
||||||
|
const poldaName = params?.polda_name;
|
||||||
|
const satkerName = params?.satker_name;
|
||||||
|
|
||||||
|
let prefixPath = poldaName
|
||||||
|
? `/polda/${poldaName}`
|
||||||
|
: satkerName
|
||||||
|
? `/satker/${satkerName}`
|
||||||
|
: "";
|
||||||
|
|
||||||
|
// === INIT ===
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => setIsLoading(false), 1200);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const pageFromUrl = searchParams?.get("page");
|
||||||
|
if (pageFromUrl) setPage(Number(pageFromUrl));
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (categorie) {
|
||||||
|
setCategoryFilter(
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [categorie]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategories(categoryPage);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchCategories = async (pageNumber: number) => {
|
||||||
|
const groupParam =
|
||||||
|
poldaName && poldaName.length > 1
|
||||||
|
? poldaName
|
||||||
|
: satkerName && satkerName.length > 1
|
||||||
|
? "satker-" + satkerName
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const isInt = locale === "en";
|
||||||
|
|
||||||
|
const response = await getPublicCategoryData(
|
||||||
|
groupParam,
|
||||||
|
"",
|
||||||
|
isInt,
|
||||||
|
pageNumber
|
||||||
|
); // halaman 1-based
|
||||||
|
|
||||||
|
const content = response?.data?.data?.content || [];
|
||||||
|
const total = response?.data?.data?.totalPages || 1;
|
||||||
|
|
||||||
|
setCategories(content);
|
||||||
|
setCategoryTotalPages(total);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (asPath?.includes("/regional")) getDataRegional();
|
||||||
|
else getDataAll();
|
||||||
|
}, [
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
|
async function getDataAll() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listData(
|
||||||
|
"2",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
locale == "en" ? true : false
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setVideoData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataRegional() {
|
||||||
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
|
const name = title || "";
|
||||||
|
const format = formatFilter?.length > 0 ? formatFilter.join(",") : "";
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const response = await listDataRegional(
|
||||||
|
"2",
|
||||||
|
name,
|
||||||
|
filter,
|
||||||
|
format,
|
||||||
|
"",
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
|
12,
|
||||||
|
pages,
|
||||||
|
sortByOpt
|
||||||
|
);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const data = response?.data?.data;
|
||||||
|
setVideoData(data?.content || []);
|
||||||
|
setTotalData(data?.totalElements || 0);
|
||||||
|
setTotalPage(data?.totalPages || 1);
|
||||||
|
setTotalContent(data?.totalElements || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCategoryFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...categoryFilter];
|
||||||
|
if (e) filter.push(String(id));
|
||||||
|
else filter = filter.filter((item) => item !== String(id));
|
||||||
|
router.push(`?category=${filter.join("&")}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormatFilter = (e: boolean, id: string) => {
|
||||||
|
let filter = [...formatFilter];
|
||||||
|
if (e) filter.push(id);
|
||||||
|
else filter = filter.filter((item) => item !== id);
|
||||||
|
setFormatFilter(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSorting = (e: any) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setSortByOpt(value === "latest" ? "createdAt" : "clickCount");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteDate = () => {
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setStartDateString("");
|
||||||
|
setEndDateString("");
|
||||||
|
setHandleClose(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyUp = () => {
|
||||||
|
if (!searchTitle) router.push("?title=");
|
||||||
|
else router.push(`?title=${searchTitle.toLowerCase()}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// === REACT TABLE ===
|
||||||
|
const table = useReactTable({
|
||||||
|
data: videoData,
|
||||||
|
columns,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
onRowSelectionChange: setRowSelection,
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
state: {
|
||||||
|
sorting,
|
||||||
|
columnFilters,
|
||||||
|
columnVisibility,
|
||||||
|
rowSelection,
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [calenderState, setCalenderState] = useState(false);
|
||||||
|
const [categoryPage, setCategoryPage] = useState(1);
|
||||||
|
const [categoryTotalPages, setCategoryTotalPages] = useState(1);
|
||||||
|
let typingTimer: any;
|
||||||
|
|
||||||
|
const cleanCheckbox = () => {
|
||||||
|
setCategoryFilter([]);
|
||||||
|
setFormatFilter([]);
|
||||||
|
router.push(`?category=&title=`);
|
||||||
|
setDateRange([null, null]);
|
||||||
|
setMonthYearFilter(null);
|
||||||
|
setChange(!change);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = () => {
|
||||||
|
clearTimeout(typingTimer);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex flex-row items-start gap-3 py-10 px-4 lg:px-20 bg-[#f7f7f7] dark:bg-black">
|
||||||
|
<p>{t("video", { defaultValue: "Video" })}</p> {">"}
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">
|
||||||
|
{t("allVideo", { defaultValue: "All Video" })}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="font-bold">|</p>
|
||||||
|
{!title ? (
|
||||||
|
<p>
|
||||||
|
{`${t("thereIs", { defaultValue: "Terdapat" })} ${totalContent} ${t(
|
||||||
|
"downloadablevideo",
|
||||||
|
{ defaultValue: "artikel berisi Foto yang dapat diunduh" }
|
||||||
|
)}`}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
{t("search-results", { defaultValue: "Hasil pencarian untuk" })}{" "}
|
||||||
|
<span className="font-bold">"{title}"</span>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col lg:flex-row gap-6 pl-4 lg:pl-20 py-4">
|
||||||
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
|
Filter
|
||||||
|
</h2>
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
|
{t("search", { defaultValue: "Search" })}
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
value={searchTitle}
|
||||||
|
onChange={(e) => setSearchTitle(e.target.value)}
|
||||||
|
onKeyUp={handleKeyUp}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
type="text"
|
||||||
|
id="search"
|
||||||
|
placeholder={t("searchTitle", { defaultValue: "Search Title" })}
|
||||||
|
className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear", { defaultValue: "Month Year" })}
|
||||||
|
</label>
|
||||||
|
<ReactDatePicker
|
||||||
|
selected={monthYearFilter}
|
||||||
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
onChange={(date) => setMonthYearFilter(date)}
|
||||||
|
dateFormat="MM | yyyy"
|
||||||
|
placeholderText={t("selectYear", {
|
||||||
|
defaultValue: "Select Year",
|
||||||
|
})}
|
||||||
|
showMonthYearPicker
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date", { defaultValue: "Date" })}
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
|
<ReactDatePicker
|
||||||
|
selectsRange
|
||||||
|
className="mt-1 w-full text-sm border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
startDate={dateRange[0]}
|
||||||
|
endDate={dateRange[1]}
|
||||||
|
onChange={(update) => {
|
||||||
|
setDateRange(update);
|
||||||
|
}}
|
||||||
|
placeholderText={t("selectDate", {
|
||||||
|
defaultValue: "Select Date",
|
||||||
|
})}
|
||||||
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* ⬇️ Pagination kategori (rata sejajar) */}
|
||||||
|
<div className="mt-4 flex justify-center items-center gap-2 flex-wrap">
|
||||||
|
{/* Tombol Prev */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{(() => {
|
||||||
|
const maxVisible = 4;
|
||||||
|
let startPage = Math.max(
|
||||||
|
1,
|
||||||
|
Math.min(
|
||||||
|
categoryPage - Math.floor(maxVisible / 2),
|
||||||
|
categoryTotalPages - maxVisible + 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const endPage = Math.min(
|
||||||
|
categoryTotalPages,
|
||||||
|
startPage + maxVisible - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const visiblePages = [];
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
visiblePages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visiblePages.map((pageNum) => (
|
||||||
|
<button
|
||||||
|
key={pageNum}
|
||||||
|
onClick={() => setCategoryPage(pageNum)}
|
||||||
|
className={`px-3 py-1 border rounded text-sm transition-colors ${
|
||||||
|
categoryPage === pageNum
|
||||||
|
? "bg-[#bb3523] text-white"
|
||||||
|
: "bg-white dark:bg-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pageNum}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{/* Tombol Next */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories", { defaultValue: "Categories" })}
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
<div className="mt-4 flex gap-2 justify-center items-center">
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{Array.from({ length: categoryTotalPages }, (_, i) => (
|
||||||
|
<button
|
||||||
|
key={i}
|
||||||
|
onClick={() => setCategoryPage(i + 1)}
|
||||||
|
className={`px-3 py-1 border rounded ${
|
||||||
|
categoryPage === i + 1 ? "bg-[#bb3523] text-white" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{i + 1}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-3 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</div> */}
|
||||||
|
{/* Garis */}
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
{/* Garis */}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="mk4"
|
||||||
|
value="mk4"
|
||||||
|
checked={formatFilter.includes("mk4")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mk4")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MK4
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="mov"
|
||||||
|
value="mov"
|
||||||
|
checked={formatFilter.includes("mov")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mov")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MOV
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="mp4"
|
||||||
|
value="mp4"
|
||||||
|
checked={formatFilter.includes("mp4")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mp4")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MP4
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="avi"
|
||||||
|
value="avi"
|
||||||
|
checked={formatFilter.includes("avi")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "avi")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
AVI
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="wmv"
|
||||||
|
value="wmv"
|
||||||
|
checked={formatFilter.includes("wmv")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "wmv")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
WMV
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
|
<div className="text-center">
|
||||||
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
|
<b>Reset Filter</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* CONTENT */}
|
||||||
|
<div className="w-full pr-4 lg:pr-16 pb-4">
|
||||||
|
<Reveal>
|
||||||
|
<div className="flex flex-col items-end mb-4">
|
||||||
|
<h2 className="text-lg font-semibold">Sort By</h2>
|
||||||
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "popular" : "latest"}
|
||||||
|
onChange={handleSorting}
|
||||||
|
className="border rounded-md py-2 px-3"
|
||||||
|
>
|
||||||
|
<option value="latest">Latest</option>
|
||||||
|
<option value="popular">Most Popular</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
<Skeleton className="h-[200px] w-full rounded-xl" />
|
||||||
|
</div>
|
||||||
|
) : videoData?.length > 0 ? (
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{videoData.map((video: any) => (
|
||||||
|
<Card
|
||||||
|
key={video?.id}
|
||||||
|
className="hover:scale-105 transition-transform duration-300"
|
||||||
|
>
|
||||||
|
<CardContent className="flex flex-col p-0">
|
||||||
|
<Link
|
||||||
|
href={`${prefixPath}/video/detail/${video?.slug
|
||||||
|
?.split("/")
|
||||||
|
.pop()}`}
|
||||||
|
// href={`/video/detail/${video?.slug}`}
|
||||||
|
>
|
||||||
|
<div className="h-60 bg-[#e9e9e9]">
|
||||||
|
<ImageBlurry
|
||||||
|
src={
|
||||||
|
video?.smallThumbnailLink || video?.thumbnailLink
|
||||||
|
}
|
||||||
|
alt={video?.title}
|
||||||
|
style={{
|
||||||
|
objectFit: "cover",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="flex flex-row justify-between mb-1">
|
||||||
|
<p className="text-[9px] font-bold text-[#bb3523]">
|
||||||
|
{video?.categoryName?.toUpperCase() ??
|
||||||
|
"Giat Pimpinan"}
|
||||||
|
</p>
|
||||||
|
<p className="flex flex-row items-center text-[9px] gap-1 text-gray-600">
|
||||||
|
{formatDateToIndonesian(
|
||||||
|
new Date(video?.createdAt)
|
||||||
|
)}{" "}
|
||||||
|
{video?.timezone ?? "WIB"} |
|
||||||
|
<Icon
|
||||||
|
icon="formkit:eye"
|
||||||
|
width="15"
|
||||||
|
height="15"
|
||||||
|
/>{" "}
|
||||||
|
{video.clickCount}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm lg:text-base font-semibold text-black dark:text-white line-clamp-3">
|
||||||
|
{video?.title}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex justify-center items-center py-10">
|
||||||
|
<Image
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{totalPage > 1 && (
|
||||||
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Reveal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// import AllContentPage from "@/components/landing-page/all-content-page";
|
||||||
|
|
||||||
|
// const regions = [
|
||||||
|
// { name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
|
||||||
|
// { name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bangka Belitung",
|
||||||
|
// slug: "bangka-belitung",
|
||||||
|
// logo: "/logo/polda/polda-bangka-belitung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Banten",
|
||||||
|
// slug: "banten",
|
||||||
|
// logo: "/logo/polda/polda-banten.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Bengkulu",
|
||||||
|
// slug: "bengkulu",
|
||||||
|
// logo: "/logo/polda/polda-bengkulu.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda DIY",
|
||||||
|
// slug: "jogja",
|
||||||
|
// logo: "/logo/polda/polda-jogja.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Gorontalo",
|
||||||
|
// slug: "gorontalo",
|
||||||
|
// logo: "/logo/polda/polda-gorontalo.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Barat",
|
||||||
|
// slug: "jawa-barat",
|
||||||
|
// logo: "/logo/polda/polda-jawa-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Tengah",
|
||||||
|
// slug: "jawa-tengah",
|
||||||
|
// logo: "/logo/polda/polda-jawa-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Jawa Timur",
|
||||||
|
// slug: "jawa-timur",
|
||||||
|
// logo: "/logo/polda/polda-jawa-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Barat",
|
||||||
|
// slug: "kalimantan-barat",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Selatan",
|
||||||
|
// slug: "kalimantan-selatan",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Tengah",
|
||||||
|
// slug: "kalimantan-tengah",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Timur",
|
||||||
|
// slug: "kalimantan-timur",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-timur.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kalimantan Utara",
|
||||||
|
// slug: "kalimantan-utara",
|
||||||
|
// logo: "/logo/polda/polda-kalimantan-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Kepulauan Riau",
|
||||||
|
// slug: "kepulauan-riau",
|
||||||
|
// logo: "/logo/polda/polda-kepulauan-riau.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Lampung",
|
||||||
|
// slug: "lampung",
|
||||||
|
// logo: "/logo/polda/polda-lampung.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku",
|
||||||
|
// slug: "maluku",
|
||||||
|
// logo: "/logo/polda/polda-maluku.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Maluku Utara",
|
||||||
|
// slug: "maluku-utara",
|
||||||
|
// logo: "/logo/polda/polda-maluku-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Metro Jaya",
|
||||||
|
// slug: "metro-jaya",
|
||||||
|
// logo: "/logo/polda/polda-metro-jaya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTB",
|
||||||
|
// slug: "ntb",
|
||||||
|
// logo: "/logo/polda/polda-ntb.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda NTT",
|
||||||
|
// slug: "ntt",
|
||||||
|
// logo: "/logo/polda/polda-ntt.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat",
|
||||||
|
// slug: "papua-barat",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Barat Daya",
|
||||||
|
// slug: "papua-barat-daya",
|
||||||
|
// logo: "/logo/polda/polda-papua-barat-daya.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Papua Tengah",
|
||||||
|
// slug: "papua-tengah",
|
||||||
|
// logo: "/logo/polda/polda-papua-tengah.png",
|
||||||
|
// },
|
||||||
|
// { name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Barat",
|
||||||
|
// slug: "sulawesi-barat",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Selatan",
|
||||||
|
// slug: "sulawesi-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tengah",
|
||||||
|
// slug: "sulawesi-tengah",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tengah.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Tenggara",
|
||||||
|
// slug: "sulawesi-tenggara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-tenggara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sulawesi Utara",
|
||||||
|
// slug: "sulawesi-utara",
|
||||||
|
// logo: "/logo/polda/polda-sulawesi-utara.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Barat",
|
||||||
|
// slug: "sumatera-barat",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-barat.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Selatan",
|
||||||
|
// slug: "sumatera-selatan",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-selatan.png",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Polda Sumatera Utara",
|
||||||
|
// slug: "sumatera-utara",
|
||||||
|
// logo: "/logo/polda/polda-sumatera-utara.png",
|
||||||
|
// },
|
||||||
|
// // {
|
||||||
|
// // name: "Satuan Kerja POLRI",
|
||||||
|
// // slug: "satker-polri",
|
||||||
|
// // logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
|
||||||
|
// // },
|
||||||
|
// // {
|
||||||
|
// // name: "Internasional",
|
||||||
|
// // slug: "internasional",
|
||||||
|
// // logo: "/assets/polda/internasional.png",
|
||||||
|
// // },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// export default function PoldaAllVideoPage() {
|
||||||
|
// return (
|
||||||
|
// <AllContentPage
|
||||||
|
// typeId="2"
|
||||||
|
// title="Semua Konten Audio Visual per Polda"
|
||||||
|
// basePath="video"
|
||||||
|
// mode="polda"
|
||||||
|
// dataList={regions}
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
@ -559,7 +559,88 @@ export default function FilterPage() {
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
<div className="mt-4 flex gap-2 justify-center items-center">
|
|
||||||
|
<div className="mt-4 flex justify-center items-center gap-2 flex-wrap">
|
||||||
|
{/* Tombol Prev */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
disabled={categoryPage === 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m13.15 16.15l-3.625-3.625q-.125-.125-.175-.25T9.3 12t.05-.275t.175-.25L13.15 7.85q.075-.075.163-.112T13.5 7.7q.2 0 .35.138T14 8.2v7.6q0 .225-.15.363t-.35.137q-.05 0-.35-.15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{(() => {
|
||||||
|
const maxVisible = 4;
|
||||||
|
let startPage = Math.max(
|
||||||
|
1,
|
||||||
|
Math.min(
|
||||||
|
categoryPage - Math.floor(maxVisible / 2),
|
||||||
|
categoryTotalPages - maxVisible + 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const endPage = Math.min(
|
||||||
|
categoryTotalPages,
|
||||||
|
startPage + maxVisible - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const visiblePages = [];
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
visiblePages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visiblePages.map((pageNum) => (
|
||||||
|
<button
|
||||||
|
key={pageNum}
|
||||||
|
onClick={() => setCategoryPage(pageNum)}
|
||||||
|
className={`px-3 py-1 border rounded text-sm transition-colors ${
|
||||||
|
categoryPage === pageNum
|
||||||
|
? "bg-[#bb3523] text-white"
|
||||||
|
: "bg-white dark:bg-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pageNum}
|
||||||
|
</button>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{/* Tombol Next */}
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setCategoryPage((prev) =>
|
||||||
|
Math.min(prev + 1, categoryTotalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={categoryPage === categoryTotalPages}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M10.5 16.3q-.2 0-.35-.137T10 15.8V8.2q0-.225.15-.362t.35-.138q.05 0 .35.15l3.625 3.625q.125.125.175.25t.05.275t-.05.275t-.175.25L10.85 16.15q-.075.075-.162.113t-.188.037"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="mt-4 flex gap-2 justify-center items-center">
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
setCategoryPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
|
@ -615,13 +696,13 @@ export default function FilterPage() {
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div> */}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{/* Garis */}
|
{/* Garis */}
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
{/* Garis */}
|
{/* Garis */}
|
||||||
<div>
|
{/* <div>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
Format
|
Format
|
||||||
</h3>
|
</h3>
|
||||||
|
|
@ -672,8 +753,8 @@ export default function FilterPage() {
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div> */}
|
||||||
<div className="border-t border-black dark:border-white my-4"></div>
|
{/* <div className="border-t border-black dark:border-white my-4"></div> */}
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<a
|
<a
|
||||||
onClick={cleanCheckbox}
|
onClick={cleanCheckbox}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,6 @@ export default function AllContentPage({
|
||||||
function renderCard(item: ContentItem, regionSlug: string) {
|
function renderCard(item: ContentItem, regionSlug: string) {
|
||||||
const href = `/${mode}/${regionSlug}/${basePath}/detail/${item.slug}`;
|
const href = `/${mode}/${regionSlug}/${basePath}/detail/${item.slug}`;
|
||||||
|
|
||||||
// 🖼 Image & 🎥 Video sama
|
|
||||||
if (basePath === "image" || basePath === "video") {
|
if (basePath === "image" || basePath === "video") {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
|
|
@ -102,7 +101,6 @@ export default function AllContentPage({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 📄 Document
|
|
||||||
if (basePath === "document") {
|
if (basePath === "document") {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
|
|
@ -134,7 +132,6 @@ export default function AllContentPage({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🎧 Audio
|
|
||||||
if (basePath === "audio") {
|
if (basePath === "audio") {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
|
|
|
||||||
|
|
@ -305,6 +305,34 @@ export default function FilterAudioComponent(props: {
|
||||||
</Carousel>
|
</Carousel>
|
||||||
<div className="flex justify-center mt-1 mb-6">
|
<div className="flex justify-center mt-1 mb-6">
|
||||||
<Link
|
<Link
|
||||||
|
href={`${
|
||||||
|
asPath.includes("/polda/")
|
||||||
|
? `/${asPath.split("/")[1]}/${asPath.split("/")[2]}`
|
||||||
|
: asPath.includes("/regional")
|
||||||
|
? "/regional/all-polda"
|
||||||
|
: ""
|
||||||
|
}/audio/${
|
||||||
|
group || asPath.includes("/polda/") || asPath.includes("/regional")
|
||||||
|
? "regional?"
|
||||||
|
: "filter?"
|
||||||
|
}${sortByOpt === "popular" ? "sortBy=popular" : "sortBy=latest"}${
|
||||||
|
title ? `&title=${title.toLowerCase()}` : ""
|
||||||
|
}${categorie ? `&category=${categorie}` : ""}${
|
||||||
|
startDateString ? `&startDate=${startDateString}` : ""
|
||||||
|
}${endDateString ? `&endDate=${endDateString}` : ""}${
|
||||||
|
monthYearFilter
|
||||||
|
? `&month=${getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]}`
|
||||||
|
: ""
|
||||||
|
}${
|
||||||
|
monthYearFilter
|
||||||
|
? `&year=${getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]}`
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
className="border border-red-500 text-red-500 hover:bg-red-500 text-sm hover:text-white px-4 py-2 rounded transition duration-200"
|
||||||
|
>
|
||||||
|
Lihat Semua
|
||||||
|
</Link>
|
||||||
|
{/* <Link
|
||||||
href={
|
href={
|
||||||
`${
|
`${
|
||||||
asPath.includes("/polda/")
|
asPath.includes("/polda/")
|
||||||
|
|
@ -320,7 +348,7 @@ export default function FilterAudioComponent(props: {
|
||||||
className="border border-red-500 text-red-500 hover:bg-red-500 hover:text-white transition-colors duration-200 px-4 py-2 rounded-md text-sm"
|
className="border border-red-500 text-red-500 hover:bg-red-500 hover:text-white transition-colors duration-200 px-4 py-2 rounded-md text-sm"
|
||||||
>
|
>
|
||||||
Lihat Semua
|
Lihat Semua
|
||||||
</Link>
|
</Link> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -278,6 +278,34 @@ export default function FilterDocumentComponent(props: {
|
||||||
</Carousel>
|
</Carousel>
|
||||||
<div className="flex justify-center mt-1 mb-6">
|
<div className="flex justify-center mt-1 mb-6">
|
||||||
<Link
|
<Link
|
||||||
|
href={`${
|
||||||
|
asPath.includes("/polda/")
|
||||||
|
? `/${asPath.split("/")[1]}/${asPath.split("/")[2]}`
|
||||||
|
: asPath.includes("/regional")
|
||||||
|
? "/regional/all-polda"
|
||||||
|
: ""
|
||||||
|
}/document/${
|
||||||
|
group || asPath.includes("/polda/") || asPath.includes("/regional")
|
||||||
|
? "regional?"
|
||||||
|
: "filter?"
|
||||||
|
}${sortByOpt === "popular" ? "sortBy=popular" : "sortBy=latest"}${
|
||||||
|
title ? `&title=${title.toLowerCase()}` : ""
|
||||||
|
}${categorie ? `&category=${categorie}` : ""}${
|
||||||
|
startDateString ? `&startDate=${startDateString}` : ""
|
||||||
|
}${endDateString ? `&endDate=${endDateString}` : ""}${
|
||||||
|
monthYearFilter
|
||||||
|
? `&month=${getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]}`
|
||||||
|
: ""
|
||||||
|
}${
|
||||||
|
monthYearFilter
|
||||||
|
? `&year=${getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]}`
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
className="border border-red-500 text-red-500 hover:bg-red-500 text-sm hover:text-white px-4 py-2 rounded transition duration-200"
|
||||||
|
>
|
||||||
|
Lihat Semua
|
||||||
|
</Link>
|
||||||
|
{/* <Link
|
||||||
// href={`${
|
// href={`${
|
||||||
// asPath.includes("/polda/")
|
// asPath.includes("/polda/")
|
||||||
// ? `/${asPath.split("/")[1]}/${asPath.split("/")[2]}`
|
// ? `/${asPath.split("/")[1]}/${asPath.split("/")[2]}`
|
||||||
|
|
@ -304,7 +332,7 @@ export default function FilterDocumentComponent(props: {
|
||||||
className="border border-red-500 text-red-500 hover:bg-red-500 hover:text-white transition-colors duration-200 px-4 py-2 rounded-md text-sm"
|
className="border border-red-500 text-red-500 hover:bg-red-500 hover:text-white transition-colors duration-200 px-4 py-2 rounded-md text-sm"
|
||||||
>
|
>
|
||||||
Lihat Semua
|
Lihat Semua
|
||||||
</Link>
|
</Link> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -289,6 +289,35 @@ export default function FilterImageComponent(props: {
|
||||||
</Carousel>
|
</Carousel>
|
||||||
<div className="flex justify-center mt-1 mb-6">
|
<div className="flex justify-center mt-1 mb-6">
|
||||||
<Link
|
<Link
|
||||||
|
href={`${
|
||||||
|
asPath.includes("/polda/")
|
||||||
|
? `/${asPath.split("/")[1]}/${asPath.split("/")[2]}`
|
||||||
|
: asPath.includes("/regional")
|
||||||
|
? "/regional/all-polda"
|
||||||
|
: ""
|
||||||
|
}/image/${
|
||||||
|
group || asPath.includes("/polda/") || asPath.includes("/regional")
|
||||||
|
? "regional?"
|
||||||
|
: "filter?"
|
||||||
|
}${sortByOpt === "popular" ? "sortBy=popular" : "sortBy=latest"}${
|
||||||
|
title ? `&title=${title.toLowerCase()}` : ""
|
||||||
|
}${categorie ? `&category=${categorie}` : ""}${
|
||||||
|
startDateString ? `&startDate=${startDateString}` : ""
|
||||||
|
}${endDateString ? `&endDate=${endDateString}` : ""}${
|
||||||
|
monthYearFilter
|
||||||
|
? `&month=${getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]}`
|
||||||
|
: ""
|
||||||
|
}${
|
||||||
|
monthYearFilter
|
||||||
|
? `&year=${getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]}`
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
className="border border-red-500 text-red-500 hover:bg-red-500 text-sm hover:text-white px-4 py-2 rounded transition duration-200"
|
||||||
|
>
|
||||||
|
Lihat Semua
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
{/* <Link
|
||||||
href={`${
|
href={`${
|
||||||
asPath.includes("/polda/")
|
asPath.includes("/polda/")
|
||||||
? `/${asPath.split("/")[1]}/${asPath.split("/")[2]}`
|
? `/${asPath.split("/")[1]}/${asPath.split("/")[2]}`
|
||||||
|
|
@ -312,7 +341,7 @@ export default function FilterImageComponent(props: {
|
||||||
className="border border-red-500 text-red-500 hover:bg-red-500 text-sm hover:text-white px-4 py-2 rounded transition duration-200"
|
className="border border-red-500 text-red-500 hover:bg-red-500 text-sm hover:text-white px-4 py-2 rounded transition duration-200"
|
||||||
>
|
>
|
||||||
Lihat Semua
|
Lihat Semua
|
||||||
</Link>
|
</Link> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,34 @@ export default function FilterVideoComponent(props: {
|
||||||
</Carousel>
|
</Carousel>
|
||||||
<div className="flex justify-center mt-1 mb-6">
|
<div className="flex justify-center mt-1 mb-6">
|
||||||
<Link
|
<Link
|
||||||
|
href={`${
|
||||||
|
asPath.includes("/polda/")
|
||||||
|
? `/${asPath.split("/")[1]}/${asPath.split("/")[2]}`
|
||||||
|
: asPath.includes("/regional")
|
||||||
|
? "/regional/all-polda"
|
||||||
|
: ""
|
||||||
|
}/video/${
|
||||||
|
group || asPath.includes("/polda/") || asPath.includes("/regional")
|
||||||
|
? "regional?"
|
||||||
|
: "filter?"
|
||||||
|
}${sortByOpt === "popular" ? "sortBy=popular" : "sortBy=latest"}${
|
||||||
|
title ? `&title=${title.toLowerCase()}` : ""
|
||||||
|
}${categorie ? `&category=${categorie}` : ""}${
|
||||||
|
startDateString ? `&startDate=${startDateString}` : ""
|
||||||
|
}${endDateString ? `&endDate=${endDateString}` : ""}${
|
||||||
|
monthYearFilter
|
||||||
|
? `&month=${getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]}`
|
||||||
|
: ""
|
||||||
|
}${
|
||||||
|
monthYearFilter
|
||||||
|
? `&year=${getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]}`
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
className="border border-red-500 text-red-500 hover:bg-red-500 text-sm hover:text-white px-4 py-2 rounded transition duration-200"
|
||||||
|
>
|
||||||
|
Lihat Semua
|
||||||
|
</Link>
|
||||||
|
{/* <Link
|
||||||
href={`${
|
href={`${
|
||||||
asPath.includes("/polda/")
|
asPath.includes("/polda/")
|
||||||
? `/${asPath.split("/")[1]}/${asPath.split("/")[2]}`
|
? `/${asPath.split("/")[1]}/${asPath.split("/")[2]}`
|
||||||
|
|
@ -282,7 +310,7 @@ export default function FilterVideoComponent(props: {
|
||||||
className="border border-red-500 text-red-500 hover:bg-red-500 hover:text-white px-4 py-2 text-sm rounded transition duration-200"
|
className="border border-red-500 text-red-500 hover:bg-red-500 hover:text-white px-4 py-2 text-sm rounded transition duration-200"
|
||||||
>
|
>
|
||||||
Lihat Semua
|
Lihat Semua
|
||||||
</Link>
|
</Link> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue