From bb0d5e7999d6c361b783439ef9f91c7a64e1878e Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Sun, 13 Apr 2025 20:30:26 +0800 Subject: [PATCH] feat:update ui --- .../admin/management-user/page.tsx | 53 ++- .../contributor/report/components/columns.tsx | 178 +++++++ .../report/components/report-table.tsx | 395 ++++++++++++++++ .../(protected)/contributor/report/layout.tsx | 9 + .../(protected)/contributor/report/page.tsx | 24 + .../schedule/event/components/event-table.tsx | 79 +++- .../components/presscon-table.tsx | 78 +++- .../components/pressrilis-table.tsx | 78 +++- app/[locale]/(protected)/dashboard/page.tsx | 22 +- .../contest/components/contest-table.tsx | 99 +++- app/[locale]/(public)/image/filter/page.tsx | 433 +++++++++++++----- components/landing-page/hero.tsx | 134 +++--- components/partials/auth/login-form.tsx | 11 +- messages/en.json | 11 +- messages/in.json | 13 +- service/schedule/schedule.ts | 7 +- 16 files changed, 1348 insertions(+), 276 deletions(-) create mode 100644 app/[locale]/(protected)/contributor/report/components/columns.tsx create mode 100644 app/[locale]/(protected)/contributor/report/components/report-table.tsx create mode 100644 app/[locale]/(protected)/contributor/report/layout.tsx create mode 100644 app/[locale]/(protected)/contributor/report/page.tsx diff --git a/app/[locale]/(protected)/admin/management-user/page.tsx b/app/[locale]/(protected)/admin/management-user/page.tsx index ff0e82fa..a3692b2a 100644 --- a/app/[locale]/(protected)/admin/management-user/page.tsx +++ b/app/[locale]/(protected)/admin/management-user/page.tsx @@ -2,20 +2,33 @@ import SiteBreadcrumb from "@/components/site-breadcrumb"; import UserExternalTable from "@/components/table/management-user/management-user-external-table"; import UserInternalTable from "@/components/table/management-user/management-user-internal-table"; -import InternalTable from "@/components/table/management-user/management-user-internal-table"; import { Button } from "@/components/ui/button"; -import DashboardVisualization from "@/components/visualization/dashboard-viz"; import ManagementUserVisualization from "@/components/visualization/management-user-viz"; import { Link, useRouter } from "@/i18n/routing"; import { PlusIcon } from "lucide-react"; import { useEffect, useState } from "react"; +import Cookies from "js-cookie"; +import { getCookiesDecrypt } from "@/lib/utils"; export default function ManagementUser() { const [isInternal, setIsInternal] = useState(true); + const [levelNumber, setLevelNumber] = useState(null); const router = useRouter(); + + useEffect(() => { + const encryptedLevel = Cookies.get("ulne"); + if (encryptedLevel) { + const decryptedLevel = getCookiesDecrypt("ulne"); + setLevelNumber(Number(decryptedLevel)); + } + }, []); + useEffect(() => { router.push("?page=1"); }, [isInternal]); + + const showExternalButton = levelNumber !== 2 && levelNumber !== 3; + return (
@@ -23,10 +36,7 @@ export default function ManagementUser() { -
+

Data User {isInternal ? "Internal" : "Eksternal"} @@ -40,28 +50,31 @@ export default function ManagementUser() { )}

+
- + + {showExternalButton && ( + + )}
+ {isInternal ? : }
diff --git a/app/[locale]/(protected)/contributor/report/components/columns.tsx b/app/[locale]/(protected)/contributor/report/components/columns.tsx new file mode 100644 index 00000000..87b5d362 --- /dev/null +++ b/app/[locale]/(protected)/contributor/report/components/columns.tsx @@ -0,0 +1,178 @@ +import * as React from "react"; +import { ColumnDef } from "@tanstack/react-table"; + +import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react"; +import { cn } from "@/lib/utils"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuTrigger, + DropdownMenuItem, +} from "@/components/ui/dropdown-menu"; +import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; +import { format } from "date-fns"; +import { Link, useRouter } from "@/components/navigation"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { deleteBlog } from "@/service/blog/blog"; +import { error, loading } from "@/lib/swal"; +import { useTranslations } from "next-intl"; + +const useTableColumns = () => { + const t = useTranslations("Table"); // Panggil di dalam hook + + const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: t("no"), + cell: ({ row }) => {row.getValue("no")}, + }, + { + accessorKey: "title", + header: t("title"), + cell: ({ row }) => ( + {row.getValue("title")} + ), + }, + { + accessorKey: "categoryName", + header: t("category"), + cell: ({ row }) => {row.getValue("categoryName")}, + }, + { + accessorKey: "createdAt", + header: t("upload-date"), + cell: ({ row }) => { + const createdAt = row.getValue("createdAt") as + | string + | number + | undefined; + + const formattedDate = + createdAt && !isNaN(new Date(createdAt).getTime()) + ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") + : "-"; + return {formattedDate}; + }, + }, + { + accessorKey: "tags", + header: t("tag"), + cell: ({ row }) => {row.getValue("tags")}, + }, + { + accessorKey: "statusName", + header: "Status", + cell: ({ row }) => { + const statusColors: Record = { + diterima: "bg-green-100 text-green-600", + "menunggu review": "bg-orange-100 text-orange-600", + }; + + // Mengambil `statusName` dari data API + const status = row.getValue("statusName") as string; + const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil + + // Gunakan `statusName` untuk pencocokan + const statusStyles = + statusColors[statusName] || "bg-gray-100 text-gray-600"; + + return ( + + {status} {/* Tetap tampilkan nilai asli */} + + ); + }, + }, + + { + id: "actions", + accessorKey: "action", + header: t("action"), + enableHiding: false, + cell: ({ row }) => { + const router = useRouter(); + const MySwal = withReactContent(Swal); + + async function deleteProcess(id: any) { + loading(); + const resDelete = await deleteBlog(id); + + if (resDelete?.error) { + error(resDelete.message); + return false; + } + success(); + } + + function success() { + MySwal.fire({ + title: "Sukses", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then((result) => { + if (result.isConfirmed) { + window.location.reload(); + } + }); + } + + const handleDeleteBlog = (id: any) => { + MySwal.fire({ + title: "Hapus Data", + text: "", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#3085d6", + confirmButtonColor: "#d33", + confirmButtonText: "Hapus", + }).then((result) => { + if (result.isConfirmed) { + deleteProcess(id); + } + }); + }; + return ( + + + + + + + + + View + + + + + + Edit + + + handleDeleteBlog(row.original.id)} + className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none" + > + + Delete + + + + ); + }, + }, + ]; + + return columns; +}; + +export default useTableColumns; diff --git a/app/[locale]/(protected)/contributor/report/components/report-table.tsx b/app/[locale]/(protected)/contributor/report/components/report-table.tsx new file mode 100644 index 00000000..9ba22651 --- /dev/null +++ b/app/[locale]/(protected)/contributor/report/components/report-table.tsx @@ -0,0 +1,395 @@ +"use client"; + +import * as React from "react"; +import { + ColumnDef, + ColumnFiltersState, + PaginationState, + SortingState, + VisibilityState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table"; +import { Button } from "@/components/ui/button"; + +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { ChevronDown, Plus, Search } from "lucide-react"; +import { cn } from "@/lib/utils"; +import { Input } from "@/components/ui/input"; +import { InputGroup, InputGroupText } from "@/components/ui/input-group"; +import { getBlogCategory, paginationBlog } from "@/service/blog/blog"; +import { ticketingPagination } from "@/service/ticketing/ticketing"; +import { useRouter, useSearchParams } from "next/navigation"; +import TablePagination from "@/components/table/table-pagination"; +import columns from "./columns"; +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Label } from "@/components/ui/label"; +import { listEnableCategory } from "@/service/content/content"; +import { useTranslations } from "next-intl"; +import { CardHeader, CardTitle } from "@/components/ui/card"; +import { Link } from "@/i18n/routing"; +import useTableColumns from "./columns"; + +const ReportTable = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + const t = useTranslations("Report"); + const [dataTable, setDataTable] = React.useState([]); + const [totalData, setTotalData] = React.useState(1); + const [sorting, setSorting] = React.useState([]); + const [columnFilters, setColumnFilters] = React.useState( + [] + ); + const [columnVisibility, setColumnVisibility] = + React.useState({}); + const [rowSelection, setRowSelection] = React.useState({}); + const [showData, setShowData] = React.useState("50"); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: Number(showData), + }); + const [page, setPage] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); + const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); + const [categories, setCategories] = React.useState([]); + const [selectedCategories, setSelectedCategories] = React.useState( + [] + ); + const [categoryFilter, setCategoryFilter] = React.useState(""); + const [dateFilter, setDateFilter] = React.useState(""); + const [statusFilter, setStatusFilter] = React.useState([]); + const columns = useTableColumns(); + const table = useReactTable({ + data: dataTable, + 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, + }, + }); + + React.useEffect(() => { + const pageFromUrl = searchParams?.get("page"); + if (pageFromUrl) { + setPage(Number(pageFromUrl)); + } + }, [searchParams]); + + React.useEffect(() => { + fetchData(); + getCategories(); + }, [categoryFilter, statusFilter, page, showData, search]); + + async function fetchData() { + try { + const res = await paginationBlog( + showData, + page - 1, + search, + categoryFilter, + statusFilter + ); + const data = res?.data?.data; + const contentData = data?.content; + contentData.forEach((item: any, index: number) => { + item.no = (page - 1) * Number(showData) + index + 1; + }); + + console.log("contentData : ", contentData); + + setDataTable(contentData); + setTotalData(data?.totalElements); + setTotalPage(data?.totalPages); + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + + async function getCategories() { + const category = await getBlogCategory(); + const resCategory = category?.data?.data?.content; + setCategories(resCategory || []); + } + + const handleCheckboxChange = (categoryId: number) => { + setSelectedCategories( + (prev: any) => + prev.includes(categoryId) + ? prev.filter((id: any) => id !== categoryId) // Hapus jika sudah dipilih + : [...prev, categoryId] // Tambahkan jika belum dipilih + ); + + // Perbarui filter kategori + setCategoryFilter((prev) => { + const updatedCategories = prev.split(",").filter(Boolean).map(Number); + + const newCategories = updatedCategories.includes(categoryId) + ? updatedCategories.filter((id) => id !== categoryId) + : [...updatedCategories, categoryId]; + + return newCategories.join(","); + }); + }; + + function handleStatusCheckboxChange(value: any) { + setStatusFilter((prev: any) => + prev.includes(value) + ? prev.filter((status: any) => status !== value) + : [...prev, value] + ); + } + + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + + return ( +
+ + +
+
+ {t("table")} {t("report")} +
+
+ + + +
+
+
+
+ +
+
+
+ + + + + + +
+
+
+
+ + + + + + + + 1 - 10 Data + + + 1 - 50 Data + + + 1 - 100 Data + + + 1 - 250 Data + + + + +
+ + + + + +
+

Filter

+
+
+ + setDateFilter(e.target.value)} + className="max-w-sm" + /> +
+ {/*
+ + +
*/} + +
+ handleStatusCheckboxChange(1)} + /> + +
+
+ handleStatusCheckboxChange(2)} + /> + +
+
+
+
+
+ + + + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => { + return ( + + column.toggleVisibility(!!value) + } + > + {column.id} + + ); + })} + + +
+
+
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ))} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+ +
+
+ ); +}; + +export default ReportTable; diff --git a/app/[locale]/(protected)/contributor/report/layout.tsx b/app/[locale]/(protected)/contributor/report/layout.tsx new file mode 100644 index 00000000..47e2f324 --- /dev/null +++ b/app/[locale]/(protected)/contributor/report/layout.tsx @@ -0,0 +1,9 @@ +export const metadata = { + title: "Blog", +}; + +const Layout = ({ children }: { children: React.ReactNode }) => { + return <>{children}; +}; + +export default Layout; diff --git a/app/[locale]/(protected)/contributor/report/page.tsx b/app/[locale]/(protected)/contributor/report/page.tsx new file mode 100644 index 00000000..644566df --- /dev/null +++ b/app/[locale]/(protected)/contributor/report/page.tsx @@ -0,0 +1,24 @@ +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import BlogTable from "./components/report-table"; +import { Plus } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { Link } from "@/components/navigation"; +import ReportTable from "./components/report-table"; + +const ReportPage = async () => { + return ( +
+ +
+ + + + + +
+
+ ); +}; + +export default ReportPage; diff --git a/app/[locale]/(protected)/contributor/schedule/event/components/event-table.tsx b/app/[locale]/(protected)/contributor/schedule/event/components/event-table.tsx index 2400e864..a4524e72 100644 --- a/app/[locale]/(protected)/contributor/schedule/event/components/event-table.tsx +++ b/app/[locale]/(protected)/contributor/schedule/event/components/event-table.tsx @@ -22,7 +22,7 @@ import { TableHeader, TableRow, } from "@/components/ui/table"; -import { Search, UploadIcon } from "lucide-react"; +import { ChevronDown, Search, UploadIcon } from "lucide-react"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; import { useRouter, useSearchParams } from "next/navigation"; @@ -41,6 +41,7 @@ import { DropdownMenuRadioItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; +import { Label } from "@/components/ui/label"; const EventTable = () => { const router = useRouter(); @@ -64,6 +65,7 @@ const EventTable = () => { const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); const [search, setSearch] = React.useState(""); + const [statusFilter, setStatusFilter] = React.useState([]); const columns = useTableColumns(); const table = useReactTable({ data: dataTable, @@ -95,11 +97,17 @@ const EventTable = () => { React.useEffect(() => { fetchData(); - }, [page, showData, search]); + }, [page, showData, search, statusFilter]); async function fetchData() { try { - const res = await paginationSchedule(showData, page - 1, 2, search); + const res = await paginationSchedule( + showData, + page - 1, + 2, + search, + statusFilter + ); const data = res?.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -116,6 +124,14 @@ const EventTable = () => { } } + const handleStatusCheckboxChange = (statusId: number) => { + const updatedFilter = statusFilter.includes(statusId) + ? statusFilter.filter((id) => id !== statusId) + : [...statusFilter, statusId]; + + setStatusFilter(updatedFilter); + }; + const handleSearch = (e: React.ChangeEvent) => { setSearch(e.target.value); // Perbarui state search table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel @@ -141,8 +157,8 @@ const EventTable = () => {
-
-
+
+
@@ -185,17 +201,48 @@ const EventTable = () => {
-
- ) => - table.getColumn("status")?.setFilterValue(event.target.value) - } - className="max-w-sm " - /> +
+ + + + + +
+

Filter

+
+ + +
+ handleStatusCheckboxChange(1)} + /> + +
+
+ handleStatusCheckboxChange(2)} + /> + +
+
+
diff --git a/app/[locale]/(protected)/contributor/schedule/press-conference/components/presscon-table.tsx b/app/[locale]/(protected)/contributor/schedule/press-conference/components/presscon-table.tsx index dac07d26..c409f222 100644 --- a/app/[locale]/(protected)/contributor/schedule/press-conference/components/presscon-table.tsx +++ b/app/[locale]/(protected)/contributor/schedule/press-conference/components/presscon-table.tsx @@ -26,6 +26,7 @@ import { } from "@/components/ui/table"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { + ChevronDown, ChevronLeft, ChevronRight, Eye, @@ -54,6 +55,7 @@ import { DropdownMenuRadioItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; +import { Label } from "@/components/ui/label"; const PressConferenceTable = () => { const router = useRouter(); @@ -77,6 +79,7 @@ const PressConferenceTable = () => { const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); const [search, setSearch] = React.useState(""); + const [statusFilter, setStatusFilter] = React.useState([]); const columns = useTableColumns(); const table = useReactTable({ data: dataTable, @@ -108,11 +111,17 @@ const PressConferenceTable = () => { React.useEffect(() => { fetchData(); - }, [page, showData, search]); + }, [page, showData, search, statusFilter]); async function fetchData() { try { - const res = await paginationSchedule(showData, page - 1, 1, search); + const res = await paginationSchedule( + showData, + page - 1, + 1, + search, + statusFilter + ); const data = res?.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -129,6 +138,14 @@ const PressConferenceTable = () => { } } + const handleStatusCheckboxChange = (statusId: number) => { + const updatedFilter = statusFilter.includes(statusId) + ? statusFilter.filter((id) => id !== statusId) + : [...statusFilter, statusId]; + + setStatusFilter(updatedFilter); + }; + const handleSearch = (e: React.ChangeEvent) => { setSearch(e.target.value); // Perbarui state search table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel @@ -154,8 +171,8 @@ const PressConferenceTable = () => {
-
-
+
+
@@ -198,17 +215,48 @@ const PressConferenceTable = () => {
-
- ) => - table.getColumn("status")?.setFilterValue(event.target.value) - } - className="max-w-sm " - /> +
+ + + + + +
+

Filter

+
+ + +
+ handleStatusCheckboxChange(1)} + /> + +
+
+ handleStatusCheckboxChange(2)} + /> + +
+
+
diff --git a/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx b/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx index 97bdafb7..3315fc3e 100644 --- a/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx +++ b/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx @@ -26,6 +26,7 @@ import { } from "@/components/ui/table"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { + ChevronDown, ChevronLeft, ChevronRight, Eye, @@ -55,6 +56,7 @@ import { DropdownMenuRadioItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; +import { Label } from "@/components/ui/label"; const PressReleaseTable = () => { const router = useRouter(); @@ -78,6 +80,7 @@ const PressReleaseTable = () => { const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); const [search, setSearch] = React.useState(""); + const [statusFilter, setStatusFilter] = React.useState([]); const columns = useTableColumns(); const table = useReactTable({ data: dataTable, @@ -109,11 +112,17 @@ const PressReleaseTable = () => { React.useEffect(() => { fetchData(); - }, [page, showData, search]); + }, [page, showData, search, statusFilter]); async function fetchData() { try { - const res = await paginationSchedule(showData, page - 1, 3, search); + const res = await paginationSchedule( + showData, + page - 1, + 3, + search, + statusFilter + ); const data = res?.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -130,6 +139,14 @@ const PressReleaseTable = () => { } } + const handleStatusCheckboxChange = (statusId: number) => { + const updatedFilter = statusFilter.includes(statusId) + ? statusFilter.filter((id) => id !== statusId) + : [...statusFilter, statusId]; + + setStatusFilter(updatedFilter); + }; + const handleSearch = (e: React.ChangeEvent) => { setSearch(e.target.value); // Perbarui state search table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel @@ -155,8 +172,8 @@ const PressReleaseTable = () => {
-
-
+
+
@@ -199,17 +216,48 @@ const PressReleaseTable = () => {
-
- ) => - table.getColumn("status")?.setFilterValue(event.target.value) - } - className="w-full " - /> +
+ + + + + +
+

Filter

+
+ + +
+ handleStatusCheckboxChange(1)} + /> + +
+
+ handleStatusCheckboxChange(2)} + /> + +
+
+
diff --git a/app/[locale]/(protected)/dashboard/page.tsx b/app/[locale]/(protected)/dashboard/page.tsx index b9d7421e..29d17565 100644 --- a/app/[locale]/(protected)/dashboard/page.tsx +++ b/app/[locale]/(protected)/dashboard/page.tsx @@ -19,6 +19,7 @@ import BlogTable from "../contributor/blog/components/blog-table"; import ContentTable from "./routine-task/components/content-table"; import RecentActivity from "./routine-task/components/recent-activity"; import { Link } from "@/components/navigation"; +import ReportTable from "../contributor/report/components/report-table"; const DashboardPage = () => { const t = useTranslations("AnalyticsDashboard"); @@ -59,6 +60,12 @@ const DashboardPage = () => { > {t("indeks")} + + {t("report")} + @@ -157,7 +164,7 @@ const DashboardPage = () => {
- + {/*
Table Indeks @@ -171,7 +178,7 @@ const DashboardPage = () => {
-
+
*/} @@ -179,6 +186,17 @@ const DashboardPage = () => {
+ +
+
+ + + + + +
+
+
diff --git a/app/[locale]/(protected)/shared/contest/components/contest-table.tsx b/app/[locale]/(protected)/shared/contest/components/contest-table.tsx index 59e08c6f..e6576478 100644 --- a/app/[locale]/(protected)/shared/contest/components/contest-table.tsx +++ b/app/[locale]/(protected)/shared/contest/components/contest-table.tsx @@ -26,6 +26,7 @@ import { } from "@/components/ui/table"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { + ChevronDown, ChevronLeft, ChevronRight, Eye, @@ -50,6 +51,7 @@ import { DropdownMenuRadioItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; +import { Label } from "@/components/ui/label"; const TaskTable = () => { const router = useRouter(); @@ -72,6 +74,7 @@ const TaskTable = () => { const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); const [search, setSearch] = React.useState(""); + const [statusFilter, setStatusFilter] = React.useState([]); const columns = useTableColumns(); const table = useReactTable({ data: dataTable, @@ -103,13 +106,28 @@ const TaskTable = () => { React.useEffect(() => { fetchData(); - }, [page, showData, search]); + }, [page, showData, search, statusFilter]); async function fetchData() { try { const res = await listContest(search, showData, page - 1); const data = res?.data?.data; - const contentData = data?.content; + let contentData = data?.content; + + if (statusFilter.length > 0) { + contentData = contentData.filter((item: any) => { + const { isPublishForAll, isPublishForMabes } = item; + + const status = (() => { + if (isPublishForAll && isPublishForMabes) return 1; // Publish + if (!isPublishForAll && isPublishForMabes) return 3; // Terkirim + return 2; // Pending + })(); + + return statusFilter.includes(status); + }); + } + contentData.forEach((item: any, index: number) => { item.no = (page - 1) * Number(showData) + index + 1; }); @@ -124,6 +142,14 @@ const TaskTable = () => { } } + const handleStatusCheckboxChange = (status: number) => { + setStatusFilter((prev) => + prev.includes(status) + ? prev.filter((item) => item !== status) + : [...prev, status] + ); + }; + const handleSearch = (e: React.ChangeEvent) => { setSearch(e.target.value); table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel @@ -131,8 +157,8 @@ const TaskTable = () => { return (
-
-
+
+
@@ -175,17 +201,60 @@ const TaskTable = () => {
-
- ) => - table.getColumn("status")?.setFilterValue(event.target.value) - } - className="max-w-sm " - /> +
+ + + + + +
+

Filter

+
+ + +
+ handleStatusCheckboxChange(1)} + /> + +
+
+ handleStatusCheckboxChange(2)} + /> + +
+
+ handleStatusCheckboxChange(3)} + /> + +
+
+
diff --git a/app/[locale]/(public)/image/filter/page.tsx b/app/[locale]/(public)/image/filter/page.tsx index d1684afb..51f6e492 100644 --- a/app/[locale]/(public)/image/filter/page.tsx +++ b/app/[locale]/(public)/image/filter/page.tsx @@ -3,10 +3,30 @@ 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 { + formatDateToIndonesian, + getOnlyDate, + getOnlyMonthAndYear, +} from "@/utils/globals"; import { useParams, usePathname, useSearchParams } from "next/navigation"; -import { getUserLevelListByParent, listCategory, listData, listDataRegional } from "@/service/landing/landing"; -import { ColumnDef, ColumnFiltersState, PaginationState, SortingState, VisibilityState, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table"; +import { + getUserLevelListByParent, + listCategory, + 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"; @@ -38,8 +58,11 @@ const FilterPage = () => { const [totalData, setTotalData] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); const [sorting, setSorting] = React.useState([]); - const [columnFilters, setColumnFilters] = React.useState([]); - const [columnVisibility, setColumnVisibility] = React.useState({}); + const [columnFilters, setColumnFilters] = React.useState( + [] + ); + const [columnVisibility, setColumnVisibility] = + React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); const [pagination, setPagination] = React.useState({ pageIndex: 0, @@ -60,7 +83,9 @@ const FilterPage = () => { const [categoryFilter, setCategoryFilter] = useState([]); const [monthYearFilter, setMonthYearFilter] = useState(); const [searchTitle, setSearchTitle] = useState(""); - const [sortByOpt, setSortByOpt] = useState(sortBy === "popular" ? "clickCount" : "createdAt"); + const [sortByOpt, setSortByOpt] = useState( + sortBy === "popular" ? "clickCount" : "createdAt" + ); const isRegional = asPath?.includes("regional"); const isSatker = asPath?.includes("satker"); const [formatFilter, setFormatFilter] = useState([]); @@ -73,6 +98,7 @@ const FilterPage = () => { const [categories, setCategories] = useState([]); const [userLevels, setUserLevels] = useState([]); const t = useTranslations("FilterPage"); + const [isFilterOpen, setIsFilterOpen] = useState(true); // const [startDate, endDate] = dateRange; @@ -105,8 +131,14 @@ const FilterPage = () => { useEffect(() => { if (categorie) { - setCategoryFilter(categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]); - console.log("Kategori", categorie, categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]); + setCategoryFilter( + categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie] + ); + console.log( + "Kategori", + categorie, + categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie] + ); } }, [categorie]); @@ -124,7 +156,19 @@ const FilterPage = () => { } console.log(monthYearFilter, "monthFilter"); initState(); - }, [change, asPath, monthYearFilter, page, sortBy, sortByOpt, title, startDateString, endDateString, categorie, formatFilter]); + }, [ + change, + asPath, + monthYearFilter, + page, + sortBy, + sortByOpt, + title, + startDateString, + endDateString, + categorie, + formatFilter, + ]); async function getCategories() { const category = await listCategory("1"); @@ -147,7 +191,10 @@ const FilterPage = () => { async function getDataAll() { if (asPath?.includes("/polda/") == true) { if (asPath?.split("/")[2] !== "[polda_name]") { - const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || ""; + const filter = + categoryFilter?.length > 0 + ? categoryFilter?.sort().join(",") + : categorie || ""; const name = title == undefined ? "" : title; const format = formatFilter == undefined ? "" : formatFilter?.join(","); @@ -165,8 +212,14 @@ const FilterPage = () => { filterGroup, startDateString, endDateString, - monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "", - monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "", + monthYearFilter + ? getOnlyMonthAndYear(monthYearFilter) + ?.split("/")[0] + ?.replace("", "") + : "", + monthYearFilter + ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] + : "", locale == "en" ? true : false ); close(); @@ -181,7 +234,10 @@ const FilterPage = () => { setTotalContent(response?.data?.data?.totalElements); } } else { - const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || ""; + const filter = + categoryFilter?.length > 0 + ? categoryFilter?.sort().join(",") + : categorie || ""; const name = title == undefined ? "" : title; const format = formatFilter == undefined ? "" : formatFilter?.join(","); @@ -198,8 +254,12 @@ const FilterPage = () => { "", startDateString, endDateString, - monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "", - monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "", + monthYearFilter + ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") + : "", + monthYearFilter + ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] + : "", locale == "en" ? true : false ); close(); @@ -250,7 +310,10 @@ const FilterPage = () => { }; async function getDataRegional() { - const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || ""; + const filter = + categoryFilter?.length > 0 + ? categoryFilter?.sort().join(",") + : categorie || ""; const name = title == undefined ? "" : title; const format = formatFilter == undefined ? "" : formatFilter?.join(","); @@ -263,8 +326,12 @@ const FilterPage = () => { "", startDateString, endDateString, - monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "", - monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "", + monthYearFilter + ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") + : "", + monthYearFilter + ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] + : "", 12, pages, sortByOpt @@ -381,16 +448,20 @@ const FilterPage = () => { `; - const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str)); + const toBase64 = (str: string) => + typeof window === "undefined" + ? Buffer.from(str).toString("base64") + : window.btoa(str); return (
{/* Header */} -
+
+

{t("image")}

+ {">"}

- {" "} - {t("image")} {">"} {t("allImage")} + {t("allImage")}

|

{`${t("thereIs")} ${totalContent} ${t("downloadableImage")}`}

@@ -398,106 +469,182 @@ const FilterPage = () => { {/* Left */}
-
-

- - Filter -

-
-
-
- - setSearchTitle(e.target.value)} - onKeyUp={handleKeyUp} - onKeyDown={handleKeyDown} - type="text" - id="search" - placeholder={t("searchTitle")} - className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" - /> -
+
+ +
-
- - setMonthYearFilter(date)} - dateFormat="MM | yyyy" - placeholderText={t("selectYear")} - showMonthYearPicker - /> -
- -
- -
- { - setDateRange(update); - }} - placeholderText={t("selectDate")} - onCalendarClose={() => setCalenderState(!calenderState)} + {isFilterOpen && ( +
+

+ + Filter +

+
+
+
+ + setSearchTitle(e.target.value)} + onKeyUp={handleKeyUp} + onKeyDown={handleKeyDown} + type="text" + id="search" + placeholder={t("searchTitle")} + className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" /> -
{handleClose ? : ""}
-
-
-

{t("categories")}

-
    - {categories.map((category: any) => ( -
  • -
  • + +
  • +
  • + +
  • +
+
+
+
-
+ )} {/* Right */}
@@ -505,7 +652,11 @@ const FilterPage = () => {

{t("sortBy")}

- handleSorting(e)} + className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500" + > @@ -529,24 +680,50 @@ const FilterPage = () => { {imageData?.length > 0 ? (
{imageData?.map((image: any) => ( - + {/* */}
- +
- {formatDateToIndonesian(new Date(image?.createdAt))} {image?.timezone ? image?.timezone : "WIB"}| + {formatDateToIndonesian( + new Date(image?.createdAt) + )}{" "} + {image?.timezone ? image?.timezone : "WIB"}|{" "} + {image?.clickCount}{" "} - + {" "}
-
{image?.title}
+
+ {image?.title} +
@@ -554,12 +731,24 @@ const FilterPage = () => {
) : (

- empty + empty

)} )} - {totalData > 1 && } + {totalData > 1 && ( + + )}
diff --git a/components/landing-page/hero.tsx b/components/landing-page/hero.tsx index 69f7482a..1d3e4c39 100644 --- a/components/landing-page/hero.tsx +++ b/components/landing-page/hero.tsx @@ -37,6 +37,10 @@ import { DialogHeader, DialogTitle, } from "../ui/dialog"; +import { Autoplay, Pagination } from "swiper/modules"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/pagination"; const HeroModal = ({ onClose }: { onClose: () => void }) => { const [heroData, setHeroData] = useState(); @@ -73,63 +77,73 @@ const HeroModal = ({ onClose }: { onClose: () => void }) => { return (
- - - {heroData?.map((list: any, index: any) => ( - -
- - gambar-utama + + {heroData?.map((list: any, index: number) => ( + +
+ + gambar-utama -
-
- - {list?.categoryName || "Liputan Kegiatan"} - +
+
+ + {list?.categoryName || "Liputan Kegiatan"} + - -

{list?.title}

- + +

{list?.title}

+ -

- {formatDateToIndonesian(new Date(list?.createdAt))}{" "} - {list?.timezone || "WIB"} |{" "} - - - - {list?.clickCount} -

-
+

+ {formatDateToIndonesian(new Date(list?.createdAt))}{" "} + {list?.timezone || "WIB"} |{" "} + + + + {list?.clickCount} +

- - ))} - - - - +
+
+ ))} + +
); @@ -568,14 +582,17 @@ const Hero: React.FC = () => { ) : (
    - + Nasional Polda Satker {heroData?.map((item: any) => ( -
  • +
  • { .map((item: any, index: any) => (
  • { {heroData?.map((item: any) => ( -
  • +
  • { const [otpValidate, setOtpValidate] = useState(""); const [showPassword, setShowPassword] = useState(false); - const [otp1, setOtp1] = useState(); - const [otp2, setOtp2] = useState(); - const [otp3, setOtp3] = useState(); - const [otp4, setOtp4] = useState(); - const [otp5, setOtp5] = useState(); - const [otp6, setOtp6] = useState(); - const togglePasswordType = () => { setPasswordType((prevType) => prevType === "password" ? "text" : "password" @@ -268,7 +261,7 @@ const LoginForm = () => { } else if (msg == "Username & password valid") { onSubmit(data); } else { - setStep(2); + setStep(1); } }; @@ -485,7 +478,7 @@ const LoginForm = () => { fullWidth className="bg-red-500" onClick={handleSetupEmail} - type="submit" + type="button" > Simpan diff --git a/messages/en.json b/messages/en.json index bf6918a4..a85c416c 100644 --- a/messages/en.json +++ b/messages/en.json @@ -29,7 +29,8 @@ "task-routine": "Task Routine", "task": "Task", "schedule": "Schedule", - "indeks": "Indeks", + "indeks": "Blog", + "report": "Report", "Total-Content-Production": "Total Content Production", "average": "average", "create-image": "Create Image", @@ -598,6 +599,14 @@ "create-indeks": "Add Blog", "category": "Category" }, + "report": { + "table": "Table", + "report": "Report", + "generate-report": "Generate Report", + "category": "Category", + "acc": "Diterima", + "wait-review": "Menunggu Review" + }, "Communication": { "internal-questions": "Internal Question", "escalation": "Escalation", diff --git a/messages/in.json b/messages/in.json index dab71d24..438d000d 100644 --- a/messages/in.json +++ b/messages/in.json @@ -27,10 +27,11 @@ "Hasil_unggah_disetujui_hari_ini": "Hasil unggah disetujui hari ini", "Hasil_unggah_direvisi_hari_ini": "Hasil unggah direvisi hari ini", "Hasil_unggah_ditolak_hari_ini": "Hasil unggah ditolak hari ini", - "task-routine": "Task Routine", + "task-routine": "Tugas Rutin", "task": "Penugasan", "schedule": "Jadwal", - "indeks": "Blog", + "indeks": "Indeks", + "report": "Laporan", "Total-Content-Production": "Total Produksi Konten", "average": "Rata Rata", "create-image": "Unggah Foto", @@ -599,6 +600,14 @@ "create-indeks": "Tambah Indeks", "category": "Kategori" }, + "Report": { + "table": "Tabel", + "report": "Laporan", + "generate-report": "Generate Laporan", + "category": "Kategori", + "acc": "Diterima", + "wait-review": "Menunggu Review" + }, "Communication": { "internal-questions": "Pertanyaan Internal", "escalation": "Eskalasi", diff --git a/service/schedule/schedule.ts b/service/schedule/schedule.ts index 607a94a8..ffac5040 100644 --- a/service/schedule/schedule.ts +++ b/service/schedule/schedule.ts @@ -9,10 +9,13 @@ export async function paginationSchedule( size: any, page: number, type: any, - title: string = "" + title: string = "", + statusFilter: number[] = [] ) { + const statusQuery = + statusFilter.length > 0 ? `&statusId=${statusFilter.join(",")}` : ""; return await httpGetInterceptor( - `schedule/pagination?enablePage=1&scheduleTypeId=${type}&page=${page}&size=${size}&title=${title}` + `schedule/pagination?enablePage=1&scheduleTypeId=${type}&page=${page}&size=${size}&title=${title}${statusQuery}` ); }