diff --git a/src/app/api/admin/event/[status]/route.ts b/src/app/api/admin/event/[status]/route.ts new file mode 100644 index 00000000..9e840305 --- /dev/null +++ b/src/app/api/admin/event/[status]/route.ts @@ -0,0 +1,143 @@ +import { prisma } from "@/app/lib"; +import backendLogger from "@/util/backendLogger"; +import _ from "lodash"; +import { NextResponse } from "next/server"; + +export async function GET( + request: Request, + { params }: { params: { status: string } } +) { + const method = request.method; + if (method !== "GET") { + return NextResponse.json( + { success: false, message: "Method not allowed" }, + { status: 405 } + ); + } + + const { status } = params; + const { searchParams } = new URL(request.url); + const search = searchParams.get("search"); + const page = searchParams.get("page"); + const takeData = 1; + const skipData = Number(page) * takeData - takeData; + + try { + let fixData; + const fixStatus = _.startCase(status); + + if (!page && !search) { + fixData = await prisma.event.findMany({ + orderBy: { + createdAt: "desc", + }, + where: { + active: true, + isArsip: false, + EventMaster_Status: { + name: fixStatus, + }, + }, + }); + } else if (!page && search) { + fixData = await prisma.event.findMany({ + orderBy: { + createdAt: "desc", + }, + where: { + active: true, + isArsip: false, + EventMaster_Status: { + name: fixStatus, + }, + title: { + contains: search, + mode: "insensitive", + }, + }, + }); + } else if (page && !search) { + const data = await prisma.event.findMany({ + take: takeData, + skip: skipData, + orderBy: { + createdAt: "desc", + }, + where: { + active: true, + isArsip: false, + EventMaster_Status: { + name: fixStatus, + }, + }, + }); + + const nCount = await prisma.event.count({ + where: { + active: true, + eventMaster_StatusId: "1", + isArsip: false, + }, + }); + + fixData = { + data: data, + nPage: _.ceil(nCount / takeData), + }; + } else if (page && search) { + const data = await prisma.event.findMany({ + take: takeData, + skip: skipData, + orderBy: { + createdAt: "desc", + }, + where: { + active: true, + isArsip: false, + EventMaster_Status: { + name: fixStatus, + }, + title: { + contains: search, + mode: "insensitive", + }, + }, + }); + + const nCount = await prisma.event.count({ + where: { + active: true, + eventMaster_StatusId: "1", + isArsip: false, + title: { + contains: search, + mode: "insensitive", + }, + }, + }); + + fixData = { + data: data, + nPage: _.ceil(nCount / takeData), + }; + } + + return NextResponse.json({ + success: true, + message: `Success get data table event ${status}`, + data: fixData, + }); + } catch (error) { + backendLogger.error("Error get data table event dashboard >>", error); + return NextResponse.json( + { + success: false, + message: "Failed get data table event dashboard", + reason: (error as Error).message, + }, + { status: 500 } + ); + } finally { + await prisma.$disconnect(); + } +} diff --git a/src/app/dev/admin/event/_lib/api_fecth_admin_event.ts b/src/app/dev/admin/event/_lib/api_fecth_admin_event.ts index 0fe61529..4cd0999d 100644 --- a/src/app/dev/admin/event/_lib/api_fecth_admin_event.ts +++ b/src/app/dev/admin/event/_lib/api_fecth_admin_event.ts @@ -2,6 +2,7 @@ export { apiGetEventStatusCountDashboard, apiGetEventTipeAcara, apiGetEventRiwayatCount, + apiGetDataEventByStatus, }; const apiGetEventStatusCountDashboard = async ({ @@ -26,25 +27,25 @@ const apiGetEventStatusCountDashboard = async ({ }; const apiGetEventRiwayatCount = async () => { - const { token } = await fetch("/api/get-cookie").then((res) => res.json()); - if (!token) return await token.json().catch(() => null); + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) return await token.json().catch(() => null); - const response = await fetch(`/api/admin/event/dashboard/riwayat`, { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - "Access-Control-Allow-Origin": "*", - Authorization: `Bearer ${token}`, - }, - }); + const response = await fetch(`/api/admin/event/dashboard/riwayat`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }); - return await response.json().catch(() => null); -} + return await response.json().catch(() => null); +}; const apiGetEventTipeAcara = async () => { const { token } = await fetch("/api/get-cookie").then((res) => res.json()); - if (!token) return await token.json().catch(() => null); + if (!token) return await token.json().catch(() => null); const response = await fetch(`/api/admin/event/dashboard/tipe-acara`, { method: "GET", @@ -54,7 +55,33 @@ const apiGetEventTipeAcara = async () => { "Access-Control-Allow-Origin": "*", Authorization: `Bearer ${token}`, }, - }); + }); return await response.json().catch(() => null); }; + +const apiGetDataEventByStatus = async ({ + status, + page, + search, +}: { + status: "Publish" | "Review" | "Reject"; + page: string; + search: string; +}) => { + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) return await token.json().catch(() => null); + + const isPage = page ? `?page=${page}` : ""; + const isSearch = search ? `&search=${search}` : ""; + const respone = await fetch(`/api/admin/event/${status}${isPage}${isSearch}`, { + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }); + + return await respone.json().catch(() => null); +}; diff --git a/src/app/dev/admin/event/table/publish/page.tsx b/src/app/dev/admin/event/table/publish/page.tsx index a7c514dc..cf840dff 100644 --- a/src/app/dev/admin/event/table/publish/page.tsx +++ b/src/app/dev/admin/event/table/publish/page.tsx @@ -2,11 +2,9 @@ import { AdminEvent_TablePublish } from "@/app_modules/admin/event"; import { adminEvent_funGetListPublish } from "@/app_modules/admin/event/fun"; async function Page() { - const listPublish = await adminEvent_funGetListPublish({ page: 1 }); - return ( <> - + ); } diff --git a/src/app_modules/admin/event/table_status/table_publish.tsx b/src/app_modules/admin/event/table_status/table_publish.tsx index 2e7c1cb0..740fdbdd 100644 --- a/src/app_modules/admin/event/table_status/table_publish.tsx +++ b/src/app_modules/admin/event/table_status/table_publish.tsx @@ -1,12 +1,12 @@ "use client"; +import { apiGetDataEventByStatus } from "@/app/dev/admin/event/_lib/api_fecth_admin_event"; import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event"; import { MODEL_EVENT } from "@/app_modules/event/_lib/interface"; +import { clientLogger } from "@/util/clientLogger"; import { - Box, Button, Center, - Group, Pagination, Paper, ScrollArea, @@ -15,87 +15,115 @@ import { Table, Text, TextInput, - Title, } from "@mantine/core"; -import { IconCircleCheck, IconDetails, IconEyeCheck, IconSearch } from "@tabler/icons-react"; +import { useEffect } from "react"; +import { IconEyeCheck, IconSearch } from "@tabler/icons-react"; import _ from "lodash"; import { useRouter } from "next/navigation"; import { useState } from "react"; +import QRCode from "react-qr-code"; +import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component"; import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate"; import { adminEvent_funGetListPublish } from "../fun"; -import QRCode from "react-qr-code"; -import { useShallowEffect } from "@mantine/hooks"; -import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component"; -import { MainColor } from "@/app_modules/_global/color"; -import { AdminColor } from "@/app_modules/_global/color/color_pallet"; +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; -export default function AdminEvent_TablePublish({ - listPublish, -}: { - listPublish: any; -}) { +export default function AdminEvent_TablePublish() { return ( - <> - - - - - + + + + ); } -function TableStatus({ listPublish }: { listPublish: any }) { +function TableStatus() { const router = useRouter(); - const [data, setData] = useState(listPublish.data); - const [isNPage, setNPage] = useState(listPublish.nPage); - const [isActivePage, setActivePage] = useState(1); + const [data, setData] = useState(null); + const [isNPage, setNPage] = useState(1); + const [activePage, setActivePage] = useState(1); const [isSearch, setSearch] = useState(""); const [eventId, setEventId] = useState(""); const [loading, setLoading] = useState(false); - const [origin, setOrigin] = useState(""); - useShallowEffect(() => { + useEffect(() => { if (typeof window !== "undefined") { - // console.log(window.location.origin); setOrigin(window.location.origin); } - }, [setOrigin]); + }, []); - // async function onLoadOrigin(setOrigin: any) { - // const res = await fetch("/api/origin-url"); - // const result = await res.json(); - // setOrigin(result.origin); - // } + useEffect(() => { + const loadInitialData = async () => { + try { + const response = await apiGetDataEventByStatus({ + status: "Publish", + page: `${activePage}`, + search: isSearch, + }); - async function onSearch(s: string) { - setSearch(s); - const loadData = await adminEvent_funGetListPublish({ - page: 1, - search: s, - }); - setData(loadData.data as any); - setNPage(loadData.nPage); + console.log("Received data:", response.data.data); + console.log("Received nPage:", response.data.nPage); + + if (response && Array.isArray(response.data)) { + setData(response.data.data); + setNPage(response.data.nPage || 1); + } else { + console.error("Invalid data format received:", response); + setData([]); + } + } catch (error) { + clientLogger.error("Error get data table publish", error); + setData([]); + } + }; + + loadInitialData(); + }, [activePage, isSearch]); + + const onSearch = async (searchTerm: string) => { + setSearch(searchTerm); + setActivePage(1); + }; + + const onPageClick = (page: number) => { + setActivePage(page); + }; + + const handleDownloadQR = (id: string, title: string) => { + const svg: any = document.getElementById(id); + const svgData = new XMLSerializer().serializeToString(svg); + const canvas = document.createElement("canvas"); + const ctx: any = canvas.getContext("2d"); + const img = new Image(); + img.onload = () => { + canvas.width = img.width; + canvas.height = img.height; + ctx.drawImage(img, 0, 0); + const pngFile = canvas.toDataURL("image/png"); + const downloadLink = document.createElement("a"); + downloadLink.download = `QRCode ${title}`; + downloadLink.href = `${pngFile}`; + downloadLink.click(); + }; + img.src = `data:image/svg+xml;base64,${btoa(svgData)}`; + }; + + if (!data) { + return ; } - async function onPageClick(p: any) { - setActivePage(p); - const loadData = await adminEvent_funGetListPublish({ - search: isSearch, - page: p, - }); - setData(loadData.data as any); - setNPage(loadData.nPage); - } + const renderTableBody = () => { + if (!Array.isArray(data) || data.length === 0) { + return ( + + +
Belum Ada Data
+ + + ); + } - const TableRows = _.isEmpty(data) ? ( - - -
Belum Ada Data
- - - ) : ( - data.map((e, i) => ( + return data.map((e, i) => (
@@ -108,28 +136,9 @@ function TableStatus({ listPublish }: { listPublish: any }) {
- { - const svg: any = document.getElementById(e.id); - const svgData = new XMLSerializer().serializeToString(svg); - const canvas = document.createElement("canvas"); - const ctx: any = canvas.getContext("2d"); - const img = new Image(); - img.onload = () => { - canvas.width = img.width; - canvas.height = img.height; - ctx.drawImage(img, 0, 0); - const pngFile = canvas.toDataURL("image/png"); - const downloadLink = document.createElement("a"); - downloadLink.download = `QRCode ${e.title}`; - downloadLink.href = `${pngFile}`; - downloadLink.click(); - }; - img.src = `data:image/svg+xml;base64,${btoa(svgData)}`; - }} - /> +
@@ -152,19 +161,17 @@ function TableStatus({ listPublish }: { listPublish: any }) { {e.EventMaster_TipeAcara.name}
-
- {" "} {new Intl.DateTimeFormat("id-ID", { dateStyle: "full", - }).format(e?.tanggal)} + }).format(new Date(e?.tanggal))} ,{" "} {new Intl.DateTimeFormat("id-ID", { timeStyle: "short", - }).format(e?.tanggal)} + }).format(new Date(e?.tanggal))}
@@ -172,20 +179,18 @@ function TableStatus({ listPublish }: { listPublish: any }) {
- {" "} {new Intl.DateTimeFormat("id-ID", { dateStyle: "full", - }).format(e?.tanggalSelesai)} + }).format(new Date(e?.tanggalSelesai))} ,{" "} {new Intl.DateTimeFormat("id-ID", { timeStyle: "short", - }).format(e?.tanggalSelesai)} + }).format(new Date(e?.tanggalSelesai))}
-
- - )) - ); + )); + }; return ( - <> - - } - radius={"xl"} - placeholder="Masukan judul" - onChange={(val) => { - onSearch(val.currentTarget.value); - }} - /> - } - /> - {/* - Publish + + } - radius={"xl"} + radius="xl" placeholder="Masukan judul" - onChange={(val) => { - onSearch(val.currentTarget.value); - }} + value={isSearch} + onChange={(e) => onSearch(e.currentTarget.value)} /> - */} + } + /> - - - - - - - + + +
-
QR Code
-
-
Download QR
-
+ + + + + + + + + + + + + + + {renderTableBody()} +
+
QR Code
+
+
Download QR
+
+
Username
+
+
Judul
+
+
Lokasi
+
+
Tipe Acara
+
+
Tanggal & Waktu Mulai
+
+
Tanggal & Waktu Selesai
+
+
Deskripsi
+
+
Aksi
+
+
- -
Username
- - -
Judul
- - -
Lokasi
- - -
Tipe Acara
- - -
Tanggal & Waktu Mulai
- - -
Tanggal & Waktu Selesai
- - - -
Deskripsi
- - -
Aksi
- - - - {TableRows} - - - -
- { - onPageClick(val); - }} - /> -
-
-
- +
+ +
+ + ); } diff --git a/test/coba.test.ts b/test/coba.test.ts new file mode 100644 index 00000000..2241898c --- /dev/null +++ b/test/coba.test.ts @@ -0,0 +1,9 @@ +import { prisma } from "@/app/lib"; +import { describe, test, expect } from "bun:test"; + +describe("coba test", () => { + test("coba", async () => { + const user = await prisma.user.findMany(); + expect(user).not.toBeEmpty(); + }); +});