From a95f4a480ed0e8d81d5b05716c885ed6a664dfc6 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Wed, 4 Dec 2024 11:12:52 +0800 Subject: [PATCH 01/36] Fix layout realtime --- package.json | 4 +- src/app/api/user/route.ts | 41 +++ src/app/dev/layout.tsx | 4 +- src/app/lib/realtime_provider.tsx | 283 ++++++++++-------- .../fun/get/fun_get_user_id_by_token.ts | 5 +- src/app_modules/event/_ui/konfirmasi.tsx | 3 - src/middleware.ts | 2 + 7 files changed, 204 insertions(+), 138 deletions(-) create mode 100644 src/app/api/user/route.ts diff --git a/package.json b/package.json index 3a2f0c4d..b9ead47c 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ }, "scripts": { "dev": "bun --bun run next dev --experimental-https", - "build": "bun --bun run next build", + "build": "NODE_OPTIONS='--max-old-space-size=2048' bun --bun run next build", "start": "bun --bun run next start", "lint": "bun --bun run next lint", "ver": "bunx commit-and-tag-version -- --prerelease" @@ -94,4 +94,4 @@ "wibu-pkg": "^1.0.3", "yaml": "^2.3.2" } -} +} \ No newline at end of file diff --git a/src/app/api/user/route.ts b/src/app/api/user/route.ts new file mode 100644 index 00000000..33b4d093 --- /dev/null +++ b/src/app/api/user/route.ts @@ -0,0 +1,41 @@ +import { jwtVerify } from "jose"; +import _ from "lodash"; +import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; + +export async function GET() { + // const data = await req.text(); + // console.log(data); + const c = cookies().get(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!); + + if (!c || !c?.value || _.isEmpty(c?.value) || _.isUndefined(c?.value)) { + return NextResponse.json({ status: 401, message: "Unauthorized" }); + } + + const token = c.value; + const dataUser = await decrypt({ + token: token, + encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, + }); + + return NextResponse.json({ status: 200, message: "OK", data: dataUser }); +} + +async function decrypt({ + token, + encodedKey, +}: { + token: string; + encodedKey: string; +}): Promise | null> { + try { + const enc = new TextEncoder().encode(encodedKey); + const { payload } = await jwtVerify(token, enc, { + algorithms: ["HS256"], + }); + return (payload.user as Record) || null; + } catch (error) { + console.error("Gagal verifikasi session", error); + return null; + } +} diff --git a/src/app/dev/layout.tsx b/src/app/dev/layout.tsx index 4c91bd10..aad4db0b 100644 --- a/src/app/dev/layout.tsx +++ b/src/app/dev/layout.tsx @@ -11,7 +11,7 @@ export default async function Layout({ }: { children: React.ReactNode; }) { - const userLoginId = await funGetUserIdByToken(); + // const userLoginId = await funGetUserIdByToken(); // const dataUser = await funGlobal_getUserById({ // userId: userLoginId as string, // }); @@ -27,7 +27,7 @@ export default async function Layout({ return ( <> { - // if (WIBU_REALTIME_TOKEN === undefined) return alert("gak dapet key"); - try { - WibuRealtime.init({ - project: "hipmi", - WIBU_REALTIME_TOKEN: WIBU_REALTIME_TOKEN, - onData(data: TypeNotification) { - if ( - data.type == "notification" && - data.pushNotificationTo == "ADMIN" - ) { - setNewAdminNtf((e) => e + 1); + onLoadUser({ + onSetUser(val: string) { + + if (val !== "" || val !== undefined) { + try { + WibuRealtime.init({ + project: "hipmi", + WIBU_REALTIME_TOKEN: WIBU_REALTIME_TOKEN, + onData(data: TypeNotification) { + if ( + data.type == "notification" && + data.pushNotificationTo == "ADMIN" + ) { + setNewAdminNtf((e) => e + 1); + } + + // Notifikasi ke semua user , yang datanya di acc admin + if ( + data.type == "notification" && + data.pushNotificationTo == "USER" && + data.dataMessage?.userId == userId + ) { + setNewUserNtf((e) => e + 1); + setDataRealtime(data.dataMessage as any); + } + + // ---------------------- JOB ------------------------- // + if ( + data.type == "trigger" && + data.pushNotificationTo == "ADMIN" && + data.dataMessage?.kategoriApp == "JOB" + ) { + setIsAdminJob_TriggerReview(true); + } + + if ( + data.type == "trigger" && + data.pushNotificationTo == "USER" && + data.dataMessage?.kategoriApp == "JOB" && + data.dataMessage.status == "Publish" + ) { + setIsTriggerJobBeranda(true); + } + // ---------------------- JOB ------------------------- // + + // ---------------------- EVENT ------------------------- // + if ( + data.type == "trigger" && + data.pushNotificationTo == "ADMIN" && + data.dataMessage?.kategoriApp == "EVENT" + ) { + setIsAdminEvent_TriggerReview(true); + } + + if ( + data.type == "trigger" && + data.pushNotificationTo == "USER" && + data.dataMessage?.kategoriApp == "EVENT" && + data.dataMessage.status == "Publish" + ) { + setIsTriggerEventBeranda(true); + } + + if ( + data.type == "notification" && + data.pushNotificationTo == "USER" && + data.dataMessage?.status == "Peserta Event" && + userId !== data.dataMessage?.userId + ) { + setNewUserNtf((e) => e + 1); + } + // ---------------------- EVENT ------------------------- // + + // ---------------------- VOTING ------------------------- // + if ( + data.type == "trigger" && + data.pushNotificationTo == "ADMIN" && + data.dataMessage?.kategoriApp == "VOTING" + ) { + setIsAdminVoting_TriggerReview(true); + } + + if ( + data.type == "trigger" && + data.pushNotificationTo == "USER" && + data.dataMessage?.kategoriApp == "VOTING" && + data.dataMessage.status == "Publish" + ) { + setIsTriggerVotingBeranda(true); + } + + if ( + data.type == "notification" && + data.pushNotificationTo == "USER" && + data.dataMessage?.status == "Voting Masuk" && + userId !== data.dataMessage?.userId + ) { + setNewUserNtf((e) => e + 1); + } + // ---------------------- VOTING ------------------------- // + + // ---------------------- DONASI ------------------------- // + if ( + data.type == "trigger" && + data.pushNotificationTo == "ADMIN" && + data.dataMessage?.kategoriApp == "DONASI" + ) { + setIsAdminDonasi_TriggerReview(true); + } + + if ( + data.type == "trigger" && + data.pushNotificationTo == "USER" && + data.dataMessage?.kategoriApp == "DONASI" && + data.dataMessage.status == "Publish" + ) { + setIsTriggerDonasiBeranda(true); + } + + // if ( + // data.type == "notification" && + // data.pushNotificationTo == "ADMIN" && + // data.dataMessage?.status == "Menunggu" && + // userLoginId !== data.dataMessage?.userId + // ) { + // console.log("yes"); + // } + + // ---------------------- DONASI ------------------------- // + }, + }); + } catch (error) { + console.log(error); } + } else { + return undefined; + } + }, + }); + }, [setUserId]); - // Notifikasi ke semua user , yang datanya di acc admin - if ( - data.type == "notification" && - data.pushNotificationTo == "USER" && - data.dataMessage?.userId == userLoginId - ) { - setNewUserNtf((e) => e + 1); - setDataRealtime(data.dataMessage as any); - } - - // ---------------------- JOB ------------------------- // - if ( - data.type == "trigger" && - data.pushNotificationTo == "ADMIN" && - data.dataMessage?.kategoriApp == "JOB" - ) { - setIsAdminJob_TriggerReview(true); - } - - if ( - data.type == "trigger" && - data.pushNotificationTo == "USER" && - data.dataMessage?.kategoriApp == "JOB" && - data.dataMessage.status == "Publish" - ) { - setIsTriggerJobBeranda(true); - } - // ---------------------- JOB ------------------------- // - - // ---------------------- EVENT ------------------------- // - if ( - data.type == "trigger" && - data.pushNotificationTo == "ADMIN" && - data.dataMessage?.kategoriApp == "EVENT" - ) { - setIsAdminEvent_TriggerReview(true); - } - - if ( - data.type == "trigger" && - data.pushNotificationTo == "USER" && - data.dataMessage?.kategoriApp == "EVENT" && - data.dataMessage.status == "Publish" - ) { - setIsTriggerEventBeranda(true); - } - - if ( - data.type == "notification" && - data.pushNotificationTo == "USER" && - data.dataMessage?.status == "Peserta Event" && - userLoginId !== data.dataMessage?.userId - ) { - setNewUserNtf((e) => e + 1); - } - // ---------------------- EVENT ------------------------- // - - // ---------------------- VOTING ------------------------- // - if ( - data.type == "trigger" && - data.pushNotificationTo == "ADMIN" && - data.dataMessage?.kategoriApp == "VOTING" - ) { - setIsAdminVoting_TriggerReview(true); - } - - if ( - data.type == "trigger" && - data.pushNotificationTo == "USER" && - data.dataMessage?.kategoriApp == "VOTING" && - data.dataMessage.status == "Publish" - ) { - setIsTriggerVotingBeranda(true); - } - - if ( - data.type == "notification" && - data.pushNotificationTo == "USER" && - data.dataMessage?.status == "Voting Masuk" && - userLoginId !== data.dataMessage?.userId - ) { - setNewUserNtf((e) => e + 1); - } - // ---------------------- VOTING ------------------------- // - - // ---------------------- DONASI ------------------------- // - if ( - data.type == "trigger" && - data.pushNotificationTo == "ADMIN" && - data.dataMessage?.kategoriApp == "DONASI" - ) { - setIsAdminDonasi_TriggerReview(true); - } - - if ( - data.type == "trigger" && - data.pushNotificationTo == "USER" && - data.dataMessage?.kategoriApp == "DONASI" && - data.dataMessage.status == "Publish" - ) { - setIsTriggerDonasiBeranda(true); - } - - // if ( - // data.type == "notification" && - // data.pushNotificationTo == "ADMIN" && - // data.dataMessage?.status == "Menunggu" && - // userLoginId !== data.dataMessage?.userId - // ) { - // console.log("yes"); - // } - - // ---------------------- DONASI ------------------------- // - }, - }); - } catch (error) { - console.log(error); - } - }, []); + async function onLoadUser({ + onSetUser, + }: { + onSetUser: (val: string) => void; + }) { + const res = await fetch("/api/user", { + method: "GET", + }); + const result = await res.json(); + onSetUser(result.data.id); + } return null; } diff --git a/src/app_modules/_global/fun/get/fun_get_user_id_by_token.ts b/src/app_modules/_global/fun/get/fun_get_user_id_by_token.ts index d08bc9cb..ed2d0ee0 100644 --- a/src/app_modules/_global/fun/get/fun_get_user_id_by_token.ts +++ b/src/app_modules/_global/fun/get/fun_get_user_id_by_token.ts @@ -7,13 +7,16 @@ import { jwtVerify } from "jose"; import { cookies } from "next/headers"; export async function funGetUserIdByToken() { - const c = cookies().get(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!); + const SESSION_KEY = process.env.NEXT_PUBLIC_BASE_SESSION_KEY!; + // console.log("SESSION_KEY", SESSION_KEY); + const c = cookies().get("hipmi-key"); const cekUser = await decrypt({ token: c?.value as string, encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, }); + // console.log("userid" , cekUser?.id) // const token = JSON.parse( // await unsealData(c?.value as string, { diff --git a/src/app_modules/event/_ui/konfirmasi.tsx b/src/app_modules/event/_ui/konfirmasi.tsx index 468e8c14..3e1f3a43 100644 --- a/src/app_modules/event/_ui/konfirmasi.tsx +++ b/src/app_modules/event/_ui/konfirmasi.tsx @@ -74,9 +74,6 @@ export default function Ui_Konfirmasi({ } } - if (isPresent === null) { - return <>; - } return ( <> diff --git a/src/middleware.ts b/src/middleware.ts index 30cee1e5..11acde45 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -19,8 +19,10 @@ const middlewareConfig: MiddlewareConfig = { userPath: "/dev/home", publicRoutes: [ "/", + "/api/validation", "/api/auth/*", "/api/origin-url", + "/api/user", "/login", "/register", "/validasi", From 2e0a5c1c2ea09518af0ce0eb76e2949b7d0e514d Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Wed, 4 Dec 2024 11:13:51 +0800 Subject: [PATCH 02/36] chore(release): 1.2.17 --- CHANGELOG.md | 2 ++ package.json | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63858849..4d26ddfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [1.2.17](https://github.com/bipproduction/hipmi/compare/v1.2.16...v1.2.17) (2024-12-04) + ## [1.2.16](https://github.com/bipproduction/hipmi/compare/v1.2.15...v1.2.16) (2024-12-03) ## [1.2.15](https://github.com/bipproduction/hipmi/compare/v1.2.14...v1.2.15) (2024-12-03) diff --git a/package.json b/package.json index b9ead47c..663d9389 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hipmi", - "version": "1.2.16", + "version": "1.2.17", "private": true, "prisma": { "seed": "npx tsx prisma/seed.ts --yes" @@ -94,4 +94,4 @@ "wibu-pkg": "^1.0.3", "yaml": "^2.3.2" } -} \ No newline at end of file +} From 9a9bbe3bd600c609a00a2b417797a438f8faa452 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Wed, 4 Dec 2024 15:45:33 +0800 Subject: [PATCH 03/36] chore(release): 1.2.18 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d26ddfc..108876d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [1.2.18](https://github.com/bipproduction/hipmi/compare/v1.2.17...v1.2.18) (2024-12-04) + ## [1.2.17](https://github.com/bipproduction/hipmi/compare/v1.2.16...v1.2.17) (2024-12-04) ## [1.2.16](https://github.com/bipproduction/hipmi/compare/v1.2.15...v1.2.16) (2024-12-03) diff --git a/package.json b/package.json index 663d9389..fb9c76ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hipmi", - "version": "1.2.17", + "version": "1.2.18", "private": true, "prisma": { "seed": "npx tsx prisma/seed.ts --yes" From 5917a1b8d04294d833cc1898d637b922e325c9d0 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Wed, 4 Dec 2024 15:45:55 +0800 Subject: [PATCH 04/36] Fix : Event scanbarcode --- src/app/api/event/check-kehadiran/route.ts | 15 +++++ src/app/dev/event/konfirmasi/[id]/page.tsx | 6 +- .../event/table_status/table_publish.tsx | 56 ++++++++++++++----- src/app_modules/event/_ui/konfirmasi.tsx | 19 ++----- src/app_modules/event/main/beranda.tsx | 4 +- src/middleware.ts | 1 + 6 files changed, 71 insertions(+), 30 deletions(-) create mode 100644 src/app/api/event/check-kehadiran/route.ts diff --git a/src/app/api/event/check-kehadiran/route.ts b/src/app/api/event/check-kehadiran/route.ts new file mode 100644 index 00000000..3b2ef875 --- /dev/null +++ b/src/app/api/event/check-kehadiran/route.ts @@ -0,0 +1,15 @@ +import { event_funCheckKehadiran } from "@/app_modules/event/fun"; +import { NextResponse } from "next/server"; + +export async function GET(req: Request) { + const { searchParams } = new URL(req.url); + const userId = searchParams.get("userId"); + const eventId = searchParams.get("eventId"); + + const res = await event_funCheckKehadiran({ + eventId: eventId as string, + userId: userId as string, + }); + + return NextResponse.json({ res }); +} diff --git a/src/app/dev/event/konfirmasi/[id]/page.tsx b/src/app/dev/event/konfirmasi/[id]/page.tsx index a7de2574..eb04ea33 100644 --- a/src/app/dev/event/konfirmasi/[id]/page.tsx +++ b/src/app/dev/event/konfirmasi/[id]/page.tsx @@ -5,6 +5,7 @@ import { event_funCheckPesertaByUserId, } from "@/app_modules/event/fun"; import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id"; +import moment from "moment"; import { redirect } from "next/navigation"; export default async function Page({ params }: { params: { id: string } }) { @@ -17,7 +18,10 @@ export default async function Page({ params }: { params: { id: string } }) { userId: userLoginId as string, }); - + if (dataEvent == null) return redirect("/dev/event/main/beranda"); + + if (moment(dataEvent?.tanggal).diff(moment(), "minutes") > 0) + return redirect("/dev/event/main/beranda"); if (dataEvent?.isArsip) return redirect(`/dev/event/detail/riwayat/${dataEvent.id}`); 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 01316545..7bcd290b 100644 --- a/src/app_modules/admin/event/table_status/table_publish.tsx +++ b/src/app_modules/admin/event/table_status/table_publish.tsx @@ -50,20 +50,20 @@ function TableStatus({ listPublish }: { listPublish: any }) { const [eventId, setEventId] = useState(""); const [loading, setLoading] = useState(false); - const [origin, setOrigin] = useState(""); + const [origin, setOrigin] = useState(""); - useShallowEffect(() => { - onLoadOrigin(setOrigin); - // if (typeof window !== "undefined") { - // setOrigin(window.location.origin); - // } - }, [setOrigin]); + useShallowEffect(() => { + 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); - } + // async function onLoadOrigin(setOrigin: any) { + // const res = await fetch("/api/origin-url"); + // const result = await res.json(); + // setOrigin(result.origin); + // } async function onSearch(s: string) { setSearch(s); @@ -97,11 +97,38 @@ 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)}`; + }} + /> +
+
{e?.Author?.username} @@ -225,6 +252,9 @@ function TableStatus({ listPublish }: { listPublish: any }) {
QR Code
+ +
Download QR
+
Username
diff --git a/src/app_modules/event/_ui/konfirmasi.tsx b/src/app_modules/event/_ui/konfirmasi.tsx index 3e1f3a43..ec95fc00 100644 --- a/src/app_modules/event/_ui/konfirmasi.tsx +++ b/src/app_modules/event/_ui/konfirmasi.tsx @@ -30,14 +30,6 @@ export default function Ui_Konfirmasi({ const [isLoading, setLoading] = useState(false); const [isPresent, setIsPresent] = useState(null); - // useShallowEffect(() => { - // onLoadData({ - // onPublish(val) { - // setData(val); - // }, - // }); - // }, [setData]); - useShallowEffect(() => { onLoadKehadiran({ onChange(val) { @@ -51,12 +43,12 @@ export default function Ui_Konfirmasi({ }: { onChange: (val: boolean) => void; }) { - const checkKehadiran = await event_funCheckKehadiran({ - eventId: dataEvent.id, - userId: userLoginId as string, - }); + const res = await fetch( + `/api/event/check-kehadiran?userId=${userLoginId}&eventId=${dataEvent.id}` + ); + const checkKehadiran = await res.json(); - onChange(checkKehadiran); + onChange(checkKehadiran.res); } async function onUpdateKonfirmasi() { setLoading(true); @@ -74,6 +66,7 @@ export default function Ui_Konfirmasi({ } } + console.log(isPresent, "isPresent"); return ( <> diff --git a/src/app_modules/event/main/beranda.tsx b/src/app_modules/event/main/beranda.tsx index 5714cc6a..9a814ed8 100644 --- a/src/app_modules/event/main/beranda.tsx +++ b/src/app_modules/event/main/beranda.tsx @@ -20,7 +20,7 @@ export default function Event_Beranda({ }: { dataEvent: MODEL_EVENT[]; }) { - const [data, setData] = useState(dataEvent); + const [data, setData] = useState([]); const [activePage, setActivePage] = useState(1); const [isLoading, setIsLoading] = useState(false); @@ -76,8 +76,6 @@ export default function Event_Beranda({ setData(val); }, }); - - }} > Update beranda diff --git a/src/middleware.ts b/src/middleware.ts index 11acde45..d08b310f 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -23,6 +23,7 @@ const middlewareConfig: MiddlewareConfig = { "/api/auth/*", "/api/origin-url", "/api/user", + "/api/event/*", "/login", "/register", "/validasi", From 6fd2a81a593723013012463d161339f0d785380b Mon Sep 17 00:00:00 2001 From: amel Date: Wed, 4 Dec 2024 16:22:43 +0800 Subject: [PATCH 05/36] upd: home Deskripsi: - kompres gambar di home - clean code yg ga dipake No Issues --- public/aset/home/home-hipmi-new.png | Bin 0 -> 130912 bytes src/app/dev/(user)/home/page.tsx | 9 -------- src/app_modules/home/component/ui_home.tsx | 2 +- src/app_modules/home/view_home.tsx | 23 ++++++--------------- 4 files changed, 7 insertions(+), 27 deletions(-) create mode 100644 public/aset/home/home-hipmi-new.png diff --git a/public/aset/home/home-hipmi-new.png b/public/aset/home/home-hipmi-new.png new file mode 100644 index 0000000000000000000000000000000000000000..968807de426998b2db429e70e1973c3c17d971a0 GIT binary patch literal 130912 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

KQC8i<*W*|K2FHxQbEj<6DSl4=cCS>GrU6P!w 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 literal 0 HcmV?d00001 diff --git a/src/app/dev/(user)/home/page.tsx b/src/app/dev/(user)/home/page.tsx index 86f17573..dcfc7882 100644 --- a/src/app/dev/(user)/home/page.tsx +++ b/src/app/dev/(user)/home/page.tsx @@ -10,15 +10,6 @@ export default async function PageHome() { const dataJob = await job_getTwoForHomeView(); const countNotifikasi = await notifikasi_countUserNotifikasi(); - // console.log(userLoginId, "ini di home"); - // console.log(dataUser, "ini di home"); - - // if (dataUser?.active === false) { - // return redirect(RouterHome.home_user_non_active); - // } - - // if (dataUser?.masterUserRoleId === "2" || dataUser?.masterUserRoleId === "3") - // return redirect(RouterAdminDashboard.main_admin); return ( <> diff --git a/src/app_modules/home/component/ui_home.tsx b/src/app_modules/home/component/ui_home.tsx index 9ce1203d..a87ce053 100644 --- a/src/app_modules/home/component/ui_home.tsx +++ b/src/app_modules/home/component/ui_home.tsx @@ -104,7 +104,7 @@ export function Home_UiView({ border: `2px solid ${AccentColor.blue}`, }} > - logo + logo diff --git a/src/app_modules/home/view_home.tsx b/src/app_modules/home/view_home.tsx index 88e38bd1..4d6a5cc4 100644 --- a/src/app_modules/home/view_home.tsx +++ b/src/app_modules/home/view_home.tsx @@ -1,21 +1,15 @@ "use client"; - -import { useEffect, useState } from "react"; +import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state"; +import { useShallowEffect } from "@mantine/hooks"; +import { useAtom } from "jotai"; +import { useState } from "react"; import UIGlobal_LayoutHeaderTamplate from "../_global/ui/ui_header_tamplate"; import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate"; import { MODEL_JOB } from "../job/model/interface"; -import { - ComponentHome_ButtonHeaderLeft, - ComponentHome_ButtonHeaderRight, -} from "./component/button_header"; +import notifikasi_countUserNotifikasi from "../notifikasi/fun/count/fun_count_by_id"; +import { ComponentHome_ButtonHeaderLeft, ComponentHome_ButtonHeaderRight, } from "./component/button_header"; import { Home_UiFooter, Home_UiView } from "./component/ui_home"; import { MODEL_USER } from "./model/interface"; -import { useShallowEffect } from "@mantine/hooks"; -import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state"; -import { useAtom } from "jotai"; -import notifikasi_countUserNotifikasi from "../notifikasi/fun/count/fun_count_by_id"; -import { Center, Text, Title } from "@mantine/core"; -import { useRouter } from "next/navigation"; export default function HomeView({ dataUser, @@ -26,7 +20,6 @@ export default function HomeView({ dataJob: MODEL_JOB[]; countNotifikasi: number; }) { - const router = useRouter(); const [countNtf, setCountNtf] = useState(countNotifikasi); const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf); const [countLoadNtf, setCountLoadNtf] = useAtom(gs_count_ntf); @@ -60,15 +53,11 @@ export default function HomeView({ onLoad(loadNotif); } - // console.log(dataUser, "dipage") return ( <> - // HIPMI - //

Date: Wed, 4 Dec 2024 17:48:58 +0800 Subject: [PATCH 06/36] Fix beranda event --- src/app/api/event/get-all-by-userId/route.ts | 9 ++++ src/app_modules/event/main/beranda.tsx | 53 +++++++++++++------- 2 files changed, 44 insertions(+), 18 deletions(-) create mode 100644 src/app/api/event/get-all-by-userId/route.ts diff --git a/src/app/api/event/get-all-by-userId/route.ts b/src/app/api/event/get-all-by-userId/route.ts new file mode 100644 index 00000000..2ae65ce8 --- /dev/null +++ b/src/app/api/event/get-all-by-userId/route.ts @@ -0,0 +1,9 @@ +import { NextResponse } from "next/server"; + +export async function GET(params: Request) { + const { searchParams } = new URL(params.url); + const userId = searchParams.get("userId"); + + + return NextResponse.json({ userId }); +} \ No newline at end of file diff --git a/src/app_modules/event/main/beranda.tsx b/src/app_modules/event/main/beranda.tsx index 9a814ed8..3387a29b 100644 --- a/src/app_modules/event/main/beranda.tsx +++ b/src/app_modules/event/main/beranda.tsx @@ -5,7 +5,15 @@ import { RouterEvent } from "@/app/lib/router_hipmi/router_event"; import { AccentColor } from "@/app_modules/_global/color"; import ComponentGlobal_CreateButton from "@/app_modules/_global/component/button_create"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; -import { Affix, Box, Button, Center, Loader, rem } from "@mantine/core"; +import { + Affix, + Box, + Button, + Center, + Loader, + rem, + Skeleton, +} from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; import { useAtom } from "jotai"; import _ from "lodash"; @@ -20,7 +28,7 @@ export default function Event_Beranda({ }: { dataEvent: MODEL_EVENT[]; }) { - const [data, setData] = useState([]); + const [data, setData] = useState(null); const [activePage, setActivePage] = useState(1); const [isLoading, setIsLoading] = useState(false); @@ -31,23 +39,24 @@ export default function Event_Beranda({ const [isShowUpdate, setIsShowUpdate] = useState(false); useShallowEffect(() => { - onLoadData({ - onPublish(val) { - setData(val); - }, - }); - }, [setData]); + loadData(); + }, []); useShallowEffect(() => { if (isTriggerEventBeranda) { setIsShowUpdate(true); } - }, [isTriggerEventBeranda, setIsShowUpdate]); + }, [isTriggerEventBeranda]); - async function onLoadData({ onPublish }: { onPublish: (val: any) => void }) { + async function loadData() { + const loadData = await event_getListAllPublish({ page: 1 }); + setData(loadData as any); + } + + async function onLoadNewData() { setIsLoading(true); const loadData = await event_getListAllPublish({ page: 1 }); - onPublish(loadData); + setData(loadData as any); setIsShowUpdate(false); setIsTriggerEventBeranca(false); @@ -71,11 +80,7 @@ export default function Event_Beranda({ radius={"xl"} opacity={0.8} onClick={() => { - onLoadData({ - onPublish(val) { - setData(val); - }, - }); + onLoadNewData(); }} > Update beranda @@ -85,7 +90,19 @@ export default function Event_Beranda({ )} - {_.isEmpty(data) ? ( + + {data == null ? ( + Array.from({ length: 10 }).map((_, index) => ( + + )) + ) : _.isEmpty(data) ? ( ) : ( @@ -97,7 +114,7 @@ export default function Event_Beranda({ )} data={data} - setData={setData} + setData={setData as any} moreData={async () => { const loadData = await event_getListAllPublish({ page: activePage + 1, From 1e971c15265e8c7add5ad4d6e42dd5b45dbc5a47 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Thu, 5 Dec 2024 12:11:40 +0800 Subject: [PATCH 07/36] Fix prisma Deskripsi: - Cek pemanggilan prisma di develop mode --- next.config.js | 2 +- package.json | 3 +- src/app/dev/layout.tsx | 24 +-- src/app/lib/new_fun_user_id.ts | 38 ++++ src/app/lib/prisma.ts | 33 ++-- src/app/lib/realtime_provider.tsx | 281 ++++++++++++++---------------- 6 files changed, 194 insertions(+), 187 deletions(-) create mode 100644 src/app/lib/new_fun_user_id.ts diff --git a/next.config.js b/next.config.js index 5c728631..b00f93a2 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - reactStrictMode: false, + // reactStrictMode: false, experimental: { serverActions: true }, diff --git a/package.json b/package.json index fb9c76ac..bb7c07b7 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "scripts": { "dev": "bun --bun run next dev --experimental-https", "build": "NODE_OPTIONS='--max-old-space-size=2048' bun --bun run next build", + "build:dev": "bun --bun run next build", "start": "bun --bun run next start", "lint": "bun --bun run next lint", "ver": "bunx commit-and-tag-version -- --prerelease" @@ -94,4 +95,4 @@ "wibu-pkg": "^1.0.3", "yaml": "^2.3.2" } -} +} \ No newline at end of file diff --git a/src/app/dev/layout.tsx b/src/app/dev/layout.tsx index aad4db0b..1ac8606a 100644 --- a/src/app/dev/layout.tsx +++ b/src/app/dev/layout.tsx @@ -1,42 +1,24 @@ -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { funGlobal_getUserById } from "@/app_modules/_global/fun/get/fun_get_user_by_id"; -import { redirect } from "next/navigation"; import { RealtimeProvider } from "../lib"; +import { newFunGetUserId } from "../lib/new_fun_user_id"; import { ServerEnv } from "../lib/server_env"; -import { RouterAdminDashboard } from "../lib/router_hipmi/router_admin"; -import { funGlobal_checkActivationUseById } from "@/app_modules/_global/fun/get/fun_check_activation_use_by_id"; export default async function Layout({ children, }: { children: React.ReactNode; }) { - // const userLoginId = await funGetUserIdByToken(); - // const dataUser = await funGlobal_getUserById({ - // userId: userLoginId as string, - // }); - - // if (dataUser?.masterUserRoleId != "1") return redirect("/dev/home"); - - // const activationUser = await funGlobal_checkActivationUseById({ - // userId: userLoginId as string, - // }); - - // if (activationUser == false) return redirect("/waiting-room"); + const userLoginId = await newFunGetUserId(); return ( <> {children} - {/* - {children} - */} ); } diff --git a/src/app/lib/new_fun_user_id.ts b/src/app/lib/new_fun_user_id.ts new file mode 100644 index 00000000..188afff5 --- /dev/null +++ b/src/app/lib/new_fun_user_id.ts @@ -0,0 +1,38 @@ +import { jwtVerify } from "jose"; +import _ from "lodash"; +import { cookies } from "next/headers"; + +export async function newFunGetUserId() { + const c = cookies().get(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!); + + if (!c || !c?.value || _.isEmpty(c?.value) || _.isUndefined(c?.value)) { + return null; + } + + const token = c.value; + const dataUser = await decrypt({ + token: token, + encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, + }); + + return dataUser?.id; +} + +async function decrypt({ + token, + encodedKey, +}: { + token: string; + encodedKey: string; +}): Promise | null> { + try { + const enc = new TextEncoder().encode(encodedKey); + const { payload } = await jwtVerify(token, enc, { + algorithms: ["HS256"], + }); + return (payload.user as Record) || null; + } catch (error) { + console.error("Gagal verifikasi session", error); + return null; + } +} diff --git a/src/app/lib/prisma.ts b/src/app/lib/prisma.ts index 553b19ad..a0d1a749 100644 --- a/src/app/lib/prisma.ts +++ b/src/app/lib/prisma.ts @@ -1,17 +1,26 @@ -import { PrismaClient } from '@prisma/client' - -const prismaClientSingleton = () => { - return new PrismaClient() -} - -type PrismaClientSingleton = ReturnType +import { PrismaClient } from '@prisma/client'; +// Singleton PrismaClient untuk pengembangan const globalForPrisma = globalThis as unknown as { - prisma: PrismaClientSingleton | undefined + __prisma__: PrismaClient | undefined; +}; + +export const prisma = globalForPrisma.__prisma__ ?? new PrismaClient({ + // log: process.env.NODE_ENV === 'development' ? ['query', 'info', 'warn', 'error'] : [], +}); + +// Gunakan PrismaClient yang sama jika sudah ada +if (process.env.NODE_ENV !== 'production') { + if (!globalForPrisma.__prisma__) { + console.log('PrismaClient initialized in development mode'); + } + globalForPrisma.__prisma__ = prisma; } -const prisma = globalForPrisma.prisma ?? prismaClientSingleton() +process.on('SIGINT', async () => { + console.log('Disconnecting PrismaClient...'); + await prisma.$disconnect(); + process.exit(0); +}); -export default prisma - -if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma \ No newline at end of file +export default prisma; diff --git a/src/app/lib/realtime_provider.tsx b/src/app/lib/realtime_provider.tsx index ba302d45..42b32e7a 100644 --- a/src/app/lib/realtime_provider.tsx +++ b/src/app/lib/realtime_provider.tsx @@ -17,8 +17,6 @@ import { gs_votingTiggerBeranda, IRealtimeData, } from "./global_state"; -import { useState } from "react"; -import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global"; // const WIBU_REALTIME_TOKEN: string | undefined = // process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN; @@ -38,7 +36,6 @@ export default function RealtimeProvider({ userLoginId: string; WIBU_REALTIME_TOKEN: string; }) { - const [userId, setUserId] = useState(""); const [dataRealtime, setDataRealtime] = useAtom(gs_realtimeData); const [newAdminNtf, setNewAdminNtf] = useAtom(gs_admin_ntf); const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf); @@ -75,158 +72,138 @@ export default function RealtimeProvider({ ); useShallowEffect(() => { - onLoadUser({ - onSetUser(val: string) { - if (val !== "" || val !== undefined) { - try { - WibuRealtime.init({ - project: "hipmi", - WIBU_REALTIME_TOKEN: WIBU_REALTIME_TOKEN, - onData(data: TypeNotification) { - if ( - data.type == "notification" && - data.pushNotificationTo == "ADMIN" - ) { - setNewAdminNtf((e) => e + 1); - } - - // Notifikasi ke semua user , yang datanya di acc admin - if ( - data.type == "notification" && - data.pushNotificationTo == "USER" && - data.dataMessage?.userId == userId - ) { - setNewUserNtf((e) => e + 1); - setDataRealtime(data.dataMessage as any); - } - - // ---------------------- JOB ------------------------- // - if ( - data.type == "trigger" && - data.pushNotificationTo == "ADMIN" && - data.dataMessage?.kategoriApp == "JOB" - ) { - setIsAdminJob_TriggerReview(true); - } - - if ( - data.type == "trigger" && - data.pushNotificationTo == "USER" && - data.dataMessage?.kategoriApp == "JOB" && - data.dataMessage.status == "Publish" - ) { - setIsTriggerJobBeranda(true); - } - // ---------------------- JOB ------------------------- // - - // ---------------------- EVENT ------------------------- // - if ( - data.type == "trigger" && - data.pushNotificationTo == "ADMIN" && - data.dataMessage?.kategoriApp == "EVENT" - ) { - setIsAdminEvent_TriggerReview(true); - } - - if ( - data.type == "trigger" && - data.pushNotificationTo == "USER" && - data.dataMessage?.kategoriApp == "EVENT" && - data.dataMessage.status == "Publish" - ) { - setIsTriggerEventBeranda(true); - } - - if ( - data.type == "notification" && - data.pushNotificationTo == "USER" && - data.dataMessage?.status == "Peserta Event" && - userId !== data.dataMessage?.userId - ) { - setNewUserNtf((e) => e + 1); - } - // ---------------------- EVENT ------------------------- // - - // ---------------------- VOTING ------------------------- // - if ( - data.type == "trigger" && - data.pushNotificationTo == "ADMIN" && - data.dataMessage?.kategoriApp == "VOTING" - ) { - setIsAdminVoting_TriggerReview(true); - } - - if ( - data.type == "trigger" && - data.pushNotificationTo == "USER" && - data.dataMessage?.kategoriApp == "VOTING" && - data.dataMessage.status == "Publish" - ) { - setIsTriggerVotingBeranda(true); - } - - if ( - data.type == "notification" && - data.pushNotificationTo == "USER" && - data.dataMessage?.status == "Voting Masuk" && - userId !== data.dataMessage?.userId - ) { - setNewUserNtf((e) => e + 1); - } - // ---------------------- VOTING ------------------------- // - - // ---------------------- DONASI ------------------------- // - if ( - data.type == "trigger" && - data.pushNotificationTo == "ADMIN" && - data.dataMessage?.kategoriApp == "DONASI" - ) { - setIsAdminDonasi_TriggerReview(true); - } - - if ( - data.type == "trigger" && - data.pushNotificationTo == "USER" && - data.dataMessage?.kategoriApp == "DONASI" && - data.dataMessage.status == "Publish" - ) { - setIsTriggerDonasiBeranda(true); - } - - // if ( - // data.type == "notification" && - // data.pushNotificationTo == "ADMIN" && - // data.dataMessage?.status == "Menunggu" && - // userLoginId !== data.dataMessage?.userId - // ) { - // console.log("yes"); - // } - - // ---------------------- DONASI ------------------------- // - }, - }); - } catch (error) { - console.log(error); + try { + WibuRealtime.init({ + project: "hipmi", + WIBU_REALTIME_TOKEN: WIBU_REALTIME_TOKEN, + onData(data: TypeNotification) { + if ( + data.type == "notification" && + data.pushNotificationTo == "ADMIN" + ) { + setNewAdminNtf((e) => e + 1); } - } else { - return undefined; - } - }, - }); - }, [setUserId]); - async function onLoadUser({ - onSetUser, - }: { - onSetUser: (val: string) => void; - }) { - const res = await fetch("/api/user", { - method: "GET", - }); - const result = await res.json(); - onSetUser(result.data.id); - } + // Notifikasi ke semua user , yang datanya di acc admin + if ( + data.type == "notification" && + data.pushNotificationTo == "USER" && + data.dataMessage?.userId == userLoginId + ) { + setNewUserNtf((e) => e + 1); + setDataRealtime(data.dataMessage as any); + } + + // ---------------------- JOB ------------------------- // + if ( + data.type == "trigger" && + data.pushNotificationTo == "ADMIN" && + data.dataMessage?.kategoriApp == "JOB" + ) { + setIsAdminJob_TriggerReview(true); + } + + if ( + data.type == "trigger" && + data.pushNotificationTo == "USER" && + data.dataMessage?.kategoriApp == "JOB" && + data.dataMessage.status == "Publish" + ) { + setIsTriggerJobBeranda(true); + } + // ---------------------- JOB ------------------------- // + + // ---------------------- EVENT ------------------------- // + if ( + data.type == "trigger" && + data.pushNotificationTo == "ADMIN" && + data.dataMessage?.kategoriApp == "EVENT" + ) { + setIsAdminEvent_TriggerReview(true); + } + + if ( + data.type == "trigger" && + data.pushNotificationTo == "USER" && + data.dataMessage?.kategoriApp == "EVENT" && + data.dataMessage.status == "Publish" + ) { + setIsTriggerEventBeranda(true); + } + + if ( + data.type == "notification" && + data.pushNotificationTo == "USER" && + data.dataMessage?.status == "Peserta Event" && + userLoginId !== data.dataMessage?.userId + ) { + setNewUserNtf((e) => e + 1); + } + // ---------------------- EVENT ------------------------- // + + // ---------------------- VOTING ------------------------- // + if ( + data.type == "trigger" && + data.pushNotificationTo == "ADMIN" && + data.dataMessage?.kategoriApp == "VOTING" + ) { + setIsAdminVoting_TriggerReview(true); + } + + if ( + data.type == "trigger" && + data.pushNotificationTo == "USER" && + data.dataMessage?.kategoriApp == "VOTING" && + data.dataMessage.status == "Publish" + ) { + setIsTriggerVotingBeranda(true); + } + + if ( + data.type == "notification" && + data.pushNotificationTo == "USER" && + data.dataMessage?.status == "Voting Masuk" && + userLoginId !== data.dataMessage?.userId + ) { + setNewUserNtf((e) => e + 1); + } + // ---------------------- VOTING ------------------------- // + + // ---------------------- DONASI ------------------------- // + if ( + data.type == "trigger" && + data.pushNotificationTo == "ADMIN" && + data.dataMessage?.kategoriApp == "DONASI" + ) { + setIsAdminDonasi_TriggerReview(true); + } + + if ( + data.type == "trigger" && + data.pushNotificationTo == "USER" && + data.dataMessage?.kategoriApp == "DONASI" && + data.dataMessage.status == "Publish" + ) { + setIsTriggerDonasiBeranda(true); + } + + // if ( + // data.type == "notification" && + // data.pushNotificationTo == "ADMIN" && + // data.dataMessage?.status == "Menunggu" && + // userLoginId !== data.dataMessage?.userId + // ) { + // console.log("yes"); + // } + + // ---------------------- DONASI ------------------------- // + }, + }); + } catch (error) { + console.log("Error!:", error); + } + }, []); return null; } From 59584f246120432d68b5c204c6072804124b9576 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Thu, 5 Dec 2024 14:27:57 +0800 Subject: [PATCH 08/36] Fix prisma Deskripsi: - Fun user id di buat baru dan mengambil dari cookies --- next.config.js | 2 +- src/app/dev/layout.tsx | 3 --- src/app/lib/new_fun_user_id.ts | 25 ++++--------------------- src/app/lib/realtime_provider.tsx | 12 ++++++++++-- 4 files changed, 15 insertions(+), 27 deletions(-) diff --git a/next.config.js b/next.config.js index b00f93a2..5c728631 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - // reactStrictMode: false, + reactStrictMode: false, experimental: { serverActions: true }, diff --git a/src/app/dev/layout.tsx b/src/app/dev/layout.tsx index 1ac8606a..49f4a4c7 100644 --- a/src/app/dev/layout.tsx +++ b/src/app/dev/layout.tsx @@ -7,12 +7,9 @@ export default async function Layout({ }: { children: React.ReactNode; }) { - const userLoginId = await newFunGetUserId(); - return ( <> | null> { - try { - const enc = new TextEncoder().encode(encodedKey); - const { payload } = await jwtVerify(token, enc, { - algorithms: ["HS256"], - }); - return (payload.user as Record) || null; - } catch (error) { - console.error("Gagal verifikasi session", error); - return null; - } -} +} \ No newline at end of file diff --git a/src/app/lib/realtime_provider.tsx b/src/app/lib/realtime_provider.tsx index 42b32e7a..07919a7f 100644 --- a/src/app/lib/realtime_provider.tsx +++ b/src/app/lib/realtime_provider.tsx @@ -17,6 +17,8 @@ import { gs_votingTiggerBeranda, IRealtimeData, } from "./global_state"; +import { newFunGetUserId } from "./new_fun_user_id"; +import { useState } from "react"; // const WIBU_REALTIME_TOKEN: string | undefined = // process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN; @@ -30,12 +32,11 @@ export type TypeNotification = { }; export default function RealtimeProvider({ - userLoginId, WIBU_REALTIME_TOKEN, }: { - userLoginId: string; WIBU_REALTIME_TOKEN: string; }) { + const [userLoginId, setUserLoginId] = useState(""); const [dataRealtime, setDataRealtime] = useAtom(gs_realtimeData); const [newAdminNtf, setNewAdminNtf] = useAtom(gs_admin_ntf); const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf); @@ -71,7 +72,14 @@ export default function RealtimeProvider({ gs_donasiTriggerBeranda ); + async function loadUserId() { + const userId = await newFunGetUserId(); + + setUserLoginId(userId as string); + } + useShallowEffect(() => { + loadUserId(); try { WibuRealtime.init({ From 2fa96d47baa91a5c90a2ac9a15c3f8beae69a15f Mon Sep 17 00:00:00 2001 From: amel Date: Thu, 5 Dec 2024 15:12:18 +0800 Subject: [PATCH 09/36] fix :home Deskripsi: - home pake api No Issues --- src/app/api/new/home/route.ts | 68 ++++++ src/app/api/new/user/route.ts | 61 ++++++ src/app/dev/(user)/home/page.tsx | 16 +- src/app_modules/home/component/body_home.tsx | 193 ++++++++++++++++++ .../home/component/footer_home.tsx | 113 ++++++++++ .../home/component/list_menu_home.tsx | 67 ++++++ src/app_modules/home/fun/get/api_home.ts | 4 + src/app_modules/home/index.ts | 4 +- src/app_modules/home/view_home_new.tsx | 127 ++++++++++++ src/app_modules/user/index.ts | 5 + src/app_modules/user/lib/api_user.ts | 4 + src/app_modules/user/lib/type_user.ts | 14 ++ src/middleware.ts | 1 + 13 files changed, 667 insertions(+), 10 deletions(-) create mode 100644 src/app/api/new/home/route.ts create mode 100644 src/app/api/new/user/route.ts create mode 100644 src/app_modules/home/component/body_home.tsx create mode 100644 src/app_modules/home/component/footer_home.tsx create mode 100644 src/app_modules/home/component/list_menu_home.tsx create mode 100644 src/app_modules/home/fun/get/api_home.ts create mode 100644 src/app_modules/home/view_home_new.tsx create mode 100644 src/app_modules/user/index.ts create mode 100644 src/app_modules/user/lib/api_user.ts create mode 100644 src/app_modules/user/lib/type_user.ts diff --git a/src/app/api/new/home/route.ts b/src/app/api/new/home/route.ts new file mode 100644 index 00000000..3e07f313 --- /dev/null +++ b/src/app/api/new/home/route.ts @@ -0,0 +1,68 @@ +import { prisma } from "@/app/lib"; +import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; +import { NextResponse } from "next/server"; + + +// GET DATA HOME +export async function GET(request: Request) { + try { + let fixData + const { searchParams } = new URL(request.url) + const kategori = searchParams.get("cat") + + const userLoginId = await funGetUserIdByToken() + if (userLoginId == null) { + return NextResponse.json({ success: false, message: "Gagal mendapatkan data, user id tidak ada" }, { status: 500 }); + } + + if (kategori == "job") { + fixData = await prisma.job.findMany({ + take: 2, + orderBy: { + createdAt: "desc", + }, + where: { + isActive: true, + masterStatusId: "1" + }, + select: { + id: true, + Author: { + select: { + id: true, + username: true, + }, + }, + title: true, + deskripsi: true + }, + }); + } else if (kategori == "cek_profile") { + const data = await prisma.user.findUnique({ + where: { + id: userLoginId, + }, + select: { + Profile: { + select: { + id: true, + imageId: true, + } + } + } + }); + + fixData = { + profile: data?.Profile?.id, + imageId: data?.Profile?.imageId + } + + } + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: fixData }, { status: 200 }); + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/new/user/route.ts b/src/app/api/new/user/route.ts new file mode 100644 index 00000000..8a343879 --- /dev/null +++ b/src/app/api/new/user/route.ts @@ -0,0 +1,61 @@ +import { prisma } from "@/app/lib"; +import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; +import { NextResponse } from "next/server"; + + +// GET DATA USER LOGIN +export async function GET(request: Request) { + try { + const userLoginId = await funGetUserIdByToken() + if (userLoginId == null) { + return NextResponse.json({ success: false, message: "Gagal mendapatkan data, user id tidak ada" }, { status: 500 }); + } + + const data = await prisma.user.findFirst({ + where: { + id: userLoginId, + }, + select: { + id: true, + username: true, + nomor: true, + active: true, + masterUserRoleId: true, + Profile: { + select: { + id: true, + name: true, + email: true, + alamat: true, + jenisKelamin: true, + imageId: true, + imageBackgroundId: true + } + } + } + }); + + const dataFix = { + id: data?.id, + username: data?.username, + nomor: data?.nomor, + active: data?.active, + masterUserRoleId: data?.masterUserRoleId, + idProfile: data?.Profile?.id, + name: data?.Profile?.name, + email: data?.Profile?.email, + alamat: data?.Profile?.alamat, + jenisKelamin: data?.Profile?.jenisKelamin, + imageId: data?.Profile?.imageId, + imageBackgroundId: data?.Profile?.imageBackgroundId + + } + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix, }, { status: 200 }); + + } + catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/dev/(user)/home/page.tsx b/src/app/dev/(user)/home/page.tsx index dcfc7882..4bd78e32 100644 --- a/src/app/dev/(user)/home/page.tsx +++ b/src/app/dev/(user)/home/page.tsx @@ -1,23 +1,21 @@ -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { HomeView } from "@/app_modules/home"; -import { user_getOneByUserId } from "@/app_modules/home/fun/get/get_one_user_by_id"; -import { job_getTwoForHomeView } from "@/app_modules/job/fun/get/get_two_for_home_view"; +import { HomeViewNew } from "@/app_modules/home"; import notifikasi_countUserNotifikasi from "@/app_modules/notifikasi/fun/count/fun_count_by_id"; export default async function PageHome() { - const userLoginId = await funGetUserIdByToken(); - const dataUser = await user_getOneByUserId(userLoginId as string); - const dataJob = await job_getTwoForHomeView(); + // const userLoginId = await funGetUserIdByToken(); + // const dataUser = await user_getOneByUserId(userLoginId as string); + // const dataJob = await job_getTwoForHomeView(); const countNotifikasi = await notifikasi_countUserNotifikasi(); return ( <> - + /> */} + ); } diff --git a/src/app_modules/home/component/body_home.tsx b/src/app_modules/home/component/body_home.tsx new file mode 100644 index 00000000..d5984b8d --- /dev/null +++ b/src/app_modules/home/component/body_home.tsx @@ -0,0 +1,193 @@ +import { AccentColor, MainColor } from "@/app_modules/_global/color"; +import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; +import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global"; +import { ActionIcon, Box, Group, Image, Paper, SimpleGrid, Skeleton, Stack, Text } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { IconUserSearch } from "@tabler/icons-react"; +import _ from "lodash"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { apiGetDataHome } from "../fun/get/api_home"; +import { listMenuHomeBody, menuHomeJob } from "./list_menu_home"; + +export default function BodyHome() { + const router = useRouter() + const [dataUser, setDataUser] = useState({}) + const [dataJob, setDataJob] = useState([]) + const [loadingJob, setLoadingJob] = useState(true) + + useShallowEffect(() => { + cekUserLogin() + getHomeJob() + }, []); + + + async function cekUserLogin() { + try { + const response = await apiGetDataHome("?cat=cek_profile") + if (response.success) { + setDataUser(response.data); + } + } catch (error) { + console.error(error); + } + } + + async function getHomeJob() { + try { + setLoadingJob(true) + const response = await apiGetDataHome("?cat=job") + if (response.success) { + setDataJob(response.data); + } + } catch (error) { + console.error(error); + } finally { + setLoadingJob(false) + } + } + + return ( + + + logo + + + + + {listMenuHomeBody.map((e, i) => ( + { + if (dataUser.profile === undefined || dataUser?.profile === null) { + return ComponentGlobal_NotifikasiPeringatan( + "Lengkapi Profile" + ); + } else { + if (e.link === "") { + return ComponentGlobal_NotifikasiPeringatan( + "Cooming Soon !!" + ); + } else { + router.push(e.link, { scroll: false }); + } + } + }} + > + + + {e.icon} + + + {e.name} + + + + ))} + + + {/* Job View */} + + { + if (dataUser.profile === undefined || dataUser?.profile === null) { + return ComponentGlobal_NotifikasiPeringatan( + "Lengkapi Profile" + ); + } else { + if (menuHomeJob.link === "") { + return ComponentGlobal_NotifikasiPeringatan( + "Cooming Soon !!" + ); + } else { + return router.push(menuHomeJob.link, { scroll: false }); + } + } + }} + > + + + {menuHomeJob.icon} + + + {menuHomeJob.name} + + + { + loadingJob ? + Array(2) + .fill(null) + .map((_, i) => ( + + + + + + )) + : _.isEmpty(dataJob) ? + () + : ( + + {dataJob.map((e, i) => ( + + + + + + + + {e?.Author.username} + + + {e?.title} + + + + + ))} + + ) + } + + + + + ); +} \ No newline at end of file diff --git a/src/app_modules/home/component/footer_home.tsx b/src/app_modules/home/component/footer_home.tsx new file mode 100644 index 00000000..f116b19d --- /dev/null +++ b/src/app_modules/home/component/footer_home.tsx @@ -0,0 +1,113 @@ +import { APIs } from "@/app/lib"; +import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog"; +import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global"; +import { ActionIcon, Box, Center, SimpleGrid, Stack, Text } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { IconUserCircle } from "@tabler/icons-react"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { apiGetDataHome } from "../fun/get/api_home"; +import { Home_ComponentAvatarProfile } from "./comp_avatar_profile"; +import { listMenuHomeFooter } from "./list_menu_home"; + +export default function FooterHome() { + const router = useRouter() + const [dataUser, setDataUser] = useState({}) + + useShallowEffect(() => { + cekUserLogin(); + }, []); + + + async function cekUserLogin() { + try { + const response = await apiGetDataHome("?cat=cek_profile") + if (response.success) { + setDataUser(response.data); + } + } catch (error) { + console.error(error); + } + } + + return ( + + + {listMenuHomeFooter.map((e) => ( +
+ { + if (dataUser.profile === undefined || dataUser?.profile === null) { + ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile"); + } else { + if (e.link == "") { + ComponentGlobal_NotifikasiPeringatan("Cooming Soon") + } else { + router.push(e.link, { scroll: false }) + } + } + }} + > + + {e.icon} + + + {e.name} + + +
+ ))} + +
+ { + if (dataUser.profile === undefined || dataUser?.profile === null) { + router.push(RouterProfile.create, { scroll: false }); + } else { + router.push( + RouterProfile.katalogOLD + `${dataUser?.profile}`, + { scroll: false } + ); + } + }} + > + + {dataUser.profile === undefined || dataUser?.profile === null + ? + + : + + } + + + Profile + + +
+
+
+ ); +} \ No newline at end of file diff --git a/src/app_modules/home/component/list_menu_home.tsx b/src/app_modules/home/component/list_menu_home.tsx new file mode 100644 index 00000000..8b9de429 --- /dev/null +++ b/src/app_modules/home/component/list_menu_home.tsx @@ -0,0 +1,67 @@ +import { RouterColab } from '@/app/lib/router_hipmi/router_colab'; +import { RouterEvent } from '@/app/lib/router_hipmi/router_event'; +import { RouterForum } from '@/app/lib/router_hipmi/router_forum'; +import { RouterJob } from '@/app/lib/router_hipmi/router_job'; +import { RouterMap } from '@/app/lib/router_hipmi/router_map'; +import { RouterVote } from '@/app/lib/router_hipmi/router_vote'; +import { IconAffiliate, IconBriefcase, IconHeartHandshake, IconMap2, IconMessages, IconPackageImport, IconPresentation, IconShoppingBag } from '@tabler/icons-react'; + + +// yg ada di footer home +export const listMenuHomeFooter = [ + { + id: 1, + name: "Forums", + icon: , + link: RouterForum.splash, + }, + { + id: 2, + name: "MarketPlace", + icon: , + link: "", + }, + { + id: 3, + name: "Business Maps", + icon: , + link: RouterMap.splash, + }, +]; + + +// yg ada di kotak2 home (body) +export const listMenuHomeBody = [ + { + id: 1, + name: "Event", + icon: , + link: RouterEvent.splash, + }, + { + id: 2, + name: "Collaboration", + icon: , + link: RouterColab.splash, + }, + + { + id: 3, + name: "Voting", + icon: , + link: RouterVote.splash, + }, + + { + id: 4, + name: "Crowd Funding", + icon: , + link: `/dev/crowd/splash`, + }, +]; + +export const menuHomeJob = { + name: "Job Vacancy", + icon: , + link: RouterJob.spalsh, +}; \ No newline at end of file diff --git a/src/app_modules/home/fun/get/api_home.ts b/src/app_modules/home/fun/get/api_home.ts new file mode 100644 index 00000000..e55ec5eb --- /dev/null +++ b/src/app_modules/home/fun/get/api_home.ts @@ -0,0 +1,4 @@ +export const apiGetDataHome = async (path?: string) => { + const response = await fetch(`/api/new/home${(path) ? path : ''}`) + return await response.json().catch(() => null) +} \ No newline at end of file diff --git a/src/app_modules/home/index.ts b/src/app_modules/home/index.ts index 07785dd4..e0eda0b5 100644 --- a/src/app_modules/home/index.ts +++ b/src/app_modules/home/index.ts @@ -1,4 +1,6 @@ +import { listMenuHomeFooter } from './component/list_menu_home'; import HomeView from "./view_home"; +import HomeViewNew from "./view_home_new"; import Home_UserNotActive from "./user_non_active"; -export { HomeView, Home_UserNotActive as Home_UserNonActive }; +export { HomeView, HomeViewNew, listMenuHomeFooter, Home_UserNotActive as Home_UserNonActive }; diff --git a/src/app_modules/home/view_home_new.tsx b/src/app_modules/home/view_home_new.tsx new file mode 100644 index 00000000..8fbe5441 --- /dev/null +++ b/src/app_modules/home/view_home_new.tsx @@ -0,0 +1,127 @@ +"use client"; +import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state"; +import { RouterNotifikasi } from "@/app/lib/router_hipmi/router_notifikasi"; +import { RouterUserSearch } from "@/app/lib/router_hipmi/router_user_search"; +import { ActionIcon, Indicator, Text } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { IconBell, IconUserSearch } from "@tabler/icons-react"; +import { useAtom } from "jotai"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { MainColor } from "../_global/color"; +import { ComponentGlobal_NotifikasiPeringatan } from "../_global/notif_global"; +import UIGlobal_LayoutHeaderTamplate from "../_global/ui/ui_header_tamplate"; +import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate"; +import notifikasi_countUserNotifikasi from "../notifikasi/fun/count/fun_count_by_id"; +import BodyHome from "./component/body_home"; +import FooterHome from "./component/footer_home"; +import { apiGetDataHome } from "./fun/get/api_home"; + +export default function HomeViewNew({ countNotifikasi }: { countNotifikasi: number; }) { + const [countNtf, setCountNtf] = useState(countNotifikasi); + const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf); + const [countLoadNtf, setCountLoadNtf] = useAtom(gs_count_ntf); + const [dataUser, setDataUser] = useState({}) + const router = useRouter(); + + + useShallowEffect(() => { + onLoadNotifikasi({ + onLoad(val) { + setCountNtf(val); + }, + }); + + setCountNtf(countLoadNtf as any); + }, [countLoadNtf, setCountNtf]); + + useShallowEffect(() => { + setCountNtf(countNtf + newUserNtf); + setNewUserNtf(0); + }, [newUserNtf, setCountNtf]); + + async function onLoadNotifikasi({ onLoad }: { onLoad: (val: any) => void }) { + const loadNotif = await notifikasi_countUserNotifikasi(); + onLoad(loadNotif); + } + + useShallowEffect(() => { + cekUserLogin(); + }, []); + + + async function cekUserLogin() { + try { + const response = await apiGetDataHome("?cat=cek_profile") + if (response.success) { + setDataUser(response.data); + } + } catch (error) { + console.error(error); + } + } + + return ( + <> + { + if (dataUser.profile === undefined || dataUser?.profile === null) { + ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile"); + } else { + router.push(RouterUserSearch.main, { scroll: false }); + } + }} + > + + + } + customButtonRight={ + { + if (dataUser.profile === undefined || dataUser?.profile === null) { + ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile"); + } else { + router.push(RouterNotifikasi.categoryApp({ name: "semua" }), { + scroll: false, + }); + } + }} + > + { + countNotifikasi > 0 + ? + + {countNotifikasi > 99 ? "99+" : countNotifikasi} + + } + > + + + : + + } + + + } + /> + } + + footer={} + > + + + + ); +} diff --git a/src/app_modules/user/index.ts b/src/app_modules/user/index.ts new file mode 100644 index 00000000..343e274c --- /dev/null +++ b/src/app_modules/user/index.ts @@ -0,0 +1,5 @@ +import { IUserLogin } from './lib/type_user'; +import { apiGetUserLogin } from "./lib/api_user"; + +export { apiGetUserLogin }; +export type { IUserLogin }; diff --git a/src/app_modules/user/lib/api_user.ts b/src/app_modules/user/lib/api_user.ts new file mode 100644 index 00000000..8db7415b --- /dev/null +++ b/src/app_modules/user/lib/api_user.ts @@ -0,0 +1,4 @@ +export const apiGetUserLogin = async () => { + const response = await fetch(`/api/new/user`) + return await response.json().catch(() => null) +} \ No newline at end of file diff --git a/src/app_modules/user/lib/type_user.ts b/src/app_modules/user/lib/type_user.ts new file mode 100644 index 00000000..a0f63da4 --- /dev/null +++ b/src/app_modules/user/lib/type_user.ts @@ -0,0 +1,14 @@ +export interface IUserLogin { + id: string + username: string + nomor: string + active:boolean + masterUserRoleId: string + idProfile: string + name: string + email: string + alamat: string + jenisKelamin: string + imageId: string + imageBackgroundId: string +} \ No newline at end of file diff --git a/src/middleware.ts b/src/middleware.ts index d08b310f..621bde58 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -32,6 +32,7 @@ const middlewareConfig: MiddlewareConfig = { "/auth/api/login", "/aset/global/main_background.png", "/aset/logo/logo-hipmi.png", + "/api/new/*" ], encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, From 66c65bc937089fb0f3bcf09f32e239790d704be3 Mon Sep 17 00:00:00 2001 From: amel Date: Thu, 5 Dec 2024 17:21:59 +0800 Subject: [PATCH 10/36] upd: profile dan katalog Deskripsi: - mecah dan ganti ke api No Issues --- src/app/api/new/portofolio/route.ts | 55 +++++++ src/app/api/new/user/route.ts | 61 ++++---- src/app/dev/katalog/[id]/page.tsx | 8 +- src/app_modules/katalog/index.ts | 2 + src/app_modules/katalog/portofolio/index.ts | 4 + .../katalog/portofolio/lib/api_portofolio.ts | 4 + .../katalog/portofolio/lib/type_portofolio.ts | 6 + .../katalog/ui/list_portolio_new.tsx | 139 ++++++++++++++++++ src/app_modules/katalog/ui/profile_detail.tsx | 131 +++++++++++++++++ .../katalog/ui/skeleton_profile.tsx | 42 ++++++ src/app_modules/katalog/view_katalog_new.tsx | 20 +++ src/app_modules/user/index.ts | 8 +- src/app_modules/user/lib/api_user.ts | 4 +- src/app_modules/user/lib/type_user.ts | 2 +- 14 files changed, 444 insertions(+), 42 deletions(-) create mode 100644 src/app/api/new/portofolio/route.ts create mode 100644 src/app_modules/katalog/portofolio/lib/api_portofolio.ts create mode 100644 src/app_modules/katalog/portofolio/lib/type_portofolio.ts create mode 100644 src/app_modules/katalog/ui/list_portolio_new.tsx create mode 100644 src/app_modules/katalog/ui/profile_detail.tsx create mode 100644 src/app_modules/katalog/ui/skeleton_profile.tsx create mode 100644 src/app_modules/katalog/view_katalog_new.tsx diff --git a/src/app/api/new/portofolio/route.ts b/src/app/api/new/portofolio/route.ts new file mode 100644 index 00000000..357f42b3 --- /dev/null +++ b/src/app/api/new/portofolio/route.ts @@ -0,0 +1,55 @@ +import { prisma } from "@/app/lib"; +import { NextResponse } from "next/server"; + + +// GET ALL DATA PORTOFOLIO BY PROFILE ID +export async function GET(request: Request) { + try { + let fixData + const { searchParams } = new URL(request.url) + const profile = searchParams.get("profile") + const page = searchParams.get("page") + + if (page == "profile") { + fixData = await prisma.portofolio.findMany({ + take: 2, + orderBy: { + createdAt: "desc", + }, + where: { + profileId: profile, + active: true, + }, + select: { + id: true, + id_Portofolio: true, + namaBisnis: true, + profileId: true, + }, + }); + } else if (page == "portofolio") { + fixData = await prisma.portofolio.findMany({ + orderBy: { + createdAt: "desc", + }, + where: { + profileId: profile, + active: true, + }, + select: { + id: true, + id_Portofolio: true, + namaBisnis: true, + profileId: true, + }, + }); + } + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: fixData }, { status: 200 }); + + } + catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/new/user/route.ts b/src/app/api/new/user/route.ts index 8a343879..73a4fb52 100644 --- a/src/app/api/new/user/route.ts +++ b/src/app/api/new/user/route.ts @@ -1,53 +1,50 @@ import { prisma } from "@/app/lib"; -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; import { NextResponse } from "next/server"; -// GET DATA USER LOGIN +// GET ONE DATA USER PROFILE BY PROFILE ID export async function GET(request: Request) { try { - const userLoginId = await funGetUserIdByToken() - if (userLoginId == null) { - return NextResponse.json({ success: false, message: "Gagal mendapatkan data, user id tidak ada" }, { status: 500 }); - } + const { searchParams } = new URL(request.url) + const profile = searchParams.get("profile") - const data = await prisma.user.findFirst({ + const data = await prisma.profile.findUnique({ where: { - id: userLoginId, + id: String(profile), }, select: { id: true, - username: true, - nomor: true, - active: true, - masterUserRoleId: true, - Profile: { + name: true, + email: true, + alamat: true, + jenisKelamin: true, + imageId: true, + imageBackgroundId: true, + userId: true, + User: { select: { - id: true, - name: true, - email: true, - alamat: true, - jenisKelamin: true, - imageId: true, - imageBackgroundId: true + username: true, + nomor: true, + active: true, + masterUserRoleId: true } } } }); const dataFix = { - id: data?.id, - username: data?.username, - nomor: data?.nomor, - active: data?.active, - masterUserRoleId: data?.masterUserRoleId, - idProfile: data?.Profile?.id, - name: data?.Profile?.name, - email: data?.Profile?.email, - alamat: data?.Profile?.alamat, - jenisKelamin: data?.Profile?.jenisKelamin, - imageId: data?.Profile?.imageId, - imageBackgroundId: data?.Profile?.imageBackgroundId + id: data?.userId, + username: data?.User?.username, + nomor: data?.User?.nomor, + active: data?.User?.active, + masterUserRoleId: data?.User?.masterUserRoleId, + idProfile: data?.id, + name: data?.name, + email: data?.email, + alamat: data?.alamat, + jenisKelamin: data?.jenisKelamin, + imageId: data?.imageId, + imageBackgroundId: data?.imageBackgroundId } diff --git a/src/app/dev/katalog/[id]/page.tsx b/src/app/dev/katalog/[id]/page.tsx index 24cccdab..e37c8933 100644 --- a/src/app/dev/katalog/[id]/page.tsx +++ b/src/app/dev/katalog/[id]/page.tsx @@ -1,5 +1,5 @@ import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { Katalog_MainView } from "@/app_modules/katalog"; +import { Katalog_MainView, ViewKatalogNew } from "@/app_modules/katalog"; import { funGetListPortofolio } from "@/app_modules/katalog/portofolio/fun/get/get_list_portofolio"; import { Profile_getOneProfileAndUserById } from "@/app_modules/katalog/profile/fun/get/get_one_user_profile"; @@ -12,11 +12,13 @@ export default async function Page({ params }: { params: { id: string } }) { return ( <> - + /> */} + + ); } diff --git a/src/app_modules/katalog/index.ts b/src/app_modules/katalog/index.ts index 9892f2b6..165c1ec3 100644 --- a/src/app_modules/katalog/index.ts +++ b/src/app_modules/katalog/index.ts @@ -1,2 +1,4 @@ +import ViewKatalogNew from "./view_katalog_new"; export { Katalog_MainView } from "./view_katalog"; +export { ViewKatalogNew } diff --git a/src/app_modules/katalog/portofolio/index.ts b/src/app_modules/katalog/portofolio/index.ts index 062117f7..b45526dc 100644 --- a/src/app_modules/katalog/portofolio/index.ts +++ b/src/app_modules/katalog/portofolio/index.ts @@ -1,3 +1,5 @@ +import { IListPortofolio } from './lib/type_portofolio'; +import { apiGetPortofolioByProfile } from './lib/api_portofolio'; import CreatePortofolio from "./create/view"; import CreatePortofolioLayout from "./create/layout"; import PortofolioLayout from "./ui/ui_layout"; @@ -20,6 +22,8 @@ export { LayoutPortofolio_EditDataBisnis, LayoutPortofolio_EditLogoBisnis, LayoutPortofolio_EditMedsosBisnis, + apiGetPortofolioByProfile }; +export type { IListPortofolio }; export { Portofolio_ViewListDetail } from "./view/view_list_detail_portofolio"; diff --git a/src/app_modules/katalog/portofolio/lib/api_portofolio.ts b/src/app_modules/katalog/portofolio/lib/api_portofolio.ts new file mode 100644 index 00000000..a4c460db --- /dev/null +++ b/src/app_modules/katalog/portofolio/lib/api_portofolio.ts @@ -0,0 +1,4 @@ +export const apiGetPortofolioByProfile = async (path?: string) => { + const response = await fetch(`/api/new/portofolio${(path) ? path : ''}`) + return await response.json().catch(() => null) +} \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/lib/type_portofolio.ts b/src/app_modules/katalog/portofolio/lib/type_portofolio.ts new file mode 100644 index 00000000..637935e1 --- /dev/null +++ b/src/app_modules/katalog/portofolio/lib/type_portofolio.ts @@ -0,0 +1,6 @@ +export interface IListPortofolio { + id: string + id_Portofolio: string + profileId: string + namaBisnis: string +} \ No newline at end of file diff --git a/src/app_modules/katalog/ui/list_portolio_new.tsx b/src/app_modules/katalog/ui/list_portolio_new.tsx new file mode 100644 index 00000000..b1118bb3 --- /dev/null +++ b/src/app_modules/katalog/ui/list_portolio_new.tsx @@ -0,0 +1,139 @@ +import { AccentColor, MainColor } from "@/app_modules/_global/color"; +import { Box, Center, Group, Paper, Skeleton, Stack, Text, Title } from "@mantine/core"; +import { apiGetPortofolioByProfile, IListPortofolio } from "../portofolio"; +import { useState } from "react"; +import { useParams, useRouter } from "next/navigation"; +import { useShallowEffect } from "@mantine/hooks"; +import _ from "lodash"; +import { RouterPortofolio } from "@/app/lib/router_hipmi/router_katalog"; +import { IconCaretRight } from "@tabler/icons-react"; + +export default function ListPortofolioProfileNew() { + const router = useRouter(); + const param = useParams<{ id: string }>() + const [loading, setLoading] = useState(true) + const [dataPortofolio, setDataPortofolio] = useState([]) + + async function getPortofolio() { + try { + setLoading(true) + const response = await apiGetPortofolioByProfile(`?profile=${param.id}&page=profile`) + if (response.success) { + setDataPortofolio(response.data); + } + } catch (error) { + console.error(error); + } finally { + setLoading(false) + } + } + + + useShallowEffect(() => { + getPortofolio() + }, []); + + + return ( + <> + + + + Portofolio + + + + { + loading ? + <> + + + + : + + _.isEmpty(dataPortofolio) ? ( +
+ + - Belum Ada Portofolio - + +
+ ) : ( + + {dataPortofolio.map((e, i) => ( + { + router.push(RouterPortofolio.main_detail + e?.id); + }} + style={{ + backgroundColor: MainColor.darkblue, + border: `2px solid ${AccentColor.blue}`, + borderRadius: "10px ", + padding: "15px", + color: "white", + }} + > + + + + {e?.namaBisnis} + + + #{e.id_Portofolio} + + + + + + + + ))} + + ) + } + + { + loading ? <> + : + _.isEmpty(dataPortofolio) ? ( + "" + ) : ( + + + router.push( + RouterPortofolio.daftar_portofolio + param.id, + { scroll: false } + ) + } + fw={"bold"} + fz={"sm"} + > + Lihat semua + + + ) + } +
+
+
+ + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/ui/profile_detail.tsx b/src/app_modules/katalog/ui/profile_detail.tsx new file mode 100644 index 00000000..e5c4ca20 --- /dev/null +++ b/src/app_modules/katalog/ui/profile_detail.tsx @@ -0,0 +1,131 @@ +import { AccentColor } from "@/app_modules/_global/color"; +import { apiGetUserProfile, IUserProfile } from "@/app_modules/user"; +import { Box, Center, Group, Stack, Text, ThemeIcon } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { IconBrandGmail, IconGenderFemale, IconGenderMale, IconHome, IconPhone } from "@tabler/icons-react"; +import { useParams } from "next/navigation"; +import { useState } from "react"; +import { Profile_ComponentAvatarProfile, Profile_ComponentLoadBackgroundImage } from "../profile/_component"; +import SkeletonProfile from "./skeleton_profile"; + +export default function ProfileDetail() { + const param = useParams<{ id: string }>() + const [loading, setLoading] = useState(true) + const [dataProfile, setDataProfile] = useState() + const listInformation = [ + { + icon: , + value: "+" + dataProfile?.nomor, + }, + { + icon: , + value: dataProfile?.email, + }, + { + icon: , + value: dataProfile?.alamat, + }, + { + icon: + dataProfile?.jenisKelamin === "Laki-laki" ? ( + + ) : ( + + ), + value: dataProfile?.jenisKelamin, + }, + ]; + + + async function getProfile() { + try { + setLoading(true) + const response = await apiGetUserProfile(`?profile=${param.id}`) + if (response.success) { + setDataProfile(response.data); + } + } catch (error) { + console.error(error); + } finally { + setLoading(false) + } + } + + + useShallowEffect(() => { + getProfile() + }, []); + + return <> + + { + loading ? + : + <> + + + + +
+ +
+ + + {dataProfile?.name} + + + @{dataProfile?.username} + + +
+
+ + + {listInformation.map((e, i) => ( + + + {e.icon} + + + {e?.value} + + + ))} + + + + } +
+ ; +} \ No newline at end of file diff --git a/src/app_modules/katalog/ui/skeleton_profile.tsx b/src/app_modules/katalog/ui/skeleton_profile.tsx new file mode 100644 index 00000000..bc64b0da --- /dev/null +++ b/src/app_modules/katalog/ui/skeleton_profile.tsx @@ -0,0 +1,42 @@ +import { Avatar, Box, Center, Grid, Skeleton, Stack } from "@mantine/core"; + +export default function SkeletonProfile() { + return ( + <> + + + +
+ +
+
+ + + + + + + {[...Array(4)].map((_, index) => ( + + + + + + + + + + + ))} + +
+ + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/view_katalog_new.tsx b/src/app_modules/katalog/view_katalog_new.tsx new file mode 100644 index 00000000..1ce3c013 --- /dev/null +++ b/src/app_modules/katalog/view_katalog_new.tsx @@ -0,0 +1,20 @@ +'use client' +import { Stack } from "@mantine/core"; +import ProfileDetail from "./ui/profile_detail"; +import ListPortofolioProfileNew from "./ui/list_portolio_new"; + +export default function ViewKatalogNew() { + return ( + <> + + + {/* */} + + + + ) +} \ No newline at end of file diff --git a/src/app_modules/user/index.ts b/src/app_modules/user/index.ts index 343e274c..8779b5f7 100644 --- a/src/app_modules/user/index.ts +++ b/src/app_modules/user/index.ts @@ -1,5 +1,5 @@ -import { IUserLogin } from './lib/type_user'; -import { apiGetUserLogin } from "./lib/api_user"; +import { IUserProfile } from './lib/type_user'; +import { apiGetUserProfile } from "./lib/api_user"; -export { apiGetUserLogin }; -export type { IUserLogin }; +export { apiGetUserProfile }; +export type { IUserProfile }; diff --git a/src/app_modules/user/lib/api_user.ts b/src/app_modules/user/lib/api_user.ts index 8db7415b..7fca1371 100644 --- a/src/app_modules/user/lib/api_user.ts +++ b/src/app_modules/user/lib/api_user.ts @@ -1,4 +1,4 @@ -export const apiGetUserLogin = async () => { - const response = await fetch(`/api/new/user`) +export const apiGetUserProfile = async (path?: string) => { + const response = await fetch(`/api/new/user${(path) ? path : ''}`) return await response.json().catch(() => null) } \ No newline at end of file diff --git a/src/app_modules/user/lib/type_user.ts b/src/app_modules/user/lib/type_user.ts index a0f63da4..2f5a2177 100644 --- a/src/app_modules/user/lib/type_user.ts +++ b/src/app_modules/user/lib/type_user.ts @@ -1,4 +1,4 @@ -export interface IUserLogin { +export interface IUserProfile { id: string username: string nomor: string From 057df80c316fe6385e407536b71cbd91115b5fc3 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Fri, 6 Dec 2024 09:08:57 +0800 Subject: [PATCH 11/36] Fix event Deskripsi: - Fix konfirmasi - Fix qr code --- next.config.js | 13 +- src/app/api/event/check-kehadiran/route.ts | 2 +- src/app/api/event/get-all-by-userId/route.ts | 9 - src/app/api/event/get-all/route.ts | 12 + src/app/api/event/get-one-by-id/route.ts | 21 + src/app/dev/event/create/page.tsx | 4 +- src/app/dev/event/konfirmasi/[id]/page.tsx | 45 +- src/app/dev/event/main/beranda/page.tsx | 4 +- .../lib/api_user_router/route_api_event.ts | 7 + .../admin/event/_view/view_table_review.tsx | 12 +- src/app_modules/event/_ui/konfirmasi.tsx | 396 ++++++++++++++---- .../component/card_view/card_beranda.tsx | 6 +- src/app_modules/event/component/index.ts | 2 + .../skeleton/comp_skeleton_beranda.tsx | 29 ++ src/app_modules/event/main/beranda.tsx | 31 +- src/app_modules/event/splash/index.tsx | 2 +- 16 files changed, 436 insertions(+), 159 deletions(-) delete mode 100644 src/app/api/event/get-all-by-userId/route.ts create mode 100644 src/app/api/event/get-all/route.ts create mode 100644 src/app/api/event/get-one-by-id/route.ts create mode 100644 src/app/lib/api_user_router/route_api_event.ts create mode 100644 src/app_modules/event/component/skeleton/comp_skeleton_beranda.tsx diff --git a/next.config.js b/next.config.js index 5c728631..79d67970 100644 --- a/next.config.js +++ b/next.config.js @@ -1,10 +1,9 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - reactStrictMode: false, - experimental: { - serverActions: true - }, - -} + reactStrictMode: false, + experimental: { + serverActions: true, + }, +}; -module.exports = nextConfig +module.exports = nextConfig; diff --git a/src/app/api/event/check-kehadiran/route.ts b/src/app/api/event/check-kehadiran/route.ts index 3b2ef875..083f6e05 100644 --- a/src/app/api/event/check-kehadiran/route.ts +++ b/src/app/api/event/check-kehadiran/route.ts @@ -11,5 +11,5 @@ export async function GET(req: Request) { userId: userId as string, }); - return NextResponse.json({ res }); + return NextResponse.json(res, { status: 200 }); } diff --git a/src/app/api/event/get-all-by-userId/route.ts b/src/app/api/event/get-all-by-userId/route.ts deleted file mode 100644 index 2ae65ce8..00000000 --- a/src/app/api/event/get-all-by-userId/route.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { NextResponse } from "next/server"; - -export async function GET(params: Request) { - const { searchParams } = new URL(params.url); - const userId = searchParams.get("userId"); - - - return NextResponse.json({ userId }); -} \ No newline at end of file diff --git a/src/app/api/event/get-all/route.ts b/src/app/api/event/get-all/route.ts new file mode 100644 index 00000000..33e9c89a --- /dev/null +++ b/src/app/api/event/get-all/route.ts @@ -0,0 +1,12 @@ +import { event_getListAllPublish } from "@/app_modules/event/fun/get/get_list_all_publish"; +import { toNumber } from "lodash"; +import { NextResponse } from "next/server"; + +export async function GET(params: Request) { + const { searchParams } = new URL(params.url); + const page = searchParams.get("page"); + + const data = await event_getListAllPublish({ page: toNumber(page) }); + + return NextResponse.json({ data }); +} diff --git a/src/app/api/event/get-one-by-id/route.ts b/src/app/api/event/get-one-by-id/route.ts new file mode 100644 index 00000000..7ab66fac --- /dev/null +++ b/src/app/api/event/get-one-by-id/route.ts @@ -0,0 +1,21 @@ +import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id"; +import { NextResponse } from "next/server"; + +export async function GET(params: Request) { + const { searchParams } = new URL(params.url); + const eventId = searchParams.get("eventId"); + + const res = await event_getOneById(eventId as string); + + if (!res) { + return NextResponse.json( + { message: "Event Not Found", data: null }, + { status: 404 } + ); + } + + return NextResponse.json( + { message: "Event Found", data: res }, + { status: 200 } + ); +} diff --git a/src/app/dev/event/create/page.tsx b/src/app/dev/event/create/page.tsx index 5363ccb1..b731e460 100644 --- a/src/app/dev/event/create/page.tsx +++ b/src/app/dev/event/create/page.tsx @@ -1,9 +1,9 @@ -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; +import { newFunGetUserId } from "@/app/lib/new_fun_user_id"; import { Event_Create } from "@/app_modules/event"; import { Event_getMasterTipeAcara } from "@/app_modules/event/fun/master/get_tipe_acara"; export default async function Page() { - const userLoginId = await funGetUserIdByToken(); + const userLoginId = await newFunGetUserId(); const listTipeAcara = await Event_getMasterTipeAcara(); return ( diff --git a/src/app/dev/event/konfirmasi/[id]/page.tsx b/src/app/dev/event/konfirmasi/[id]/page.tsx index eb04ea33..05703cb1 100644 --- a/src/app/dev/event/konfirmasi/[id]/page.tsx +++ b/src/app/dev/event/konfirmasi/[id]/page.tsx @@ -1,33 +1,35 @@ import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; import Ui_Konfirmasi from "@/app_modules/event/_ui/konfirmasi"; -import { - event_funCheckKehadiran, - event_funCheckPesertaByUserId, -} from "@/app_modules/event/fun"; +import { event_funCheckPesertaByUserId } from "@/app_modules/event/fun"; import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id"; import moment from "moment"; import { redirect } from "next/navigation"; -export default async function Page({ params }: { params: { id: string } }) { - const eventId = params.id; - const userLoginId = await funGetUserIdByToken(); - const dataEvent = await event_getOneById(eventId); +export default async function Page({ + params, +}: { + params: Promise<{ id: string }>; +}) { + const eventId = (await params).id; - const checkPeserta = await event_funCheckPesertaByUserId({ - eventId: eventId, - userId: userLoginId as string, - }); - if (dataEvent == null) return redirect("/dev/event/main/beranda"); + // const userLoginId = await funGetUserIdByToken(); - if (moment(dataEvent?.tanggal).diff(moment(), "minutes") > 0) - return redirect("/dev/event/main/beranda"); + // const checkPeserta = await event_funCheckPesertaByUserId({ + // eventId: eventId, + // userId: userLoginId as string, + // }); - if (dataEvent?.isArsip) - return redirect(`/dev/event/detail/riwayat/${dataEvent.id}`); + // if (dataEvent == null) return redirect("/dev/event/main/beranda"); - if (checkPeserta == false) - return redirect(`/dev/event/detail/main/${eventId}`); + // if (moment(dataEvent?.tanggal).diff(moment(), "minutes") > 0) + // return redirect("/dev/event/main/beranda"); + + // if (dataEvent?.isArsip) + // return redirect(`/dev/event/detail/riwayat/${dataEvent.id}`); + + // if (checkPeserta == false) + // return redirect(`/dev/event/detail/main/${eventId}`); // if (checkKehadiran) { // return redirect(`/dev/event/main/beranda`); @@ -35,10 +37,7 @@ export default async function Page({ params }: { params: { id: string } }) { return ( <> - + ); } diff --git a/src/app/dev/event/main/beranda/page.tsx b/src/app/dev/event/main/beranda/page.tsx index e5201847..5bde2a88 100644 --- a/src/app/dev/event/main/beranda/page.tsx +++ b/src/app/dev/event/main/beranda/page.tsx @@ -1,12 +1,10 @@ import { Event_Beranda } from "@/app_modules/event"; -import { event_getListAllPublish } from "@/app_modules/event/fun/get/get_list_all_publish"; export default async function Page() { - const dataEvent = await event_getListAllPublish({ page: 1 }); return ( <> - + ); } diff --git a/src/app/lib/api_user_router/route_api_event.ts b/src/app/lib/api_user_router/route_api_event.ts new file mode 100644 index 00000000..1394e4ec --- /dev/null +++ b/src/app/lib/api_user_router/route_api_event.ts @@ -0,0 +1,7 @@ +export const API_RouteEvent = { + get_all: ({ page }: { page: number }) => `/api/event/get-all?page=${page}`, + get_one_by_id: ({ eventId }: { eventId: string }) => + `/api/event/get-one-by-id?eventId=${eventId}`, + check_kehadiran: ({ eventId, userId }: { eventId: string; userId: string }) => + `/api/event/check-kehadiran?eventId=${eventId}&userId=${userId}`, +}; diff --git a/src/app_modules/admin/event/_view/view_table_review.tsx b/src/app_modules/admin/event/_view/view_table_review.tsx index 4b9ab12c..4b64fb13 100644 --- a/src/app_modules/admin/event/_view/view_table_review.tsx +++ b/src/app_modules/admin/event/_view/view_table_review.tsx @@ -108,15 +108,15 @@ export default function AdminEvent_ComponentTableReview({ async function onPublish({ eventId, - tanggalSelesai, + tanggal, }: { eventId: string; - tanggalSelesai: Date; + tanggal: Date; }) { const checkStatus = await event_checkStatus({ id: eventId }); if (checkStatus) { - if (moment(tanggalSelesai).diff(Date.now(), "minutes") < 0) + if (moment(tanggal).diff(Date.now(), "minutes") < 0) return ComponentGlobal_NotifikasiPeringatan( "Waktu acara telah lewat, Report untuk memberitahu user !" ); @@ -267,7 +267,7 @@ export default function AdminEvent_ComponentTableReview({ - +
@@ -286,7 +286,7 @@ export default function AdminEvent_ComponentTableReview({ onClick={() => onPublish({ eventId: e.id, - tanggalSelesai: e.tanggalSelesai, + tanggal: e.tanggal, }) } > @@ -297,7 +297,7 @@ export default function AdminEvent_ComponentTableReview({ leftIcon={} radius={"xl"} onClick={async () => { - const checkStatus = await event_checkStatus({ id: eventId }); + const checkStatus = await event_checkStatus({ id: e.id }); if (checkStatus) { open(); diff --git a/src/app_modules/event/_ui/konfirmasi.tsx b/src/app_modules/event/_ui/konfirmasi.tsx index ec95fc00..90194d65 100644 --- a/src/app_modules/event/_ui/konfirmasi.tsx +++ b/src/app_modules/event/_ui/konfirmasi.tsx @@ -4,7 +4,17 @@ import { UIGlobal_LayoutDefault, UIGlobal_LayoutTamplate, } from "@/app_modules/_global/ui"; -import { Button, Paper, Skeleton, Stack, Text, Title } from "@mantine/core"; +import { + Button, + Card, + Center, + Group, + Paper, + Skeleton, + Stack, + Text, + Title, +} from "@mantine/core"; import { MODEL_EVENT } from "../model/interface"; import { useShallowEffect } from "@mantine/hooks"; import { AccentColor, MainColor } from "@/app_modules/_global/color"; @@ -13,112 +23,328 @@ import { ComponentGlobal_NotifikasiBerhasil, ComponentGlobal_NotifikasiGagal, } from "@/app_modules/_global/notif_global"; -import { useRouter } from "next/navigation"; +import { redirect, useRouter } from "next/navigation"; import { RouterEvent } from "@/app/lib/router_hipmi/router_event"; import { useState } from "react"; +import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event"; +import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; +import moment from "moment"; +import { gs_event_hotMenu } from "../global_state"; +import { useAtom } from "jotai"; export default function Ui_Konfirmasi({ - dataEvent, userLoginId, + eventId, }: { - dataEvent: MODEL_EVENT; userLoginId: string; + eventId: string; }) { // console.log(dataEvent); const router = useRouter(); - const [isLoading, setLoading] = useState(false); + const [data, setData] = useState(null); const [isPresent, setIsPresent] = useState(null); useShallowEffect(() => { - onLoadKehadiran({ - onChange(val) { - setIsPresent(val); - }, - }); - }, [setIsPresent]); + onLoadData(); + }, []); - async function onLoadKehadiran({ - onChange, - }: { - onChange: (val: boolean) => void; - }) { - const res = await fetch( - `/api/event/check-kehadiran?userId=${userLoginId}&eventId=${dataEvent.id}` + async function onLoadData() { + const data = await fetch( + API_RouteEvent.get_one_by_id({ eventId: eventId }) ); - const checkKehadiran = await res.json(); - - onChange(checkKehadiran.res); - } - async function onUpdateKonfirmasi() { - setLoading(true); - const res = await event_funUpdateKehadiran({ - eventId: dataEvent.id, - userId: userLoginId, - }); - - if (res.status === 200) { - ComponentGlobal_NotifikasiBerhasil(res.message, 2000); - router.push(RouterEvent.detail_main + dataEvent.id); - } else { - setLoading(false); - ComponentGlobal_NotifikasiGagal(res.message); - } + const res = await data.json(); + console.log(res.data, "data event"); + setData(res.data); } - console.log(isPresent, "isPresent"); + useShallowEffect(() => { + onLoadKehadiran(); + }, []); + + async function onLoadKehadiran() { + const res = await fetch( + API_RouteEvent.check_kehadiran({ eventId: eventId, userId: userLoginId }) + ); + const data = await res.json(); + + setIsPresent(data); + } + + // console.log("kehadiran:", isPresent); + // console.log("data:", data); + + if (data == null && isPresent == null) { + return ; + } + + if (data == null) { + return ( + <> + + + ); + } + + if (moment(data?.tanggal).diff(moment(), "minute") < 0) { + return ( + <> + + + ); + } + + if (isPresent && data) { + return ; + } + + if (isPresent == false && data) { + return ( + + ); + } + // const tgl = moment(data?.tanggal).diff(moment(), "minute") < 0; + // return ( + // <> + // + // + // {JSON.stringify(tgl)} + // + // + // + // ); +} + +function DataNotFound() { + const router = useRouter(); + const [isLoading, setLoading] = useState(false); + const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu); return ( <> - - {isPresent == null ? ( - - ) : isPresent ? ( - - - - Anda telah terkonfirmasi silahkan kembali ke beranda ! - - {dataEvent.title} - - - - ) : ( - - - - Anda mengkonfirmasi bahwa anda telah datang & ikut menghadir - di event - - {dataEvent.title} - - - - )} + + + + + Data Event Tidak Ditemukan + + + + + + + + + ); +} + +function SkeletonIsDataNull() { + return ( + <> + + + + + {" "} + {" "} + +
+ +
+
+
+
+
+ + ); +} + +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 {"Hadir"} 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/component/card_view/card_beranda.tsx b/src/app_modules/event/component/card_view/card_beranda.tsx index d751c207..adb952fa 100644 --- a/src/app_modules/event/component/card_view/card_beranda.tsx +++ b/src/app_modules/event/component/card_view/card_beranda.tsx @@ -34,11 +34,11 @@ export function ComponentEvent_CardBeranda({ data }: { data: any }) { {data.title} - + {/* {new Intl.DateTimeFormat("id-ID", { dateStyle: "medium", - }).format(data.tanggal)} - + }).format(data?.tanggal)} + */} diff --git a/src/app_modules/event/component/index.ts b/src/app_modules/event/component/index.ts index d9cc4eeb..b146da16 100644 --- a/src/app_modules/event/component/index.ts +++ b/src/app_modules/event/component/index.ts @@ -1,5 +1,7 @@ import Event_ComponentCreateButton from "./button/button_create_event"; +import Event_ComponentSkeletonBeranda from "./skeleton/comp_skeleton_beranda"; import { Event_ComponentSkeletonDetailData } from "./skeleton/comp_skeleton_detail_data"; export { Event_ComponentSkeletonDetailData }; export { Event_ComponentCreateButton }; +export { Event_ComponentSkeletonBeranda }; diff --git a/src/app_modules/event/component/skeleton/comp_skeleton_beranda.tsx b/src/app_modules/event/component/skeleton/comp_skeleton_beranda.tsx new file mode 100644 index 00000000..e45a9247 --- /dev/null +++ b/src/app_modules/event/component/skeleton/comp_skeleton_beranda.tsx @@ -0,0 +1,29 @@ +import { AccentColor } from "@/app_modules/_global/color"; +import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; +import { Grid, Group, Paper, Skeleton, Stack, Text } from "@mantine/core"; + +export default function Event_ComponentSkeletonBeranda() { + return ( + <> + {Array.from({ length: 10 }).map((_, index) => ( + + + + + + + + + + + + + + + + + + ))} + + ); +} diff --git a/src/app_modules/event/main/beranda.tsx b/src/app_modules/event/main/beranda.tsx index 3387a29b..33565488 100644 --- a/src/app_modules/event/main/beranda.tsx +++ b/src/app_modules/event/main/beranda.tsx @@ -13,6 +13,7 @@ import { Loader, rem, Skeleton, + Paper, } from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; import { useAtom } from "jotai"; @@ -22,12 +23,10 @@ import { useState } from "react"; import { ComponentEvent_CardBeranda } from "../component/card_view/card_beranda"; import { event_getListAllPublish } from "../fun/get/get_list_all_publish"; import { MODEL_EVENT } from "../model/interface"; +import { Event_ComponentSkeletonBeranda } from "../component"; +import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event"; -export default function Event_Beranda({ - dataEvent, -}: { - dataEvent: MODEL_EVENT[]; -}) { +export default function Event_Beranda() { const [data, setData] = useState(null); const [activePage, setActivePage] = useState(1); const [isLoading, setIsLoading] = useState(false); @@ -39,6 +38,7 @@ export default function Event_Beranda({ const [isShowUpdate, setIsShowUpdate] = useState(false); useShallowEffect(() => { + setIsShowUpdate(false); loadData(); }, []); @@ -49,14 +49,16 @@ export default function Event_Beranda({ }, [isTriggerEventBeranda]); async function loadData() { - const loadData = await event_getListAllPublish({ page: 1 }); - setData(loadData as any); + const res = await fetch(API_RouteEvent.get_all({ page: activePage })); + const data = await res.json(); + setData(data.data as any); } async function onLoadNewData() { setIsLoading(true); - const loadData = await event_getListAllPublish({ page: 1 }); - setData(loadData as any); + const res = await fetch(API_RouteEvent.get_all({ page: 1 })); + const data = await res.json(); + setData(data.data as any); setIsShowUpdate(false); setIsTriggerEventBeranca(false); @@ -92,16 +94,7 @@ export default function Event_Beranda({ {data == null ? ( - Array.from({ length: 10 }).map((_, index) => ( - - )) + ) : _.isEmpty(data) ? ( ) : ( diff --git a/src/app_modules/event/splash/index.tsx b/src/app_modules/event/splash/index.tsx index e6d75e20..bd06d4ca 100644 --- a/src/app_modules/event/splash/index.tsx +++ b/src/app_modules/event/splash/index.tsx @@ -16,7 +16,7 @@ export default function Event_SplashScreen() { setTimeout(() => { router.replace(RouterEvent.beranda); setHotMenu(0); - }, 1000); + }, 500); }, []); return ( <> From ea491231a8ec9e3a1db9523e029b07f4ba53ffd6 Mon Sep 17 00:00:00 2001 From: amel Date: Fri, 6 Dec 2024 11:44:48 +0800 Subject: [PATCH 12/36] upd: kataloh Deskripsi: - api di katalog No Issues --- src/app/dev/katalog/[id]/layout.tsx | 27 ++--- src/app/dev/katalog/[id]/page.tsx | 13 +-- .../katalog/component/drawer_katalog_new.tsx | 110 ++++++++++++++++++ src/app_modules/katalog/main/index.ts | 2 + src/app_modules/katalog/main/layout_new.tsx | 60 ++++++++++ src/app_modules/katalog/view_katalog_new.tsx | 5 - 6 files changed, 187 insertions(+), 30 deletions(-) create mode 100644 src/app_modules/katalog/component/drawer_katalog_new.tsx create mode 100644 src/app_modules/katalog/main/layout_new.tsx diff --git a/src/app/dev/katalog/[id]/layout.tsx b/src/app/dev/katalog/[id]/layout.tsx index bd874c57..98b718f6 100644 --- a/src/app/dev/katalog/[id]/layout.tsx +++ b/src/app/dev/katalog/[id]/layout.tsx @@ -1,31 +1,24 @@ -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { KatalogLayout } from "@/app_modules/katalog/main"; -import { Profile_getOneProfileAndUserById } from "@/app_modules/katalog/profile/fun/get/get_one_user_profile"; +import { LayoutKatalogNew } from "@/app_modules/katalog/main"; -export default async function Layout({ - children, - params, -}: { - children: any; - params: { id: string }; -}) { - const profileId = params.id; - const dataProfile = await Profile_getOneProfileAndUserById(profileId); - const authorId = dataProfile?.userId; +export default async function Layout({ children, params, }: { children: any; params: { id: string } }) { + // const profileId = params.id; + // const dataProfile = await Profile_getOneProfileAndUserById(profileId); + // const authorId = dataProfile?.userId; - const userLoginId = await funGetUserIdByToken(); - const userRoleId = dataProfile?.User?.masterUserRoleId; + // const userLoginId = await funGetUserIdByToken(); + // const userRoleId = dataProfile?.User?.masterUserRoleId; return ( <> - {children} - + */} + {children} ); } diff --git a/src/app/dev/katalog/[id]/page.tsx b/src/app/dev/katalog/[id]/page.tsx index e37c8933..98ab33e3 100644 --- a/src/app/dev/katalog/[id]/page.tsx +++ b/src/app/dev/katalog/[id]/page.tsx @@ -1,14 +1,11 @@ -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { Katalog_MainView, ViewKatalogNew } from "@/app_modules/katalog"; -import { funGetListPortofolio } from "@/app_modules/katalog/portofolio/fun/get/get_list_portofolio"; -import { Profile_getOneProfileAndUserById } from "@/app_modules/katalog/profile/fun/get/get_one_user_profile"; +import { ViewKatalogNew } from "@/app_modules/katalog"; export default async function Page({ params }: { params: { id: string } }) { - let profileId = params.id; - const userLoginId = await funGetUserIdByToken(); + // let profileId = params.id; + // const userLoginId = await funGetUserIdByToken(); - const listPorto = await funGetListPortofolio(profileId); - const dataProfile = await Profile_getOneProfileAndUserById(profileId); + // const listPorto = await funGetListPortofolio(profileId); + // const dataProfile = await Profile_getOneProfileAndUserById(profileId); return ( <> diff --git a/src/app_modules/katalog/component/drawer_katalog_new.tsx b/src/app_modules/katalog/component/drawer_katalog_new.tsx new file mode 100644 index 00000000..c0ef291f --- /dev/null +++ b/src/app_modules/katalog/component/drawer_katalog_new.tsx @@ -0,0 +1,110 @@ +import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; +import { RouterPortofolio, RouterProfile } from "@/app/lib/router_hipmi/router_katalog"; +import { AccentColor } from "@/app_modules/_global/color"; +import Component_ButtonLogout from "@/app_modules/auth/logout/view"; +import { ActionIcon, Drawer, Group, SimpleGrid, Stack, Text } from "@mantine/core"; +import { IconDashboard } from "@tabler/icons-react"; +import { IconEdit, IconPencilPlus, IconPhotoEdit, IconPolaroid, IconX } from "@tabler/icons-react"; +import { useParams, useRouter } from "next/navigation"; + +export default function DrawerKatalogNew({ opened, close, userRoleId, userId }: { opened: boolean, close: () => void, userRoleId: string, userId: string }) { + const param = useParams<{ id: string }>() + const router = useRouter() + + const listPage = [ + { + id: "1", + name: "Edit profile", + icon: , + path: RouterProfile.edit + param.id, + }, + { + id: "2", + name: "Ubah foto profile", + icon: , + path: RouterProfile.update_foto_profile + param.id, + }, + { + id: "3", + name: "Ubah latar belakang", + icon: , + path: RouterProfile.update_foto_background + param.id, + }, + { + id: "4", + name: "Tambah portofolio", + icon: , + path: RouterPortofolio.create + param.id, + }, + ]; + + return <> + close()} + position={"bottom"} + size={"auto"} + withCloseButton={false} + styles={{ + content: { + padding: 0, + position: "absolute", + margin: "auto", + backgroundColor: "transparent", + left: 0, + right: 0, + width: 500, + }, + body: { + backgroundColor: AccentColor.darkblue, + borderTop: `2px solid ${AccentColor.blue}`, + borderRight: `1px solid ${AccentColor.blue}`, + borderLeft: `1px solid ${AccentColor.blue}`, + borderRadius: "20px 20px 0px 0px", + color: "white", + paddingBottom: "5%", + }, + }} + > + + + + + + + + {listPage.map((e, i) => ( + + { router.push(e.path, { scroll: false }); }} + > + {e.icon} + + + {e.name} + + + ))} + + + {userRoleId != "1" && ( + + { router.push(RouterAdminDashboard.main_admin, { scroll: false }); }} + > + + + + Dashboard Admin + + + )} + + + + ; +} \ No newline at end of file diff --git a/src/app_modules/katalog/main/index.ts b/src/app_modules/katalog/main/index.ts index 793e49ee..127d7b75 100644 --- a/src/app_modules/katalog/main/index.ts +++ b/src/app_modules/katalog/main/index.ts @@ -1,3 +1,5 @@ import KatalogLayout from "./layout"; +import LayoutKatalogNew from "./layout_new"; export { KatalogLayout }; +export { LayoutKatalogNew } diff --git a/src/app_modules/katalog/main/layout_new.tsx b/src/app_modules/katalog/main/layout_new.tsx new file mode 100644 index 00000000..a0aa4d8e --- /dev/null +++ b/src/app_modules/katalog/main/layout_new.tsx @@ -0,0 +1,60 @@ +'use client' +import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; +import { UIGlobal_LayoutHeaderTamplate, UIGlobal_LayoutTamplate } from "@/app_modules/_global/ui"; +import { apiGetUserProfile } from "@/app_modules/user"; +import { ActionIcon } from "@mantine/core"; +import { useDisclosure, useShallowEffect } from "@mantine/hooks"; +import { IconDotsVertical } from "@tabler/icons-react"; +import { useParams } from "next/navigation"; +import { useState } from "react"; +import DrawerKatalogNew from "../component/drawer_katalog_new"; + +export default function LayoutKatalogNew({ children }: { children: any }) { + const param = useParams<{ id: string }>() + const [authorId, setAuthorId] = useState("") + const [userRoleId, setUserRoleId] = useState("") + const [userLoginId, setUserLoginId] = useState("") + const [opened, { open, close }] = useDisclosure() + + async function getProfile() { + try { + const response = await apiGetUserProfile(`?profile=${param.id}`) + const response2 = await funGetUserIdByToken() + if (response.success) { + setAuthorId(response.data.id) + setUserRoleId(response.data.masterUserRoleId) + setUserLoginId(response2) + } + } catch (error) { + console.error(error); + } + } + + useShallowEffect(() => { + getProfile() + }, []) + + return ( + <> + + ) : ( + open()}> + + + ) + } + /> + } + > + {children} + close()} userRoleId={userRoleId} userId={userLoginId} /> + + + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/view_katalog_new.tsx b/src/app_modules/katalog/view_katalog_new.tsx index 1ce3c013..108e2c93 100644 --- a/src/app_modules/katalog/view_katalog_new.tsx +++ b/src/app_modules/katalog/view_katalog_new.tsx @@ -8,11 +8,6 @@ export default function ViewKatalogNew() { <> - {/* */} From dc8e30ae8763b551399262155851db983e4e719f Mon Sep 17 00:00:00 2001 From: amel Date: Fri, 6 Dec 2024 12:19:42 +0800 Subject: [PATCH 13/36] upd: kataloh deskripsi: - update api list portofolio No Issues --- src/app/api/new/portofolio/route.ts | 8 ++- .../daftar-portofolio/[id]/page.tsx | 16 ++--- src/app_modules/katalog/portofolio/index.ts | 4 +- .../ui/ui_list_detail_portofolio_new.tsx | 59 +++++++++++++++++++ .../view/list_detail_portofolio_new.tsx | 13 ++++ .../katalog/ui/list_portolio_new.tsx | 2 +- 6 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 src/app_modules/katalog/portofolio/ui/ui_list_detail_portofolio_new.tsx create mode 100644 src/app_modules/katalog/portofolio/view/list_detail_portofolio_new.tsx diff --git a/src/app/api/new/portofolio/route.ts b/src/app/api/new/portofolio/route.ts index 357f42b3..b25478d5 100644 --- a/src/app/api/new/portofolio/route.ts +++ b/src/app/api/new/portofolio/route.ts @@ -8,9 +8,11 @@ export async function GET(request: Request) { let fixData const { searchParams } = new URL(request.url) const profile = searchParams.get("profile") + const kategori_halaman = searchParams.get("cat") const page = searchParams.get("page") + const dataSkip = Number(page) * 10 - 10; - if (page == "profile") { + if (kategori_halaman == "profile") { fixData = await prisma.portofolio.findMany({ take: 2, orderBy: { @@ -27,8 +29,10 @@ export async function GET(request: Request) { profileId: true, }, }); - } else if (page == "portofolio") { + } else if (kategori_halaman == "portofolio") { fixData = await prisma.portofolio.findMany({ + skip: dataSkip, + take: 10, orderBy: { createdAt: "desc", }, diff --git a/src/app/dev/portofolio/daftar-portofolio/[id]/page.tsx b/src/app/dev/portofolio/daftar-portofolio/[id]/page.tsx index 45a30f23..2252757b 100644 --- a/src/app/dev/portofolio/daftar-portofolio/[id]/page.tsx +++ b/src/app/dev/portofolio/daftar-portofolio/[id]/page.tsx @@ -1,17 +1,17 @@ -import { Portofolio_ViewListDetail } from "@/app_modules/katalog/portofolio"; -import { portofolio_funGetAllDaftarByid } from "@/app_modules/katalog/portofolio/fun/get/get_all_portofolio"; +import { ListDetailPortofolioNew } from "@/app_modules/katalog/portofolio"; export default async function Page({ params }: { params: { id: string } }) { - const profileId = params.id; - const dataPortofolio = await portofolio_funGetAllDaftarByid({ - profileId, - page: 1, - }); + // const profileId = params.id; + // const dataPortofolio = await portofolio_funGetAllDaftarByid({ + // profileId, + // page: 1, + // }); return ( <> - + {/* */} + ); } diff --git a/src/app_modules/katalog/portofolio/index.ts b/src/app_modules/katalog/portofolio/index.ts index b45526dc..9d31be0f 100644 --- a/src/app_modules/katalog/portofolio/index.ts +++ b/src/app_modules/katalog/portofolio/index.ts @@ -10,6 +10,7 @@ import Portofolio_EditMedsosBisnis from "./edit/medsos/ui_edit_medsos"; import LayoutPortofolio_EditDataBisnis from "./edit/data/layout"; import LayoutPortofolio_EditLogoBisnis from "./edit/logo/layout"; import LayoutPortofolio_EditMedsosBisnis from "./edit/medsos/layout"; +import ListDetailPortofolioNew from './view/list_detail_portofolio_new'; export { CreatePortofolio, @@ -22,8 +23,9 @@ export { LayoutPortofolio_EditDataBisnis, LayoutPortofolio_EditLogoBisnis, LayoutPortofolio_EditMedsosBisnis, - apiGetPortofolioByProfile + apiGetPortofolioByProfile, }; export type { IListPortofolio }; export { Portofolio_ViewListDetail } from "./view/view_list_detail_portofolio"; +export { ListDetailPortofolioNew } diff --git a/src/app_modules/katalog/portofolio/ui/ui_list_detail_portofolio_new.tsx b/src/app_modules/katalog/portofolio/ui/ui_list_detail_portofolio_new.tsx new file mode 100644 index 00000000..9add314b --- /dev/null +++ b/src/app_modules/katalog/portofolio/ui/ui_list_detail_portofolio_new.tsx @@ -0,0 +1,59 @@ +import ComponentGlobal_Loader from "@/app_modules/_global/component/loader"; +import { Box, Center } from "@mantine/core"; +import { ScrollOnly } from "next-scroll-loader"; +import { useState } from "react"; +import { ComponentPortofolio_DaftarBoxView } from "../component/card_view_daftar"; +import { portofolio_funGetAllDaftarByid } from "../fun/get/get_all_portofolio"; +import { MODEL_PORTOFOLIO } from "../model/interface"; +import { useParams } from "next/navigation"; +import { useShallowEffect } from "@mantine/hooks"; +import { apiGetPortofolioByProfile } from "../lib/api_portofolio"; + +export default function Portofolio_UiListDetailNew() { + const param = useParams<{ id: string }>() + const profileId = param.id + const [data, setData] = useState([]) + const [activePage, setActivePage] = useState(1) + + async function getPortofolio() { + try { + const response = await apiGetPortofolioByProfile(`?profile=${param.id}&cat=portofolio&page=1`) + if (response.success) { + setData(response.data); + } + } catch (error) { + console.error(error); + } + } + + + useShallowEffect(() => { + getPortofolio() + }, []); + + return <> + + ( +
+ +
+ )} + data={data} + setData={setData} + moreData={async () => { + const loadData = await portofolio_funGetAllDaftarByid({ + profileId, + page: activePage + 1, + }); + setActivePage((val) => val + 1); + + return loadData; + }} + > + {(item) => } +
+
+ ; +} \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/view/list_detail_portofolio_new.tsx b/src/app_modules/katalog/portofolio/view/list_detail_portofolio_new.tsx new file mode 100644 index 00000000..1920461d --- /dev/null +++ b/src/app_modules/katalog/portofolio/view/list_detail_portofolio_new.tsx @@ -0,0 +1,13 @@ +'use client' +import { UIGlobal_LayoutHeaderTamplate, UIGlobal_LayoutTamplate } from "@/app_modules/_global/ui"; +import Portofolio_UiListDetailNew from "../ui/ui_list_detail_portofolio_new"; + +export default function ListDetailPortofolioNew() { + return ( + <> + } > + + + + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/ui/list_portolio_new.tsx b/src/app_modules/katalog/ui/list_portolio_new.tsx index b1118bb3..ff7d96a4 100644 --- a/src/app_modules/katalog/ui/list_portolio_new.tsx +++ b/src/app_modules/katalog/ui/list_portolio_new.tsx @@ -17,7 +17,7 @@ export default function ListPortofolioProfileNew() { async function getPortofolio() { try { setLoading(true) - const response = await apiGetPortofolioByProfile(`?profile=${param.id}&page=profile`) + const response = await apiGetPortofolioByProfile(`?profile=${param.id}&cat=profile`) if (response.success) { setDataPortofolio(response.data); } From 72cd56deb89eb231213ce63a2add7aefe421af68 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Fri, 6 Dec 2024 13:51:04 +0800 Subject: [PATCH 14/36] chore(release): 1.2.19 --- CHANGELOG.md | 2 ++ package.json | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 108876d8..aa2c2693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [1.2.19](https://github.com/bipproduction/hipmi/compare/v1.2.18...v1.2.19) (2024-12-06) + ## [1.2.18](https://github.com/bipproduction/hipmi/compare/v1.2.17...v1.2.18) (2024-12-04) ## [1.2.17](https://github.com/bipproduction/hipmi/compare/v1.2.16...v1.2.17) (2024-12-04) diff --git a/package.json b/package.json index bb7c07b7..33896d0e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hipmi", - "version": "1.2.18", + "version": "1.2.19", "private": true, "prisma": { "seed": "npx tsx prisma/seed.ts --yes" @@ -95,4 +95,4 @@ "wibu-pkg": "^1.0.3", "yaml": "^2.3.2" } -} \ No newline at end of file +} From 2b08326bed8098f2f416f652f904b6640c38df3a Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Fri, 6 Dec 2024 13:51:39 +0800 Subject: [PATCH 15/36] Fix event Deskripsi: - Fix user server menjadi API di beranda --- next.config.js | 1 + src/app/api/event/check-peserta/route.ts | 15 ++ src/app/api/event/list-peserta/route.ts | 16 ++ .../dev/event/detail/kontribusi/[id]/page.tsx | 3 +- src/app/dev/event/detail/main/[id]/page.tsx | 15 +- .../dev/event/detail/publish/[id]/page.tsx | 3 +- .../dev/event/detail/riwayat/[id]/page.tsx | 8 +- src/app/dev/event/konfirmasi/[id]/page.tsx | 27 +--- .../lib/api_user_router/route_api_event.ts | 3 + src/app_modules/event/_ui/konfirmasi.tsx | 103 +++++++++++- .../event/component/detail/detail_main.tsx | 148 +++++++++--------- .../event/component/detail/list_peserta.tsx | 96 +++++++----- src/app_modules/event/component/index.ts | 4 + .../skeleton/comp_skeleton_detail.tsx | 36 +++++ .../skeleton/comp_skeleton_list_peserta.tsx | 32 ++++ .../event/detail/kontribusi/index.tsx | 14 +- .../event/detail/main_detail/index.tsx | 62 +++++--- .../event/detail/publish/index.tsx | 9 +- .../event/detail/riwayat/index.tsx | 48 +----- .../event/fun/create/fun_join_and_confirm.ts | 23 +++ .../event/fun/get/new_get_list_peserta.ts | 43 +++++ src/app_modules/event/fun/index.ts | 2 + 22 files changed, 476 insertions(+), 235 deletions(-) create mode 100644 src/app/api/event/check-peserta/route.ts create mode 100644 src/app/api/event/list-peserta/route.ts create mode 100644 src/app_modules/event/component/skeleton/comp_skeleton_detail.tsx create mode 100644 src/app_modules/event/component/skeleton/comp_skeleton_list_peserta.tsx create mode 100644 src/app_modules/event/fun/create/fun_join_and_confirm.ts create mode 100644 src/app_modules/event/fun/get/new_get_list_peserta.ts diff --git a/next.config.js b/next.config.js index 79d67970..48384e99 100644 --- a/next.config.js +++ b/next.config.js @@ -4,6 +4,7 @@ const nextConfig = { experimental: { serverActions: true, }, + output: "standalone" }; module.exports = nextConfig; diff --git a/src/app/api/event/check-peserta/route.ts b/src/app/api/event/check-peserta/route.ts new file mode 100644 index 00000000..49b863e2 --- /dev/null +++ b/src/app/api/event/check-peserta/route.ts @@ -0,0 +1,15 @@ +import { event_funCheckPesertaByUserId } from "@/app_modules/event/fun"; +import { NextResponse } from "next/server"; + +export async function GET(req: Request) { + const { searchParams } = new URL(req.url); + const userId = searchParams.get("userId"); + const eventId = searchParams.get("eventId"); + + const res = await event_funCheckPesertaByUserId({ + eventId: eventId as string, + userId: userId as string, + }); + + return NextResponse.json(res, { status: 200 }); +} diff --git a/src/app/api/event/list-peserta/route.ts b/src/app/api/event/list-peserta/route.ts new file mode 100644 index 00000000..be0037a6 --- /dev/null +++ b/src/app/api/event/list-peserta/route.ts @@ -0,0 +1,16 @@ +import { event_newGetListPesertaById } from "@/app_modules/event/fun"; +import { toNumber } from "lodash"; +import { NextResponse } from "next/server"; + +export async function GET(req: Request) { + const { searchParams } = new URL(req.url); + const eventId = searchParams.get("eventId"); + const page = searchParams.get("page"); + + const res = await event_newGetListPesertaById({ + eventId: eventId as string, + page: toNumber(page), + }); + + return NextResponse.json(res, { status: 200 }); +} diff --git a/src/app/dev/event/detail/kontribusi/[id]/page.tsx b/src/app/dev/event/detail/kontribusi/[id]/page.tsx index 5678dc7a..508e14ae 100644 --- a/src/app/dev/event/detail/kontribusi/[id]/page.tsx +++ b/src/app/dev/event/detail/kontribusi/[id]/page.tsx @@ -11,8 +11,7 @@ export default async function Page({ params }: { params: { id: string } }) { return ( <> diff --git a/src/app/dev/event/detail/main/[id]/page.tsx b/src/app/dev/event/detail/main/[id]/page.tsx index 9f42a181..11850c4e 100644 --- a/src/app/dev/event/detail/main/[id]/page.tsx +++ b/src/app/dev/event/detail/main/[id]/page.tsx @@ -1,27 +1,18 @@ -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; +import { newFunGetUserId } from "@/app/lib/new_fun_user_id"; import { Event_DetailMain } from "@/app_modules/event"; import { Event_countTotalPesertaById } from "@/app_modules/event/fun/count/count_total_peserta_by_id"; -import { Event_CekUserJoinById } from "@/app_modules/event/fun/get/cek_user_join_by_id"; -import { Event_getListPesertaById } from "@/app_modules/event/fun/get/get_list_peserta_by_id"; -import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id"; export default async function Page({ params }: { params: { id: string } }) { let eventId = params.id; - const userLoginId : any= await funGetUserIdByToken(); - - const dataEvent = await event_getOneById(eventId); - const listPeserta = await Event_getListPesertaById(eventId); - const isJoin = await Event_CekUserJoinById(eventId, userLoginId); + const userLoginId = await newFunGetUserId(); const totalPeserta = await Event_countTotalPesertaById(eventId); return ( <> ); diff --git a/src/app/dev/event/detail/publish/[id]/page.tsx b/src/app/dev/event/detail/publish/[id]/page.tsx index 4388c255..1123ede9 100644 --- a/src/app/dev/event/detail/publish/[id]/page.tsx +++ b/src/app/dev/event/detail/publish/[id]/page.tsx @@ -6,15 +6,14 @@ import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id"; export default async function Page({ params }: { params: { id: string } }) { let eventId = params.id; const dataEvent = await event_getOneById(eventId); - const listPeserta = await Event_getListPesertaById(eventId); const totalPeserta = await Event_countTotalPesertaById(eventId); return ( ); } diff --git a/src/app/dev/event/detail/riwayat/[id]/page.tsx b/src/app/dev/event/detail/riwayat/[id]/page.tsx index 2f506396..a6715a97 100644 --- a/src/app/dev/event/detail/riwayat/[id]/page.tsx +++ b/src/app/dev/event/detail/riwayat/[id]/page.tsx @@ -1,21 +1,15 @@ - import { Event_DetailRiwayat } from "@/app_modules/event"; import { Event_countTotalPesertaById } from "@/app_modules/event/fun/count/count_total_peserta_by_id"; -import { Event_getListPesertaById } from "@/app_modules/event/fun/get/get_list_peserta_by_id"; -import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id"; export default async function Page({ params }: { params: { id: string } }) { let eventId = params.id; - const dataEvent = await event_getOneById(eventId); - const listPeserta = await Event_getListPesertaById(eventId); const totalPeserta = await Event_countTotalPesertaById(eventId); return ( <> ); diff --git a/src/app/dev/event/konfirmasi/[id]/page.tsx b/src/app/dev/event/konfirmasi/[id]/page.tsx index 05703cb1..3a0af55b 100644 --- a/src/app/dev/event/konfirmasi/[id]/page.tsx +++ b/src/app/dev/event/konfirmasi/[id]/page.tsx @@ -1,3 +1,4 @@ +import { newFunGetUserId } from "@/app/lib/new_fun_user_id"; import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; import Ui_Konfirmasi from "@/app_modules/event/_ui/konfirmasi"; import { event_funCheckPesertaByUserId } from "@/app_modules/event/fun"; @@ -11,33 +12,11 @@ export default async function Page({ params: Promise<{ id: string }>; }) { const eventId = (await params).id; - - - // const userLoginId = await funGetUserIdByToken(); - - // const checkPeserta = await event_funCheckPesertaByUserId({ - // eventId: eventId, - // userId: userLoginId as string, - // }); - - // if (dataEvent == null) return redirect("/dev/event/main/beranda"); - - // if (moment(dataEvent?.tanggal).diff(moment(), "minutes") > 0) - // return redirect("/dev/event/main/beranda"); - - // if (dataEvent?.isArsip) - // return redirect(`/dev/event/detail/riwayat/${dataEvent.id}`); - - // if (checkPeserta == false) - // return redirect(`/dev/event/detail/main/${eventId}`); - - // if (checkKehadiran) { - // return redirect(`/dev/event/main/beranda`); - // } + const userLoginId = await newFunGetUserId(); return ( <> - + ); } diff --git a/src/app/lib/api_user_router/route_api_event.ts b/src/app/lib/api_user_router/route_api_event.ts index 1394e4ec..9b7094c2 100644 --- a/src/app/lib/api_user_router/route_api_event.ts +++ b/src/app/lib/api_user_router/route_api_event.ts @@ -4,4 +4,7 @@ export const API_RouteEvent = { `/api/event/get-one-by-id?eventId=${eventId}`, check_kehadiran: ({ eventId, userId }: { eventId: string; userId: string }) => `/api/event/check-kehadiran?eventId=${eventId}&userId=${userId}`, + check_peserta: ({ eventId, userId }: { eventId: string; userId: string }) => + `/api/event/check-peserta?eventId=${eventId}&userId=${userId}`, + list_peserta: ({ eventId, page }: { eventId: string, page: number }) => `/api/event/list-peserta?eventId=${eventId}&page=${page}`, }; diff --git a/src/app_modules/event/_ui/konfirmasi.tsx b/src/app_modules/event/_ui/konfirmasi.tsx index 90194d65..8b1814b7 100644 --- a/src/app_modules/event/_ui/konfirmasi.tsx +++ b/src/app_modules/event/_ui/konfirmasi.tsx @@ -31,6 +31,8 @@ import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; import moment from "moment"; import { gs_event_hotMenu } from "../global_state"; import { useAtom } from "jotai"; +import { Event_funJoinEvent } from "../fun/create/fun_join_event"; +import { Event_funJoinAndConfirmEvent } from "../fun/create/fun_join_and_confirm"; export default function Ui_Konfirmasi({ userLoginId, @@ -43,6 +45,7 @@ export default function Ui_Konfirmasi({ const router = useRouter(); const [data, setData] = useState(null); + const [isJoin, setIsJoin] = useState(null); const [isPresent, setIsPresent] = useState(null); useShallowEffect(() => { @@ -54,10 +57,24 @@ export default function Ui_Konfirmasi({ API_RouteEvent.get_one_by_id({ eventId: eventId }) ); const res = await data.json(); - console.log(res.data, "data event"); setData(res.data); } + // CEK PESERTA + useShallowEffect(() => { + onCheckPeserta(); + }, []); + + async function onCheckPeserta() { + const res = await fetch( + API_RouteEvent.check_peserta({ eventId: eventId, userId: userLoginId }) + ); + const data = await res.json(); + console.log("cek peserta", data); + setIsJoin(data); + } + + // CEK KEHADIRAN useShallowEffect(() => { onLoadKehadiran(); }, []); @@ -67,7 +84,6 @@ export default function Ui_Konfirmasi({ API_RouteEvent.check_kehadiran({ eventId: eventId, userId: userLoginId }) ); const data = await res.json(); - setIsPresent(data); } @@ -94,6 +110,18 @@ export default function Ui_Konfirmasi({ ); } + if (isJoin == false) { + return ( + <> + + + ); + } + if (isPresent && data) { return ; } @@ -177,6 +205,77 @@ function SkeletonIsDataNull() { ); } +function UserNotJoin({ + 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, diff --git a/src/app_modules/event/component/detail/detail_main.tsx b/src/app_modules/event/component/detail/detail_main.tsx index bfcdefea..4625b1e6 100644 --- a/src/app_modules/event/component/detail/detail_main.tsx +++ b/src/app_modules/event/component/detail/detail_main.tsx @@ -4,104 +4,110 @@ import { ComponentGlobal_AvatarAndUsername, ComponentGlobal_CardStyles, } from "@/app_modules/_global/component"; -import { Grid, Stack, Text, Title } from "@mantine/core"; +import { Center, Grid, Skeleton, Stack, Text, Title } from "@mantine/core"; import { MODEL_EVENT } from "../../model/interface"; +import { useShallowEffect } from "@mantine/hooks"; +import { useState } from "react"; +import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event"; +import { Event_ComponentSkeletonDetail } from "../skeleton/comp_skeleton_detail"; +import moment from "moment"; +import "moment/locale/id"; export default function ComponentEvent_DetailMainData({ - data, + eventId, }: { - data: MODEL_EVENT; + eventId: string; }) { - const tgl = data.tanggal; - const hari = tgl.toLocaleString("id-ID", { dateStyle: "full" }); + const [data, setData] = useState(null); - const jam = tgl.toLocaleTimeString([], { - timeStyle: "short", - hourCycle: "h24", - }); + useShallowEffect(() => { + onLoadData(); + }, []); + + async function onLoadData() { + const data = await fetch( + API_RouteEvent.get_one_by_id({ eventId: eventId }) + ); + const res = await data.json(); + setData(res.data); + } return ( <> - - - + {data == null ? ( + + ) : ( + + + - - - {data ? data.title : null} - - - - Lokasi - - : - - {data ? data.lokasi : null} - - - - - Tipe Acara - - : - - {data ? data.EventMaster_TipeAcara.name : null} - - - - - Tanggal & Waktu + + + {data ? data.title : null} + - Mulai + Lokasi : - - {" "} - {new Intl.DateTimeFormat("id-ID", { - dateStyle: "full", - }).format(data?.tanggal)} - ,{" "} - - {new Intl.DateTimeFormat("id-ID", { - timeStyle: "short", - }).format(data?.tanggal)} - - + {data ? data.lokasi : null} - Selesai + Tipe Acara : - - {" "} - {new Intl.DateTimeFormat("id-ID", { - dateStyle: "full", - }).format(data?.tanggalSelesai)} - ,{" "} - - {new Intl.DateTimeFormat("id-ID", { - timeStyle: "short", - }).format(data?.tanggalSelesai)} - - + {data ? data.EventMaster_TipeAcara.name : null} - - - Deskripsi - {data ? data?.deskripsi : null} + + Tanggal & Waktu + + + Mulai + + : + + + {moment( + data.tanggal?.toLocaleString("id-ID", { + dateStyle: "full", + }) + ).format("dddd, DD MMMM YYYY, LT")} + + + + + + Selesai + + : + + + {moment( + data.tanggalSelesai?.toLocaleString("id-ID", { + dateStyle: "full", + }) + ).format("dddd, DD MMMM YYYY, LT")} + + + + + + + Deskripsi + {data ? data?.deskripsi : null} + - - + + )} ); } diff --git a/src/app_modules/event/component/detail/list_peserta.tsx b/src/app_modules/event/component/detail/list_peserta.tsx index 73d56a58..a8c53851 100644 --- a/src/app_modules/event/component/detail/list_peserta.tsx +++ b/src/app_modules/event/component/detail/list_peserta.tsx @@ -6,6 +6,7 @@ import { Center, Grid, Group, + Skeleton, Stack, Text, Title, @@ -26,55 +27,78 @@ import { funGlobal_CheckProfile } from "@/app_modules/_global/fun/get"; import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global"; import { useState } from "react"; import moment from "moment"; +import { useShallowEffect } from "@mantine/hooks"; +import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event"; +import Event_ComponentSkeletonListPeserta from "../skeleton/comp_skeleton_list_peserta"; export default function ComponentEvent_ListPeserta({ - listPeserta, total, + eventId, + isNewPeserta, }: { - listPeserta: MODEL_EVENT_PESERTA[]; total: number; + eventId: string; + isNewPeserta?: boolean | null; }) { const router = useRouter(); + const [data, setData] = useState(null); + + useShallowEffect(() => { + onLoadPeserta(); + }, []); + + useShallowEffect(() => { + if (isNewPeserta !== null && isNewPeserta === true) { + onLoadPeserta(); + } + }, [isNewPeserta]); + + async function onLoadPeserta() { + const res = await fetch( + API_RouteEvent.list_peserta({ eventId: eventId, page: 1 }) + ); + const data = await res.json(); + setData(data); + } + return ( <> - - -
- Daftar Peserta ({total}) -
- - {_.isEmpty(listPeserta) ? ( + {data === null ? ( + + ) : ( + +
- - - Tidak ada peserta - - + Daftar Peserta ({total})
- ) : ( - - {listPeserta.map((e, i) => ( - - {/* */} - + {_.isEmpty(data) ? ( +
+ + - Tidak ada peserta - + +
+ ) : ( + + {data.map((e, i) => ( + + - {/* */} - - ))} - - )} -
-
+ {/* */} +
+ ))} + + )} + +
+ )} ); } diff --git a/src/app_modules/event/component/index.ts b/src/app_modules/event/component/index.ts index b146da16..6180e8a6 100644 --- a/src/app_modules/event/component/index.ts +++ b/src/app_modules/event/component/index.ts @@ -1,7 +1,11 @@ import Event_ComponentCreateButton from "./button/button_create_event"; import Event_ComponentSkeletonBeranda from "./skeleton/comp_skeleton_beranda"; +import { Event_ComponentSkeletonDetail } from "./skeleton/comp_skeleton_detail"; import { Event_ComponentSkeletonDetailData } from "./skeleton/comp_skeleton_detail_data"; +import Event_ComponentSkeletonListPeserta from "./skeleton/comp_skeleton_list_peserta"; export { Event_ComponentSkeletonDetailData }; export { Event_ComponentCreateButton }; export { Event_ComponentSkeletonBeranda }; +export { Event_ComponentSkeletonDetail }; +export { Event_ComponentSkeletonListPeserta }; diff --git a/src/app_modules/event/component/skeleton/comp_skeleton_detail.tsx b/src/app_modules/event/component/skeleton/comp_skeleton_detail.tsx new file mode 100644 index 00000000..200491a5 --- /dev/null +++ b/src/app_modules/event/component/skeleton/comp_skeleton_detail.tsx @@ -0,0 +1,36 @@ +import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; +import { Stack, Center, Skeleton, Grid } from "@mantine/core"; + +export function Event_ComponentSkeletonDetail() { + return ( + <> + + + + + + + + + + + + +
+ +
+ + + + + + + + + + +
+
+ + ); +} diff --git a/src/app_modules/event/component/skeleton/comp_skeleton_list_peserta.tsx b/src/app_modules/event/component/skeleton/comp_skeleton_list_peserta.tsx new file mode 100644 index 00000000..9cca2112 --- /dev/null +++ b/src/app_modules/event/component/skeleton/comp_skeleton_list_peserta.tsx @@ -0,0 +1,32 @@ +import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; +import { Stack, Center, Skeleton, Grid } from "@mantine/core"; + +export default function Event_ComponentSkeletonListPeserta() { + return ( + <> + + +
+ +
+ + + {Array.from(new Array(3)).map((e, i) => ( + + + + + + + + + + + + ))} + +
+
+ + ); +} diff --git a/src/app_modules/event/detail/kontribusi/index.tsx b/src/app_modules/event/detail/kontribusi/index.tsx index ee709ea4..6d667ad1 100644 --- a/src/app_modules/event/detail/kontribusi/index.tsx +++ b/src/app_modules/event/detail/kontribusi/index.tsx @@ -3,25 +3,19 @@ import { Stack } from "@mantine/core"; import ComponentEvent_DetailMainData from "../../component/detail/detail_main"; import ComponentEvent_ListPeserta from "../../component/detail/list_peserta"; -import { MODEL_EVENT, MODEL_EVENT_PESERTA } from "../../model/interface"; export default function Event_DetailKontribusi({ - dataEvent, - listKontributor, + eventId, totalPeserta, }: { - dataEvent: MODEL_EVENT; - listKontributor: MODEL_EVENT_PESERTA[]; + eventId: string; totalPeserta: number; }) { return ( <> - - + + ); diff --git a/src/app_modules/event/detail/main_detail/index.tsx b/src/app_modules/event/detail/main_detail/index.tsx index 71376d11..3438ba1a 100644 --- a/src/app_modules/event/detail/main_detail/index.tsx +++ b/src/app_modules/event/detail/main_detail/index.tsx @@ -1,11 +1,12 @@ "use client"; +import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event"; import { IRealtimeData } from "@/app/lib/global_state"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal"; import notifikasiToUser_funCreate from "@/app_modules/notifikasi/fun/create/create_notif_to_user"; -import { Button, Stack } from "@mantine/core"; -import { useRouter } from "next/navigation"; +import { Button, Skeleton, Stack } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; import { useState } from "react"; import { WibuRealtime } from "wibu-pkg"; import ComponentEvent_DetailMainData from "../../component/detail/detail_main"; @@ -13,31 +14,43 @@ import ComponentEvent_ListPeserta from "../../component/detail/list_peserta"; import { Event_countTotalPesertaById } from "../../fun/count/count_total_peserta_by_id"; import { Event_funJoinEvent } from "../../fun/create/fun_join_event"; import { Event_getListPesertaById } from "../../fun/get/get_list_peserta_by_id"; -import { MODEL_EVENT, MODEL_EVENT_PESERTA } from "../../model/interface"; export default function Event_DetailMain({ - dataEvent, - listPeserta, userLoginId, - isJoin, totalPeserta, + eventId, }: { - dataEvent: MODEL_EVENT; - listPeserta: MODEL_EVENT_PESERTA[]; userLoginId: string; - isJoin: boolean; totalPeserta: number; + eventId: string; }) { - const router = useRouter(); const [total, setTotal] = useState(totalPeserta); - const [peserta, setPeserta] = useState(listPeserta); const [isLoading, setLoading] = useState(false); + const [isJoinSuccess, setIsJoinSuccess] = useState(null); + const [isNewPeserta, setIsNewPeserta] = useState(null); + + useShallowEffect(() => { + onCheckPeserta(); + }, []); + + async function onCheckPeserta() { + const res = await fetch( + API_RouteEvent.check_peserta({ eventId: eventId, userId: userLoginId }) + ); + const data = await res.json(); + setIsJoinSuccess(data); + } return ( <> - - {isJoin ? ( + + + {isJoinSuccess == null ? ( + + ) : isJoinSuccess ? ( @@ -50,10 +63,11 @@ export default function Event_DetailMain({ onClick={() => { onJoin( userLoginId, - dataEvent.id, - setPeserta, + eventId, setTotal, - setLoading + setLoading, + setIsJoinSuccess, + setIsNewPeserta ); }} > @@ -61,7 +75,11 @@ export default function Event_DetailMain({ )} - + ); @@ -70,9 +88,11 @@ export default function Event_DetailMain({ async function onJoin( userId: string, eventId: string, - setPeserta: any, setTotal: any, - setLoading: any + setLoading: any, + setIsJoinSuccess: (val: boolean | null) => void, + setIsNewPeserta: any + ) { const body = { userId: userId, @@ -84,7 +104,7 @@ async function onJoin( const res = await Event_funJoinEvent(body as any); if (res.status === 200) { const resPeserta = await Event_getListPesertaById(eventId); - setPeserta(resPeserta); + setIsNewPeserta(true); const resTotal = await Event_countTotalPesertaById(eventId); setTotal(resTotal); @@ -111,7 +131,7 @@ async function onJoin( }); } } - + setIsJoinSuccess(true); setLoading(true); ComponentGlobal_NotifikasiBerhasil(res.message, 2000); } else { diff --git a/src/app_modules/event/detail/publish/index.tsx b/src/app_modules/event/detail/publish/index.tsx index 9afb7e66..71df87a8 100644 --- a/src/app_modules/event/detail/publish/index.tsx +++ b/src/app_modules/event/detail/publish/index.tsx @@ -6,20 +6,17 @@ import { MODEL_EVENT } from "../../model/interface"; export default function Event_DetailPublish({ dataEvent, - listPeserta, totalPeserta, + eventId, }: { dataEvent: MODEL_EVENT; - listPeserta: any[]; totalPeserta: number; + eventId: string; }) { return ( <> - + ); } diff --git a/src/app_modules/event/detail/riwayat/index.tsx b/src/app_modules/event/detail/riwayat/index.tsx index 3d9ef6e9..774eced6 100644 --- a/src/app_modules/event/detail/riwayat/index.tsx +++ b/src/app_modules/event/detail/riwayat/index.tsx @@ -1,63 +1,27 @@ "use client"; -import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; -import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal"; -import { - Stack -} from "@mantine/core"; +import { Stack } from "@mantine/core"; import { useRouter } from "next/navigation"; import { useState } from "react"; import ComponentEvent_DetailMainData from "../../component/detail/detail_main"; import ComponentEvent_ListPeserta from "../../component/detail/list_peserta"; -import { Event_countTotalPesertaById } from "../../fun/count/count_total_peserta_by_id"; -import { Event_funJoinEvent } from "../../fun/create/fun_join_event"; -import { Event_getListPesertaById } from "../../fun/get/get_list_peserta_by_id"; -import { MODEL_EVENT, MODEL_EVENT_PESERTA } from "../../model/interface"; export default function Event_DetailRiwayat({ - dataEvent, - listPeserta, totalPeserta, + eventId, }: { - dataEvent: MODEL_EVENT; - listPeserta: MODEL_EVENT_PESERTA[]; totalPeserta: number; + eventId: string; }) { const router = useRouter(); const [total, setTotal] = useState(totalPeserta); - const [peserta, setPeserta] = useState(listPeserta); + return ( <> - - + + ); } - -async function onJoin( - userId: string, - eventId: string, - setPeserta: any, - setTotal: any -) { - const body = { - userId: userId, - eventId: eventId, - }; - - await Event_funJoinEvent(body as any).then(async (res) => { - if (res.status === 200) { - await Event_getListPesertaById(eventId).then(async (val) => { - await Event_countTotalPesertaById(eventId).then((ttl) => { - setPeserta(val); - setTotal(ttl); - ComponentGlobal_NotifikasiBerhasil(res.message, 2000); - }); - }); - } else { - ComponentGlobal_NotifikasiGagal(res.message); - } - }); -} diff --git a/src/app_modules/event/fun/create/fun_join_and_confirm.ts b/src/app_modules/event/fun/create/fun_join_and_confirm.ts new file mode 100644 index 00000000..6cee969c --- /dev/null +++ b/src/app_modules/event/fun/create/fun_join_and_confirm.ts @@ -0,0 +1,23 @@ +"use server"; + +import prisma from "@/app/lib/prisma"; +import { MODEL_EVENT_PESERTA } from "../../model/interface"; +import { revalidatePath } from "next/cache"; + +export async function Event_funJoinAndConfirmEvent(data: MODEL_EVENT_PESERTA) { + const join = await prisma.event_Peserta.create({ + data: { + eventId: data.eventId, + userId: data.userId, + isPresent: true, + }, + }); + + if (!join) return { status: 400, message: "Gagal Join & Konfirmasi" }; + + revalidatePath("/dev/event/detail/main"); + return { + status: 200, + message: "Berhasil Join & Konfirmasi", + }; +} diff --git a/src/app_modules/event/fun/get/new_get_list_peserta.ts b/src/app_modules/event/fun/get/new_get_list_peserta.ts new file mode 100644 index 00000000..cf44bf0c --- /dev/null +++ b/src/app_modules/event/fun/get/new_get_list_peserta.ts @@ -0,0 +1,43 @@ +"use server"; + +import prisma from "@/app/lib/prisma"; + +export async function event_newGetListPesertaById({ + eventId, + page, +}: { + eventId: string; + page: number; +}) { + const takeData = 10; + const skipData = page * takeData - takeData; + + const data = await prisma.event_Peserta.findMany({ + take: takeData, + skip: skipData, + orderBy: { + updatedAt: "desc", + }, + where: { + eventId: eventId, + }, + select: { + id: true, + active: true, + createdAt: true, + updatedAt: true, + userId: true, + + isPresent: true, + User: { + select: { + Profile: true, + }, + }, + Event: true, + eventId: true, + }, + }); + + return data; +} diff --git a/src/app_modules/event/fun/index.ts b/src/app_modules/event/fun/index.ts index 39702477..b63c8c35 100644 --- a/src/app_modules/event/fun/index.ts +++ b/src/app_modules/event/fun/index.ts @@ -1,6 +1,7 @@ import { event_funUpdateKehadiran } from "./edit/fun_update_konfirmasi_by_user_id"; import { event_funCheckKehadiran } from "./get/fun_check_kehadiran"; import { event_funCheckPesertaByUserId } from "./get/fun_check_peserta_by_user_id"; +import { event_newGetListPesertaById } from "./get/new_get_list_peserta"; import { event_getAllByStatusId } from "./get/status/get_all_by_status_id"; import { event_getMasterStatus } from "./master/get_status_event"; @@ -9,3 +10,4 @@ export { event_getMasterStatus }; export { event_funCheckPesertaByUserId }; export { event_funUpdateKehadiran }; export { event_funCheckKehadiran }; +export { event_newGetListPesertaById }; From 3cb5416cfb3fd8e7e3d9db47ef11fe1fc00f9df4 Mon Sep 17 00:00:00 2001 From: amel Date: Fri, 6 Dec 2024 21:33:24 +0800 Subject: [PATCH 16/36] upd: portofolio detail Deskripsi: - update api detail portofolio - delete api portofolio No Issues --- src/app/api/new/portofolio/[id]/route.ts | 172 ++++++++++++++++++ src/app/dev/portofolio/main/[id]/layout.tsx | 23 +-- src/app/dev/portofolio/main/[id]/page.tsx | 15 +- .../component/button_delete_new.tsx | 97 ++++++++++ .../portofolio/component/button_more_new.tsx | 87 +++++++++ src/app_modules/katalog/portofolio/index.ts | 4 + .../katalog/portofolio/lib/api_portofolio.ts | 15 ++ .../katalog/portofolio/lib/type_portofolio.ts | 29 +++ .../portofolio/ui/ui_detail_data_new.tsx | 131 +++++++++++++ .../portofolio/ui/ui_detail_map_new.tsx | 129 +++++++++++++ .../portofolio/ui/ui_detail_media_new.tsx | 131 +++++++++++++ .../ui/ui_detail_portofolio_new.tsx | 19 ++ .../katalog/portofolio/ui/ui_layout_new.tsx | 20 ++ .../ui/ui_skeleton_detail_bisnis.tsx | 35 ++++ 14 files changed, 884 insertions(+), 23 deletions(-) create mode 100644 src/app/api/new/portofolio/[id]/route.ts create mode 100644 src/app_modules/katalog/portofolio/component/button_delete_new.tsx create mode 100644 src/app_modules/katalog/portofolio/component/button_more_new.tsx create mode 100644 src/app_modules/katalog/portofolio/ui/ui_detail_data_new.tsx create mode 100644 src/app_modules/katalog/portofolio/ui/ui_detail_map_new.tsx create mode 100644 src/app_modules/katalog/portofolio/ui/ui_detail_media_new.tsx create mode 100644 src/app_modules/katalog/portofolio/ui/ui_detail_portofolio_new.tsx create mode 100644 src/app_modules/katalog/portofolio/ui/ui_layout_new.tsx create mode 100644 src/app_modules/katalog/portofolio/ui/ui_skeleton_detail_bisnis.tsx diff --git a/src/app/api/new/portofolio/[id]/route.ts b/src/app/api/new/portofolio/[id]/route.ts new file mode 100644 index 00000000..5d783cb5 --- /dev/null +++ b/src/app/api/new/portofolio/[id]/route.ts @@ -0,0 +1,172 @@ +import { prisma } from "@/app/lib"; +import { NextResponse } from "next/server"; +import fs from "fs"; + + + +// GET ONE DATA PORTOFOLIO BY ID PORTOFOLIO +export async function GET(request: Request, context: { params: { id: string } }) { + try { + let dataFix + const { id } = context.params; + const { searchParams } = new URL(request.url); + const kategori = searchParams.get('cat'); + + if (kategori == "bisnis") { + const data = await prisma.portofolio.findUnique({ + where: { + id: id, + }, + select: { + id_Portofolio: true, + namaBisnis: true, + alamatKantor: true, + tlpn: true, + deskripsi: true, + logoId: true, + MasterBidangBisnis: { + select: { + name: true + } + }, + Profile: { + select: { + userId: true + } + } + } + }); + + dataFix = { + id_Portofolio: data?.id_Portofolio, + namaBisnis: data?.namaBisnis, + alamatKantor: data?.alamatKantor, + tlpn: data?.tlpn, + deskripsi: data?.deskripsi, + logoId: data?.logoId, + bidangBisnis: data?.MasterBidangBisnis?.name, + authorId: data?.Profile?.userId + } + + } else if (kategori == "lokasi") { + const data = await prisma.portofolio.findUnique({ + where: { + id: id, + }, + select: { + logoId: true, + BusinessMaps: { + select: { + id: true, + namePin: true, + latitude: true, + longitude: true, + imageId: true, + pinId: true + } + } + } + }); + + dataFix = { + mapId: data?.BusinessMaps?.id, + logoId: data?.logoId, + namePin: data?.BusinessMaps?.namePin, + latitude: data?.BusinessMaps?.latitude, + longitude: data?.BusinessMaps?.longitude, + imageId: data?.BusinessMaps?.imageId, + pinId: data?.BusinessMaps?.pinId + } + + } else if (kategori == "sosmed") { + const data = await prisma.portofolio.findUnique({ + where: { + id: id, + }, + select: { + Portofolio_MediaSosial: { + select: { + facebook: true, + twitter: true, + instagram: true, + tiktok: true, + youtube: true + } + } + } + }); + + dataFix = { + facebook: data?.Portofolio_MediaSosial?.facebook, + twitter: data?.Portofolio_MediaSosial?.twitter, + instagram: data?.Portofolio_MediaSosial?.instagram, + tiktok: data?.Portofolio_MediaSosial?.tiktok, + youtube: data?.Portofolio_MediaSosial?.youtube + } + } + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 }); + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 }); + } +} + +// DELETE ONE DATA PORTOFOLIO +export async function DELETE(request: Request, context: { params: { id: string } }) { + try { + const { id } = context.params + + const data = await prisma.portofolio.findUnique({ + where: { + id: id + } + }) + + const findLogo = await prisma.images.findFirst({ + where: { + id: String(data?.logoId), + }, + select: { + id: true, + url: true, + }, + }); + + if (findLogo) { + fs.unlinkSync(`./public/portofolio/logo/${findLogo.url}`) + const deleteLogo = await prisma.images.delete({ + where: { + id: String(findLogo?.id), + }, + }); + } + + + + const deletePortoMedsos = await prisma.portofolio_MediaSosial.delete({ + where: { + portofolioId: id, + }, + }); + + const deleteMap = await prisma.businessMaps.delete({ + where: { + portofolioId: id + } + }) + + const deletePortofolio = await prisma.portofolio.delete({ + where: { + id: id, + }, + }); + + return NextResponse.json({ success: true, message: "Berhasil menghapus data" }, { status: 200 }); + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal menghapus data, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/dev/portofolio/main/[id]/layout.tsx b/src/app/dev/portofolio/main/[id]/layout.tsx index 42f4bc01..1be53c84 100644 --- a/src/app/dev/portofolio/main/[id]/layout.tsx +++ b/src/app/dev/portofolio/main/[id]/layout.tsx @@ -1,27 +1,20 @@ -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { PortofolioLayout } from "@/app_modules/katalog/portofolio"; -import { portofolio_getOneById } from "@/app_modules/katalog/portofolio/fun/get/get_one_portofolio"; +import { PortofolioLayoutNew } from "@/app_modules/katalog/portofolio"; -export default async function Layout({ - children, - params, -}: { - children: any; - params: { id: string }; -}) { - let portoId = params.id; - const getPorto = await portofolio_getOneById(portoId); - const userLoginId = await funGetUserIdByToken(); +export default async function Layout({ children, params, }: { children: any; params: { id: string }; }) { + // let portoId = params.id; + // const getPorto = await portofolio_getOneById(portoId); + // const userLoginId = await funGetUserIdByToken(); return ( <> - {children} - + */} + {children} ); } diff --git a/src/app/dev/portofolio/main/[id]/page.tsx b/src/app/dev/portofolio/main/[id]/page.tsx index 61d37c14..ab45a811 100644 --- a/src/app/dev/portofolio/main/[id]/page.tsx +++ b/src/app/dev/portofolio/main/[id]/page.tsx @@ -1,20 +1,19 @@ -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { ViewPortofolio } from "@/app_modules/katalog/portofolio"; -import { portofolio_getOneById } from "@/app_modules/katalog/portofolio/fun/get/get_one_portofolio"; +import { Portofolio_UiDetailNew } from "@/app_modules/katalog/portofolio"; const mapboxToken = process.env.MAPBOX_TOKEN!; export default async function Page({ params }: { params: { id: string } }) { - const portofolioId = params.id; - const dataPortofolio = await portofolio_getOneById(portofolioId); - const userLoginId = await funGetUserIdByToken(); + // const portofolioId = params.id; + // const dataPortofolio = await portofolio_getOneById(portofolioId); + // const userLoginId = await funGetUserIdByToken(); return ( <> - + /> */} + ); } diff --git a/src/app_modules/katalog/portofolio/component/button_delete_new.tsx b/src/app_modules/katalog/portofolio/component/button_delete_new.tsx new file mode 100644 index 00000000..84d890d2 --- /dev/null +++ b/src/app_modules/katalog/portofolio/component/button_delete_new.tsx @@ -0,0 +1,97 @@ +import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; +import { ComponentGlobal_NotifikasiBerhasil, ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global"; +import { UIGlobal_Modal } from "@/app_modules/_global/ui"; +import { Button } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { IconTrash } from "@tabler/icons-react"; +import { useParams, useRouter } from "next/navigation"; +import { useState } from "react"; +import { apiDeletePortofolio, apiGetOnePortofolioById } from "../lib/api_portofolio"; +import { IDetailPortofolioBisnis } from "../lib/type_portofolio"; + +export default function ComponentPortofolio_ButtonDeleteNew() { + const param = useParams<{ id: string }>() + const [openModal, setModal] = useState(false) + const [loadingDel, setLoadingDel] = useState(false) + const [userLoginId, setUserLoginId] = useState("") + const [dataPorto, setDataPorto] = useState() + const router = useRouter() + + + async function onDelete() { + try { + setLoadingDel(true) + const response = await apiDeletePortofolio(param.id) + if (response.success) { + ComponentGlobal_NotifikasiBerhasil(response.message) + router.back() + } else { + ComponentGlobal_NotifikasiGagal(response.message); + } + } catch (error) { + console.error(error) + ComponentGlobal_NotifikasiGagal("Gagal menghapus portofolio"); + } finally { + setLoadingDel(false) + } + } + + async function funGetPortofolio() { + try { + const response = await apiGetOnePortofolioById(param.id, "bisnis") + const response2 = await funGetUserIdByToken() + if (response.success) { + setDataPorto(response.data) + setUserLoginId(response2) + } + } catch (error) { + console.error(error); + } + } + + useShallowEffect(() => { + funGetPortofolio() + }, []); + + + return ( + <> + {userLoginId === dataPorto?.authorId ? ( + + ) : ( + "" + )} + + setModal(false)} + buttonKiri={ + + } + buttonKanan={ + + } + /> + + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/component/button_more_new.tsx b/src/app_modules/katalog/portofolio/component/button_more_new.tsx new file mode 100644 index 00000000..d28ed708 --- /dev/null +++ b/src/app_modules/katalog/portofolio/component/button_more_new.tsx @@ -0,0 +1,87 @@ +import { RouterPortofolio } from "@/app/lib/router_hipmi/router_katalog"; +import { RouterMap } from "@/app/lib/router_hipmi/router_map"; +import { UIGlobal_Drawer } from "@/app_modules/_global/ui"; +import { ActionIcon } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { IconEdit, IconPhotoEdit, IconId, IconMapPin2, IconMapPin, IconDotsVertical } from "@tabler/icons-react"; +import { useParams } from "next/navigation"; +import { useState } from "react"; +import { apiGetOnePortofolioById } from "../lib/api_portofolio"; +import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; + +export default function ComponentPortofolio_ButtonMoreNew() { + const param = useParams<{ id: string }>() + const [userLoginId, setUserLoginId] = useState("") + const [authorId, setAuthorId] = useState("") + const [openDrawer, setOpenDrawer] = useState(false) + + const listPage = [ + { + id: "1", + name: "Edit detail ", + icon: , + path: RouterPortofolio.edit_data_bisnis + `${param.id}`, + }, + { + id: "2", + name: "Edit logo ", + icon: , + path: RouterPortofolio.edit_logo_bisnis + `${param.id}`, + }, + { + id: "3", + name: "Edit sosial media", + icon: , + path: RouterPortofolio.edit_medsos_bisnis + `${param.id}`, + }, + { + id: "4", + name: "Edit data map", + icon: , + path: RouterMap.edit + `${param.id}`, + }, + { + id: "5", + name: "Custom pin map", + icon: , + path: RouterMap.custom_pin + `${param.id}`, + }, + ]; + + + async function funGetPortofolio() { + try { + const response = await apiGetOnePortofolioById(param.id, "bisnis") + const response2 = await funGetUserIdByToken() + if (response.success) { + setAuthorId(response.data.authorId) + setUserLoginId(response2) + } + } catch (error) { + console.error(error); + } + } + + useShallowEffect(() => { + funGetPortofolio() + }, []); + + + return ( + <> + {userLoginId === authorId ? ( + setOpenDrawer(true)}> + + + ) : ( + + )} + + setOpenDrawer(false)} + component={listPage} + /> + + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/index.ts b/src/app_modules/katalog/portofolio/index.ts index 9d31be0f..e123bbff 100644 --- a/src/app_modules/katalog/portofolio/index.ts +++ b/src/app_modules/katalog/portofolio/index.ts @@ -11,6 +11,8 @@ import LayoutPortofolio_EditDataBisnis from "./edit/data/layout"; import LayoutPortofolio_EditLogoBisnis from "./edit/logo/layout"; import LayoutPortofolio_EditMedsosBisnis from "./edit/medsos/layout"; import ListDetailPortofolioNew from './view/list_detail_portofolio_new'; +import Portofolio_UiDetailNew from './ui/ui_detail_portofolio_new'; +import PortofolioLayoutNew from './ui/ui_layout_new'; export { CreatePortofolio, @@ -28,4 +30,6 @@ export { export type { IListPortofolio }; export { Portofolio_ViewListDetail } from "./view/view_list_detail_portofolio"; export { ListDetailPortofolioNew } +export { Portofolio_UiDetailNew } +export { PortofolioLayoutNew } diff --git a/src/app_modules/katalog/portofolio/lib/api_portofolio.ts b/src/app_modules/katalog/portofolio/lib/api_portofolio.ts index a4c460db..c152514d 100644 --- a/src/app_modules/katalog/portofolio/lib/api_portofolio.ts +++ b/src/app_modules/katalog/portofolio/lib/api_portofolio.ts @@ -1,4 +1,19 @@ export const apiGetPortofolioByProfile = async (path?: string) => { const response = await fetch(`/api/new/portofolio${(path) ? path : ''}`) return await response.json().catch(() => null) +} + +export const apiGetOnePortofolioById = async (path: string, cat:string) => { + const response = await fetch(`/api/new/portofolio/${path}?cat=${cat}`); + return await response.json().catch(() => null); +} + +export const apiDeletePortofolio = async (path: string) => { + const response = await fetch(`/api/new/portofolio/${path}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + }); + return await response.json().catch(() => null); } \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/lib/type_portofolio.ts b/src/app_modules/katalog/portofolio/lib/type_portofolio.ts index 637935e1..1a543763 100644 --- a/src/app_modules/katalog/portofolio/lib/type_portofolio.ts +++ b/src/app_modules/katalog/portofolio/lib/type_portofolio.ts @@ -3,4 +3,33 @@ export interface IListPortofolio { id_Portofolio: string profileId: string namaBisnis: string +} + +export interface IDetailPortofolioBisnis { + id_Portofolio: string + namaBisnis: string + alamatKantor: string + tlpn: string + deskripsi: string + logoId: string + bidangBisnis: string + authorId: string +} + +export interface IDetailPortofolioLokasi { + mapId: string + logoId: string + namePin: string + latitude: string + longitude: string + imageId: string + pinId: string +} + +export interface IDetailPortofolioSosmed { + facebook: string + twitter: string + instagram: string + tiktok: string + youtube: string } \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/ui/ui_detail_data_new.tsx b/src/app_modules/katalog/portofolio/ui/ui_detail_data_new.tsx new file mode 100644 index 00000000..92d2cead --- /dev/null +++ b/src/app_modules/katalog/portofolio/ui/ui_detail_data_new.tsx @@ -0,0 +1,131 @@ +import { AccentColor, MainColor } from "@/app_modules/_global/color"; +import { ComponentGlobal_LoadImage } from "@/app_modules/_global/component"; +import { Paper, Stack, Group, Title, SimpleGrid, Box, Grid, Divider, Text } from "@mantine/core"; +import { IconBuildingSkyscraper, IconListDetails, IconPhoneCall, IconMapPin, IconPinned } from "@tabler/icons-react"; +import { useState } from "react"; +import { IDetailPortofolioBisnis } from "../lib/type_portofolio"; +import { useParams } from "next/navigation"; +import { apiGetOnePortofolioById } from "../lib/api_portofolio"; +import { useShallowEffect } from "@mantine/hooks"; +import SkeletonDetailBisnis from "./ui_skeleton_detail_bisnis"; + +export default function Portofolio_UiDetailDataNew() { + const [loading, setLoading] = useState(true) + const param = useParams<{ id: string }>() + const [dataPorto, setDataPorto] = useState(); + + async function funGetPortofolio() { + try { + setLoading(true) + const response = await apiGetOnePortofolioById(param.id, "bisnis"); + if (response.success) { + setDataPorto(response.data); + } + } catch (error) { + console.error(error); + } finally { + setLoading(false) + } + } + + useShallowEffect(() => { + funGetPortofolio() + }, []); + + return ( + <> + + { + loading ? + + : + + + Data Bisnis + + id: {" "} + + #{dataPorto?.id_Portofolio} + + + + + + + + + + + + + + + + + + {dataPorto?.namaBisnis} + + + + + + + + {dataPorto?.bidangBisnis} + + + + + + + + {dataPorto?.tlpn} + + + + + + + + {dataPorto?.alamatKantor} + + + + + + + + + + + + + Tentang Kami + + + {dataPorto?.deskripsi} + + + } + + + + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/ui/ui_detail_map_new.tsx b/src/app_modules/katalog/portofolio/ui/ui_detail_map_new.tsx new file mode 100644 index 00000000..54faf735 --- /dev/null +++ b/src/app_modules/katalog/portofolio/ui/ui_detail_map_new.tsx @@ -0,0 +1,129 @@ +import { APIs } from "@/app/lib"; +import { AccentColor } from "@/app_modules/_global/color"; +import { defaultMapZoom } from "@/app_modules/map/lib/default_lat_long"; +import { Paper, Stack, Title, Avatar, Skeleton } from "@mantine/core"; +import "mapbox-gl/dist/mapbox-gl.css"; +import { useParams } from "next/navigation"; +import { useState } from "react"; +import { AttributionControl, Map, Marker, NavigationControl, ScaleControl, } from "react-map-gl"; +import { IDetailPortofolioLokasi } from "../lib/type_portofolio"; +import { apiGetOnePortofolioById } from "../lib/api_portofolio"; +import { useShallowEffect } from "@mantine/hooks"; +import { ComponentMap_DetailData, ComponentMap_DrawerDetailData } from "@/app_modules/map/_component"; + +export default function Portofolio_UiMapNew({ mapboxToken }: { mapboxToken: string }) { + const [loading, setLoading] = useState(true) + const param = useParams<{ id: string }>() + const [dataPorto, setDataPorto] = useState() + const [openDrawer, setOpenDrawer] = useState(false) + + async function funGetPortofolio() { + try { + setLoading(true) + const response = await apiGetOnePortofolioById(param.id, "lokasi"); + if (response.success) { + setDataPorto(response.data); + } + } catch (error) { + console.error(error); + } finally { + setLoading(false) + } + } + + useShallowEffect(() => { + funGetPortofolio() + }, []); + + + return ( + <> + + + + Lokasi Bisnis + + { + loading ? + + : + + { + setOpenDrawer(true); + }} + pitchAlignment="auto" + > + + + + + + + + + + + } + + + + setOpenDrawer(false)} + mapId={String(dataPorto?.mapId)} + component={} + /> + + + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/ui/ui_detail_media_new.tsx b/src/app_modules/katalog/portofolio/ui/ui_detail_media_new.tsx new file mode 100644 index 00000000..132fe798 --- /dev/null +++ b/src/app_modules/katalog/portofolio/ui/ui_detail_media_new.tsx @@ -0,0 +1,131 @@ +import { AccentColor } from "@/app_modules/_global/color"; +import { Paper, Title, Stack, Grid, Text, Skeleton, Box } from "@mantine/core"; +import { IconBrandFacebook, IconBrandInstagram, IconBrandTiktok, IconBrandTwitter, IconBrandYoutube } from "@tabler/icons-react"; +import { useParams } from "next/navigation"; +import { useState } from "react"; +import { IDetailPortofolioSosmed } from "../lib/type_portofolio"; +import { apiGetOnePortofolioById } from "../lib/api_portofolio"; +import { useShallowEffect } from "@mantine/hooks"; + +export default function Portofolio_UiSosialMediaNew() { + const [loading, setLoading] = useState(true) + const param = useParams<{ id: string }>() + const [dataPorto, setDataPorto] = useState(); + + async function funGetPortofolio() { + try { + setLoading(true) + const response = await apiGetOnePortofolioById(param.id, "sosmed"); + if (response.success) { + setDataPorto(response.data); + } + } catch (error) { + console.error(error); + } finally { + setLoading(false) + } + } + + useShallowEffect(() => { + funGetPortofolio() + }, []); + + + return ( + <> + + Media Sosial Bisnis + { + loading ? + + {[...Array(4)].map((_, index) => ( + + + + + + + + + + + ))} + + : + + + + + + + {dataPorto?.facebook ? ( + {dataPorto?.facebook} + ) : ( + "-" + )} + + + + + + + + {dataPorto?.instagram ? ( + {dataPorto?.instagram} + ) : ( + "-" + )} + + + + + + + + {dataPorto?.tiktok ? ( + {dataPorto?.tiktok} + ) : ( + "-" + )} + + + + + + + + {dataPorto?.twitter ? ( + {dataPorto?.twitter} + ) : ( + "-" + )} + + + + + + + + {dataPorto?.youtube ? ( + {dataPorto?.youtube} + ) : ( + "-" + )} + + + + + } + + + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/ui/ui_detail_portofolio_new.tsx b/src/app_modules/katalog/portofolio/ui/ui_detail_portofolio_new.tsx new file mode 100644 index 00000000..a0203528 --- /dev/null +++ b/src/app_modules/katalog/portofolio/ui/ui_detail_portofolio_new.tsx @@ -0,0 +1,19 @@ +'use client' +import { Stack } from "@mantine/core"; +import Portofolio_UiDetailDataNew from "./ui_detail_data_new"; +import Portofolio_UiMapNew from "./ui_detail_map_new"; +import Portofolio_UiSosialMediaNew from "./ui_detail_media_new"; +import ComponentPortofolio_ButtonDeleteNew from "../component/button_delete_new"; + +export default function Portofolio_UiDetailNew({ mapboxToken }: { mapboxToken: string }) { + return ( + <> + + + + + + + + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/ui/ui_layout_new.tsx b/src/app_modules/katalog/portofolio/ui/ui_layout_new.tsx new file mode 100644 index 00000000..9f6b5d75 --- /dev/null +++ b/src/app_modules/katalog/portofolio/ui/ui_layout_new.tsx @@ -0,0 +1,20 @@ +'use client' +import { UIGlobal_LayoutHeaderTamplate, UIGlobal_LayoutTamplate } from "@/app_modules/_global/ui"; +import ComponentPortofolio_ButtonMoreNew from "../component/button_more_new"; + +export default function PortofolioLayoutNew({ children }: { children: any }) { + return ( + <> + } + /> + } + > + {children} + + + ) +} \ No newline at end of file diff --git a/src/app_modules/katalog/portofolio/ui/ui_skeleton_detail_bisnis.tsx b/src/app_modules/katalog/portofolio/ui/ui_skeleton_detail_bisnis.tsx new file mode 100644 index 00000000..b8708f23 --- /dev/null +++ b/src/app_modules/katalog/portofolio/ui/ui_skeleton_detail_bisnis.tsx @@ -0,0 +1,35 @@ +import { Box, Grid, Group, Skeleton, Stack } from "@mantine/core"; + +export default function SkeletonDetailBisnis() { + return <> + + + + + + + + {[...Array(4)].map((_, index) => ( + + + + + + + + + + + ))} + + + + + + + + + + + ; +} \ No newline at end of file From 231f713005cb1b16b3c671cb52abedbe58607c0c Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Sun, 8 Dec 2024 17:16:05 +0800 Subject: [PATCH 17/36] Fix event & auth Deskripsi: - Fix event kondisi user melewatkan event - Fix bug force-dynamic di beberapa api --- src/app/api/auth/check/route.ts | 14 +++--- src/app/api/auth/login/route.ts | 35 ++++++-------- src/app/api/auth/logout/route.ts | 39 +++++++-------- src/app/api/auth/register/route.ts | 28 ++++------- src/app/api/auth/resend/route.ts | 30 +++++++----- src/app/api/auth/validasi/route.ts | 47 ++++-------------- src/app/api/check-cookies/route.ts | 2 +- src/app/api/event/list-peserta/route.ts | 1 + src/app/api/origin-url/route.ts | 3 +- src/app/api/test-scroll/route.ts | 5 +- src/app/api/validasi/route.ts | 8 ++-- src/app/api/zz-makuro/route.ts | 3 +- src/app/auth/api/login/route.ts | 8 ++-- src/app/auth/api/logout/route.ts | 5 +- src/app/dev/event/konfirmasi/[id]/page.tsx | 5 -- src/app_modules/event/_ui/konfirmasi.tsx | 55 +++++++++------------- 16 files changed, 121 insertions(+), 167 deletions(-) diff --git a/src/app/api/auth/check/route.ts b/src/app/api/auth/check/route.ts index ff617b41..d8176b13 100644 --- a/src/app/api/auth/check/route.ts +++ b/src/app/api/auth/check/route.ts @@ -1,10 +1,12 @@ import { prisma } from "@/app/lib"; import { data } from "autoprefixer"; -import { NextResponse } from "next/server"; +import { NextRequest, NextResponse } from "next/server"; +export const dynamic = "force-dynamic"; -export async function GET(request: Request) { - const { searchParams } = new URL(request.url); - const id = searchParams.get("id"); +export async function GET(request: NextRequest) { + const id = request.nextUrl.searchParams.get("id"); + // const { searchParams } = new URL(request.url); + // const id = searchParams.get("id"); try { const data = await prisma.kodeOtp.findFirst({ @@ -12,10 +14,10 @@ export async function GET(request: Request) { id: id as string, }, }); - return new Response(JSON.stringify({ data }), { status: 200 }); + return NextResponse.json(data, { status: 200 }); } catch (error) { console.log(error); } - return new Response(JSON.stringify({ data: null }), { status: 404 }); + return NextResponse.json(null, { status: 500 }); } diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts index 3aac1607..97c36643 100644 --- a/src/app/api/auth/login/route.ts +++ b/src/app/api/auth/login/route.ts @@ -18,14 +18,11 @@ export async function POST(req: Request) { const sendWa = await res.json(); if (sendWa.status !== "success") - return new Response( - JSON.stringify({ - success: false, - message: "Nomor Whatsapp Tidak Aktif", - }), + return NextResponse.json( + { success: false, message: "Nomor Whatsapp Tidak Aktif" }, { status: 400 } ); - + const createOtpId = await prisma.kodeOtp.create({ data: { nomor: nomor, @@ -34,32 +31,30 @@ export async function POST(req: Request) { }); if (!createOtpId) - return new Response( - JSON.stringify({ - success: false, - message: "Gagal Membuat Kode OTP", - }), + return NextResponse.json( + { success: false, message: "Gagal Membuat Kode OTP" }, { status: 400 } ); - return new Response( - JSON.stringify({ + return NextResponse.json( + { success: true, message: "Kode Verifikasi Dikirim", kodeId: createOtpId.id, - }), + }, { status: 200 } ); } catch (error) { console.log(error); - return new Response( - JSON.stringify({ - success: false, - message: "Server Whatsapp Error !!", - }), + + return NextResponse.json( + { success: false, message: "Server Whatsapp Error !! " }, { status: 500 } ); } } - return NextResponse.json({ success: false }); + return NextResponse.json( + { success: false, message: "Method Not Allowed" }, + { status: 405 } + ); } diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts index 9a5356ff..0f9be556 100644 --- a/src/app/api/auth/logout/route.ts +++ b/src/app/api/auth/logout/route.ts @@ -1,28 +1,21 @@ import { prisma } from "@/app/lib"; import { cookies } from "next/headers"; -export async function GET(request: Request) { - const { searchParams } = new URL(request.url); - const id = searchParams.get("id"); +import { NextRequest, NextResponse } from "next/server"; +export const dynamic = "force-dynamic"; +export async function GET(request: NextRequest) { + const id = request.nextUrl.searchParams.get("id"); + // const { searchParams } = new URL(request.url); + // const id = searchParams.get("id"); - const delToken = await prisma.userSession.delete({ - where: { - userId: id as string, - }, - }); + const delToken = await prisma.userSession.delete({ + where: { + userId: id as string, + }, + }); const del = cookies().delete(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!); - return new Response(JSON.stringify({ success: true, message: "Logout Berhasil" }), {status: 200}); -} - -// import { cookies } from "next/headers"; -// import { NextResponse } from "next/server"; - -// export async function GET() { -// cookies().set({ -// name: "mySession", -// value: "", -// maxAge: 0, -// }); - -// return NextResponse.json({ status: 200, message: "Logout" }); -// } + return NextResponse.json( + { success: true, message: "Logout Berhasil" }, + { status: 200 } + ); + } diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index 19366387..f25500d7 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -1,5 +1,6 @@ import { sessionCreate } from "@/app/auth/_lib/session_create"; import prisma from "@/app/lib/prisma"; +import { NextResponse } from "next/server"; export async function POST(req: Request) { if (req.method === "POST") { @@ -12,11 +13,8 @@ export async function POST(req: Request) { }); if (cekUsername) - return new Response( - JSON.stringify({ - success: false, - message: "Username sudah digunakan", - }), + return NextResponse.json( + { success: false, message: "Username sudah digunakan" }, { status: 400 } ); @@ -43,28 +41,22 @@ export async function POST(req: Request) { }); if (!createUserSession) - return new Response( - JSON.stringify({ - success: false, - message: "Gagal Membuat Session", - }), + return NextResponse.json( + { success: false, message: "Gagal Membuat Session" }, { status: 400 } ); } catch (error) { console.log(error); } - return new Response( - JSON.stringify({ - success: true, - message: "Berhasil Login", - }), - + return NextResponse.json( + { success: true, message: "Berhasil Login", data: createUser }, { status: 200 } ); } - return new Response( - JSON.stringify({ success: false, message: "Method Not Allowed" }), + + return NextResponse.json( + { success: false, message: "Method Not Allowed" }, { status: 405 } ); } diff --git a/src/app/api/auth/resend/route.ts b/src/app/api/auth/resend/route.ts index 3aac1607..3e02b0ef 100644 --- a/src/app/api/auth/resend/route.ts +++ b/src/app/api/auth/resend/route.ts @@ -18,11 +18,11 @@ export async function POST(req: Request) { const sendWa = await res.json(); if (sendWa.status !== "success") - return new Response( - JSON.stringify({ + return NextResponse.json( + { success: false, message: "Nomor Whatsapp Tidak Aktif", - }), + }, { status: 400 } ); @@ -34,32 +34,36 @@ export async function POST(req: Request) { }); if (!createOtpId) - return new Response( - JSON.stringify({ + return NextResponse.json( + { success: false, message: "Gagal Membuat Kode OTP", - }), + }, { status: 400 } ); - return new Response( - JSON.stringify({ + return NextResponse.json( + { success: true, message: "Kode Verifikasi Dikirim", kodeId: createOtpId.id, - }), + }, { status: 200 } ); } catch (error) { console.log(error); - return new Response( - JSON.stringify({ + + return NextResponse.json( + { success: false, message: "Server Whatsapp Error !!", - }), + }, { status: 500 } ); } } - return NextResponse.json({ success: false }); + return NextResponse.json( + { success: false, message: "Method Not Allowed" }, + { status: 405 } + ); } diff --git a/src/app/api/auth/validasi/route.ts b/src/app/api/auth/validasi/route.ts index f865cc07..2f432b70 100644 --- a/src/app/api/auth/validasi/route.ts +++ b/src/app/api/auth/validasi/route.ts @@ -1,9 +1,5 @@ import { sessionCreate } from "@/app/auth/_lib/session_create"; import prisma from "@/app/lib/prisma"; -import { ServerEnv } from "@/app/lib/server_env"; -import { sealData } from "iron-session"; -import { revalidatePath } from "next/cache"; -import { cookies } from "next/headers"; import { NextResponse } from "next/server"; export async function POST(req: Request) { @@ -23,10 +19,9 @@ export async function POST(req: Request) { }, }); - if (dataUser === null) - return new Response( - JSON.stringify({ success: false, message: "Nomor Belum Terdaftar" }), + return NextResponse.json( + { success: false, message: "Nomor Belum Terdaftar" }, { status: 404 } ); @@ -59,49 +54,27 @@ export async function POST(req: Request) { }); if (!createUserSession) - return new Response( - JSON.stringify({ success: false, message: "Gagal Membuat Session" }), + return NextResponse.json( + { success: false, message: "Gagal Membuat Session" }, { status: 400 } ); } catch (error) { console.log(error); } - // if (data) { - // const res = await sealData( - // JSON.stringify({ - // id: data.id, - // username: data.username, - // }), - // { - // password: ServerEnv.value?.WIBU_PWD as string, - // } - // ); - - // cookies().set({ - // name: "mySession", - // value: res, - // maxAge: 60 * 60 * 24 * 7, - // }); - - // revalidatePath("/dev/home"); - - // return NextResponse.json({ status: 200, data }); - // } - - // return NextResponse.json({ success: true }); - return new Response( - JSON.stringify({ + return NextResponse.json( + { success: true, message: "Berhasil Login", roleId: dataUser.masterUserRoleId, active: dataUser.active, - }), + }, { status: 200 } ); } - return new Response( - JSON.stringify({ success: false, message: "Method Not Allowed" }), + + return NextResponse.json( + { success: false, message: "Method Not Allowed" }, { status: 405 } ); } diff --git a/src/app/api/check-cookies/route.ts b/src/app/api/check-cookies/route.ts index b02fce67..ebc446be 100644 --- a/src/app/api/check-cookies/route.ts +++ b/src/app/api/check-cookies/route.ts @@ -8,7 +8,7 @@ export async function GET(req: Request) { if (!c || !c?.value || _.isEmpty(c?.value) || _.isUndefined(c?.value)) { return NextResponse.json({ success: false }); - // return new Response(JSON.stringify({ success: false })); + } return NextResponse.json({ success: true }); } diff --git a/src/app/api/event/list-peserta/route.ts b/src/app/api/event/list-peserta/route.ts index be0037a6..6acbbc08 100644 --- a/src/app/api/event/list-peserta/route.ts +++ b/src/app/api/event/list-peserta/route.ts @@ -1,4 +1,5 @@ import { event_newGetListPesertaById } from "@/app_modules/event/fun"; +import { Event_getListPesertaById } from "@/app_modules/event/fun/get/get_list_peserta_by_id"; import { toNumber } from "lodash"; import { NextResponse } from "next/server"; diff --git a/src/app/api/origin-url/route.ts b/src/app/api/origin-url/route.ts index 186624ae..4cbd28d7 100644 --- a/src/app/api/origin-url/route.ts +++ b/src/app/api/origin-url/route.ts @@ -1,6 +1,7 @@ import { headers } from "next/headers"; +import { NextResponse } from "next/server"; export async function GET(req: Request) { const origin = new URL(req.url).origin; - return new Response(JSON.stringify({ success: true, origin })); + return NextResponse.json({ success: true, origin }); } diff --git a/src/app/api/test-scroll/route.ts b/src/app/api/test-scroll/route.ts index c722ba33..f2fdc9ea 100644 --- a/src/app/api/test-scroll/route.ts +++ b/src/app/api/test-scroll/route.ts @@ -1,8 +1,11 @@ import prisma from "@/app/lib/prisma"; +import { NextResponse } from "next/server"; export async function GET(req: Request) { const page = new URL(req.url).searchParams.get("page"); - if (!page) return new Response("page require", { status: 400 }); + if (!page) + return NextResponse.json({ message: "Page not found" }, { status: 400 }); + const res = await prisma.projectCollaboration_Message.findMany({ take: 5, skip: +page * 5 - 5, diff --git a/src/app/api/validasi/route.ts b/src/app/api/validasi/route.ts index 65467cdb..4562aa95 100644 --- a/src/app/api/validasi/route.ts +++ b/src/app/api/validasi/route.ts @@ -1,7 +1,9 @@ +import { NextResponse } from "next/server"; + export async function GET(req: Request) { const auth = req.headers.get("Authorization"); const token = auth?.split(" ")[1]; - if (!token) - return new Response(JSON.stringify({ success: false }), { status: 401 }); - return new Response(JSON.stringify({ success: true })); + if (!token) return NextResponse.json({ success: false }, { status: 401 }); + return NextResponse.json({ success: true }); + } diff --git a/src/app/api/zz-makuro/route.ts b/src/app/api/zz-makuro/route.ts index df7b0d72..da2e4655 100644 --- a/src/app/api/zz-makuro/route.ts +++ b/src/app/api/zz-makuro/route.ts @@ -1,7 +1,8 @@ import { headers } from "next/headers"; +import { NextResponse } from "next/server"; export async function GET( req: Request) { const origin = new URL(req.url).origin; - return new Response(JSON.stringify({ success: true, origin })); + return NextResponse.json({ success: true, origin }); } diff --git a/src/app/auth/api/login/route.ts b/src/app/auth/api/login/route.ts index 370b5bad..eb59a9f0 100644 --- a/src/app/auth/api/login/route.ts +++ b/src/app/auth/api/login/route.ts @@ -1,5 +1,6 @@ import { prisma } from "@/app/lib"; import { sessionCreate } from "../../_lib/session_create"; +import { NextResponse } from "next/server"; export async function POST(req: Request) { const user = await prisma.user.findUnique({ @@ -12,10 +13,7 @@ export async function POST(req: Request) { }, }); - if (!user) - return new Response( - JSON.stringify({ success: false, message: "User not found" }), {status: 404} - ); + if (!user) return NextResponse.json({ success: false }, { status: 404 }); const token = await sessionCreate({ sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, @@ -23,5 +21,5 @@ export async function POST(req: Request) { user: user as any, }); - return new Response(JSON.stringify({ success: true, token })); + return NextResponse.json({ success: true, token }); } diff --git a/src/app/auth/api/logout/route.ts b/src/app/auth/api/logout/route.ts index af733975..25aab3db 100644 --- a/src/app/auth/api/logout/route.ts +++ b/src/app/auth/api/logout/route.ts @@ -1,5 +1,8 @@ import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; + export async function GET() { const del = cookies().delete(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!); - return new Response(JSON.stringify({ success: true })); + + return NextResponse.json({ success: true, message: "Logout Berhasil" }); } diff --git a/src/app/dev/event/konfirmasi/[id]/page.tsx b/src/app/dev/event/konfirmasi/[id]/page.tsx index 3a0af55b..bb2200b5 100644 --- a/src/app/dev/event/konfirmasi/[id]/page.tsx +++ b/src/app/dev/event/konfirmasi/[id]/page.tsx @@ -1,10 +1,5 @@ import { newFunGetUserId } from "@/app/lib/new_fun_user_id"; -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; import Ui_Konfirmasi from "@/app_modules/event/_ui/konfirmasi"; -import { event_funCheckPesertaByUserId } from "@/app_modules/event/fun"; -import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id"; -import moment from "moment"; -import { redirect } from "next/navigation"; export default async function Page({ params, diff --git a/src/app_modules/event/_ui/konfirmasi.tsx b/src/app_modules/event/_ui/konfirmasi.tsx index 8b1814b7..fb72b2ed 100644 --- a/src/app_modules/event/_ui/konfirmasi.tsx +++ b/src/app_modules/event/_ui/konfirmasi.tsx @@ -1,38 +1,33 @@ "use client"; -import { - UIGlobal_LayoutDefault, - UIGlobal_LayoutTamplate, -} from "@/app_modules/_global/ui"; -import { - Button, - Card, - Center, - Group, - Paper, - Skeleton, - Stack, - Text, - Title, -} from "@mantine/core"; -import { MODEL_EVENT } from "../model/interface"; -import { useShallowEffect } from "@mantine/hooks"; -import { AccentColor, MainColor } from "@/app_modules/_global/color"; -import { event_funCheckKehadiran, event_funUpdateKehadiran } from "../fun"; +import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event"; +import { RouterEvent } from "@/app/lib/router_hipmi/router_event"; +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 { redirect, useRouter } from "next/navigation"; -import { RouterEvent } from "@/app/lib/router_hipmi/router_event"; -import { useState } from "react"; -import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event"; -import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; -import moment from "moment"; -import { gs_event_hotMenu } from "../global_state"; +import { + UIGlobal_LayoutDefault +} from "@/app_modules/_global/ui"; +import { + Button, + Center, + Group, + Skeleton, + Stack, + Text +} from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; import { useAtom } from "jotai"; -import { Event_funJoinEvent } from "../fun/create/fun_join_event"; +import moment from "moment"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { event_funUpdateKehadiran } from "../fun"; import { Event_funJoinAndConfirmEvent } from "../fun/create/fun_join_and_confirm"; +import { gs_event_hotMenu } from "../global_state"; +import { MODEL_EVENT } from "../model/interface"; export default function Ui_Konfirmasi({ userLoginId, @@ -70,7 +65,6 @@ export default function Ui_Konfirmasi({ API_RouteEvent.check_peserta({ eventId: eventId, userId: userLoginId }) ); const data = await res.json(); - console.log("cek peserta", data); setIsJoin(data); } @@ -87,9 +81,6 @@ export default function Ui_Konfirmasi({ setIsPresent(data); } - // console.log("kehadiran:", isPresent); - // console.log("data:", data); - if (data == null && isPresent == null) { return ; } @@ -102,7 +93,7 @@ export default function Ui_Konfirmasi({ ); } - if (moment(data?.tanggal).diff(moment(), "minute") < 0) { + if (moment(data?.tanggalSelesai).diff(moment(), "minute") < 0) { return ( <> From 1dfaa4bb74bf4a3cf01f650ead540493dbf18be7 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Mon, 9 Dec 2024 09:10:16 +0800 Subject: [PATCH 18/36] Fix auth --- src/app/api/auth/check/route.ts | 1 + src/app/api/auth/logout/route.ts | 13 ++- src/app/api/auth/validasi/route.ts | 117 +++++++++++++------------ src/app_modules/auth/validasi/view.tsx | 4 +- 4 files changed, 69 insertions(+), 66 deletions(-) diff --git a/src/app/api/auth/check/route.ts b/src/app/api/auth/check/route.ts index d8176b13..b51a6f31 100644 --- a/src/app/api/auth/check/route.ts +++ b/src/app/api/auth/check/route.ts @@ -14,6 +14,7 @@ export async function GET(request: NextRequest) { id: id as string, }, }); + return NextResponse.json(data, { status: 200 }); } catch (error) { console.log(error); diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts index 0f9be556..44a4a2ab 100644 --- a/src/app/api/auth/logout/route.ts +++ b/src/app/api/auth/logout/route.ts @@ -1,4 +1,3 @@ -import { prisma } from "@/app/lib"; import { cookies } from "next/headers"; import { NextRequest, NextResponse } from "next/server"; export const dynamic = "force-dynamic"; @@ -7,15 +6,15 @@ export async function GET(request: NextRequest) { // const { searchParams } = new URL(request.url); // const id = searchParams.get("id"); - const delToken = await prisma.userSession.delete({ - where: { - userId: id as string, - }, - }); + // const delToken = await prisma.userSession.delete({ + // where: { + // userId: id as string, + // }, + // }); const del = cookies().delete(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!); return NextResponse.json( { success: true, message: "Logout Berhasil" }, { status: 200 } ); - } +} diff --git a/src/app/api/auth/validasi/route.ts b/src/app/api/auth/validasi/route.ts index 2f432b70..05ee6b26 100644 --- a/src/app/api/auth/validasi/route.ts +++ b/src/app/api/auth/validasi/route.ts @@ -6,73 +6,76 @@ export async function POST(req: Request) { if (req.method === "POST") { const { nomor } = await req.json(); - const dataUser = await prisma.user.findUnique({ - where: { - nomor: nomor, - }, - select: { - id: true, - nomor: true, - username: true, - active: true, - masterUserRoleId: true, - }, - }); - - if (dataUser === null) - return NextResponse.json( - { success: false, message: "Nomor Belum Terdaftar" }, - { status: 404 } - ); - - const token = await sessionCreate({ - sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, - encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, - user: dataUser as any, - }); - - const cekSessionUser = await prisma.userSession.findFirst({ - where: { - userId: dataUser.id, - }, - }); - - if (cekSessionUser !== null) { - await prisma.userSession.delete({ - where: { - userId: dataUser.id, - }, - }); - } - try { - const createUserSession = await prisma.userSession.create({ - data: { - token: token as string, - userId: dataUser.id, + const dataUser = await prisma.user.findUnique({ + where: { + nomor: nomor, + }, + select: { + id: true, + nomor: true, + username: true, + active: true, + masterUserRoleId: true, }, }); - if (!createUserSession) + if (dataUser === null) return NextResponse.json( - { success: false, message: "Gagal Membuat Session" }, - { status: 400 } + { success: false, message: "Nomor Belum Terdaftar" }, + { status: 404 } ); + + const token = await sessionCreate({ + sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, + encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, + user: dataUser as any, + }); + + // const cekSessionUser = await prisma.userSession.findFirst({ + // where: { + // userId: dataUser.id, + // }, + // }); + + // if (cekSessionUser !== null) { + // await prisma.userSession.delete({ + // where: { + // userId: dataUser.id, + // }, + // }); + // } + + // try { + // const createUserSession = await prisma.userSession.create({ + // data: { + // token: token as string, + // userId: dataUser.id, + // }, + // }); + + // if (!createUserSession) + // return NextResponse.json( + // { success: false, message: "Gagal Membuat Session" }, + // { status: 400 } + // ); + // } catch (error) { + // console.log(error); + // } + + return NextResponse.json( + { + success: true, + message: "Berhasil Login", + roleId: dataUser.masterUserRoleId, + active: dataUser.active, + }, + { status: 200 } + ); } catch (error) { console.log(error); } - - return NextResponse.json( - { - success: true, - message: "Berhasil Login", - roleId: dataUser.masterUserRoleId, - active: dataUser.active, - }, - { status: 200 } - ); } - return NextResponse.json( { success: false, message: "Method Not Allowed" }, { status: 405 } diff --git a/src/app_modules/auth/validasi/view.tsx b/src/app_modules/auth/validasi/view.tsx index d817b00e..2429b25a 100644 --- a/src/app_modules/auth/validasi/view.tsx +++ b/src/app_modules/auth/validasi/view.tsx @@ -70,8 +70,8 @@ export default function Validasi() { const result = await res.json(); onSetData({ - nomor: result.data.nomor, - code: result.data.otp, + nomor: result.nomor, + code: result.otp, }); } From 667d90bdad31ad7edc01b8da14f4c23ed106f21f Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Mon, 9 Dec 2024 11:45:22 +0800 Subject: [PATCH 19/36] chore(release): 1.2.20 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa2c2693..dbad195b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [1.2.20](https://github.com/bipproduction/hipmi/compare/v1.2.19...v1.2.20) (2024-12-09) + ## [1.2.19](https://github.com/bipproduction/hipmi/compare/v1.2.18...v1.2.19) (2024-12-06) ## [1.2.18](https://github.com/bipproduction/hipmi/compare/v1.2.17...v1.2.18) (2024-12-04) diff --git a/package.json b/package.json index 33896d0e..b47b092a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hipmi", - "version": "1.2.19", + "version": "1.2.20", "private": true, "prisma": { "seed": "npx tsx prisma/seed.ts --yes" From 8e4615e25603cdd39c158cd2a1e10b4425653af5 Mon Sep 17 00:00:00 2001 From: amel Date: Mon, 9 Dec 2024 12:02:01 +0800 Subject: [PATCH 20/36] upd: map Deskripsi; - error url get di api - api pada bussines map No Issues --- src/app/api/new/home/route.ts | 1 + src/app/api/new/map/[id]/route.ts | 76 +++++++ src/app/api/new/map/route.ts | 40 ++++ src/app/api/new/portofolio/[id]/route.ts | 1 + src/app/api/new/portofolio/route.ts | 1 + src/app/api/new/user/route.ts | 1 + src/app/dev/map/main/page.tsx | 8 +- .../map/_component/detail_data.tsx | 2 +- src/app_modules/map/_component/drawer_new.tsx | 206 ++++++++++++++++++ src/app_modules/map/lib/api_map.ts | 9 + src/app_modules/map/lib/type_map.ts | 24 ++ src/app_modules/map/ui/ui_map_new.tsx | 120 ++++++++++ src/app_modules/map/view/main_view_new.tsx | 13 ++ 13 files changed, 497 insertions(+), 5 deletions(-) create mode 100644 src/app/api/new/map/[id]/route.ts create mode 100644 src/app/api/new/map/route.ts create mode 100644 src/app_modules/map/_component/drawer_new.tsx create mode 100644 src/app_modules/map/lib/api_map.ts create mode 100644 src/app_modules/map/lib/type_map.ts create mode 100644 src/app_modules/map/ui/ui_map_new.tsx create mode 100644 src/app_modules/map/view/main_view_new.tsx diff --git a/src/app/api/new/home/route.ts b/src/app/api/new/home/route.ts index 3e07f313..bdb110d8 100644 --- a/src/app/api/new/home/route.ts +++ b/src/app/api/new/home/route.ts @@ -1,6 +1,7 @@ import { prisma } from "@/app/lib"; import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; import { NextResponse } from "next/server"; +export const dynamic = "force-dynamic"; // GET DATA HOME diff --git a/src/app/api/new/map/[id]/route.ts b/src/app/api/new/map/[id]/route.ts new file mode 100644 index 00000000..8047965d --- /dev/null +++ b/src/app/api/new/map/[id]/route.ts @@ -0,0 +1,76 @@ +import { prisma } from "@/app/lib"; +import { NextResponse } from "next/server"; +export const dynamic = "force-dynamic"; + +export async function GET(request: Request, context: { params: { id: string } }) { + try { + const { id } = context.params + const data = await prisma.businessMaps.findUnique({ + where: { + id: id, + }, + select: { + namePin: true, + latitude: true, + longitude: true, + pinId: true, + imageId: true, + Author: { + select: { + Profile: { + select: { + id: true, + name: true, + imageId: true, + } + } + } + }, + Portofolio: { + select: { + id: true, + alamatKantor: true, + tlpn: true, + deskripsi: true, + namaBisnis: true, + MasterBidangBisnis: { + select: { + name: true, + }, + }, + }, + }, + } + }); + + const dataLokasi = { + namePin: data?.namePin, + latitude: data?.latitude, + longitude: data?.longitude, + pinId: data?.pinId, + imageId: data?.imageId, + } + + const dataAuthor = { + id: data?.Author?.Profile?.id, + name: data?.Author?.Profile?.name, + imageId: data?.Author?.Profile?.imageId, + } + + const dataBisnis = { + id: data?.Portofolio?.id, + alamatKantor: data?.Portofolio?.alamatKantor, + tlpn: data?.Portofolio?.tlpn, + deskripsi: data?.Portofolio?.deskripsi, + namaBisnis: data?.Portofolio?.namaBisnis, + bidangBisnis: data?.Portofolio?.MasterBidangBisnis?.name, + } + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", dataLokasi, dataAuthor, dataBisnis }, { status: 200 }); + + } + catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/new/map/route.ts b/src/app/api/new/map/route.ts new file mode 100644 index 00000000..7a07e5ec --- /dev/null +++ b/src/app/api/new/map/route.ts @@ -0,0 +1,40 @@ +import { prisma } from "@/app/lib"; +import _ from "lodash"; +import { NextResponse } from "next/server"; +export const dynamic = "force-dynamic"; + + +// GET ALL DATA MAP +export async function GET(request: Request) { + try { + const data = await prisma.businessMaps.findMany({ + where: { + isActive: true, + }, + select: { + id: true, + namePin: true, + latitude: true, + longitude: true, + pinId: true, + Portofolio: { + select: { + logoId: true, + } + } + } + }); + + const dataFix = data.map((v: any) => ({ + ..._.omit(v, ["Portofolio"]), + logoId: v.Portofolio.logoId + })) + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 }); + + } + catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/new/portofolio/[id]/route.ts b/src/app/api/new/portofolio/[id]/route.ts index 5d783cb5..747cabd0 100644 --- a/src/app/api/new/portofolio/[id]/route.ts +++ b/src/app/api/new/portofolio/[id]/route.ts @@ -1,6 +1,7 @@ import { prisma } from "@/app/lib"; import { NextResponse } from "next/server"; import fs from "fs"; +export const dynamic = "force-dynamic"; diff --git a/src/app/api/new/portofolio/route.ts b/src/app/api/new/portofolio/route.ts index b25478d5..fbf91221 100644 --- a/src/app/api/new/portofolio/route.ts +++ b/src/app/api/new/portofolio/route.ts @@ -1,5 +1,6 @@ import { prisma } from "@/app/lib"; import { NextResponse } from "next/server"; +export const dynamic = "force-dynamic"; // GET ALL DATA PORTOFOLIO BY PROFILE ID diff --git a/src/app/api/new/user/route.ts b/src/app/api/new/user/route.ts index 73a4fb52..8f710f53 100644 --- a/src/app/api/new/user/route.ts +++ b/src/app/api/new/user/route.ts @@ -1,5 +1,6 @@ import { prisma } from "@/app/lib"; import { NextResponse } from "next/server"; +export const dynamic = "force-dynamic"; // GET ONE DATA USER PROFILE BY PROFILE ID diff --git a/src/app/dev/map/main/page.tsx b/src/app/dev/map/main/page.tsx index 8b1b6fd6..f7867fa4 100644 --- a/src/app/dev/map/main/page.tsx +++ b/src/app/dev/map/main/page.tsx @@ -1,13 +1,13 @@ -import { map_funGetAllMap } from "@/app_modules/map/fun/get/fun_get_all_map"; -import { Map_View } from "@/app_modules/map/view"; +import { Map_ViewNew } from "@/app_modules/map/view/main_view_new"; const mapboxToken = process.env.MAPBOX_TOKEN!; export default async function Page() { - const dataMap = await map_funGetAllMap(); + // const dataMap = await map_funGetAllMap(); return ( <> - + {/* */} + ); } diff --git a/src/app_modules/map/_component/detail_data.tsx b/src/app_modules/map/_component/detail_data.tsx index d76b7b5c..91686323 100644 --- a/src/app_modules/map/_component/detail_data.tsx +++ b/src/app_modules/map/_component/detail_data.tsx @@ -74,7 +74,7 @@ export function ComponentMap_DetailData({ - +{data?.Portofolio.tlpn} + {data?.Portofolio.tlpn} diff --git a/src/app_modules/map/_component/drawer_new.tsx b/src/app_modules/map/_component/drawer_new.tsx new file mode 100644 index 00000000..1a571316 --- /dev/null +++ b/src/app_modules/map/_component/drawer_new.tsx @@ -0,0 +1,206 @@ +import { RouterPortofolio } from "@/app/lib/router_hipmi/router_katalog"; +import { AccentColor, MainColor } from "@/app_modules/_global/color"; +import { ComponentGlobal_LoaderAvatar } from "@/app_modules/_global/component"; +import { ActionIcon, Box, Button, Drawer, Grid, Group, Skeleton, Stack, Text, Title } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { IconBuildingSkyscraper, IconListDetails, IconMapPin, IconPhoneCall, IconX } from "@tabler/icons-react"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { apiGetOneMapById } from "../lib/api_map"; +import { IDataMap, IDataMapDetailAuthor, IDataMapDetailBisnis } from "../lib/type_map"; +import { ComponentMap_LoadImageMap } from "./comp_load_image_map"; +import { ComponentMap_SkeletonDrawerDetailData } from "./skeleton_detail_data"; + + + + + +// SALAHHHHHHHH ---- HARUS ULANGG +export function ComponentMap_DrawerDetailDataNew({ opened, close, mapId, }: { opened: boolean; close: () => void; mapId: string }) { + const router = useRouter(); + const [dataLokasi, setDataLokasi] = useState() + const [dataAuthor, setDataAuthor] = useState() + const [dataBisnis, setDataBisnis] = useState() + const [loading, setLoading] = useState(false) + + useShallowEffect(() => { + onLoadData(); + }, []); + + async function onLoadData() { + try { + setLoading(true) + const response = await apiGetOneMapById(mapId) + if (response.success) { + setDataLokasi(response.dataLokasi) + setDataAuthor(response.dataAuthor) + setDataBisnis(response.dataBisnis) + } + } catch (error) { + console.error(error) + } finally { + setLoading(false) + } + } + + return ( + <> + close()} + position={"bottom"} + size={"auto"} + withCloseButton={false} + styles={{ + content: { + padding: 0, + position: "absolute", + margin: "auto", + backgroundColor: "transparent", + left: 0, + right: 0, + width: 500, + }, + body: { + backgroundColor: AccentColor.darkblue, + borderTop: `2px solid ${AccentColor.blue}`, + borderRight: `1px solid ${AccentColor.blue}`, + borderLeft: `1px solid ${AccentColor.blue}`, + borderRadius: "20px 20px 0px 0px", + color: "white", + paddingBottom: "5%", + }, + }} + > + + + + {dataLokasi?.namePin ? ( + dataLokasi?.namePin + ) : ( + <Skeleton radius={"xl"} w={100} /> + )} + + + + + + + + + + + { + loading ? + : + + + + onCheckProfile()} + > + + + + + + onCheckProfile()} + > + {dataAuthor?.name} + + + + + + + + + + + + + + + + {dataBisnis?.namaBisnis} + + + + + + + + {dataBisnis?.bidangBisnis} + + + + + + + + +{dataBisnis?.tlpn} + + + + + + + + {dataBisnis?.alamatKantor} + + + + + + + + + + + } + + + + + + + + + + ); +} \ No newline at end of file diff --git a/src/app_modules/map/lib/api_map.ts b/src/app_modules/map/lib/api_map.ts new file mode 100644 index 00000000..f0368959 --- /dev/null +++ b/src/app_modules/map/lib/api_map.ts @@ -0,0 +1,9 @@ +export const apiGetAllMap = async (path?: string) => { + const response = await fetch(`/api/new/map${(path) ? path : ''}`) + return await response.json().catch(() => null) +} + +export const apiGetOneMapById = async (path: string) => { + const response = await fetch(`/api/new/map/${path}`); + return await response.json().catch(() => null); +} diff --git a/src/app_modules/map/lib/type_map.ts b/src/app_modules/map/lib/type_map.ts new file mode 100644 index 00000000..f4b21aa6 --- /dev/null +++ b/src/app_modules/map/lib/type_map.ts @@ -0,0 +1,24 @@ +export interface IDataMap { + id: string + namePin: string + latitude: string + longitude: string + pinId: string + logoId: string + imageId: string +} + +export interface IDataMapDetailAuthor { + id: string + name: string + imageId: string +} + +export interface IDataMapDetailBisnis { + id: string + alamatKantor: string + tlpn: string + deskripsi: string + namaBisnis: string + bidangBisnis: string +} \ No newline at end of file diff --git a/src/app_modules/map/ui/ui_map_new.tsx b/src/app_modules/map/ui/ui_map_new.tsx new file mode 100644 index 00000000..6797cee0 --- /dev/null +++ b/src/app_modules/map/ui/ui_map_new.tsx @@ -0,0 +1,120 @@ +"use client"; +import { APIs } from "@/app/lib"; +import { AccentColor } from "@/app_modules/_global/color/color_pallet"; +import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; +import { Avatar, Stack } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import "mapbox-gl/dist/mapbox-gl.css"; +import { useState } from "react"; +import Map, { AttributionControl, Marker, NavigationControl, ScaleControl, } from "react-map-gl"; +import { ComponentMap_DetailData, ComponentMap_DrawerDetailData } from "../_component"; +import { apiGetAllMap } from "../lib/api_map"; +import { defaultLatLong, defaultMapZoom } from "../lib/default_lat_long"; +import { IDataMap } from "../lib/type_map"; + +export function UiMap_MapBoxViewNew({ mapboxToken, }: { mapboxToken: string }) { + const [mapId, setMapId] = useState(""); + const [openDrawer, setOpenDrawer] = useState(false); + const [data, setData] = useState([]); + const [loading, setLoading] = useState(false); + + useShallowEffect(() => { + onLoadData(); + }, []); + + async function onLoadData() { + try { + setLoading(true) + const response = await apiGetAllMap() + if (response.success) { + setData(response.data) + } + } catch (error) { + console.error(error) + } finally { + setLoading(false) + } + } + + if (!mapboxToken) + return ; + + return ( + <> + + { + loading ? + <> : + + {data.map((e, i) => ( + + + { + setMapId(e.id); + setOpenDrawer(true); + }} + > + + + + + ))} + + + + + + } + + + setOpenDrawer(false)} + mapId={mapId} + component={} + /> + + {/* setOpenDrawer(false)} mapId={mapId}/> */} + + ); +} diff --git a/src/app_modules/map/view/main_view_new.tsx b/src/app_modules/map/view/main_view_new.tsx new file mode 100644 index 00000000..5c9cfb0a --- /dev/null +++ b/src/app_modules/map/view/main_view_new.tsx @@ -0,0 +1,13 @@ +import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate"; +import { ComponentMap_Header } from "../_component"; +import { UiMap_MapBoxViewNew } from "../ui/ui_map_new"; + +export async function Map_ViewNew({ mapboxToken }: { mapboxToken: string }) { + return ( + <> + }> + + + + ); +} From a308f41eb1d31e08b45ef2baae11a7e317bb2496 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Mon, 9 Dec 2024 13:57:40 +0800 Subject: [PATCH 21/36] Fix event Deskripsi: - Fix logika konfirmasi event - Penambahan tampilan kehadiran peserta di admin --- src/app/api/auth/register/route.ts | 30 ++-- .../admin/event/_view/view_detail_peserta.tsx | 14 ++ .../event/fun/get/get_list_peserta_by_id.ts | 1 + src/app_modules/auth/register/view.tsx | 2 +- src/app_modules/auth/validasi/view.tsx | 10 +- src/app_modules/event/_ui/konfirmasi.tsx | 149 ++++++++++++++---- .../event/component/detail/list_peserta.tsx | 20 +-- .../button/comp_create_new_profile.tsx | 66 ++++---- 8 files changed, 196 insertions(+), 96 deletions(-) diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index f25500d7..45d3cd9e 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -32,22 +32,22 @@ export async function POST(req: Request) { user: createUser as any, }); - try { - const createUserSession = await prisma.userSession.create({ - data: { - token: token as string, - userId: createUser.id, - }, - }); + // try { + // const createUserSession = await prisma.userSession.create({ + // data: { + // token: token as string, + // userId: createUser.id, + // }, + // }); - if (!createUserSession) - return NextResponse.json( - { success: false, message: "Gagal Membuat Session" }, - { status: 400 } - ); - } catch (error) { - console.log(error); - } + // if (!createUserSession) + // return NextResponse.json( + // { success: false, message: "Gagal Membuat Session" }, + // { status: 400 } + // ); + // } catch (error) { + // console.log(error); + // } return NextResponse.json( { success: true, message: "Berhasil Login", data: createUser }, diff --git a/src/app_modules/admin/event/_view/view_detail_peserta.tsx b/src/app_modules/admin/event/_view/view_detail_peserta.tsx index 6c09ef87..c1b76811 100644 --- a/src/app_modules/admin/event/_view/view_detail_peserta.tsx +++ b/src/app_modules/admin/event/_view/view_detail_peserta.tsx @@ -2,6 +2,7 @@ import { MODEL_EVENT_PESERTA } from "@/app_modules/event/model/interface"; import { + Badge, Button, Center, Pagination, @@ -26,6 +27,7 @@ export function AdminEvent_ViewDetailPeserta({ const [isNPage, setNPage] = useState(dataPeserta.nPage); const [isActivePage, setActivePage] = useState(1); + async function onPageClick(p: any) { setActivePage(p); const loadData = await adminEvent_getListPesertaById({ @@ -52,6 +54,15 @@ export function AdminEvent_ViewDetailPeserta({
{e?.User?.Profile?.email}
+ +
+ {e.isPresent ? ( + Hadir + ) : ( + Tidak Hadir + )} +
+ )); @@ -81,6 +92,9 @@ export function AdminEvent_ViewDetailPeserta({
Email
+ +
Konfirmasi Kehadiran
+ {tableRow} diff --git a/src/app_modules/admin/event/fun/get/get_list_peserta_by_id.ts b/src/app_modules/admin/event/fun/get/get_list_peserta_by_id.ts index 7809a34a..b5b9764c 100644 --- a/src/app_modules/admin/event/fun/get/get_list_peserta_by_id.ts +++ b/src/app_modules/admin/event/fun/get/get_list_peserta_by_id.ts @@ -22,6 +22,7 @@ export async function adminEvent_getListPesertaById({ eventId: eventId, }, select: { + isPresent: true, User: { include: { Profile: true, diff --git a/src/app_modules/auth/register/view.tsx b/src/app_modules/auth/register/view.tsx index 7c1de36f..f72d7e50 100644 --- a/src/app_modules/auth/register/view.tsx +++ b/src/app_modules/auth/register/view.tsx @@ -41,7 +41,7 @@ export default function Register() { const res = await fetch(`/api/auth/check?id=${kodeId}`); const result = await res.json(); - onSetData(result.data.nomor); + onSetData(result.nomor); } async function onRegistarsi() { diff --git a/src/app_modules/auth/validasi/view.tsx b/src/app_modules/auth/validasi/view.tsx index 2429b25a..d0b39c01 100644 --- a/src/app_modules/auth/validasi/view.tsx +++ b/src/app_modules/auth/validasi/view.tsx @@ -43,7 +43,7 @@ export default function Validasi() { useShallowEffect(() => { const kodeId = localStorage.getItem("hipmi_auth_code_id"); if (kodeId != null) { - onCheckAuthCode({ kodeId: kodeId as string, onSetData: setData }); + onCheckAuthCode({ kodeId: kodeId as string }); } else { console.log("code id not found"); } @@ -51,25 +51,23 @@ export default function Validasi() { if (triggerOtp) { const kodeId = localStorage.getItem("hipmi_auth_code_id"); if (kodeId != null) { - onCheckAuthCode({ kodeId: kodeId as string, onSetData: setData }); + onCheckAuthCode({ kodeId: kodeId as string }); } else { console.log("code id not found"); } setTriggerOtp(false); } - }, [triggerOtp, setData, setTriggerOtp]); + }, [triggerOtp]); async function onCheckAuthCode({ kodeId, - onSetData, }: { kodeId: string; - onSetData: any; }) { const res = await fetch(`/api/auth/check?id=${kodeId}`); const result = await res.json(); - onSetData({ + setData({ nomor: result.nomor, code: result.otp, }); diff --git a/src/app_modules/event/_ui/konfirmasi.tsx b/src/app_modules/event/_ui/konfirmasi.tsx index fb72b2ed..2062d1b0 100644 --- a/src/app_modules/event/_ui/konfirmasi.tsx +++ b/src/app_modules/event/_ui/konfirmasi.tsx @@ -8,17 +8,8 @@ import { ComponentGlobal_NotifikasiBerhasil, ComponentGlobal_NotifikasiGagal, } from "@/app_modules/_global/notif_global"; -import { - UIGlobal_LayoutDefault -} from "@/app_modules/_global/ui"; -import { - Button, - Center, - Group, - Skeleton, - Stack, - Text -} from "@mantine/core"; +import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui"; +import { Button, Center, Group, Skeleton, Stack, Text } from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; import { useAtom } from "jotai"; import moment from "moment"; @@ -28,6 +19,7 @@ import { event_funUpdateKehadiran } from "../fun"; import { Event_funJoinAndConfirmEvent } from "../fun/create/fun_join_and_confirm"; import { gs_event_hotMenu } from "../global_state"; import { MODEL_EVENT } from "../model/interface"; +import { Event_funJoinEvent } from "../fun/create/fun_join_event"; export default function Ui_Konfirmasi({ userLoginId, @@ -68,7 +60,7 @@ export default function Ui_Konfirmasi({ setIsJoin(data); } - // CEK KEHADIRAN + // =========== CEK KEHADIRAN ===========// useShallowEffect(() => { onLoadKehadiran(); }, []); @@ -80,11 +72,14 @@ export default function Ui_Konfirmasi({ const data = await res.json(); setIsPresent(data); } + // =========== CEK KEHADIRAN ===========// + // Jika data kosong if (data == null && isPresent == null) { return ; } + // Jika data tidak ada if (data == null) { return ( <> @@ -93,6 +88,7 @@ export default function Ui_Konfirmasi({ ); } + // Jika tanggal acara lewat if (moment(data?.tanggalSelesai).diff(moment(), "minute") < 0) { return ( <> @@ -101,10 +97,26 @@ export default function Ui_Konfirmasi({ ); } - if (isJoin == false) { + // Jika belum join dan tanggal mulai acara belum lewat + if (isJoin == false && moment(data?.tanggal).diff(moment(), "minute") > 0) { return ( <> - + + ); + } + + // Jika belum join dan tanggal mulai acara sudah lewat + if (isJoin == false && moment(data?.tanggal).diff(moment(), "minute") < 0) { + return ( + <> + ; } @@ -126,16 +139,6 @@ export default function Ui_Konfirmasi({ /> ); } - // const tgl = moment(data?.tanggal).diff(moment(), "minute") < 0; - // return ( - // <> - // - // - // {JSON.stringify(tgl)} - // - // - // - // ); } function DataNotFound() { @@ -196,7 +199,91 @@ function SkeletonIsDataNull() { ); } -function UserNotJoin({ +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 + [Nama Aplikasi] agar dapat berpartisipasi. Kami sangat + menantikan kehadiran Anda. Sampai jumpa di acara ini. + + + + + + + + + ); +} + +function UserNotJoinAndEventReady({ title, eventId, userLoginId, @@ -373,8 +460,12 @@ function UserNotConfirm({ {title}
{" "} pada hari ini. Mohon untuk mengonfirmasi kehadiran Anda dengan - menekan tombol {"Hadir"} atau fitur konfirmasi yang tersedia di - bawah. Terima kasih dan selamat menikmati acara. + menekan tombol{" "} + + Konfirmasi Kehadiran + {" "} + atau fitur konfirmasi yang tersedia di bawah. Terima kasih dan + selamat menikmati acara. diff --git a/src/app_modules/event/component/detail/list_peserta.tsx b/src/app_modules/event/component/detail/list_peserta.tsx index a8c53851..ab93a45d 100644 --- a/src/app_modules/event/component/detail/list_peserta.tsx +++ b/src/app_modules/event/component/detail/list_peserta.tsx @@ -3,6 +3,7 @@ import { ActionIcon, Avatar, + Badge, Center, Grid, Group, @@ -136,11 +137,8 @@ function ComponentEvent_AvatarAndUsername({ } } - const tglMulai = moment(tanggalMulai).diff(moment(), "minutes"); + const tglMulai = moment(tanggalMulai).diff(moment(), "minutes") < 0; - const tglSelesai = moment(tanggalSelesai).diff(moment(), "minutes"); - - // console.log("mulai:", tglMulai, "selesai:", tglSelesai); return ( <> @@ -177,20 +175,12 @@ function ComponentEvent_AvatarAndUsername({ - {/* {component && ( - - - {component} - - - )} */} - - {tglMulai < 0 && ( - + {tglMulai && ( + - {isPresent ? "Hadir" : "-"} + {isPresent ? Hadir : -} diff --git a/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx b/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx index 02bd0b77..cd7b5204 100644 --- a/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx +++ b/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx @@ -47,40 +47,46 @@ export function Profile_ComponentCreateNewProfile({ "Lengkapi background profile" ); - setLoading(true); + try { + setLoading(true); - const uploadPhoto = await funGlobal_UploadToStorage({ - file: filePP, - dirId: DIRECTORY_ID.profile_foto, - }); - if (!uploadPhoto.success) { - setLoading(false); - return ComponentGlobal_NotifikasiPeringatan("Gagal upload foto profile"); - } + const uploadPhoto = await funGlobal_UploadToStorage({ + file: filePP, + dirId: DIRECTORY_ID.profile_foto, + }); + if (!uploadPhoto.success) { + setLoading(false); + return ComponentGlobal_NotifikasiPeringatan( + "Gagal upload foto profile" + ); + } - const uploadBackground = await funGlobal_UploadToStorage({ - file: fileBG, - dirId: DIRECTORY_ID.profile_background, - }); - if (!uploadBackground.success) { - setLoading(false); - return ComponentGlobal_NotifikasiPeringatan( - "Gagal upload background profile" - ); - } + const uploadBackground = await funGlobal_UploadToStorage({ + file: fileBG, + dirId: DIRECTORY_ID.profile_background, + }); + if (!uploadBackground.success) { + setLoading(false); + return ComponentGlobal_NotifikasiPeringatan( + "Gagal upload background profile" + ); + } - const create = await funCreateNewProfile({ - data: newData as any, - imageId: uploadPhoto.data.id, - imageBackgroundId: uploadBackground.data.id, - }); + const create = await funCreateNewProfile({ + data: newData as any, + imageId: uploadPhoto.data.id, + imageBackgroundId: uploadBackground.data.id, + }); - if (create.status === 201) { - ComponentGlobal_NotifikasiBerhasil("Berhasil membuat profile", 3000); - router.push(RouterHome.main_home, { scroll: false }); - } else { - ComponentGlobal_NotifikasiGagal(create.message); - setLoading(false); + if (create.status === 201) { + ComponentGlobal_NotifikasiBerhasil("Berhasil membuat profile", 3000); + router.push(RouterHome.main_home, { scroll: false }); + } else { + ComponentGlobal_NotifikasiGagal(create.message); + setLoading(false); + } + } catch (error) { + console.log(error); } } From 2ae15e9f93ffd322b49b93ff5328174c7df59bf7 Mon Sep 17 00:00:00 2001 From: amel Date: Mon, 9 Dec 2024 14:47:35 +0800 Subject: [PATCH 22/36] upd: lainnya Deskripsi: - api get all forum (blm jadi) - loading on bussines map No Issues --- src/app/api/new/forum/route.ts | 67 +++++++++++++++++++++++++++ src/app_modules/map/ui/ui_map_new.tsx | 7 ++- 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 src/app/api/new/forum/route.ts diff --git a/src/app/api/new/forum/route.ts b/src/app/api/new/forum/route.ts new file mode 100644 index 00000000..84d3523a --- /dev/null +++ b/src/app/api/new/forum/route.ts @@ -0,0 +1,67 @@ +import { prisma } from "@/app/lib" +import { NextResponse } from "next/server"; +export const dynamic = "force-dynamic"; + +// GET ALL DATA PORTOFOLIO BY PROFILE ID +export async function GET(request: Request) { + try { + const { searchParams } = new URL(request.url) + const page = searchParams.get("page") + const search = searchParams.get("search") + const dataSkip = Number(page) * 5 - 5; + + const data = await prisma.forum_Posting.findMany({ + take: 5, + skip: dataSkip, + orderBy: { + createdAt: "desc", + }, + where: { + isActive: true, + diskusi: { + mode: "insensitive", + contains: (search == undefined || search == "null") ? "" : search, + }, + }, + select: { + id: true, + diskusi: true, + createdAt: true, + isActive: true, + authorId: true, + Author: { + select: { + id: true, + username: true, + Profile: { + select: { + id: true, + name: true, + imageId: true, + }, + }, + }, + }, + Forum_Komentar: { + where: { + isActive: true, + }, + }, + ForumMaster_StatusPosting: { + select: { + id: true, + status: true, + }, + }, + forumMaster_StatusPostingId: true, + }, + }); + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data }, { status: 200 }); + + } + catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app_modules/map/ui/ui_map_new.tsx b/src/app_modules/map/ui/ui_map_new.tsx index 6797cee0..2ce61efc 100644 --- a/src/app_modules/map/ui/ui_map_new.tsx +++ b/src/app_modules/map/ui/ui_map_new.tsx @@ -2,7 +2,7 @@ import { APIs } from "@/app/lib"; import { AccentColor } from "@/app_modules/_global/color/color_pallet"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; -import { Avatar, Stack } from "@mantine/core"; +import { Avatar, Loader, Stack } from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; import "mapbox-gl/dist/mapbox-gl.css"; import { useState } from "react"; @@ -44,7 +44,10 @@ export function UiMap_MapBoxViewNew({ mapboxToken, }: { mapboxToken: string }) { { loading ? - <> : + + + + : Date: Mon, 9 Dec 2024 15:46:28 +0800 Subject: [PATCH 23/36] upd: katalog profile Deskripsi: - update bug button admin No Issues --- .../katalog/component/drawer_katalog_new.tsx | 2 +- src/app_modules/katalog/main/layout_new.tsx | 20 ++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/app_modules/katalog/component/drawer_katalog_new.tsx b/src/app_modules/katalog/component/drawer_katalog_new.tsx index c0ef291f..9e154560 100644 --- a/src/app_modules/katalog/component/drawer_katalog_new.tsx +++ b/src/app_modules/katalog/component/drawer_katalog_new.tsx @@ -89,7 +89,7 @@ export default function DrawerKatalogNew({ opened, close, userRoleId, userId }: ))} - {userRoleId != "1" && ( + {userRoleId != "1" && userRoleId != "" && ( - ) : ( - open()}> - - - ) + loading ? + : + authorId == userLoginId ? ( + open()}> + + + ) : ( + + ) } /> } From ead4913514c9da8388e6d841f20a01fc02f78756 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Mon, 9 Dec 2024 17:29:32 +0800 Subject: [PATCH 24/36] Fix event Deskripsi: - Fix konfirmasi event --- src/app_modules/event/_ui/konfirmasi.tsx | 67 ++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/src/app_modules/event/_ui/konfirmasi.tsx b/src/app_modules/event/_ui/konfirmasi.tsx index 2062d1b0..bc243cc1 100644 --- a/src/app_modules/event/_ui/konfirmasi.tsx +++ b/src/app_modules/event/_ui/konfirmasi.tsx @@ -20,6 +20,7 @@ import { Event_funJoinAndConfirmEvent } from "../fun/create/fun_join_and_confirm import { gs_event_hotMenu } from "../global_state"; import { MODEL_EVENT } from "../model/interface"; import { Event_funJoinEvent } from "../fun/create/fun_join_event"; +import "moment/locale/id"; export default function Ui_Konfirmasi({ userLoginId, @@ -88,7 +89,7 @@ export default function Ui_Konfirmasi({ ); } - // Jika tanggal acara lewat + // Jika tanggal acara sudah lewat if (moment(data?.tanggalSelesai).diff(moment(), "minute") < 0) { return ( <> @@ -97,6 +98,15 @@ export default function Ui_Konfirmasi({ ); } + // Jika join true + if (isJoin == true && moment(data?.tanggal).diff(moment(), "minute") > 0) { + return ( + <> + + + ); + } + // Jika belum join dan tanggal mulai acara belum lewat if (isJoin == false && moment(data?.tanggal).diff(moment(), "minute") > 0) { return ( @@ -125,8 +135,13 @@ export default function Ui_Konfirmasi({ ); } - // Jika sudah join, belum konfirm dan acara sudah mulai - if (isPresent && moment(data?.tanggal).diff(moment(), "minute") < 0) { + // Jika sudah join, sudah konfirmasi dan tanggal mulai acara sudah lewat + // if (isPresent && moment(data?.tanggal).diff(moment(), "minute") < 0) + if ( + isPresent && + isJoin && + moment(data?.tanggal).diff(moment(), "minute") < 0 + ) { return ; } @@ -199,6 +214,52 @@ function SkeletonIsDataNull() { ); } +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, From a48a9ca99d05b91613db5d30dc4ae47d9a7740ed Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Mon, 9 Dec 2024 17:29:56 +0800 Subject: [PATCH 25/36] chore(release): 1.2.21 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbad195b..73e2314d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [1.2.21](https://github.com/bipproduction/hipmi/compare/v1.2.20...v1.2.21) (2024-12-09) + ## [1.2.20](https://github.com/bipproduction/hipmi/compare/v1.2.19...v1.2.20) (2024-12-09) ## [1.2.19](https://github.com/bipproduction/hipmi/compare/v1.2.18...v1.2.19) (2024-12-06) diff --git a/package.json b/package.json index b47b092a..7f57f862 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hipmi", - "version": "1.2.20", + "version": "1.2.21", "private": true, "prisma": { "seed": "npx tsx prisma/seed.ts --yes" From bfddf58caaaed1e5573a080c865e0614d9e433ad Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Mon, 9 Dec 2024 17:30:30 +0800 Subject: [PATCH 26/36] Fix version 1.2.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f57f862..ae8b1fa2 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "prisma": { "seed": "npx tsx prisma/seed.ts --yes" - }, + }, "scripts": { "dev": "bun --bun run next dev --experimental-https", "build": "NODE_OPTIONS='--max-old-space-size=2048' bun --bun run next build", From d166b1b9b68e891e677a23f7ec54d0b985b17983 Mon Sep 17 00:00:00 2001 From: amel Date: Tue, 10 Dec 2024 10:52:54 +0800 Subject: [PATCH 27/36] upd: waktu splash --- src/app_modules/colab/splash/index.tsx | 2 +- src/app_modules/crowd/splash/view.tsx | 2 +- src/app_modules/forum/splash/index.tsx | 2 +- src/app_modules/map/ui/ui_splash.tsx | 2 +- src/app_modules/vote/splash/index.tsx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app_modules/colab/splash/index.tsx b/src/app_modules/colab/splash/index.tsx index 48839abb..3d6ee713 100644 --- a/src/app_modules/colab/splash/index.tsx +++ b/src/app_modules/colab/splash/index.tsx @@ -17,7 +17,7 @@ export default function Colab_Splash() { setHotMenu(1); // setStatus("Publish"); router.replace(RouterColab.beranda, {scroll: false}); - }, 1000); + }, 500); }, []); return ( diff --git a/src/app_modules/crowd/splash/view.tsx b/src/app_modules/crowd/splash/view.tsx index 65e4e84f..e60ab74a 100644 --- a/src/app_modules/crowd/splash/view.tsx +++ b/src/app_modules/crowd/splash/view.tsx @@ -10,7 +10,7 @@ export default function SplashCrowd() { const router = useRouter(); useShallowEffect(() => { - setTimeout(() => router.push(RouterCrowd.main), 1000); + setTimeout(() => router.push(RouterCrowd.main), 500); }, []); return ( <> diff --git a/src/app_modules/forum/splash/index.tsx b/src/app_modules/forum/splash/index.tsx index 205abb33..49d9eda6 100644 --- a/src/app_modules/forum/splash/index.tsx +++ b/src/app_modules/forum/splash/index.tsx @@ -11,7 +11,7 @@ export default function Forum_Splash() { useShallowEffect(() => { setTimeout(() => { router.replace(RouterForum.beranda, { scroll: false }); - }, 1000); + }, 500); }, []); return ( diff --git a/src/app_modules/map/ui/ui_splash.tsx b/src/app_modules/map/ui/ui_splash.tsx index d945b96c..607f58b8 100644 --- a/src/app_modules/map/ui/ui_splash.tsx +++ b/src/app_modules/map/ui/ui_splash.tsx @@ -11,7 +11,7 @@ export function UiMap_SplashView() { useShallowEffect(() => { setTimeout(() => { - router.replace(RouterMap.main_view, { scroll: false }), 1000; + router.replace(RouterMap.main_view, { scroll: false }), 500; }); }, []); return ( diff --git a/src/app_modules/vote/splash/index.tsx b/src/app_modules/vote/splash/index.tsx index 17a90c19..5a348b18 100644 --- a/src/app_modules/vote/splash/index.tsx +++ b/src/app_modules/vote/splash/index.tsx @@ -24,7 +24,7 @@ export default function Vote_Splash() { setTabsStatus("Publish"); setTabsRiwayat("Semua"); router.replace(RouterVote.beranda); - }, 1000); + }, 500); }, []); return ( From 8f5acae10d51484bc8fefc3272a0b7c10b297b83 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Tue, 10 Dec 2024 11:06:00 +0800 Subject: [PATCH 28/36] chore(release): 1.2.22 --- CHANGELOG.md | 2 ++ package.json | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73e2314d..75c82718 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [1.2.22](https://github.com/bipproduction/hipmi/compare/v1.2.21...v1.2.22) (2024-12-10) + ## [1.2.21](https://github.com/bipproduction/hipmi/compare/v1.2.20...v1.2.21) (2024-12-09) ## [1.2.20](https://github.com/bipproduction/hipmi/compare/v1.2.19...v1.2.20) (2024-12-09) diff --git a/package.json b/package.json index ae8b1fa2..5440fb7a 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "hipmi", - "version": "1.2.21", + "version": "1.2.22", "private": true, "prisma": { "seed": "npx tsx prisma/seed.ts --yes" - }, + }, "scripts": { "dev": "bun --bun run next dev --experimental-https", "build": "NODE_OPTIONS='--max-old-space-size=2048' bun --bun run next build", From b2e48ba06c5fcdb6d1543fa85342c1921d29e8db Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Tue, 10 Dec 2024 11:11:45 +0800 Subject: [PATCH 29/36] Fix create profile --- .../event/table_status/table_publish.tsx | 2 +- src/app_modules/event/_ui/konfirmasi.tsx | 20 +++--- .../event/component/detail/list_peserta.tsx | 72 ++++++++++++++----- .../button/comp_create_new_profile.tsx | 52 ++++++++------ 4 files changed, 96 insertions(+), 50 deletions(-) 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 7bcd290b..1553c712 100644 --- a/src/app_modules/admin/event/table_status/table_publish.tsx +++ b/src/app_modules/admin/event/table_status/table_publish.tsx @@ -54,7 +54,7 @@ function TableStatus({ listPublish }: { listPublish: any }) { useShallowEffect(() => { if (typeof window !== "undefined") { - console.log(window.location.origin); + // console.log(window.location.origin); setOrigin(window.location.origin); } }, [setOrigin]); diff --git a/src/app_modules/event/_ui/konfirmasi.tsx b/src/app_modules/event/_ui/konfirmasi.tsx index bc243cc1..ecaa99df 100644 --- a/src/app_modules/event/_ui/konfirmasi.tsx +++ b/src/app_modules/event/_ui/konfirmasi.tsx @@ -135,16 +135,6 @@ export default function Ui_Konfirmasi({ ); } - // Jika sudah join, sudah konfirmasi dan tanggal mulai acara sudah lewat - // if (isPresent && moment(data?.tanggal).diff(moment(), "minute") < 0) - if ( - isPresent && - isJoin && - moment(data?.tanggal).diff(moment(), "minute") < 0 - ) { - return ; - } - if (isPresent == false && data) { return ( ); } + + // Jika sudah join, sudah konfirmasi dan tanggal mulai acara sudah lewat + // if (isPresent && moment(data?.tanggal).diff(moment(), "minute") < 0) + if ( + isPresent && + isJoin && + moment(data?.tanggal).diff(moment(), "minute") < 0 + ) { + return ; + } } function DataNotFound() { diff --git a/src/app_modules/event/component/detail/list_peserta.tsx b/src/app_modules/event/component/detail/list_peserta.tsx index ab93a45d..0089b2f2 100644 --- a/src/app_modules/event/component/detail/list_peserta.tsx +++ b/src/app_modules/event/component/detail/list_peserta.tsx @@ -7,6 +7,7 @@ import { Center, Grid, Group, + Loader, Skeleton, Stack, Text, @@ -31,6 +32,8 @@ import moment from "moment"; import { useShallowEffect } from "@mantine/hooks"; import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event"; import Event_ComponentSkeletonListPeserta from "../skeleton/comp_skeleton_list_peserta"; +import { ScrollOnly } from "next-scroll-loader"; +import { event_newGetListPesertaById } from "../../fun"; export default function ComponentEvent_ListPeserta({ total, @@ -43,6 +46,7 @@ export default function ComponentEvent_ListPeserta({ }) { const router = useRouter(); const [data, setData] = useState(null); + const [activePage, setActivePage] = useState(1); useShallowEffect(() => { onLoadPeserta(); @@ -80,22 +84,53 @@ export default function ComponentEvent_ListPeserta({
) : ( - - {data.map((e, i) => ( - - + // + // {data.map((e, i) => ( + // + // - {/* */} - - ))} - + // {/* */} + // + // ))} + // + ( +
+ +
+ )} + data={data} + setData={setData as any} + moreData={async () => { + const loadData = await event_newGetListPesertaById({ + eventId: eventId as string, + page: activePage + 1, + }); + + setActivePage((val) => val + 1); + + return loadData; + }} + > + {(item) => ( + + )} +
)} @@ -139,7 +174,6 @@ function ComponentEvent_AvatarAndUsername({ const tglMulai = moment(tanggalMulai).diff(moment(), "minutes") < 0; - return ( <> @@ -180,7 +214,11 @@ function ComponentEvent_AvatarAndUsername({ - {isPresent ? Hadir : -} + {isPresent ? ( + Hadir + ) : ( + - + )} diff --git a/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx b/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx index cd7b5204..2ac6621b 100644 --- a/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx +++ b/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx @@ -54,6 +54,7 @@ export function Profile_ComponentCreateNewProfile({ file: filePP, dirId: DIRECTORY_ID.profile_foto, }); + // console.log("ini foto", uploadPhoto); if (!uploadPhoto.success) { setLoading(false); return ComponentGlobal_NotifikasiPeringatan( @@ -61,29 +62,36 @@ export function Profile_ComponentCreateNewProfile({ ); } - const uploadBackground = await funGlobal_UploadToStorage({ - file: fileBG, - dirId: DIRECTORY_ID.profile_background, - }); - if (!uploadBackground.success) { - setLoading(false); - return ComponentGlobal_NotifikasiPeringatan( - "Gagal upload background profile" - ); - } + if (uploadPhoto.success) { + const uploadBackground = await funGlobal_UploadToStorage({ + file: fileBG, + dirId: DIRECTORY_ID.profile_background, + }); + // console.log("ini background", uploadBackground); + if (!uploadBackground.success) { + setLoading(false); + return ComponentGlobal_NotifikasiPeringatan( + "Gagal upload background profile" + ); + } - const create = await funCreateNewProfile({ - data: newData as any, - imageId: uploadPhoto.data.id, - imageBackgroundId: uploadBackground.data.id, - }); - - if (create.status === 201) { - ComponentGlobal_NotifikasiBerhasil("Berhasil membuat profile", 3000); - router.push(RouterHome.main_home, { scroll: false }); - } else { - ComponentGlobal_NotifikasiGagal(create.message); - setLoading(false); + if (uploadBackground.success) { + const create = await funCreateNewProfile({ + data: newData as any, + imageId: uploadPhoto.data.id, + imageBackgroundId: uploadBackground.data.id, + }); + if (create.status === 201) { + ComponentGlobal_NotifikasiBerhasil( + "Berhasil membuat profile", + 3000 + ); + router.push(RouterHome.main_home, { scroll: false }); + } else { + ComponentGlobal_NotifikasiGagal(create.message); + setLoading(false); + } + } } } catch (error) { console.log(error); From 6e1a2e4bd3f78acd50ed737d4f6c97022b4acba9 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Wed, 11 Dec 2024 10:32:00 +0800 Subject: [PATCH 30/36] Fix upload Deksripsi: - Fix upload foto - Fix email regex --- bun.lockb | Bin 703886 -> 708596 bytes package.json | 2 + src/app/api/auth/register/route.ts | 65 ++--- src/app/api/auth/validasi/route.ts | 33 +-- src/app/api/upload/route.ts | 51 ++++ src/app/zCoba/page.tsx | 109 +++++++- .../fun/upload/fun_upload_to_storage.ts | 2 - src/app_modules/auth/register/view.tsx | 10 +- .../katalog/component/drawer_katalog_new.tsx | 239 +++++++++++------- .../katalog/component/regular_expressions.ts | 1 + .../button/comp_create_new_profile.tsx | 53 ++-- .../katalog/profile/create/view.tsx | 29 ++- src/middleware.ts | 1 + 13 files changed, 376 insertions(+), 219 deletions(-) create mode 100644 src/app/api/upload/route.ts diff --git a/bun.lockb b/bun.lockb index 03d96215d1f03c487d9cdac0e7d7823cb0eee742..88eaa6ad3e0e2d12a92a93c78751e54fe7ad9b20 100755 GIT binary patch delta 125612 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 At^fc4 delta 122923 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

{ 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 diff --git a/package.json b/package.json index 5440fb7a..63e0b3b0 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "@tiptap/pm": "^2.2.3", "@tiptap/react": "^2.2.3", "@tiptap/starter-kit": "^2.2.3", + "@types/bun": "^1.1.14", "@types/lodash": "^4.17.4", "@types/mapbox-gl": "^3.4.0", "@types/node": "20.4.5", @@ -48,6 +49,7 @@ "@types/uuid": "^9.0.4", "autoprefixer": "10.4.14", "bufferutil": "^4.0.8", + "bun": "^1.1.38", "dayjs": "^1.11.10", "dotenv": "^16.4.5", "echarts": "^5.4.3", diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index 45d3cd9e..c307d724 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -12,47 +12,34 @@ export async function POST(req: Request) { }, }); - if (cekUsername) + try { + if (cekUsername) + return NextResponse.json( + { success: false, message: "Username sudah digunakan" }, + { status: 400 } + ); + + const createUser = await prisma.user.create({ + data: { + username: data.username, + nomor: data.nomor, + active: true, + }, + }); + + const token = await sessionCreate({ + sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, + encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, + user: createUser as any, + }); + return NextResponse.json( - { success: false, message: "Username sudah digunakan" }, - { status: 400 } + { success: true, message: "Berhasil Login", data: createUser }, + { status: 200 } ); - - const createUser = await prisma.user.create({ - data: { - username: data.username, - nomor: data.nomor, - active: true, - }, - }); - - const token = await sessionCreate({ - sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, - encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, - user: createUser as any, - }); - - // try { - // const createUserSession = await prisma.userSession.create({ - // data: { - // token: token as string, - // userId: createUser.id, - // }, - // }); - - // if (!createUserSession) - // return NextResponse.json( - // { success: false, message: "Gagal Membuat Session" }, - // { status: 400 } - // ); - // } catch (error) { - // console.log(error); - // } - - return NextResponse.json( - { success: true, message: "Berhasil Login", data: createUser }, - { status: 200 } - ); + } catch (error) { + console.log(error); + } } return NextResponse.json( diff --git a/src/app/api/auth/validasi/route.ts b/src/app/api/auth/validasi/route.ts index 05ee6b26..69c64a8c 100644 --- a/src/app/api/auth/validasi/route.ts +++ b/src/app/api/auth/validasi/route.ts @@ -20,7 +20,7 @@ export async function POST(req: Request) { }, }); - if (dataUser === null) + if (dataUser == null) return NextResponse.json( { success: false, message: "Nomor Belum Terdaftar" }, { status: 404 } @@ -32,37 +32,6 @@ export async function POST(req: Request) { user: dataUser as any, }); - // const cekSessionUser = await prisma.userSession.findFirst({ - // where: { - // userId: dataUser.id, - // }, - // }); - - // if (cekSessionUser !== null) { - // await prisma.userSession.delete({ - // where: { - // userId: dataUser.id, - // }, - // }); - // } - - // try { - // const createUserSession = await prisma.userSession.create({ - // data: { - // token: token as string, - // userId: dataUser.id, - // }, - // }); - - // if (!createUserSession) - // return NextResponse.json( - // { success: false, message: "Gagal Membuat Session" }, - // { status: 400 } - // ); - // } catch (error) { - // console.log(error); - // } - return NextResponse.json( { success: true, diff --git a/src/app/api/upload/route.ts b/src/app/api/upload/route.ts new file mode 100644 index 00000000..00e2b69c --- /dev/null +++ b/src/app/api/upload/route.ts @@ -0,0 +1,51 @@ +import { NextResponse } from "next/server"; +export async function POST(request: Request) { + const WS_APIKEY = process.env.WS_APIKEY; + console.log(WS_APIKEY); + + try { + const formData = await request.formData(); + + const res = await fetch("https://wibu-storage.wibudev.com/api/upload", { + method: "POST", + body: formData, + headers: { + Authorization: `Bearer ${process.env.WS_APIKEY}`, + }, + }); + + // if (res.ok) { + // console.log("Berhasil"); + // const hasil = await res.json(); + // return { success: true, data: hasil.data }; + // } else { + // const errorText = await res.text(); + // return { success: false, data: {} }; + // } + } catch (error) { + console.log(error); + } + + // try { + // const res = await fetch("https://wibu-storage.wibudev.com/api/upload", { + // method: "POST", + // body: formData, + // headers: { + // Authorization: `Bearer ${process.env.WS_APIKEY}`, + // }, + // }); + + // if (res.ok) { + // const hasil = await res.json(); + // return { success: true, data: hasil.data }; + // } else { + // const errorText = await res.text(); + // return { success: false, data: {} }; + // } + // } catch (error) { + // console.error("Upload error:", error); + // return { success: false, data: {} }; + // } + + return NextResponse.json({ success: true }); +} diff --git a/src/app/zCoba/page.tsx b/src/app/zCoba/page.tsx index f07fb56c..8df38920 100644 --- a/src/app/zCoba/page.tsx +++ b/src/app/zCoba/page.tsx @@ -1,18 +1,111 @@ +"use client"; + +import { MainColor } from "@/app_modules/_global/color"; import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; import Coba_TestLoading from "@/app_modules/zCoba"; +import { + Avatar, + Button, + Center, + FileButton, + Paper, + Stack, +} from "@mantine/core"; +import { IconCamera } from "@tabler/icons-react"; +import { useState } from "react"; +import { DIRECTORY_ID } from "../lib"; +import { TokenStorage } from "../lib/token"; +import { envs } from "@/lib/envs"; -export default async function Page() { - await new Promise((a, b) => { - setTimeout(a, 3000); - }); +export default function Page() { + const [filePP, setFilePP] = useState(null); + const [imgPP, setImgPP] = useState(); - const userLoginId = await funGetUserIdByToken(); + async function onSave() { + const body = { + file: filePP, + dirId: DIRECTORY_ID.profile_foto, + }; + + const token = + "QWERTYUIOPLKJHGFDSAZXCVBNMQAZWSXEDCRFVTGBYHNUJMIKOLPPOIUYTREWQLKJHGFDSAMNBVCXZlghvftyguhijknhbgvcfytguu8okjnhbgvfty7u8oilkjnhgvtygu7u8ojilnkhbgvhujnkhghvjhukjnhb"; + + const formData = new FormData(); + formData.append("file", filePP as any); + + const res = await fetch("/api/upload", { + method: "POST", + body: formData, + }); + + console.log(await res.json()); + } return ( <> - {/* */} - - {/* */} + +

+ {imgPP ? ( + + + + ) : ( + + + + )} +
+ + { + try { + const buffer = URL.createObjectURL( + new Blob([new Uint8Array(await files.arrayBuffer())]) + ); + setImgPP(buffer); + setFilePP(files); + } catch (error) { + console.log(error); + } + }} + accept="image/png,image/jpeg" + > + {(props) => ( + + )} + + + + ); } diff --git a/src/app_modules/_global/fun/upload/fun_upload_to_storage.ts b/src/app_modules/_global/fun/upload/fun_upload_to_storage.ts index 30bc8a51..52155b9b 100644 --- a/src/app_modules/_global/fun/upload/fun_upload_to_storage.ts +++ b/src/app_modules/_global/fun/upload/fun_upload_to_storage.ts @@ -54,6 +54,4 @@ export async function funGlobal_UploadToStorage({ console.error("Error:", error); return { success: false, data: {} }; } - - return { success: false, data: { id: "" } }; } diff --git a/src/app_modules/auth/register/view.tsx b/src/app_modules/auth/register/view.tsx index f72d7e50..a8b6f985 100644 --- a/src/app_modules/auth/register/view.tsx +++ b/src/app_modules/auth/register/view.tsx @@ -64,6 +64,11 @@ export default function Register() { const result = await res.json(); + if (res.status === 400) { + setLoading(false); + ComponentGlobal_NotifikasiPeringatan(result.message); + } + if (res.status === 200) { localStorage.removeItem("hipmi_auth_code_id"); ComponentGlobal_NotifikasiBerhasil(result.message); @@ -73,11 +78,6 @@ export default function Register() { nomor: data.nomor, }); } - - if (res.status === 400) { - setLoading(false); - ComponentGlobal_NotifikasiPeringatan(result.message); - } } catch (error) { console.log(error); } diff --git a/src/app_modules/katalog/component/drawer_katalog_new.tsx b/src/app_modules/katalog/component/drawer_katalog_new.tsx index 9e154560..752a7643 100644 --- a/src/app_modules/katalog/component/drawer_katalog_new.tsx +++ b/src/app_modules/katalog/component/drawer_katalog_new.tsx @@ -1,110 +1,153 @@ import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; -import { RouterPortofolio, RouterProfile } from "@/app/lib/router_hipmi/router_katalog"; +import { + RouterPortofolio, + RouterProfile, +} from "@/app/lib/router_hipmi/router_katalog"; import { AccentColor } from "@/app_modules/_global/color"; +import { + gs_admin_navbar_menu, + gs_admin_navbar_subMenu, +} from "@/app_modules/admin/_admin_global/new_global_state"; import Component_ButtonLogout from "@/app_modules/auth/logout/view"; -import { ActionIcon, Drawer, Group, SimpleGrid, Stack, Text } from "@mantine/core"; +import { + ActionIcon, + Drawer, + Group, + SimpleGrid, + Stack, + Text, +} from "@mantine/core"; import { IconDashboard } from "@tabler/icons-react"; -import { IconEdit, IconPencilPlus, IconPhotoEdit, IconPolaroid, IconX } from "@tabler/icons-react"; +import { + IconEdit, + IconPencilPlus, + IconPhotoEdit, + IconPolaroid, + IconX, +} from "@tabler/icons-react"; +import { useAtom } from "jotai"; import { useParams, useRouter } from "next/navigation"; -export default function DrawerKatalogNew({ opened, close, userRoleId, userId }: { opened: boolean, close: () => void, userRoleId: string, userId: string }) { - const param = useParams<{ id: string }>() - const router = useRouter() +export default function DrawerKatalogNew({ + opened, + close, + userRoleId, + userId, +}: { + opened: boolean; + close: () => void; + userRoleId: string; + userId: string; +}) { + const param = useParams<{ id: string }>(); + const router = useRouter(); + const [activeId, setActiveId] = useAtom(gs_admin_navbar_menu); + const [activeChildId, setActiveChildId] = useAtom(gs_admin_navbar_subMenu); - const listPage = [ - { - id: "1", - name: "Edit profile", - icon: , - path: RouterProfile.edit + param.id, - }, - { - id: "2", - name: "Ubah foto profile", - icon: , - path: RouterProfile.update_foto_profile + param.id, - }, - { - id: "3", - name: "Ubah latar belakang", - icon: , - path: RouterProfile.update_foto_background + param.id, - }, - { - id: "4", - name: "Tambah portofolio", - icon: , - path: RouterPortofolio.create + param.id, - }, - ]; + const listPage = [ + { + id: "1", + name: "Edit profile", + icon: , + path: RouterProfile.edit + param.id, + }, + { + id: "2", + name: "Ubah foto profile", + icon: , + path: RouterProfile.update_foto_profile + param.id, + }, + { + id: "3", + name: "Ubah latar belakang", + icon: , + path: RouterProfile.update_foto_background + param.id, + }, + { + id: "4", + name: "Tambah portofolio", + icon: , + path: RouterPortofolio.create + param.id, + }, + ]; - return <> + return ( + <> close()} - position={"bottom"} - size={"auto"} - withCloseButton={false} - styles={{ - content: { - padding: 0, - position: "absolute", - margin: "auto", - backgroundColor: "transparent", - left: 0, - right: 0, - width: 500, - }, - body: { - backgroundColor: AccentColor.darkblue, - borderTop: `2px solid ${AccentColor.blue}`, - borderRight: `1px solid ${AccentColor.blue}`, - borderLeft: `1px solid ${AccentColor.blue}`, - borderRadius: "20px 20px 0px 0px", - color: "white", - paddingBottom: "5%", - }, - }} + opened={opened} + onClose={() => close()} + position={"bottom"} + size={"auto"} + withCloseButton={false} + styles={{ + content: { + padding: 0, + position: "absolute", + margin: "auto", + backgroundColor: "transparent", + left: 0, + right: 0, + width: 500, + }, + body: { + backgroundColor: AccentColor.darkblue, + borderTop: `2px solid ${AccentColor.blue}`, + borderRight: `1px solid ${AccentColor.blue}`, + borderLeft: `1px solid ${AccentColor.blue}`, + borderRadius: "20px 20px 0px 0px", + color: "white", + paddingBottom: "5%", + }, + }} > - - - - - - - - {listPage.map((e, i) => ( - - { router.push(e.path, { scroll: false }); }} - > - {e.icon} - - - {e.name} - - - ))} + + + + + + + + {listPage.map((e, i) => ( + + { + router.push(e.path, { scroll: false }); + }} + > + {e.icon} + + + {e.name} + + + ))} - - {userRoleId != "1" && userRoleId != "" && ( - - { router.push(RouterAdminDashboard.main_admin, { scroll: false }); }} - > - - - - Dashboard Admin - - - )} - - + + {userRoleId != "1" && userRoleId != "" && ( + + { + setActiveId("Main"); + setActiveChildId(""); + router.push(RouterAdminDashboard.main_admin, { + scroll: false, + }); + }} + > + + + + Dashboard Admin + + + )} + + - ; -} \ No newline at end of file + + ); +} diff --git a/src/app_modules/katalog/component/regular_expressions.ts b/src/app_modules/katalog/component/regular_expressions.ts index 526ff127..bb809be0 100644 --- a/src/app_modules/katalog/component/regular_expressions.ts +++ b/src/app_modules/katalog/component/regular_expressions.ts @@ -1,2 +1,3 @@ export var validRegex = /^([a-zA-Z0-9\.!#$%&'*+/=?^_`{|}~-]+)@([a-zA-Z0-9])+.([a-z]+)(.[a-z]+)?$/; +export const gmailRegex = /^[a-zA-Z0-9._%+-]+@gmail\.com$/; \ No newline at end of file diff --git a/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx b/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx index 2ac6621b..e523a2ba 100644 --- a/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx +++ b/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx @@ -16,6 +16,8 @@ import { useState } from "react"; import funCreateNewProfile from "../../fun/fun_create_profile"; import { MODEL_PROFILE } from "../../model/interface"; import { validRegex } from "@/app_modules/katalog/component"; +import { envs } from "@/lib/envs"; +import { TokenProvider, TokenStorage } from "@/app/lib/token"; export function Profile_ComponentCreateNewProfile({ value, @@ -54,7 +56,6 @@ export function Profile_ComponentCreateNewProfile({ file: filePP, dirId: DIRECTORY_ID.profile_foto, }); - // console.log("ini foto", uploadPhoto); if (!uploadPhoto.success) { setLoading(false); return ComponentGlobal_NotifikasiPeringatan( @@ -62,36 +63,28 @@ export function Profile_ComponentCreateNewProfile({ ); } - if (uploadPhoto.success) { - const uploadBackground = await funGlobal_UploadToStorage({ - file: fileBG, - dirId: DIRECTORY_ID.profile_background, - }); - // console.log("ini background", uploadBackground); - if (!uploadBackground.success) { - setLoading(false); - return ComponentGlobal_NotifikasiPeringatan( - "Gagal upload background profile" - ); - } + const uploadBackground = await funGlobal_UploadToStorage({ + file: fileBG, + dirId: DIRECTORY_ID.profile_background, + }); + if (!uploadBackground.success) { + setLoading(false); + return ComponentGlobal_NotifikasiPeringatan( + "Gagal upload background profile" + ); + } - if (uploadBackground.success) { - const create = await funCreateNewProfile({ - data: newData as any, - imageId: uploadPhoto.data.id, - imageBackgroundId: uploadBackground.data.id, - }); - if (create.status === 201) { - ComponentGlobal_NotifikasiBerhasil( - "Berhasil membuat profile", - 3000 - ); - router.push(RouterHome.main_home, { scroll: false }); - } else { - ComponentGlobal_NotifikasiGagal(create.message); - setLoading(false); - } - } + const create = await funCreateNewProfile({ + data: newData as any, + imageId: uploadPhoto.data.id, + imageBackgroundId: uploadBackground.data.id, + }); + if (create.status === 201) { + ComponentGlobal_NotifikasiBerhasil("Berhasil membuat profile", 3000); + router.push(RouterHome.main_home, { scroll: false }); + } else { + ComponentGlobal_NotifikasiGagal(create.message); + setLoading(false); } } catch (error) { console.log(error); diff --git a/src/app_modules/katalog/profile/create/view.tsx b/src/app_modules/katalog/profile/create/view.tsx index 0ae5e658..c97942ee 100644 --- a/src/app_modules/katalog/profile/create/view.tsx +++ b/src/app_modules/katalog/profile/create/view.tsx @@ -24,6 +24,8 @@ import { IconAt, IconCamera, IconUpload } from "@tabler/icons-react"; import { useState } from "react"; import { validRegex } from "../../component"; import { Profile_ComponentCreateNewProfile } from "../_component"; +import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global"; +import { gmailRegex } from "../../component/regular_expressions"; export default function CreateProfile() { const [filePP, setFilePP] = useState(null); @@ -38,6 +40,9 @@ export default function CreateProfile() { jenisKelamin: "", }); + // Maksimal ukuran file dalam byte (2 MB) + const MAX_SIZE = 2 * 1024 * 1024; // 2 MB + return ( <> @@ -83,8 +88,15 @@ export default function CreateProfile() { const buffer = URL.createObjectURL( new Blob([new Uint8Array(await files.arrayBuffer())]) ); - setImgPP(buffer); - setFilePP(files); + + if (files.size > MAX_SIZE) { + ComponentGlobal_NotifikasiPeringatan( + "Ukuran file terlalu besar. Maksimal 2 MB." + ); + } else { + setImgPP(buffer); + setFilePP(files); + } } catch (error) { console.log(error); } @@ -138,8 +150,15 @@ export default function CreateProfile() { const buffer = URL.createObjectURL( new Blob([new Uint8Array(await files.arrayBuffer())]) ); - setImgBG(buffer); - setFileBG(files); + + if (files.size > MAX_SIZE) { + ComponentGlobal_NotifikasiPeringatan( + "Ukuran file terlalu besar. Maksimal 2 MB." + ); + } else { + setImgBG(buffer); + setFileBG(files); + } } catch (error) { console.log(error); } @@ -189,7 +208,7 @@ export default function CreateProfile() { maxLength={100} placeholder="Contoh: User@gmail.com" error={ - value.email.length > 0 && !value.email.match(validRegex) ? ( + value.email.length > 0 && !value.email.match(gmailRegex) ? ( ) : ( "" diff --git a/src/middleware.ts b/src/middleware.ts index 621bde58..f4cd23ab 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -19,6 +19,7 @@ const middlewareConfig: MiddlewareConfig = { userPath: "/dev/home", publicRoutes: [ "/", + "/api/upload", "/api/validation", "/api/auth/*", "/api/origin-url", From 67a66edd19040cd0de4a5df86d580014f63b9fd9 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Wed, 11 Dec 2024 11:00:46 +0800 Subject: [PATCH 31/36] chore(release): 1.2.23 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75c82718..62e0291c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [1.2.23](https://github.com/bipproduction/hipmi/compare/v1.2.22...v1.2.23) (2024-12-11) + ## [1.2.22](https://github.com/bipproduction/hipmi/compare/v1.2.21...v1.2.22) (2024-12-10) ## [1.2.21](https://github.com/bipproduction/hipmi/compare/v1.2.20...v1.2.21) (2024-12-09) diff --git a/package.json b/package.json index 63e0b3b0..68de6a42 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hipmi", - "version": "1.2.22", + "version": "1.2.23", "private": true, "prisma": { "seed": "npx tsx prisma/seed.ts --yes" From 97fe458e1dede3f2faaeb921c44cdc20d3ec25be Mon Sep 17 00:00:00 2001 From: amel Date: Wed, 11 Dec 2024 11:51:34 +0800 Subject: [PATCH 32/36] upd: button back Deskripsi: - ilangin loading button back No s No Issues --- src/app_modules/_global/ui/ui_header_tamplate.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/app_modules/_global/ui/ui_header_tamplate.tsx b/src/app_modules/_global/ui/ui_header_tamplate.tsx index 6126711c..6f6425e9 100644 --- a/src/app_modules/_global/ui/ui_header_tamplate.tsx +++ b/src/app_modules/_global/ui/ui_header_tamplate.tsx @@ -77,12 +77,21 @@ export default function UIGlobal_LayoutHeaderTamplate({ : router.push(routerLeft, { scroll: false }); }} > - {isLoading ? ( + {/* PAKE LOADING SAAT KLIK BACK */} + {/* {isLoading ? ( ) : iconLeft ? ( iconLeft ) : ( + )} */} + + + {/* GA PAKE LOADING SAAT KLIK BACK */} + {iconLeft ? ( + iconLeft + ) : ( + )} )} From eab293dd35a6f061cfa4675679de1ce68f506c3c Mon Sep 17 00:00:00 2001 From: amel Date: Wed, 11 Dec 2024 12:03:56 +0800 Subject: [PATCH 33/36] fix: drawer katalog Deskripsi: - on click kotak drawer No Issues --- .../katalog/component/drawer_katalog_new.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/app_modules/katalog/component/drawer_katalog_new.tsx b/src/app_modules/katalog/component/drawer_katalog_new.tsx index 752a7643..ab0ef95c 100644 --- a/src/app_modules/katalog/component/drawer_katalog_new.tsx +++ b/src/app_modules/katalog/component/drawer_katalog_new.tsx @@ -108,14 +108,12 @@ export default function DrawerKatalogNew({ {listPage.map((e, i) => ( - - { - router.push(e.path, { scroll: false }); - }} - > + { + router.push(e.path, { scroll: false }); + }} + > + {e.icon} From 9ceb4867e35b991449a7f64995d63096908fd02f Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Wed, 11 Dec 2024 13:58:32 +0800 Subject: [PATCH 34/36] Fix profile Deskripsi: - Fix load image saat di buka --- src/app/dev/profile/edit/[id]/page.tsx | 6 ++---- .../_global/button/comp_button_upload_photo.tsx | 12 ++++++++++-- src/app_modules/_global/lib/index.ts | 3 +++ src/app_modules/_global/lib/max_size.ts | 2 ++ src/app_modules/_global/ui/ui_image_preview.tsx | 2 +- .../_component/button/comp_create_new_profile.tsx | 7 +++---- src/app_modules/katalog/profile/create/view.tsx | 9 +++------ src/app_modules/katalog/profile/edit/view.tsx | 12 +++++++----- .../katalog/profile/upload/foto_background/index.tsx | 5 ++++- .../katalog/profile/upload/foto_profile/index.tsx | 6 +++++- 10 files changed, 40 insertions(+), 24 deletions(-) create mode 100644 src/app_modules/_global/lib/index.ts create mode 100644 src/app_modules/_global/lib/max_size.ts diff --git a/src/app/dev/profile/edit/[id]/page.tsx b/src/app/dev/profile/edit/[id]/page.tsx index 53e6ca6d..1941dc84 100644 --- a/src/app/dev/profile/edit/[id]/page.tsx +++ b/src/app/dev/profile/edit/[id]/page.tsx @@ -1,14 +1,12 @@ - import EditProfile from "@/app_modules/katalog/profile/edit/view"; import { Profile_getOneProfileAndUserById } from "@/app_modules/katalog/profile/fun/get/get_one_user_profile"; export default async function Page({ params }: { params: { id: string } }) { - let profileId = params.id - const dataProfile = await Profile_getOneProfileAndUserById(profileId) + let profileId = params.id; + const dataProfile = await Profile_getOneProfileAndUserById(profileId); return ( <> - {/* {JSON.stringify(data)} */} ); diff --git a/src/app_modules/_global/button/comp_button_upload_photo.tsx b/src/app_modules/_global/button/comp_button_upload_photo.tsx index 642feddc..8cd0b16b 100644 --- a/src/app_modules/_global/button/comp_button_upload_photo.tsx +++ b/src/app_modules/_global/button/comp_button_upload_photo.tsx @@ -3,6 +3,8 @@ import { Button, FileButton } from "@mantine/core"; import { IconCamera } from "@tabler/icons-react"; import { MainColor } from "../color"; +import { MAX_SIZE } from "../lib"; +import { ComponentGlobal_NotifikasiPeringatan } from "../notif_global"; export function ComponentGlobal_ButtonUploadFileImage({ onSetFile, @@ -19,8 +21,14 @@ export function ComponentGlobal_ButtonUploadFileImage({ new Blob([new Uint8Array(await files.arrayBuffer())]) ); - onSetFile(files); - onSetImage(buffer); + if (files.size > MAX_SIZE) { + ComponentGlobal_NotifikasiPeringatan( + "Ukuran file terlalu besar. Maksimal 2 MB." + ); + } else { + onSetFile(files); + onSetImage(buffer); + } } catch (error) { console.log(error); } diff --git a/src/app_modules/_global/lib/index.ts b/src/app_modules/_global/lib/index.ts new file mode 100644 index 00000000..78b13e14 --- /dev/null +++ b/src/app_modules/_global/lib/index.ts @@ -0,0 +1,3 @@ +import { MAX_SIZE } from "./max_size"; + +export { MAX_SIZE }; diff --git a/src/app_modules/_global/lib/max_size.ts b/src/app_modules/_global/lib/max_size.ts new file mode 100644 index 00000000..d312cf45 --- /dev/null +++ b/src/app_modules/_global/lib/max_size.ts @@ -0,0 +1,2 @@ +// Maksimal ukuran file dalam byte (2 MB) +export const MAX_SIZE = 2 * 1024 * 1024; // 2 MB diff --git a/src/app_modules/_global/ui/ui_image_preview.tsx b/src/app_modules/_global/ui/ui_image_preview.tsx index 9f37411a..a2057b2d 100644 --- a/src/app_modules/_global/ui/ui_image_preview.tsx +++ b/src/app_modules/_global/ui/ui_image_preview.tsx @@ -28,7 +28,7 @@ export function UIGlobal_ImagePreview({ fileId }: { fileId: string }) { const [isImage, setIsImage] = useState(null); const [isLoading, setIsLoading] = useState(false); - const url = APIs.GET({ fileId: fileId }); + const url = APIs.GET({ fileId: fileId, size: "500" }); useShallowEffect(() => { onLoadImage(); diff --git a/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx b/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx index e523a2ba..d649d346 100644 --- a/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx +++ b/src/app_modules/katalog/profile/_component/button/comp_create_new_profile.tsx @@ -9,15 +9,13 @@ import { ComponentGlobal_NotifikasiGagal, ComponentGlobal_NotifikasiPeringatan, } from "@/app_modules/_global/notif_global"; +import { gmailRegex } from "@/app_modules/katalog/component/regular_expressions"; import { Button } from "@mantine/core"; import _ from "lodash"; import { useRouter } from "next/navigation"; import { useState } from "react"; import funCreateNewProfile from "../../fun/fun_create_profile"; import { MODEL_PROFILE } from "../../model/interface"; -import { validRegex } from "@/app_modules/katalog/component"; -import { envs } from "@/lib/envs"; -import { TokenProvider, TokenStorage } from "@/app/lib/token"; export function Profile_ComponentCreateNewProfile({ value, @@ -40,7 +38,8 @@ export function Profile_ComponentCreateNewProfile({ }; if (_.values(newData).includes("")) return ComponentGlobal_NotifikasiPeringatan("Lengkapi Data"); - if (!newData.email.match(validRegex)) return null; + if (!newData.email.match(gmailRegex)) + return ComponentGlobal_NotifikasiPeringatan("Format email salah"); if (filePP == null) return ComponentGlobal_NotifikasiPeringatan("Lengkapi foto profile"); diff --git a/src/app_modules/katalog/profile/create/view.tsx b/src/app_modules/katalog/profile/create/view.tsx index c97942ee..dce45a60 100644 --- a/src/app_modules/katalog/profile/create/view.tsx +++ b/src/app_modules/katalog/profile/create/view.tsx @@ -6,6 +6,8 @@ import { ComponentGlobal_BoxUploadImage, ComponentGlobal_ErrorInput, } from "@/app_modules/_global/component"; +import { MAX_SIZE } from "@/app_modules/_global/lib"; +import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global"; import { AspectRatio, Avatar, @@ -22,10 +24,8 @@ import { } from "@mantine/core"; import { IconAt, IconCamera, IconUpload } from "@tabler/icons-react"; import { useState } from "react"; -import { validRegex } from "../../component"; -import { Profile_ComponentCreateNewProfile } from "../_component"; -import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global"; import { gmailRegex } from "../../component/regular_expressions"; +import { Profile_ComponentCreateNewProfile } from "../_component"; export default function CreateProfile() { const [filePP, setFilePP] = useState(null); @@ -40,9 +40,6 @@ export default function CreateProfile() { jenisKelamin: "", }); - // Maksimal ukuran file dalam byte (2 MB) - const MAX_SIZE = 2 * 1024 * 1024; // 2 MB - return ( <> diff --git a/src/app_modules/katalog/profile/edit/view.tsx b/src/app_modules/katalog/profile/edit/view.tsx index 8a907706..9b33f424 100644 --- a/src/app_modules/katalog/profile/edit/view.tsx +++ b/src/app_modules/katalog/profile/edit/view.tsx @@ -4,14 +4,14 @@ import { Button, Loader, Select, Stack, TextInput } from "@mantine/core"; import _ from "lodash"; import { useRouter } from "next/navigation"; import { useState } from "react"; - import { MainColor } from "@/app_modules/_global/color/color_pallet"; import ComponentGlobal_ErrorInput from "@/app_modules/_global/component/error_input"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal"; -import { validRegex } from "../../component/regular_expressions"; +import { gmailRegex, validRegex } from "../../component/regular_expressions"; import { Profile_funEditById } from "../fun/update/fun_edit_profile_by_id"; import { MODEL_PROFILE } from "../model/interface"; +import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global"; export default function EditProfile({ data }: { data: MODEL_PROFILE }) { const router = useRouter(); @@ -24,8 +24,10 @@ export default function EditProfile({ data }: { data: MODEL_PROFILE }) { const body = dataProfile; // console.log(body) - if (_.values(body).includes("")) return null; - if (!body.email.match(validRegex)) return null; + if (_.values(body).includes("")) + return ComponentGlobal_NotifikasiPeringatan("Lengkapi data"); + if (!body.email.match(gmailRegex)) + return ComponentGlobal_NotifikasiPeringatan("Format email salah"); await Profile_funEditById(body).then((res) => { if (res.status === 200) { @@ -126,7 +128,7 @@ export default function EditProfile({ data }: { data: MODEL_PROFILE }) { dataProfile?.email === "" ? ( ) : dataProfile?.email?.length > 0 && - !dataProfile?.email.match(validRegex) ? ( + !dataProfile?.email.match(gmailRegex) ? ( ) : ( "" diff --git a/src/app_modules/katalog/profile/upload/foto_background/index.tsx b/src/app_modules/katalog/profile/upload/foto_background/index.tsx index 12d03b46..559b003c 100644 --- a/src/app_modules/katalog/profile/upload/foto_background/index.tsx +++ b/src/app_modules/katalog/profile/upload/foto_background/index.tsx @@ -30,7 +30,10 @@ export default function Profile_UpdateFotoBackground({ src={ image ? image - : APIs.GET({ fileId: profile.imageBackgroundId as any }) + : APIs.GET({ + fileId: profile.imageBackgroundId as any, + size: "400", + }) } /> diff --git a/src/app_modules/katalog/profile/upload/foto_profile/index.tsx b/src/app_modules/katalog/profile/upload/foto_profile/index.tsx index 6e49f09f..4f1a960e 100644 --- a/src/app_modules/katalog/profile/upload/foto_profile/index.tsx +++ b/src/app_modules/katalog/profile/upload/foto_profile/index.tsx @@ -27,7 +27,11 @@ export default function UploadFotoProfile({ Avatar From 8823a01b067928cbeea195402f2bb454df8e8bea Mon Sep 17 00:00:00 2001 From: amel Date: Wed, 11 Dec 2024 14:02:04 +0800 Subject: [PATCH 35/36] fix: loading button tambah portofolio Deskripsi: - loading button selanjutjnya - loading button simpan pin No Issues --- .../component/button/comp_button_selanjutnya.tsx | 2 +- .../map/_component/button/comp_button_save_pin.tsx | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app_modules/katalog/portofolio/component/button/comp_button_selanjutnya.tsx b/src/app_modules/katalog/portofolio/component/button/comp_button_selanjutnya.tsx index c7e3fcd5..41c037b9 100644 --- a/src/app_modules/katalog/portofolio/component/button/comp_button_selanjutnya.tsx +++ b/src/app_modules/katalog/portofolio/component/button/comp_button_selanjutnya.tsx @@ -30,6 +30,7 @@ export function Portofolio_ComponentButtonSelanjutnya({ const [loading, setLoading] = useState(false); async function onSubmit() { + setLoading(true); const porto = { namaBisnis: dataPortofolio.namaBisnis, masterBidangBisnisId: dataPortofolio.masterBidangBisnisId, @@ -56,7 +57,6 @@ export function Portofolio_ComponentButtonSelanjutnya({ fileId: uploadFileToStorage.data.id, }); if (res.status === 201) { - setLoading(true); ComponentGlobal_NotifikasiBerhasil("Berhasil disimpan"); router.replace(RouterMap.create + res.id, { scroll: false }); } else { diff --git a/src/app_modules/map/_component/button/comp_button_save_pin.tsx b/src/app_modules/map/_component/button/comp_button_save_pin.tsx index 8af85a08..40a398d2 100644 --- a/src/app_modules/map/_component/button/comp_button_save_pin.tsx +++ b/src/app_modules/map/_component/button/comp_button_save_pin.tsx @@ -11,6 +11,7 @@ import { useRouter } from "next/navigation"; import { map_funCreatePin } from "../../fun/create/fun_create_pin"; import { DIRECTORY_ID } from "@/app/lib"; import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun"; +import { useState } from "react"; export function ComponentMap_ButtonSavePin({ namePin, @@ -26,7 +27,10 @@ export function ComponentMap_ButtonSavePin({ file: File; }) { const router = useRouter(); + const [loading, setLoading] = useState(false) + async function onSavePin() { + setLoading(true) const uploadFileToStorage = await funGlobal_UploadToStorage({ file: file, dirId: DIRECTORY_ID.map_image, @@ -49,15 +53,19 @@ export function ComponentMap_ButtonSavePin({ res.status === 200 ? (ComponentGlobal_NotifikasiBerhasil(res.message), router.back()) : ComponentGlobal_NotifikasiGagal(res.message); + + setLoading(false) } return ( <>