Merge pull request #261 from bipproduction/bagas/31-jan-25

fix event admin
This commit is contained in:
Bagasbanuna02
2025-01-31 17:54:47 +08:00
committed by GitHub
12 changed files with 1131 additions and 707 deletions

View File

@@ -1,6 +1,7 @@
import { prisma } from "@/app/lib"; import { prisma } from "@/app/lib";
import backendLogger from "@/util/backendLogger"; import backendLogger from "@/util/backendLogger";
import _ from "lodash"; import _ from "lodash";
import moment from "moment";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
export async function GET( export async function GET(
@@ -19,7 +20,7 @@ export async function GET(
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const search = searchParams.get("search"); const search = searchParams.get("search");
const page = searchParams.get("page"); const page = searchParams.get("page");
const takeData = 1; const takeData = 10;
const skipData = Number(page) * takeData - takeData; const skipData = Number(page) * takeData - takeData;
try { try {
@@ -29,7 +30,7 @@ export async function GET(
if (!page && !search) { if (!page && !search) {
fixData = await prisma.event.findMany({ fixData = await prisma.event.findMany({
orderBy: { orderBy: {
createdAt: "desc", updatedAt: "desc",
}, },
where: { where: {
active: true, active: true,
@@ -38,11 +39,26 @@ export async function GET(
name: fixStatus, name: fixStatus,
}, },
}, },
include: {
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: true,
EventMaster_TipeAcara: true,
},
}); });
} else if (!page && search) { } else if (!page && search) {
fixData = await prisma.event.findMany({ fixData = await prisma.event.findMany({
orderBy: { orderBy: {
createdAt: "desc", updatedAt: "desc",
}, },
where: { where: {
active: true, active: true,
@@ -55,13 +71,53 @@ export async function GET(
mode: "insensitive", mode: "insensitive",
}, },
}, },
include: {
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: true,
EventMaster_TipeAcara: true,
},
}); });
} else if (page && !search) { } else if (page && !search) {
if (fixStatus === "Publish") {
const getAllData = await prisma.event.findMany({
where: {
active: true,
EventMaster_Status: {
name: fixStatus,
},
isArsip: false,
},
});
for (let i of getAllData) {
if (moment(i.tanggalSelesai).diff(moment(), "minutes") < 0) {
await prisma.event.update({
where: {
id: i.id,
},
data: {
isArsip: true,
},
});
}
}
}
const data = await prisma.event.findMany({ const data = await prisma.event.findMany({
take: takeData, take: takeData,
skip: skipData, skip: skipData,
orderBy: { orderBy: {
createdAt: "desc", updatedAt: "desc",
}, },
where: { where: {
active: true, active: true,
@@ -70,12 +126,29 @@ export async function GET(
name: fixStatus, name: fixStatus,
}, },
}, },
include: {
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: true,
EventMaster_TipeAcara: true,
},
}); });
const nCount = await prisma.event.count({ const nCount = await prisma.event.count({
where: { where: {
EventMaster_Status: {
name: fixStatus,
},
active: true, active: true,
eventMaster_StatusId: "1",
isArsip: false, isArsip: false,
}, },
}); });
@@ -85,11 +158,36 @@ export async function GET(
nPage: _.ceil(nCount / takeData), nPage: _.ceil(nCount / takeData),
}; };
} else if (page && search) { } else if (page && search) {
if (fixStatus === "Publish") {
const getAllData = await prisma.event.findMany({
where: {
active: true,
EventMaster_Status: {
name: fixStatus,
},
isArsip: false,
},
});
for (let i of getAllData) {
if (moment(i.tanggalSelesai).diff(moment(), "minutes") < 0) {
await prisma.event.update({
where: {
id: i.id,
},
data: {
isArsip: true,
},
});
}
}
}
const data = await prisma.event.findMany({ const data = await prisma.event.findMany({
take: takeData, take: takeData,
skip: skipData, skip: skipData,
orderBy: { orderBy: {
createdAt: "desc", updatedAt: "desc",
}, },
where: { where: {
active: true, active: true,
@@ -102,12 +200,26 @@ export async function GET(
mode: "insensitive", mode: "insensitive",
}, },
}, },
include: {
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: true,
EventMaster_TipeAcara: true,
},
}); });
const nCount = await prisma.event.count({ const nCount = await prisma.event.count({
where: { where: {
active: true, active: true,
eventMaster_StatusId: "1",
isArsip: false, isArsip: false,
title: { title: {
contains: search, contains: search,

View File

@@ -0,0 +1,201 @@
import { prisma } from "@/app/lib";
import backendLogger from "@/util/backendLogger";
import _ from "lodash";
import { NextResponse } from "next/server";
export async function GET(request: Request) {
const method = request.method;
if (method !== "GET") {
return NextResponse.json(
{ success: false, message: "Method not allowed" },
{ status: 405 }
);
}
const { searchParams } = new URL(request.url);
const search = searchParams.get("search");
const page = searchParams.get("page");
const takeData = 10;
const skipData = Number(page) * takeData - takeData;
try {
let fixData;
if (!page && !search) {
fixData = await prisma.event.findMany({
orderBy: {
createdAt: "desc",
},
where: {
EventMaster_Status: {
name: "Publish",
},
isArsip: true,
},
include: {
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: true,
EventMaster_TipeAcara: true,
},
});
} else if (!page && search) {
fixData = await prisma.event.findMany({
orderBy: {
createdAt: "desc",
},
where: {
EventMaster_Status: {
name: "Publish",
},
isArsip: true,
title: {
contains: search,
mode: "insensitive",
},
},
include: {
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: true,
EventMaster_TipeAcara: true,
},
});
} else if (page && !search) {
const data = await prisma.event.findMany({
take: takeData,
skip: skipData,
orderBy: {
createdAt: "desc",
},
where: {
EventMaster_Status: {
name: "Publish",
},
isArsip: true,
},
include: {
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: true,
EventMaster_TipeAcara: true,
},
});
const nCount = await prisma.event.count({
where: {
active: true,
isArsip: true,
EventMaster_Status: {
name: "Publish",
},
},
});
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: {
EventMaster_Status: {
name: "Publish",
},
isArsip: true,
title: {
contains: search,
mode: "insensitive",
},
},
include: {
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: true,
EventMaster_TipeAcara: true,
},
});
const nCount = await prisma.event.count({
where: {
active: true,
isArsip: true,
EventMaster_Status: {
name: "Publish",
},
title: {
contains: search,
mode: "insensitive",
},
},
});
fixData = {
data,
nPage: _.ceil(nCount / takeData),
};
}
return NextResponse.json(
{
success: true,
message: "Success get data riwayat event",
data: fixData,
},
{ status: 200 }
);
} catch (error) {
backendLogger.error("Error get data riwayat event >>", error);
return NextResponse.json(
{
success: false,
message: "Error get data riwayat event",
reason: (error as Error).message,
},
{ status: 500 }
);
} finally {
await prisma.$disconnect();
}
}

View File

@@ -1,11 +1,12 @@
export { export {
apiGetEventStatusCountDashboard, apiGetAdminEventStatusCountDashboard as apiGetEventStatusCountDashboard,
apiGetEventTipeAcara, apiGetAdminEventCountTipeAcara as apiGetEventTipeAcara,
apiGetEventRiwayatCount, apiGetAdminEventRiwayatCount as apiGetEventRiwayatCount,
apiGetDataEventByStatus, apiGetAdminEventByStatus as apiGetDataEventByStatus,
apiGetAdminEventRiwayat,
}; };
const apiGetEventStatusCountDashboard = async ({ const apiGetAdminEventStatusCountDashboard = async ({
name, name,
}: { }: {
name: "Publish" | "Review" | "Reject"; name: "Publish" | "Review" | "Reject";
@@ -26,7 +27,7 @@ const apiGetEventStatusCountDashboard = async ({
return await response.json().catch(() => null); return await response.json().catch(() => null);
}; };
const apiGetEventRiwayatCount = async () => { const apiGetAdminEventRiwayatCount = async () => {
const { token } = await fetch("/api/get-cookie").then((res) => res.json()); 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);
@@ -43,7 +44,7 @@ const apiGetEventRiwayatCount = async () => {
return await response.json().catch(() => null); return await response.json().catch(() => null);
}; };
const apiGetEventTipeAcara = async () => { const apiGetAdminEventCountTipeAcara = async () => {
const { token } = await fetch("/api/get-cookie").then((res) => res.json()); 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);
@@ -60,7 +61,7 @@ const apiGetEventTipeAcara = async () => {
return await response.json().catch(() => null); return await response.json().catch(() => null);
}; };
const apiGetDataEventByStatus = async ({ const apiGetAdminEventByStatus = async ({
status, status,
page, page,
search, search,
@@ -74,7 +75,35 @@ const apiGetDataEventByStatus = async ({
const isPage = page ? `?page=${page}` : ""; const isPage = page ? `?page=${page}` : "";
const isSearch = search ? `&search=${search}` : ""; const isSearch = search ? `&search=${search}` : "";
const respone = await fetch(`/api/admin/event/${status}${isPage}${isSearch}`, { 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);
};
const apiGetAdminEventRiwayat = async ({
page,
search,
}: {
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 response = await fetch(`/api/admin/event/riwayat${isPage}${isSearch}`, {
method: "GET",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
@@ -83,5 +112,5 @@ const apiGetDataEventByStatus = async ({
}, },
}); });
return await respone.json().catch(() => null); return await response.json().catch(() => null);
}; };

View File

@@ -2,11 +2,11 @@ import { AdminEvent_Riwayat } from "@/app_modules/admin/event";
import { adminEvent_funGetListAllRiwayat } from "@/app_modules/admin/event/fun/get/get_list_all_riwayat"; import { adminEvent_funGetListAllRiwayat } from "@/app_modules/admin/event/fun/get/get_list_all_riwayat";
export default async function Page() { export default async function Page() {
const listRiwayat = await adminEvent_funGetListAllRiwayat({ page: 1 }); // const listRiwayat = await adminEvent_funGetListAllRiwayat({ page: 1 });
return ( return (
<> <>
<AdminEvent_Riwayat listRiwayat={listRiwayat} /> <AdminEvent_Riwayat />
</> </>
); );
} }

View File

@@ -1,5 +1,4 @@
import { AdminEvent_TablePublish } from "@/app_modules/admin/event"; import { AdminEvent_TablePublish } from "@/app_modules/admin/event";
import { adminEvent_funGetListPublish } from "@/app_modules/admin/event/fun";
async function Page() { async function Page() {
return ( return (

View File

@@ -2,11 +2,10 @@ import { AdminEvent_TableReject } from "@/app_modules/admin/event";
import { adminEvent_funGetListReject } from "@/app_modules/admin/event/fun"; import { adminEvent_funGetListReject } from "@/app_modules/admin/event/fun";
export default async function Page() { export default async function Page() {
const listReject = await adminEvent_funGetListReject({ page: 1 });
return ( return (
<> <>
<AdminEvent_TableReject listReject={listReject as any} /> <AdminEvent_TableReject />
</> </>
); );
} }

View File

@@ -1,12 +1,10 @@
import { AdminEvent_TableReview } from "@/app_modules/admin/event"; import { AdminEvent_TableReview } from "@/app_modules/admin/event";
import { adminEvent_funGetListReview } from "@/app_modules/admin/event/fun";
export default async function Page() { export default async function Page() {
const listReview = await adminEvent_funGetListReview({ page: 1 });
return ( return (
<> <>
<AdminEvent_TableReview listData={listReview as any} /> <AdminEvent_TableReview />
</> </>
); );
} }

View File

@@ -1,3 +1,4 @@
import { apiGetDataEventByStatus } from "@/app/dev/admin/event/_lib/api_fecth_admin_event";
import { import {
gs_adminEvent_triggerReview, gs_adminEvent_triggerReview,
IRealtimeData, IRealtimeData,
@@ -8,10 +9,12 @@ import {
ComponentGlobal_NotifikasiGagal, ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan, ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global"; } from "@/app_modules/_global/notif_global";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
import { MODEL_EVENT } from "@/app_modules/event/_lib/interface"; import { MODEL_EVENT } from "@/app_modules/event/_lib/interface";
import { event_checkStatus } from "@/app_modules/event/fun/get/fun_check_status_by_id";
import { clientLogger } from "@/util/clientLogger";
import { import {
Affix, Affix,
Box,
Button, Button,
Center, Center,
Group, Group,
@@ -26,7 +29,6 @@ import {
Text, Text,
Textarea, Textarea,
TextInput, TextInput,
Title,
} from "@mantine/core"; } from "@mantine/core";
import { useDisclosure, useShallowEffect } from "@mantine/hooks"; import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { import {
@@ -39,25 +41,19 @@ import { useAtom } from "jotai";
import moment from "moment"; import moment from "moment";
import { useState } from "react"; import { useState } from "react";
import { WibuRealtime } from "wibu-pkg"; import { WibuRealtime } from "wibu-pkg";
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
import { ComponentAdminGlobal_NotifikasiBerhasil } from "../../_admin_global/admin_notifikasi/notifikasi_berhasil"; import { ComponentAdminGlobal_NotifikasiBerhasil } from "../../_admin_global/admin_notifikasi/notifikasi_berhasil";
import { ComponentAdminGlobal_NotifikasiGagal } from "../../_admin_global/admin_notifikasi/notifikasi_gagal"; import { ComponentAdminGlobal_NotifikasiGagal } from "../../_admin_global/admin_notifikasi/notifikasi_gagal";
import { ComponentAdminGlobal_NotifikasiPeringatan } from "../../_admin_global/admin_notifikasi/notifikasi_peringatan";
import adminNotifikasi_funCreateToUser from "../../notifikasi/fun/create/fun_create_notif_user"; import adminNotifikasi_funCreateToUser from "../../notifikasi/fun/create/fun_create_notif_user";
import { adminEvent_funGetListReview } from "../fun"; import { adminEvent_funGetListReview } from "../fun";
import { AdminEvent_funEditStatusPublishById } from "../fun/edit/fun_edit_status_publish_by_id"; import { AdminEvent_funEditStatusPublishById } from "../fun/edit/fun_edit_status_publish_by_id";
import { AdminEvent_funEditCatatanById } from "../fun/edit/fun_edit_status_reject_by_id"; import { AdminEvent_funEditCatatanById } from "../fun/edit/fun_edit_status_reject_by_id";
import { event_checkStatus } from "@/app_modules/event/fun/get/fun_check_status_by_id";
import { ComponentAdminGlobal_NotifikasiPeringatan } from "../../_admin_global/admin_notifikasi/notifikasi_peringatan";
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
import { AdminColor } from "@/app_modules/_global/color/color_pallet";
export default function AdminEvent_ComponentTableReview({ export default function AdminEvent_ComponentTableReview() {
listData, const [data, setData] = useState<MODEL_EVENT[] | null>(null);
}: { const [isNPage, setNPage] = useState<number>(1);
listData: any; const [activePage, setActivePage] = useState(1);
}) {
const [data, setData] = useState<MODEL_EVENT[]>(listData.data);
const [isNPage, setNPage] = useState(listData.nPage);
const [isActivePage, setActivePage] = useState(1);
const [isSearch, setSearch] = useState(""); const [isSearch, setSearch] = useState("");
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isModal, setModal] = useState(false); const [isModal, setModal] = useState(false);
@@ -72,37 +68,41 @@ export default function AdminEvent_ComponentTableReview({
const [isShowReload, setIsShowReload] = useState(false); const [isShowReload, setIsShowReload] = useState(false);
useShallowEffect(() => { useShallowEffect(() => {
if (isAdminTriggerReview) { loadInitialData();
setIsShowReload(true); }, [activePage, isSearch]);
const loadInitialData = async () => {
try {
const response = await apiGetDataEventByStatus({
status: "Review",
page: `${activePage}`,
search: isSearch,
});
if (response?.success && response?.data?.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([]);
} }
}, [isAdminTriggerReview, setIsShowReload]); };
async function onSearch(s: string) { const onSearch = async (searchTerm: string) => {
setSearch(s); setSearch(searchTerm);
const loadData = await adminEvent_funGetListReview({ setActivePage(1);
page: 1, };
search: s,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
async function onPageClick(p: any) { const onPageClick = (page: number) => {
setActivePage(p); setActivePage(page);
const loadData = await adminEvent_funGetListReview({ };
search: isSearch,
page: p,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
async function onLoadData() { async function onLoadData() {
const loadData = await adminEvent_funGetListReview({ loadInitialData();
page: 1,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
setIsLoading(false); setIsLoading(false);
setIsShowReload(false); setIsShowReload(false);
setIsAdminTriggerReview(false); setIsAdminTriggerReview(false);
@@ -125,7 +125,7 @@ export default function AdminEvent_ComponentTableReview({
const res = await AdminEvent_funEditStatusPublishById(eventId, "1"); const res = await AdminEvent_funEditStatusPublishById(eventId, "1");
if (res.status === 200) { if (res.status === 200) {
setIsLoading(true) setIsLoading(true);
const dataNotifikasi: IRealtimeData = { const dataNotifikasi: IRealtimeData = {
appId: res.data?.id as any, appId: res.data?.id as any,
status: res.data?.EventMaster_Status?.name as any, status: res.data?.EventMaster_Status?.name as any,
@@ -153,21 +153,34 @@ export default function AdminEvent_ComponentTableReview({
}); });
} }
const loadData = await adminEvent_funGetListReview({ try {
search: isSearch, const response = await apiGetDataEventByStatus({
page: isActivePage, status: "Review",
}); page: `${activePage}`,
setData(loadData.data as any); search: isSearch,
setNPage(loadData.nPage); });
if (response?.success && response?.data?.data) {
console.log("review >>", response.data.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([]);
}
ComponentAdminGlobal_NotifikasiBerhasil("Berhasil update status"); ComponentAdminGlobal_NotifikasiBerhasil("Berhasil update status");
} else { } else {
setModal(false) setModal(false);
setIsLoading(false) setIsLoading(false);
ComponentAdminGlobal_NotifikasiGagal(res.message); ComponentAdminGlobal_NotifikasiGagal(res.message);
} }
} else { } else {
setModal(false) setModal(false);
ComponentAdminGlobal_NotifikasiPeringatan( ComponentAdminGlobal_NotifikasiPeringatan(
"Review di batalkan oleh user, reload halaman review !" "Review di batalkan oleh user, reload halaman review !"
); );
@@ -205,12 +218,26 @@ export default function AdminEvent_ComponentTableReview({
}); });
} }
const loadData = await adminEvent_funGetListReview({ try {
search: isSearch, const response = await apiGetDataEventByStatus({
page: isActivePage, status: "Review",
}); page: `${activePage}`,
setData(loadData.data as any); search: isSearch,
setNPage(loadData.nPage); });
if (response?.success && response?.data?.data) {
console.log("review >>", response.data.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([]);
}
ComponentGlobal_NotifikasiBerhasil(res.message); ComponentGlobal_NotifikasiBerhasil(res.message);
close(); close();
} else { } else {
@@ -218,220 +245,224 @@ export default function AdminEvent_ComponentTableReview({
} }
} }
const TableRows = data.map((e, i) => ( const renderTableBody = () => {
<tr key={i}> if (!Array.isArray(data) || data.length === 0) {
<td> return (
<Center w={200}> <tr>
<Text>{e?.Author?.username}</Text> <td colSpan={12}>
</Center> <Center>
</td> <Text color={"gray"}>Tidak ada data</Text>
<td> </Center>
<Center w={200}> </td>
<Text lineClamp={2}>{e.title}</Text> </tr>
</Center> );
</td> }
<td>
<Center w={200}>
<Text>{e.lokasi}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.EventMaster_TipeAcara.name}</Text>
</Center>
</td>
<td> return data.map((e, i) => (
<Center w={200}> <tr key={i}>
<Text align="center"> <td>
{" "} <Center w={200}>
{new Intl.DateTimeFormat("id-ID", { <Text>{e?.Author?.username}</Text>
dateStyle: "full", </Center>
}).format(e?.tanggal)} </td>
,{" "} <td>
<Text span inherit> <Center w={200}>
<Text lineClamp={2}>{e.title}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.lokasi}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.EventMaster_TipeAcara.name}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text align="center">
{new Intl.DateTimeFormat("id-ID", { {new Intl.DateTimeFormat("id-ID", {
timeStyle: "short", dateStyle: "full",
}).format(e?.tanggal)} }).format(new Date(e?.tanggal))}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(new Date(e?.tanggal))}
</Text>
</Text> </Text>
</Text> </Center>
</Center> </td>
</td> <td>
<td> <Center w={200}>
<Center w={200}> <Text align="center">
<Text align="center">
{" "}
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(e?.tanggalSelesai)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", { {new Intl.DateTimeFormat("id-ID", {
timeStyle: "short", dateStyle: "full",
}).format(e?.tanggalSelesai)} }).format(new Date(e?.tanggalSelesai))}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(new Date(e?.tanggalSelesai))}
</Text>
</Text> </Text>
</Text> </Center>
</Center> </td>
</td>
<td> <td>
<Center w={400}> <Center w={400}>
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan"> <Spoiler
{e.deskripsi} hideLabel="sembunyikan"
</Spoiler> maxHeight={50}
</Center> showLabel="tampilkan"
</td>
<td>
<Center>
<Stack>
<Button
color={"green"}
leftIcon={<IconCircleCheck />}
radius={"xl"}
onClick={() =>
onPublish({
eventId: e.id,
tanggal: e.tanggal,
})
}
> >
Publish {e.deskripsi}
</Button> </Spoiler>
<Button </Center>
color={"red"} </td>
leftIcon={<IconBan />}
radius={"xl"}
onClick={async () => {
const checkStatus = await event_checkStatus({ id: e.id });
if (checkStatus) { <td>
open(); <Center>
setEventId(e.id); <Stack>
} else { <Button
ComponentAdminGlobal_NotifikasiPeringatan( color={"green"}
"Review di batalkan oleh user, muat kembali halaman ini !" leftIcon={<IconCircleCheck />}
); radius={"xl"}
onClick={() =>
onPublish({
eventId: e.id,
tanggal: e.tanggal,
})
} }
}} >
> Publish
Reject </Button>
</Button> <Button
</Stack> color={"red"}
</Center> leftIcon={<IconBan />}
</td> radius={"xl"}
</tr> onClick={async () => {
)); const checkStatus = await event_checkStatus({ id: e.id });
if (checkStatus) {
open();
setEventId(e.id);
} else {
ComponentAdminGlobal_NotifikasiPeringatan(
"Review di batalkan oleh user, muat kembali halaman ini !"
);
}
}}
>
Reject
</Button>
</Stack>
</Center>
</td>
</tr>
));
};
return ( return (
<> <>
<Stack spacing={"xs"} h={"100%"}> <Stack spacing={"xs"} h={"100%"}>
<ComponentAdminGlobal_TitlePage <ComponentAdminGlobal_TitlePage
name="Review" name="Review"
color={AdminColor.orange} color={"orange.5"}
component={ component={
<TextInput <TextInput
icon={<IconSearch size={20} />} disabled={!data}
radius={"xl"} icon={<IconSearch size={20} />}
placeholder="Masukan judul" radius={"xl"}
onChange={(val) => { placeholder="Masukan judul"
onSearch(val.currentTarget.value);
}}
/>
}
/>
{/* <Group
position="apart"
bg={"orange.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4}>Review</Title>
<TextInput
icon={<IconSearch size={20} />}
radius={"xl"}
placeholder="Masukan judul"
onChange={(val) => {
onSearch(val.currentTarget.value);
}}
/>
</Group> */}
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
{isShowReload && (
<Affix position={{ top: rem(200) }} w={"100%"}>
<Center>
<Button
style={{
transition: "0.5s",
border: `1px solid ${AccentColor.skyblue}`,
}}
bg={AccentColor.blue}
loaderPosition="center"
loading={isLoading}
radius={"xl"}
opacity={0.8}
onClick={() => onLoadData()}
leftIcon={<IconRefresh />}
>
Update Data
</Button>
</Center>
</Affix>
)}
<ScrollArea w={"100%"} h={"90%"}>
<Table
verticalSpacing={"md"}
horizontalSpacing={"md"}
p={"md"}
w={1500}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>Username</Center>
</th>
<th>
<Center>Judul</Center>
</th>
<th>
<Center>Lokasi</Center>
</th>
<th>
<Center>Tipe Acara</Center>
</th>
<th>
<Center>Tanggal & Waktu Mulai</Center>
</th>
<th>
<Center>Tanggal & Waktu Selesai</Center>
</th>
<th>
<Center>Deskripsi</Center>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{TableRows}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}>
<Pagination
value={isActivePage}
total={isNPage}
onChange={(val) => { onChange={(val) => {
onPageClick(val); onSearch(val.currentTarget.value);
}} }}
/> />
</Center> }
</Paper> />
{!data ? (
<CustomSkeleton height={"80vh"} width="100%" />
) : (
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
{isShowReload && (
<Affix position={{ top: rem(200) }} w={"100%"}>
<Center>
<Button
style={{
transition: "0.5s",
border: `1px solid ${AccentColor.skyblue}`,
}}
bg={AccentColor.blue}
loaderPosition="center"
loading={isLoading}
radius={"xl"}
opacity={0.8}
onClick={() => onLoadData()}
leftIcon={<IconRefresh />}
>
Update Data
</Button>
</Center>
</Affix>
)}
<ScrollArea w={"100%"} h={"90%"}>
<Table
verticalSpacing={"md"}
horizontalSpacing={"md"}
p={"md"}
w={1500}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>Username</Center>
</th>
<th>
<Center>Judul</Center>
</th>
<th>
<Center>Lokasi</Center>
</th>
<th>
<Center>Tipe Acara</Center>
</th>
<th>
<Center>Tanggal & Waktu Mulai</Center>
</th>
<th>
<Center>Tanggal & Waktu Selesai</Center>
</th>
<th>
<Center>Deskripsi</Center>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{renderTableBody()}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}>
<Pagination
value={activePage}
total={isNPage}
onChange={(val) => {
onPageClick(val);
}}
/>
</Center>
</Paper>
)}
</Stack> </Stack>
<Modal <Modal
@@ -468,7 +499,8 @@ export default function AdminEvent_ComponentTableReview({
</Group> </Group>
</Stack> </Stack>
</Modal> </Modal>
<Modal
{/* <Modal
opened={isModal} opened={isModal}
title="Anda Yakin Ingin Mempublish Event Ini?" title="Anda Yakin Ingin Mempublish Event Ini?"
onClose={() => setModal(false)} onClose={() => setModal(false)}
@@ -491,20 +523,7 @@ export default function AdminEvent_ComponentTableReview({
</Button> </Button>
</Group> </Group>
</Stack> </Stack>
</Modal> </Modal> */}
</> </>
); );
function ModalPublish({
eventId,
tanggal,
}: {
eventId: string;
tanggal: Date;
}) {
return (
<Stack>
</Stack>
)
}
} }

View File

@@ -2,6 +2,7 @@
import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event"; import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event";
import { MODEL_EVENT } from "@/app_modules/event/_lib/interface"; import { MODEL_EVENT } from "@/app_modules/event/_lib/interface";
import { clientLogger } from "@/util/clientLogger";
import { import {
Button, Button,
Center, Center,
@@ -16,139 +17,166 @@ import {
TextInput, TextInput,
Title, Title,
} from "@mantine/core"; } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconCircleCheck, IconSearch } from "@tabler/icons-react"; import { IconCircleCheck, IconSearch } from "@tabler/icons-react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate"; import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate";
import { adminEvent_funGetListAllRiwayat } from "../fun"; import { apiGetAdminEventRiwayat } from "@/app/dev/admin/event/_lib/api_fecth_admin_event";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
export default function AdminEvent_Riwayat({ export default function AdminEvent_Riwayat() {
listRiwayat,
}: {
listRiwayat: any;
}) {
return ( return (
<> <>
<Stack> <Stack>
<ComponentAdminGlobal_HeaderTamplate name="Event: Riwayat" /> <ComponentAdminGlobal_HeaderTamplate name="Event: Riwayat" />
<DetailRiwayat listRiwayat={listRiwayat} /> <DetailRiwayat />
</Stack> </Stack>
</> </>
); );
} }
function DetailRiwayat({ listRiwayat }: { listRiwayat: any }) { function DetailRiwayat() {
const router = useRouter(); const router = useRouter();
const [eventId, setEventId] = useState(""); const [eventId, setEventId] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [data, setData] = useState<MODEL_EVENT[]>(listRiwayat.data); const [data, setData] = useState<MODEL_EVENT[] | null>(null);
const [isNPage, setNPage] = useState(listRiwayat.nPage); const [isNPage, setNPage] = useState(1);
const [isActivePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
const [isSearch, setSearch] = useState(""); const [isSearch, setSearch] = useState("");
async function onSearch(s: string) { useShallowEffect(() => {
setSearch(s); const loadInitialData = async () => {
const loadData = await adminEvent_funGetListAllRiwayat({ try {
page: 1, const response = await apiGetAdminEventRiwayat({
search: s, page: `${activePage}`,
}); search: isSearch,
setData(loadData.data as any); });
setNPage(loadData.nPage);
}
async function onPageClick(p: any) { if (response?.success && response?.data?.data) {
setActivePage(p); setData(response.data.data);
const loadData = await adminEvent_funGetListAllRiwayat({ setNPage(response.data.nPage || 1);
search: isSearch, } else {
page: p, console.error("Invalid data format received:", response);
}); setData([]);
setData(loadData.data as any); }
setNPage(loadData.nPage); } catch (error) {
} clientLogger.error("Error get data table publish", error);
setData([]);
}
};
const TableRows = data.map((e, i) => ( loadInitialData();
<tr key={i}> }, [activePage, isSearch]);
<td>
<Button
loaderPosition="center"
loading={e.id === eventId && loading ? true : false}
color={"green"}
leftIcon={<IconCircleCheck />}
radius={"xl"}
onClick={() => {
setEventId(e.id);
setLoading(true);
router.push(RouterAdminEvent.detail_peserta + e.id);
}}
>
Lihat Peserta
</Button>
</td>
<td> const onSearch = async (searchTerm: string) => {
<Center w={200}> setSearch(searchTerm);
<Text>{e?.Author?.username}</Text> setActivePage(1);
</Center> };
</td>
<td>
<Center w={200}>
<Text lineClamp={2}>{e.title}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.lokasi}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.EventMaster_TipeAcara.name}</Text>
</Center>
</td>
<td> const onPageClick = (page: number) => {
<Center w={200}> setActivePage(page);
<Text align="center"> };
{" "}
{new Intl.DateTimeFormat("id-ID", { const renderTableBody = () => {
dateStyle: "full", if (!Array.isArray(data) || data.length === 0) {
}).format(e?.tanggal)} return (
,{" "} <tr>
<Text span inherit> <td colSpan={12}>
<Center>
<Text color={"gray"}>Tidak ada data</Text>
</Center>
</td>
</tr>
);
}
return data.map((e, i) => (
<tr key={i}>
<td>
<Button
loaderPosition="center"
loading={e.id === eventId && loading ? true : false}
color={"green"}
leftIcon={<IconCircleCheck />}
radius={"xl"}
onClick={() => {
setEventId(e.id);
setLoading(true);
router.push(RouterAdminEvent.detail_peserta + e.id);
}}
>
Lihat Peserta
</Button>
</td>
<td>
<Center w={200}>
<Text>{e?.Author?.username}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text lineClamp={2}>{e.title}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.lokasi}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.EventMaster_TipeAcara.name}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text align="center">
{new Intl.DateTimeFormat("id-ID", { {new Intl.DateTimeFormat("id-ID", {
timeStyle: "short", dateStyle: "full",
}).format(e?.tanggal)} }).format(new Date(e?.tanggal))}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(new Date(e?.tanggal))}
</Text>
</Text> </Text>
</Text> </Center>
</Center> </td>
</td> <td>
<td> <Center w={200}>
<Center w={200}> <Text align="center">
<Text align="center">
{" "}
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(e?.tanggalSelesai)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", { {new Intl.DateTimeFormat("id-ID", {
timeStyle: "short", dateStyle: "full",
}).format(e?.tanggalSelesai)} }).format(new Date(e?.tanggalSelesai))}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(new Date(e?.tanggalSelesai))}
</Text>
</Text> </Text>
</Text> </Center>
</Center> </td>
</td>
<td> <td>
<Center w={400}> <Center w={400}>
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan"> <Spoiler
{e.deskripsi} hideLabel="sembunyikan"
</Spoiler> maxHeight={50}
</Center> showLabel="tampilkan"
</td> >
</tr> {e.deskripsi}
)); </Spoiler>
</Center>
</td>
</tr>
));
};
return ( return (
<> <>
@@ -170,58 +198,62 @@ function DetailRiwayat({ listRiwayat }: { listRiwayat: any }) {
/> />
</Group> </Group>
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}> {!data ? (
<ScrollArea w={"100%"} h={"90%"}> <CustomSkeleton height={"80vh"} width="100%" />
<Table ) : (
verticalSpacing={"md"} <Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
horizontalSpacing={"md"} <ScrollArea w={"100%"} h={"90%"}>
p={"md"} <Table
w={"100%"} verticalSpacing={"md"}
striped horizontalSpacing={"md"}
highlightOnHover p={"md"}
> w={"100%"}
<thead> striped
<tr> highlightOnHover
<th> >
<Center>Aksi</Center> <thead>
</th> <tr>
<th> <th>
<Center>Username</Center> <Center>Aksi</Center>
</th> </th>
<th> <th>
<Center>Judul</Center> <Center>Username</Center>
</th> </th>
<th> <th>
<Center>Lokasi</Center> <Center>Judul</Center>
</th> </th>
<th> <th>
<Center>Tipe Acara</Center> <Center>Lokasi</Center>
</th> </th>
<th> <th>
<Center>Tanggal & Waktu Mulai</Center> <Center>Tipe Acara</Center>
</th> </th>
<th> <th>
<Center>Tanggal & Waktu Selesai</Center> <Center>Tanggal & Waktu Mulai</Center>
</th> </th>
<th> <th>
<Center>Deskripsi</Center> <Center>Tanggal & Waktu Selesai</Center>
</th> </th>
</tr> <th>
</thead> <Center>Deskripsi</Center>
<tbody>{TableRows}</tbody> </th>
</Table> </tr>
</ScrollArea> </thead>
<tbody>{renderTableBody()}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}> <Center mt={"xl"}>
<Pagination <Pagination
value={isActivePage} value={activePage}
total={isNPage} total={isNPage}
onChange={(val) => { onChange={(val) => {
onPageClick(val); onPageClick(val);
}} }}
/> />
</Center> </Center>
</Paper> </Paper>
)}
</Stack> </Stack>
</> </>
); );

View File

@@ -2,6 +2,7 @@
import { apiGetDataEventByStatus } from "@/app/dev/admin/event/_lib/api_fecth_admin_event"; import { apiGetDataEventByStatus } from "@/app/dev/admin/event/_lib/api_fecth_admin_event";
import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event"; import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
import { MODEL_EVENT } from "@/app_modules/event/_lib/interface"; import { MODEL_EVENT } from "@/app_modules/event/_lib/interface";
import { clientLogger } from "@/util/clientLogger"; import { clientLogger } from "@/util/clientLogger";
import { import {
@@ -16,16 +17,13 @@ import {
Text, Text,
TextInput, TextInput,
} from "@mantine/core"; } from "@mantine/core";
import { useEffect } from "react"; import { useShallowEffect } from "@mantine/hooks";
import { IconEyeCheck, IconSearch } from "@tabler/icons-react"; import { IconEyeCheck, IconSearch } from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
import QRCode from "react-qr-code"; import QRCode from "react-qr-code";
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component"; import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate"; import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate";
import { adminEvent_funGetListPublish } from "../fun";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
export default function AdminEvent_TablePublish() { export default function AdminEvent_TablePublish() {
return ( return (
@@ -46,13 +44,13 @@ function TableStatus() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [origin, setOrigin] = useState(""); const [origin, setOrigin] = useState("");
useEffect(() => { useShallowEffect(() => {
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
setOrigin(window.location.origin); setOrigin(window.location.origin);
} }
}, []); }, []);
useEffect(() => { useShallowEffect(() => {
const loadInitialData = async () => { const loadInitialData = async () => {
try { try {
const response = await apiGetDataEventByStatus({ const response = await apiGetDataEventByStatus({
@@ -61,10 +59,7 @@ function TableStatus() {
search: isSearch, search: isSearch,
}); });
console.log("Received data:", response.data.data); if (response?.success && response?.data?.data) {
console.log("Received nPage:", response.data.nPage);
if (response && Array.isArray(response.data)) {
setData(response.data.data); setData(response.data.data);
setNPage(response.data.nPage || 1); setNPage(response.data.nPage || 1);
} else { } else {
@@ -108,16 +103,14 @@ function TableStatus() {
img.src = `data:image/svg+xml;base64,${btoa(svgData)}`; img.src = `data:image/svg+xml;base64,${btoa(svgData)}`;
}; };
if (!data) {
return <CustomSkeleton height={100} width="100%" />;
}
const renderTableBody = () => { const renderTableBody = () => {
if (!Array.isArray(data) || data.length === 0) { if (!Array.isArray(data) || data.length === 0) {
return ( return (
<tr> <tr>
<td colSpan={12}> <td colSpan={12}>
<Center>Belum Ada Data</Center> <Center>
<Text color={"gray"}>Tidak ada data</Text>
</Center>
</td> </td>
</tr> </tr>
); );
@@ -158,9 +151,10 @@ function TableStatus() {
</td> </td>
<td> <td>
<Center w={200}> <Center w={200}>
<Text>{e.EventMaster_TipeAcara.name}</Text> <Text>{e.EventMaster_TipeAcara?.name}</Text>
</Center> </Center>
</td> </td>
<td> <td>
<Center w={200}> <Center w={200}>
<Text align="center"> <Text align="center">
@@ -191,6 +185,7 @@ function TableStatus() {
</Text> </Text>
</Center> </Center>
</td> </td>
<td> <td>
<Center w={400}> <Center w={400}>
<Spoiler <Spoiler
@@ -202,6 +197,7 @@ function TableStatus() {
</Spoiler> </Spoiler>
</Center> </Center>
</td> </td>
<td> <td>
<Button <Button
loaderPosition="center" loaderPosition="center"
@@ -229,6 +225,7 @@ function TableStatus() {
color="green" color="green"
component={ component={
<TextInput <TextInput
disabled={!data}
icon={<IconSearch size={20} />} icon={<IconSearch size={20} />}
radius="xl" radius="xl"
placeholder="Masukan judul" placeholder="Masukan judul"
@@ -238,62 +235,66 @@ function TableStatus() {
} }
/> />
<Paper p="md" withBorder shadow="lg" h="80vh"> {!data ? (
<ScrollArea w="100%" h="90%"> <CustomSkeleton height={"80vh"} width="100%" />
<Table ) : (
verticalSpacing="md" <Paper p="md" withBorder shadow="lg" h="80vh">
horizontalSpacing="md" <ScrollArea w="100%" h="90%">
p="md" <Table
w={1500} verticalSpacing="md"
striped horizontalSpacing="md"
highlightOnHover p="md"
> w={1500}
<thead> striped
<tr> highlightOnHover
<th> >
<Center>QR Code</Center> <thead>
</th> <tr>
<th> <th>
<Center>Download QR</Center> <Center>QR Code</Center>
</th> </th>
<th> <th>
<Center>Username</Center> <Center>Download QR</Center>
</th> </th>
<th> <th>
<Center>Judul</Center> <Center>Username</Center>
</th> </th>
<th> <th>
<Center>Lokasi</Center> <Center>Judul</Center>
</th> </th>
<th> <th>
<Center>Tipe Acara</Center> <Center>Lokasi</Center>
</th> </th>
<th> <th>
<Center>Tanggal & Waktu Mulai</Center> <Center>Tipe Acara</Center>
</th> </th>
<th> <th>
<Center>Tanggal & Waktu Selesai</Center> <Center>Tanggal & Waktu Mulai</Center>
</th> </th>
<th> <th>
<Center>Deskripsi</Center> <Center>Tanggal & Waktu Selesai</Center>
</th> </th>
<th> <th>
<Center>Aksi</Center> <Center>Deskripsi</Center>
</th> </th>
</tr> <th>
</thead> <Center>Aksi</Center>
<tbody>{renderTableBody()}</tbody> </th>
</Table> </tr>
</ScrollArea> </thead>
<tbody>{renderTableBody()}</tbody>
</Table>
</ScrollArea>
<Center mt="xl"> <Center mt="xl">
<Pagination <Pagination
value={activePage} value={activePage}
total={isNPage} total={isNPage}
onChange={onPageClick} onChange={onPageClick}
/> />
</Center> </Center>
</Paper> </Paper>
)}
</Stack> </Stack>
); );
} }

View File

@@ -18,7 +18,7 @@ import {
} from "@mantine/core"; } from "@mantine/core";
import { IconPencilPlus, IconSearch } from "@tabler/icons-react"; import { IconPencilPlus, IconSearch } from "@tabler/icons-react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useDisclosure } from "@mantine/hooks"; import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal"; import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import { MODEL_EVENT } from "@/app_modules/event/_lib/interface"; import { MODEL_EVENT } from "@/app_modules/event/_lib/interface";
@@ -29,52 +29,65 @@ import { AdminEvent_funEditCatatanById } from "../fun/edit/fun_edit_status_rejec
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component"; import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
import { MainColor } from "@/app_modules/_global/color"; import { MainColor } from "@/app_modules/_global/color";
import { AdminColor } from "@/app_modules/_global/color/color_pallet"; import { AdminColor } from "@/app_modules/_global/color/color_pallet";
import { apiGetDataEventByStatus } from "@/app/dev/admin/event/_lib/api_fecth_admin_event";
import { clientLogger } from "@/util/clientLogger";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
export default function AdminEvent_TableReject({ export default function AdminEvent_TableReject() {
listReject,
}: {
listReject: any;
}) {
return ( return (
<> <>
<Stack> <Stack>
<ComponentAdminGlobal_HeaderTamplate name="Event" /> <ComponentAdminGlobal_HeaderTamplate name="Event" />
<TableStatus listReject={listReject} /> <TableStatus />
</Stack> </Stack>
</> </>
); );
} }
function TableStatus({ listReject }: { listReject: any }) { function TableStatus() {
const router = useRouter(); const router = useRouter();
const [data, setData] = useState<MODEL_EVENT[]>(listReject.data); const [data, setData] = useState<MODEL_EVENT[] | null>(null);
const [isNPage, setNPage] = useState(listReject.nPage); const [isNPage, setNPage] = useState(1);
const [isActivePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
const [isSearch, setSearch] = useState(""); const [isSearch, setSearch] = useState("");
const [opened, { open, close }] = useDisclosure(false); const [opened, { open, close }] = useDisclosure(false);
const [eventId, setEventId] = useState(""); const [eventId, setEventId] = useState("");
const [catatan, setCatatan] = useState(""); const [catatan, setCatatan] = useState("");
async function onSearch(s: string) { useShallowEffect(() => {
setSearch(s); const loadInitialData = async () => {
const loadData = await adminEvent_funGetListReject({ try {
page: 1, const response = await apiGetDataEventByStatus({
search: s, status: "Reject",
}); page: `${activePage}`,
setData(loadData.data as any); search: isSearch,
setNPage(loadData.nPage); });
}
async function onPageClick(p: any) { if (response?.success && response?.data?.data) {
setActivePage(p); setData(response.data.data);
const loadData = await adminEvent_funGetListReject({ setNPage(response.data.nPage || 1);
search: isSearch, } else {
page: p, console.error("Invalid data format received:", response);
}); setData([]);
setData(loadData.data as any); }
setNPage(loadData.nPage); } 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);
};
async function onUpdate(eventId: string, catatan: string) { async function onUpdate(eventId: string, catatan: string) {
const body = { const body = {
@@ -83,12 +96,24 @@ function TableStatus({ listReject }: { listReject: any }) {
}; };
const res = await AdminEvent_funEditCatatanById(body as any, "4"); const res = await AdminEvent_funEditCatatanById(body as any, "4");
if (res.status === 200) { if (res.status === 200) {
const loadData = await adminEvent_funGetListReject({ try {
search: isSearch, const response = await apiGetDataEventByStatus({
page: isActivePage, status: "Reject",
}); page: `${activePage}`,
setData(loadData.data as any); search: isSearch,
setNPage(loadData.nPage); });
if (response?.success && response?.data?.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([]);
}
ComponentGlobal_NotifikasiBerhasil(res.message); ComponentGlobal_NotifikasiBerhasil(res.message);
close(); close();
} else { } else {
@@ -96,176 +121,185 @@ function TableStatus({ listReject }: { listReject: any }) {
} }
} }
const TableRows = data.map((e, i) => ( const renderTableBody = () => {
<tr key={i}> if (!Array.isArray(data) || data.length === 0) {
<td> return (
<Center w={200}>{e?.Author?.username}</Center> <tr>
</td> <td colSpan={12}>
<td> <Center>
<Center w={200}>{e.title}</Center> <Text color={"gray"}>Tidak ada data</Text>
</td> </Center>
<td> </td>
<Center w={200}>{e.lokasi}</Center> </tr>
</td> );
<td> }
<Center w={200}>{e.EventMaster_TipeAcara.name}</Center>
</td>
<td> return data.map((e, i) => (
<Center w={200}> <tr key={i}>
<Text align="center"> <td>
{" "} <Center w={200}>{e?.Author?.username}</Center>
{new Intl.DateTimeFormat("id-ID", { </td>
dateStyle: "full", <td>
}).format(e?.tanggal)} <Center w={200}>{e.title}</Center>
,{" "} </td>
<Text span inherit> <td>
<Center w={200}>{e.lokasi}</Center>
</td>
<td>
<Center w={200}>{e.EventMaster_TipeAcara.name}</Center>
</td>
<td>
<Center w={200}>
<Text align="center">
{new Intl.DateTimeFormat("id-ID", { {new Intl.DateTimeFormat("id-ID", {
timeStyle: "short", dateStyle: "full",
}).format(e?.tanggal)} }).format(new Date(e?.tanggal))}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(new Date(e?.tanggal))}
</Text>
</Text> </Text>
</Text> </Center>
</Center> </td>
</td> <td>
<td> <Center w={200}>
<Center w={200}> <Text align="center">
<Text align="center">
{" "}
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(e?.tanggalSelesai)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", { {new Intl.DateTimeFormat("id-ID", {
timeStyle: "short", dateStyle: "full",
}).format(e?.tanggalSelesai)} }).format(new Date(e?.tanggalSelesai))}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(new Date(e?.tanggalSelesai))}
</Text>
</Text> </Text>
</Text> </Center>
</Center> </td>
</td>
<td> <td>
<Center w={500}> <Center w={500}>
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan"> <Spoiler
{e.deskripsi} hideLabel="sembunyikan"
</Spoiler> maxHeight={50}
</Center> showLabel="tampilkan"
</td> >
<td> {e.deskripsi}
{" "} </Spoiler>
<Center w={400}> </Center>
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan"> </td>
{e.catatan} <td>
</Spoiler> {" "}
</Center> <Center w={400}>
</td> <Spoiler
hideLabel="sembunyikan"
maxHeight={50}
showLabel="tampilkan"
>
{e.catatan}
</Spoiler>
</Center>
</td>
<td> <td>
<Button <Button
color={"red"} color={"red"}
leftIcon={<IconPencilPlus />} leftIcon={<IconPencilPlus />}
radius={"xl"} radius={"xl"}
onClick={() => { onClick={() => {
setEventId(e.id); setEventId(e.id);
setCatatan(e.catatan); setCatatan(e.catatan);
open(); open();
}} }}
> >
Tambah Catatan Tambah Catatan
</Button> </Button>
</td> </td>
</tr> </tr>
)); ));
};
return ( return (
<> <>
<Stack spacing={"xs"} h={"100%"}> <Stack spacing={"xs"} h={"100%"}>
<ComponentAdminGlobal_TitlePage <ComponentAdminGlobal_TitlePage
name="Reject" name="Reject"
color={AdminColor.red} color={"red.5"}
component={ component={
<TextInput <TextInput
icon={<IconSearch size={20} />} disabled={!data}
radius={"xl"} icon={<IconSearch size={20} />}
placeholder="Masukan judul" radius={"xl"}
onChange={(val) => { placeholder="Masukan judul"
onSearch(val.currentTarget.value);
}}
/>
}
/>
{/* <Group
position="apart"
bg={"red.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4}>Reject</Title>
<TextInput
icon={<IconSearch size={20} />}
radius={"xl"}
placeholder="Masukan judul"
onChange={(val) => {
onSearch(val.currentTarget.value);
}}
/>
</Group> */}
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
<ScrollArea w={"100%"} h={"90%"}>
<Table
verticalSpacing={"md"}
horizontalSpacing={"md"}
p={"md"}
w={1500}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>Username</Center>
</th>
<th>
<Center>Judul</Center>
</th>
<th>
<Center>Lokasi</Center>
</th>
<th>
<Center>Tipe Acara</Center>
</th>
<th>
<Center>Tanggal & Waktu Mulai</Center>
</th>
<th>
<Center>Tanggal & Waktu Selesai</Center>
</th>
<th>
<Center>Cacatan</Center>
</th>
<th>
<Center>Deskripsi</Center>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{TableRows}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}>
<Pagination
value={isActivePage}
total={isNPage}
onChange={(val) => { onChange={(val) => {
onPageClick(val); onSearch(val.currentTarget.value);
}} }}
/> />
</Center> }
</Paper> />
{!data ? (
<CustomSkeleton height={"80vh"} width="100%" />
) : (
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
<ScrollArea w={"100%"} h={"90%"}>
<Table
verticalSpacing={"md"}
horizontalSpacing={"md"}
p={"md"}
w={1500}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>Username</Center>
</th>
<th>
<Center>Judul</Center>
</th>
<th>
<Center>Lokasi</Center>
</th>
<th>
<Center>Tipe Acara</Center>
</th>
<th>
<Center>Tanggal & Waktu Mulai</Center>
</th>
<th>
<Center>Tanggal & Waktu Selesai</Center>
</th>
<th>
<Center>Cacatan</Center>
</th>
<th>
<Center>Deskripsi</Center>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{renderTableBody()}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}>
<Pagination
value={activePage}
total={isNPage}
onChange={(val) => {
onPageClick(val);
}}
/>
</Center>
</Paper>
)}
</Stack> </Stack>
<Modal <Modal

View File

@@ -7,15 +7,15 @@ import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamp
import { AdminEvent_ComponentTableReview } from "../_view"; import { AdminEvent_ComponentTableReview } from "../_view";
export default function AdminEvent_TableReview({ export default function AdminEvent_TableReview({
listData,
}: { }: {
listData: any;
}) { }) {
return ( return (
<> <>
<Stack> <Stack>
<ComponentAdminGlobal_HeaderTamplate name="Event" /> <ComponentAdminGlobal_HeaderTamplate name="Event" />
<AdminEvent_ComponentTableReview listData={listData} /> <AdminEvent_ComponentTableReview />
</Stack> </Stack>
</> </>
); );