From 02bbdfd5f6a2d299b8d527b9211f7b6ff598602f Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Tue, 20 May 2025 14:23:16 +0800 Subject: [PATCH] fix: event - logic & api konfirmasi kehadiran --- src/app/api/event/[id]/konfirmasi/route.ts | 98 +++ .../dev/(user)/event/konfirmasi/[id]/page.tsx | 5 +- src/app_modules/event/_lib/api_event.ts | 32 + src/app_modules/event/_ui/V2_konfirmasi.tsx | 662 ++++++++++++++++++ .../event/fun/create/fun_join_event.ts | 1 - 5 files changed, 795 insertions(+), 3 deletions(-) create mode 100644 src/app/api/event/[id]/konfirmasi/route.ts create mode 100644 src/app_modules/event/_ui/V2_konfirmasi.tsx diff --git a/src/app/api/event/[id]/konfirmasi/route.ts b/src/app/api/event/[id]/konfirmasi/route.ts new file mode 100644 index 00000000..d821a9da --- /dev/null +++ b/src/app/api/event/[id]/konfirmasi/route.ts @@ -0,0 +1,98 @@ +import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id"; +import { NextResponse } from "next/server"; +import { prisma } from "@/lib"; + +export async function GET( + request: Request, + { params }: { params: { id: string } } +) { + try { + const { id } = params; + let fixData; + const { searchParams } = new URL(request.url); + const userId = searchParams.get("userId"); + + const checkDataEvent = await prisma.event.findUnique({ + where: { + id: id, + }, + select: { + id: true, + title: true, + tanggal: true, + tanggalSelesai: true, + lokasi: true, + Author: { + select: { + id: true, + username: true, + Profile: { + select: { + id: true, + name: true, + }, + }, + }, + }, + }, + }); + + if (!checkDataEvent) { + return NextResponse.json( + { message: "Event Not Found", response: null }, + { status: 400 } + ); + } + + let peserta; + const checkPeserta = await prisma.event_Peserta.findFirst({ + where: { + userId: userId, + eventId: id, + }, + }); + + if (checkPeserta) { + peserta = true; + } else { + peserta = false; + } + + let kehadiran; + const checkKehadiran = await prisma.event_Peserta.findFirst({ + where: { + userId: userId, + eventId: id, + }, + select: { + isPresent: true, + }, + }); + + if (checkKehadiran?.isPresent) { + kehadiran = true; + } else { + kehadiran = false; + } + + fixData = { + dataEvent: checkDataEvent, + peserta: peserta, + kehadiran: kehadiran, + }; + + return NextResponse.json( + { message: "Event Found", res: fixData }, + { status: 200 } + ); + } catch (error) { + return NextResponse.json( + { + message: "Error get data event", + response: null, + error: (error as Error).message || error, + }, + { status: 500 } + ); + } +} diff --git a/src/app/dev/(user)/event/konfirmasi/[id]/page.tsx b/src/app/dev/(user)/event/konfirmasi/[id]/page.tsx index da648c02..d59a2bd5 100644 --- a/src/app/dev/(user)/event/konfirmasi/[id]/page.tsx +++ b/src/app/dev/(user)/event/konfirmasi/[id]/page.tsx @@ -1,12 +1,13 @@ import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import Ui_Konfirmasi from "@/app_modules/event/_ui/konfirmasi"; +import UiEvent_V2_Konfirmasi from "@/app_modules/event/_ui/V2_konfirmasi"; export default async function Page() { const userLoginId = await funGetUserIdByToken(); return ( <> - + {/* */} + ); } diff --git a/src/app_modules/event/_lib/api_event.ts b/src/app_modules/event/_lib/api_event.ts index a3c4ff10..ea697595 100644 --- a/src/app_modules/event/_lib/api_event.ts +++ b/src/app_modules/event/_lib/api_event.ts @@ -128,3 +128,35 @@ export const apiGetOneSponsorEventById = async ({ id }: { id: string }) => { return await response.json().catch(() => null); }; + +export const apiGetEventKonfirmasiById = async ({ id, userId }: { id: string; userId: string }) => { + try { + // Fetch token from cookie + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) { + console.error("No token found"); + return null; + } + + const response = await fetch(`/api/event/${id}/konfirmasi?userId=${userId}`, { + headers: { + "Content-Type": "application/json", + Accept: "application/json", + Authorization: `Bearer ${token}`, + }, + }); + + // Check if the response is OK + if (!response.ok) { + const errorData = await response.json().catch(() => null); + console.error("Failed to get event konfirmasi", response.statusText, errorData); + throw new Error(errorData?.message || "Failed to get event konfirmasi"); + } + + // Return the JSON response + return await response.json(); + } catch (error) { + console.error("Error get event konfirmasi", error); + throw error; // Re-throw the error to handle it in the calling function + } +}; \ No newline at end of file diff --git a/src/app_modules/event/_ui/V2_konfirmasi.tsx b/src/app_modules/event/_ui/V2_konfirmasi.tsx new file mode 100644 index 00000000..01d429da --- /dev/null +++ b/src/app_modules/event/_ui/V2_konfirmasi.tsx @@ -0,0 +1,662 @@ +"use client"; + +import { MainColor } from "@/app_modules/_global/color"; +import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; +import { + ComponentGlobal_NotifikasiBerhasil, + ComponentGlobal_NotifikasiGagal, +} from "@/app_modules/_global/notif_global"; +import UI_NewLayoutTamplate, { + UI_NewChildren, +} from "@/app_modules/_global/ui/V2_layout_tamplate"; +import { API_RouteEvent } from "@/lib/api_user_router/route_api_event"; +import { RouterEvent } from "@/lib/router_hipmi/router_event"; +import { clientLogger } from "@/util/clientLogger"; +import { Button, Center, Group, Skeleton, Stack, Text } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { useAtom } from "jotai"; +import moment from "moment"; +import "moment/locale/id"; +import { useParams, useRouter } from "next/navigation"; +import { useState } from "react"; +import { + apiGetEventDetailById, + apiGetEventKonfirmasiById, +} from "../_lib/api_event"; +import { MODEL_EVENT } from "../_lib/interface"; +import { event_funUpdateKehadiran } from "../fun"; +import { Event_funJoinAndConfirmEvent } from "../fun/create/fun_join_and_confirm"; +import { Event_funJoinEvent } from "../fun/create/fun_join_event"; +import { gs_event_hotMenu } from "../global_state"; +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; + +interface IKonfirmasiProps { + dataEvent: { + id: string; + title: string; + tanggal: Date; + tanggalSelesai: Date; + lokasi: string; + Author: { + id: string; + username: string; + Profile: { + id: string; + name: string; + }; + }; + }; + peserta: boolean | null; + kehadiran: boolean | null; +} + +export default function UiEvent_V2_Konfirmasi({ + userLoginId, +}: { + userLoginId: string; +}) { + const params = useParams<{ id: string }>(); + const eventId = params.id; + + const [data, setData] = useState(); + + const router = useRouter(); + const [isLoading, setLoading] = useState(false); + const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu); + + // Load Data + useShallowEffect(() => { + onLoadData(); + }, []); + + async function onLoadData() { + try { + const response = await apiGetEventKonfirmasiById({ + id: eventId, + userId: userLoginId, + }); + + if (response.res) { + setData(response.res); + } else { + setData(null); + } + } catch (error) { + setData(null); + console.error("Error get data detail event", error); + } + } + + // Jika data kosong + if (data === undefined) { + return ; + } + + // Jika data tidak ada + if (data?.dataEvent === null) { + return ( + <> + + + ); + } + + // Jika tanggal acara sudah lewat + if (moment(data?.dataEvent?.tanggalSelesai).diff(moment(), "minute") < 0) { + return ( + <> + + + ); + } + + // Jika join true + if ( + data?.peserta == true && + moment(data?.dataEvent?.tanggal).diff(moment(), "minute") > 0 + ) { + return ( + <> + + + ); + } + + // Jika belum join dan tanggal mulai acara belum lewat + if ( + data?.peserta === false && + moment(data?.dataEvent?.tanggal).diff(moment(), "minute") > 0 + ) { + return ( + <> + + + ); + } + + // Jika belum join dan tanggal mulai acara sudah lewat ✅ + if ( + data?.peserta === false && + moment(data?.dataEvent?.tanggal).diff(moment(), "minute") < 0 + ) { + return ( + <> + + + ); + } + + if (data?.kehadiran === false) { + return ( + + ); + } + + // Jika sudah join, sudah konfirmasi dan tanggal mulai acara sudah lewat + // if (isPresent && moment(data?.tanggal).diff(moment(), "minute") < 0) + if ( + data?.kehadiran && + data?.peserta && + moment(data?.dataEvent?.tanggal).diff(moment(), "minute") < 0 + ) { + return ; + } + + return ( + <> + + + + + + + Data Event Tidak Ditemukan + + + + + + + + + + ); +} + +function DataNotFound() { + const router = useRouter(); + const [isLoading, setLoading] = useState(false); + const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu); + + return ( + <> + + + + + + + + + + + + + ); +} + +function SkeletonIsDataNull() { + return ( + <> + + + + + + + + + ); +} + +function UserJoinTrue({ title, tanggal }: { title: string; tanggal: Date }) { + const router = useRouter(); + const [isLoading, setLoading] = useState(false); + const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu); + + return ( + <> + + + + + + + Terima kasih, Bapak/Ibu, Anda telah berhasil bergabung dalam + acara{" "} + + {title} + {" "} + . Mohon ditunggu hingga tanggal{" "} + + {moment(tanggal).format("DD-MM-YYYY")} + {" "} + untuk melakukan konfirmasi kehadiran melalui aplikasi HIPMI + APP. + + + + + + + + + + ); +} + +function UserAllowToJoin({ + title, + tanggal, + lokasi, + eventId, + userLoginId, +}: { + title: string; + tanggal: Date; + lokasi: string; + eventId: string; + userLoginId: string; +}) { + const router = useRouter(); + const [isLoading, setLoading] = useState(false); + + async function onJoinEvent() { + setLoading(true); + + const data = { + userId: userLoginId, + eventId: eventId, + }; + + const res = await Event_funJoinEvent(data as any); + if (res.status === 200) { + ComponentGlobal_NotifikasiBerhasil(res.message, 2000); + router.push(RouterEvent.detail_main + eventId); + } else { + setLoading(false); + ComponentGlobal_NotifikasiGagal(res.message); + } + } + + return ( + <> + + + + + + + Halo, Bapak/Ibu. Kami dengan senang hati mengundang Anda untuk + bergabung dalam acara{" "} + + {title} + {" "} + yang akan diselenggarakan pada{" "} + + {moment(tanggal).format("LL")} + {" "} + pukul{" "} + + {moment(tanggal).format("LT")} + {" "} + di{" "} + + {lokasi} + {" "} + . Pastikan Anda sudah melakukan registrasi melalui aplikasi{" "} + + HIPMI APP + {" "} + agar dapat berpartisipasi. Kami sangat + menantikan kehadiran Anda. Sampai jumpa dalam acara ini. + + + + + + + + + + ); +} + +function UserNotJoinAndEventReady({ + title, + eventId, + userLoginId, +}: { + title: string; + eventId: string; + userLoginId: string; +}) { + const router = useRouter(); + const [isLoading, setLoading] = useState(false); + async function onJoinAndKonfirmasi() { + setLoading(true); + + const body = { + eventId: eventId, + userId: userLoginId, + }; + + const res = await Event_funJoinAndConfirmEvent(body as any); + + if (res.status === 200) { + ComponentGlobal_NotifikasiBerhasil(res.message, 2000); + router.push(RouterEvent.detail_main + eventId); + } else { + setLoading(false); + ComponentGlobal_NotifikasiGagal(res.message); + } + } + return ( + <> + + + + + + + Halo, Bapak/Ibu. Kami mencatat bahwa Anda belum melakukan + registrasi melalui aplikasi untuk mengikuti acara,{" "} + + {title}. + {" "} + Mohon segera lakukan registrasi melalui Event App agar dapat + mengikuti acara ini. Jika membutuhkan bantuan, jangan ragu + untuk menghubungi tim kami. Terima kasih Terima kasih atas + kehadiran Anda di acara pada hari ini. Mohon untuk + mengonfirmasi kehadiran Anda dengan menekan tombol{" "} + {"Join & Konfirmasi"} + atau fitur konfirmasi yang tersedia di bawah. Terima kasih dan + selamat menikmati acara. + + + + + + + + + + ); +} + +function EventAlreadyDone({ + title, + eventId, +}: { + title: string; + eventId: string; +}) { + const router = useRouter(); + const [isLoading, setLoading] = useState(false); + const [isLoadingDetail, setLoadingDetail] = useState(false); + const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu); + + return ( + <> + + + + + + + Kami mohon maaf, Bapak/Ibu, acara{" "} + + {title} + {" "} + telah selesai, sehingga konfirmasi kehadiran sudah tidak dapat + dilakukan. Terima kasih atas perhatian dan minat Anda. Kami + berharap dapat bertemu di acara kami berikutnya. Terima kasih, + Bapak/Ibu, kehadiran Anda di acara. + + + + + + + + + + + + + ); +} + +function UserNotConfirm({ + title, + eventId, + userLoginId, +}: { + title: string; + eventId: string; + userLoginId: string; +}) { + const router = useRouter(); + const [isLoading, setLoading] = useState(false); + async function onUpdateKonfirmasi() { + setLoading(true); + const res = await event_funUpdateKehadiran({ + eventId: eventId, + userId: userLoginId, + }); + + if (res.status === 200) { + ComponentGlobal_NotifikasiBerhasil(res.message, 2000); + router.push(RouterEvent.detail_main + eventId); + } else { + setLoading(false); + ComponentGlobal_NotifikasiGagal(res.message); + } + } + return ( + <> + + + + + + + Terima kasih atas kehadiran Anda di acara{" "} + + {title} + {" "} + pada hari ini. Mohon untuk mengonfirmasi kehadiran Anda dengan + menekan tombol{" "} + + Konfirmasi Kehadiran + {" "} + atau fitur konfirmasi yang tersedia di bawah. Terima kasih dan + selamat menikmati acara. + + + + + + + + + + ); +} + +function UserAlreadyConfirm({ title }: { title: string }) { + const router = useRouter(); + const [isLoading, setLoading] = useState(false); + const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu); + + return ( + <> + + + + + + + Terima kasih, Bapak/Ibu, kehadiran Anda di acara{" "} + + {title} + {" "} + telah berhasil dikonfirmasi. Kami senang menyambut Anda dan + semoga acara ini memberikan manfaat yang maksimal. Selamat + mengikuti kegiatan. + + + + + + + + + + ); +} diff --git a/src/app_modules/event/fun/create/fun_join_event.ts b/src/app_modules/event/fun/create/fun_join_event.ts index 18400f03..cae8d02b 100644 --- a/src/app_modules/event/fun/create/fun_join_event.ts +++ b/src/app_modules/event/fun/create/fun_join_event.ts @@ -6,7 +6,6 @@ import { revalidatePath } from "next/cache"; export async function Event_funJoinEvent(data: MODEL_EVENT_PESERTA) { try { - console.log("Data >", data) const res = await prisma.event_Peserta.create({ data: { eventId: data.eventId,