diff --git a/CHANGELOG.md b/CHANGELOG.md index 86049b5d..aa2c2693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,73 @@ 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) + +## [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) + +## [1.2.14](https://github.com/bipproduction/hipmi/compare/v1.2.13...v1.2.14) (2024-12-03) + +## [1.2.13](https://github.com/bipproduction/hipmi/compare/v1.2.12...v1.2.13) (2024-12-03) + + +### Bug Fixes + +* event ([fc38813](https://github.com/bipproduction/hipmi/commit/fc388133a638d4288314dd3faeddfcce61fe7292)) +* version 1.2.12 ([932735f](https://github.com/bipproduction/hipmi/commit/932735f9238db07b331b1b26328624247371c3d6)) + +## [1.2.12](https://github.com/bipproduction/hipmi/compare/v1.2.11...v1.2.12) (2024-12-02) + + +### Bug Fixes + +* version 1.2.11 ([7afcc9c](https://github.com/bipproduction/hipmi/commit/7afcc9ced02eafab1df669fd71fdbcd4556bb322)) + +## [1.2.11](https://github.com/bipproduction/hipmi/compare/v1.2.10...v1.2.11) (2024-12-02) + + +### Bug Fixes + +* version 1.2.10 ([08eed15](https://github.com/bipproduction/hipmi/commit/08eed15b798d549146b035ffd9a44cea5e55b283)) + +## [1.2.10](https://github.com/bipproduction/hipmi/compare/v1.2.9...v1.2.10) (2024-12-02) + +## [1.2.9](https://github.com/bipproduction/hipmi/compare/v1.2.8...v1.2.9) (2024-12-02) + + +### Bug Fixes + +* version 1.2.8 ([378b2c1](https://github.com/bipproduction/hipmi/commit/378b2c19ff7a7fb07647c6a093d803d299c091f7)) +* version 1.2.8 ([23edb2d](https://github.com/bipproduction/hipmi/commit/23edb2d6317f2a8344ac3190f492f718c05b65c9)) + +## [1.2.8](https://github.com/bipproduction/hipmi/compare/v1.2.7...v1.2.8) (2024-12-02) + + +### Bug Fixes + +* version 1.2.7 ([1b83de0](https://github.com/bipproduction/hipmi/commit/1b83de0189b4581a8511cc58af2de0d5c613646b)) + +## [1.2.7](https://github.com/bipproduction/hipmi/compare/v1.2.6...v1.2.7) (2024-12-02) + + +### Bug Fixes + +* version 1.2.6 ([13142f2](https://github.com/bipproduction/hipmi/commit/13142f283d804fead233cf6bff6a41e4732a3ec0)) + +## [1.2.6](https://github.com/bipproduction/hipmi/compare/v1.2.5...v1.2.6) (2024-12-02) + + +### Bug Fixes + +* Donasi ([517b2bb](https://github.com/bipproduction/hipmi/commit/517b2bb9b0e256d31d7a10332a6e7880c58ad48f)) +* Event ([45279cd](https://github.com/bipproduction/hipmi/commit/45279cd37fb4b2a293012c9cb1a8d6e977d0edb3)) +* middleware ([31124c5](https://github.com/bipproduction/hipmi/commit/31124c5500d10a4d831c45c0da1a46a1dee995db)) + ## [1.2.5](https://github.com/bipproduction/hipmi/compare/v1.2.4...v1.2.5) (2024-11-28) diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 00000000..03d96215 Binary files /dev/null and b/bun.lockb differ diff --git a/next.config.js b/next.config.js index 5c728631..48384e99 100644 --- a/next.config.js +++ b/next.config.js @@ -1,10 +1,10 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - reactStrictMode: false, - experimental: { - serverActions: true - }, - -} + reactStrictMode: false, + experimental: { + serverActions: true, + }, + output: "standalone" +}; -module.exports = nextConfig +module.exports = nextConfig; diff --git a/package.json b/package.json index 4f88fd66..33896d0e 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,17 @@ { "name": "hipmi", - "version": "1.2.5", + "version": "1.2.19", "private": true, "prisma": { - "seed": "npx tsx prisma/seed.ts --yes" + "seed": "npx tsx prisma/seed.ts --yes" }, "scripts": { - "dev": "next dev --experimental-https", - "build": "next build", - "start": "next start", - "lint": "next lint", - "ver": "npx commit-and-tag-version -- --prerelease" + "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" }, "dependencies": { "@bounceapp/iframe": "^0.3.0", @@ -79,6 +80,7 @@ "react-international-phone": "^4.2.6", "react-map-gl": "^7.1.7", "react-pdf": "^9.1.0", + "react-qr-code": "^2.0.15", "react-quill": "^2.0.0", "react-responsive-carousel": "^3.2.23", "react-toastify": "^9.1.3", @@ -89,6 +91,7 @@ "utf-8-validate": "^6.0.3", "uuid": "^9.0.1", "wibu": "bipproduction/wibu", + "wibu-cli": "^1.0.91", "wibu-pkg": "^1.0.3", "yaml": "^2.3.2" } diff --git a/prisma/schema.prisma b/prisma/schema.prisma index c946ba04..bda6bd67 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -15,7 +15,7 @@ model User { id String @id @default(cuid()) username String @unique nomor String @unique - active Boolean @default(true) + active Boolean @default(false) createdAt DateTime? @default(now()) updatedAt DateTime? @updatedAt MasterUserRole MasterUserRole @relation(fields: [masterUserRoleId], references: [id]) @@ -573,16 +573,19 @@ model Donasi_PencairanDana { // ========================================= EVENT ========================================= // model Event { - id String @id @default(cuid()) + id String @id @default(cuid()) title String lokasi String - tanggal DateTime + tanggal DateTime? deskripsi String - active Boolean @default(true) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + active Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt catatan String? + tanggalSelesai DateTime? + isArsip Boolean? @default(false) + Author User? @relation(fields: [authorId], references: [id]) authorId String? EventMaster_Status EventMaster_Status? @relation(fields: [eventMaster_StatusId], references: [id]) @@ -615,6 +618,7 @@ model Event_Peserta { active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + isPresent Boolean @default(false) Event Event? @relation(fields: [eventId], references: [id]) eventId String? diff --git a/public/aset/home/home-hipmi-new.png b/public/aset/home/home-hipmi-new.png new file mode 100644 index 00000000..968807de Binary files /dev/null and b/public/aset/home/home-hipmi-new.png differ diff --git a/src/app/(user)/login/page.tsx b/src/app/(user)/login/page.tsx index cd18a2f8..fb36a1ae 100644 --- a/src/app/(user)/login/page.tsx +++ b/src/app/(user)/login/page.tsx @@ -1,4 +1,4 @@ -import { funCheckCookies } from "@/app_modules/_global/fun/get/fun_check_cookies"; + import { Login } from "@/app_modules/auth"; import versionUpdate from "../../../../package.json"; diff --git a/src/app/(user)/register/[id]/page.tsx b/src/app/(user)/register/[id]/page.tsx deleted file mode 100644 index ff588e30..00000000 --- a/src/app/(user)/register/[id]/page.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { Register } from "@/app_modules/auth"; -import { auth_getCodeOtpByNumber } from "@/app_modules/auth/fun/get_kode_otp_by_id"; - -export default async function Page({ params }: { params: { id: string } }) { - let otpId = params.id; - const dataOtp = await auth_getCodeOtpByNumber({ kodeId: otpId }); - return ; -} diff --git a/src/app/(user)/register/page.tsx b/src/app/(user)/register/page.tsx new file mode 100644 index 00000000..82a2fc25 --- /dev/null +++ b/src/app/(user)/register/page.tsx @@ -0,0 +1,5 @@ +import { Register } from "@/app_modules/auth"; + +export default async function Page() { + return ; +} diff --git a/src/app/(user)/splash/page.tsx b/src/app/(user)/splash/page.tsx new file mode 100644 index 00000000..17632d04 --- /dev/null +++ b/src/app/(user)/splash/page.tsx @@ -0,0 +1,7 @@ +import { SplashScreen } from "@/app_modules/auth"; + +export default async function Page() { + return <> + + +} \ No newline at end of file diff --git a/src/app/(user)/validasi/[id]/page.tsx b/src/app/(user)/validasi/[id]/page.tsx deleted file mode 100644 index 087d816f..00000000 --- a/src/app/(user)/validasi/[id]/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Validasi } from "@/app_modules/auth"; -import { auth_getCodeOtpByNumber } from "@/app_modules/auth/fun/get_kode_otp_by_id"; - -export default async function Page({ params }: { params: { id: string } }) { - let kodeId = params.id; - const dataOtp = await auth_getCodeOtpByNumber({ kodeId: kodeId }); - - return ; -} diff --git a/src/app/(user)/validasi/page.tsx b/src/app/(user)/validasi/page.tsx new file mode 100644 index 00000000..59826ee4 --- /dev/null +++ b/src/app/(user)/validasi/page.tsx @@ -0,0 +1,5 @@ +import { Validasi } from "@/app_modules/auth"; + +export default async function Page() { + return ; +} diff --git a/src/app/(user)/waiting-room/page.tsx b/src/app/(user)/waiting-room/page.tsx new file mode 100644 index 00000000..abb6e4d0 --- /dev/null +++ b/src/app/(user)/waiting-room/page.tsx @@ -0,0 +1,19 @@ +import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; +import { funGlobal_checkActivationUseById } from "@/app_modules/_global/fun/get/fun_check_activation_use_by_id"; +import WaitingRoom_View from "@/app_modules/waiting_room/view"; + +export default async function Page() { + const userLoginId = await funGetUserIdByToken(); + const activationUser = await funGlobal_checkActivationUseById({ + userId: userLoginId as string, + }); + + return ( + <> + + + ); +} diff --git a/src/app/api/auth/check/route.ts b/src/app/api/auth/check/route.ts new file mode 100644 index 00000000..ff617b41 --- /dev/null +++ b/src/app/api/auth/check/route.ts @@ -0,0 +1,21 @@ +import { prisma } from "@/app/lib"; +import { data } from "autoprefixer"; +import { NextResponse } from "next/server"; + +export async function GET(request: Request) { + const { searchParams } = new URL(request.url); + const id = searchParams.get("id"); + + try { + const data = await prisma.kodeOtp.findFirst({ + where: { + id: id as string, + }, + }); + return new Response(JSON.stringify({ data }), { status: 200 }); + } catch (error) { + console.log(error); + } + + return new Response(JSON.stringify({ data: null }), { status: 404 }); +} diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts index dd99a4b9..3aac1607 100644 --- a/src/app/api/auth/login/route.ts +++ b/src/app/api/auth/login/route.ts @@ -1,31 +1,64 @@ - - +import { prisma } from "@/app/lib"; +import { randomOTP } from "@/app_modules/auth/fun/rondom_otp"; import { NextResponse } from "next/server"; export async function POST(req: Request) { if (req.method === "POST") { + const codeOtp = randomOTP(); const body = await req.json(); - // console.log(body); + const { nomor } = body; - if (body.nomor === "1234567890") { - return NextResponse.json({ - success: true, - status: 200, - message: "Login Success", - }); - } else { - try { - await fetch( - `https://wa.wibudev.com/code?nom=${body.nomor}&text=Masukan Kode OTP:${body.otp}` + try { + const res = await fetch( + `https://wa.wibudev.com/code?nom=${nomor}&text=HIPMI - Kode ini bersifat RAHASIA dan JANGAN DI BAGIKAN KEPADA SIAPAPUN, termasuk anggota ataupun pengurus HIPMI lainnya. + \n + >> Kode OTP anda: ${codeOtp}. + ` + ); + + const sendWa = await res.json(); + if (sendWa.status !== "success") + return new Response( + JSON.stringify({ + success: false, + message: "Nomor Whatsapp Tidak Aktif", + }), + { status: 400 } ); - return NextResponse.json({ - body, - status: 200, - message: "Login Success", - }); - } catch (error) { - return NextResponse.json({ status: 500, message: "Server Error !!!" }); - } + + const createOtpId = await prisma.kodeOtp.create({ + data: { + nomor: nomor, + otp: codeOtp, + }, + }); + + if (!createOtpId) + return new Response( + JSON.stringify({ + success: false, + message: "Gagal Membuat Kode OTP", + }), + { status: 400 } + ); + + return new Response( + JSON.stringify({ + 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 !!", + }), + { status: 500 } + ); } } return NextResponse.json({ success: false }); diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts index 1ec6d2d1..9a5356ff 100644 --- a/src/app/api/auth/logout/route.ts +++ b/src/app/api/auth/logout/route.ts @@ -1,12 +1,28 @@ +import { prisma } from "@/app/lib"; import { cookies } from "next/headers"; -import { NextResponse } from "next/server"; +export async function GET(request: Request) { + const { searchParams } = new URL(request.url); + const id = searchParams.get("id"); -export async function GET() { - cookies().set({ - name: "mySession", - value: "", - maxAge: 0, - }); + const delToken = await prisma.userSession.delete({ + where: { + userId: id as string, + }, + }); - return NextResponse.json({ status: 200, message: "Logout" }); + 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" }); +// } diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index 463f63d2..19366387 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -1,51 +1,70 @@ +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 { cookies } from "next/headers"; -import { NextResponse } from "next/server"; export async function POST(req: Request) { if (req.method === "POST") { - const body = await req.json(); - // MyConsole(body); + const { data } = await req.json(); const cekUsername = await prisma.user.findUnique({ where: { - username: body.username, + username: data.username, }, }); if (cekUsername) - return NextResponse.json({ status: 400, message: "Username sudah ada" }); + return new Response( + JSON.stringify({ + success: false, + message: "Username sudah digunakan", + }), + { status: 400 } + ); - const data = await prisma.user.create({ + const createUser = await prisma.user.create({ data: { - username: body.username, - nomor: body.nomor, + username: data.username, + nomor: data.nomor, + active: true, }, }); - if (data) { - const seal = await sealData( - JSON.stringify({ - id: data.id, - username: data.username, - }), - { - password: ServerEnv.value?.WIBU_PWD as string, - } - ); + const token = await sessionCreate({ + sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, + encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, + user: createUser as any, + }); - cookies().set({ - name: "mySession", - value: seal, - maxAge: 60 * 60 * 24 * 7, + try { + const createUserSession = await prisma.userSession.create({ + data: { + token: token as string, + userId: createUser.id, + }, }); - return NextResponse.json({ status: 201 }); + if (!createUserSession) + return new Response( + JSON.stringify({ + success: false, + message: "Gagal Membuat Session", + }), + { status: 400 } + ); + } catch (error) { + console.log(error); } - return NextResponse.json({ success: true }); + return new Response( + JSON.stringify({ + success: true, + message: "Berhasil Login", + }), + + { status: 200 } + ); } - return NextResponse.json({ success: false }); + return new Response( + JSON.stringify({ 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 new file mode 100644 index 00000000..3aac1607 --- /dev/null +++ b/src/app/api/auth/resend/route.ts @@ -0,0 +1,65 @@ +import { prisma } from "@/app/lib"; +import { randomOTP } from "@/app_modules/auth/fun/rondom_otp"; +import { NextResponse } from "next/server"; + +export async function POST(req: Request) { + if (req.method === "POST") { + const codeOtp = randomOTP(); + const body = await req.json(); + const { nomor } = body; + + try { + const res = await fetch( + `https://wa.wibudev.com/code?nom=${nomor}&text=HIPMI - Kode ini bersifat RAHASIA dan JANGAN DI BAGIKAN KEPADA SIAPAPUN, termasuk anggota ataupun pengurus HIPMI lainnya. + \n + >> Kode OTP anda: ${codeOtp}. + ` + ); + + const sendWa = await res.json(); + if (sendWa.status !== "success") + return new Response( + JSON.stringify({ + success: false, + message: "Nomor Whatsapp Tidak Aktif", + }), + { status: 400 } + ); + + const createOtpId = await prisma.kodeOtp.create({ + data: { + nomor: nomor, + otp: codeOtp, + }, + }); + + if (!createOtpId) + return new Response( + JSON.stringify({ + success: false, + message: "Gagal Membuat Kode OTP", + }), + { status: 400 } + ); + + return new Response( + JSON.stringify({ + 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 !!", + }), + { status: 500 } + ); + } + } + return NextResponse.json({ success: false }); +} diff --git a/src/app/api/auth/validasi/route.ts b/src/app/api/auth/validasi/route.ts index 11ebd0a7..f865cc07 100644 --- a/src/app/api/auth/validasi/route.ts +++ b/src/app/api/auth/validasi/route.ts @@ -1,3 +1,4 @@ +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"; @@ -7,45 +8,100 @@ import { NextResponse } from "next/server"; export async function POST(req: Request) { if (req.method === "POST") { - const body = await req.json(); + const { nomor } = await req.json(); - const data = await prisma.user.findUnique({ + const dataUser = await prisma.user.findUnique({ where: { - nomor: body.nomor, + nomor: nomor, }, select: { id: true, nomor: true, username: true, active: true, + masterUserRoleId: true, }, }); - if (!data) return NextResponse.json({ status: 404 }); - if (data) { - const res = await sealData( - JSON.stringify({ - id: data.id, - username: data.username, - }), - { - password: ServerEnv.value?.WIBU_PWD as string, - } + if (dataUser === null) + return new Response( + JSON.stringify({ success: false, message: "Nomor Belum Terdaftar" }), + { status: 404 } ); - cookies().set({ - name: "mySession", - value: res, - maxAge: 60 * 60 * 24 * 7, + 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, + }, }); - - revalidatePath("/dev/home"); - - return NextResponse.json({ status: 200, data }); } - return NextResponse.json({ success: true }); + try { + const createUserSession = await prisma.userSession.create({ + data: { + token: token as string, + userId: dataUser.id, + }, + }); + + if (!createUserSession) + return new Response( + JSON.stringify({ 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({ + success: true, + message: "Berhasil Login", + roleId: dataUser.masterUserRoleId, + active: dataUser.active, + }), + { status: 200 } + ); } - return NextResponse.json({ success: false }); + return new Response( + JSON.stringify({ success: false, message: "Method Not Allowed" }), + { status: 405 } + ); } 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..083f6e05 --- /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, { status: 200 }); +} 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/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/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/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/portofolio/route.ts b/src/app/api/new/portofolio/route.ts new file mode 100644 index 00000000..b25478d5 --- /dev/null +++ b/src/app/api/new/portofolio/route.ts @@ -0,0 +1,59 @@ +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 kategori_halaman = searchParams.get("cat") + const page = searchParams.get("page") + const dataSkip = Number(page) * 10 - 10; + + if (kategori_halaman == "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 (kategori_halaman == "portofolio") { + fixData = await prisma.portofolio.findMany({ + skip: dataSkip, + take: 10, + 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 new file mode 100644 index 00000000..73a4fb52 --- /dev/null +++ b/src/app/api/new/user/route.ts @@ -0,0 +1,58 @@ +import { prisma } from "@/app/lib"; +import { NextResponse } from "next/server"; + + +// GET ONE DATA USER PROFILE BY PROFILE ID +export async function GET(request: Request) { + try { + const { searchParams } = new URL(request.url) + const profile = searchParams.get("profile") + + const data = await prisma.profile.findUnique({ + where: { + id: String(profile), + }, + select: { + id: true, + name: true, + email: true, + alamat: true, + jenisKelamin: true, + imageId: true, + imageBackgroundId: true, + userId: true, + User: { + select: { + username: true, + nomor: true, + active: true, + masterUserRoleId: true + } + } + } + }); + + const dataFix = { + 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 + + } + + 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/origin-url/route.ts b/src/app/api/origin-url/route.ts new file mode 100644 index 00000000..186624ae --- /dev/null +++ b/src/app/api/origin-url/route.ts @@ -0,0 +1,6 @@ +import { headers } from "next/headers"; +export async function GET(req: Request) { + const origin = new URL(req.url).origin; + + return new Response(JSON.stringify({ success: true, origin })); +} 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/api/validasi/route.ts b/src/app/api/validasi/route.ts new file mode 100644 index 00000000..65467cdb --- /dev/null +++ b/src/app/api/validasi/route.ts @@ -0,0 +1,7 @@ +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 })); +} diff --git a/src/app/auth/_lib/decrypt.ts b/src/app/auth/_lib/decrypt.ts new file mode 100644 index 00000000..410a7369 --- /dev/null +++ b/src/app/auth/_lib/decrypt.ts @@ -0,0 +1,22 @@ +import { jwtVerify } from "jose"; + +export 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; + } +} + +// wibu:0.2.82 diff --git a/src/app/auth/_lib/encrypt.ts b/src/app/auth/_lib/encrypt.ts new file mode 100644 index 00000000..b6979603 --- /dev/null +++ b/src/app/auth/_lib/encrypt.ts @@ -0,0 +1,25 @@ +import { SignJWT } from "jose"; + +export async function encrypt({ + user, + exp = "7 year", + encodedKey, +}: { + user: Record; + exp?: string; + encodedKey: string; +}): Promise { + try { + const enc = new TextEncoder().encode(encodedKey); + return new SignJWT({ user }) + .setProtectedHeader({ alg: "HS256" }) + .setIssuedAt() + .setExpirationTime(exp) + .sign(enc); + } catch (error) { + console.error("Gagal mengenkripsi", error); + return null; + } +} + +// wibu:0.2.82 diff --git a/src/app/auth/_lib/session_create.ts b/src/app/auth/_lib/session_create.ts new file mode 100644 index 00000000..aebfa9cd --- /dev/null +++ b/src/app/auth/_lib/session_create.ts @@ -0,0 +1,35 @@ +import { cookies } from "next/headers"; +import { encrypt } from "./encrypt"; + +export async function sessionCreate({ + sessionKey, + exp = "7 year", + encodedKey, + user, +}: { + sessionKey: string; + exp?: string; + encodedKey: string; + user: Record; +}) { + const token = await encrypt({ + exp, + encodedKey, + user, + }); + + const cookie: any = { + key: sessionKey, + value: token, + options: { + httpOnly: true, + sameSite: "lax", + path: "/", + }, + }; + + cookies().set(cookie.key, cookie.value, { ...cookie.options }); + return token; +} + +// wibu:0.2.82 diff --git a/src/app/auth/api/login/route.ts b/src/app/auth/api/login/route.ts new file mode 100644 index 00000000..370b5bad --- /dev/null +++ b/src/app/auth/api/login/route.ts @@ -0,0 +1,27 @@ +import { prisma } from "@/app/lib"; +import { sessionCreate } from "../../_lib/session_create"; + +export async function POST(req: Request) { + const user = await prisma.user.findUnique({ + where: { + nomor: "6281339158911", + }, + select: { + id: true, + nomor: true, + }, + }); + + if (!user) + return new Response( + JSON.stringify({ success: false, message: "User not found" }), {status: 404} + ); + + const token = await sessionCreate({ + sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, + encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, + user: user as any, + }); + + return new Response(JSON.stringify({ success: true, token })); +} diff --git a/src/app/auth/api/logout/route.ts b/src/app/auth/api/logout/route.ts new file mode 100644 index 00000000..af733975 --- /dev/null +++ b/src/app/auth/api/logout/route.ts @@ -0,0 +1,5 @@ +import { cookies } from "next/headers"; +export async function GET() { + const del = cookies().delete(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!); + return new Response(JSON.stringify({ success: true })); +} diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx new file mode 100644 index 00000000..7fe848b8 --- /dev/null +++ b/src/app/auth/login/page.tsx @@ -0,0 +1,39 @@ +"use client"; +import { Button } from "@mantine/core"; +import { useState } from "react"; + +export default function Page() { + const [loading, setLoading] = useState(false); + + + async function login() { + setLoading(true); + try { + const res = await fetch("/auth/api/login", { + method: "POST", + }); + + const dataText = await res.text(); + + if (!res.ok) { + console.error(dataText); + throw new Error(res.statusText); + } + + const dataJson = JSON.parse(dataText); + console.log(dataJson); + // window.location.replace("/dev/home"); + } catch (error) { + console.error(error); + } finally { + setLoading(false); + } + } + return ( + <> + + + ); +} diff --git a/src/app/dev/(user)/home/page.tsx b/src/app/dev/(user)/home/page.tsx new file mode 100644 index 00000000..4bd78e32 --- /dev/null +++ b/src/app/dev/(user)/home/page.tsx @@ -0,0 +1,21 @@ +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 countNotifikasi = await notifikasi_countUserNotifikasi(); + + + return ( + <> + {/* */} + + + ); +} diff --git a/src/app/dev/admin/event/table/publish/page.tsx b/src/app/dev/admin/event/table/publish/page.tsx index 50fc6b34..a7c514dc 100644 --- a/src/app/dev/admin/event/table/publish/page.tsx +++ b/src/app/dev/admin/event/table/publish/page.tsx @@ -1,9 +1,8 @@ import { AdminEvent_TablePublish } from "@/app_modules/admin/event"; import { adminEvent_funGetListPublish } from "@/app_modules/admin/event/fun"; -import { AdminEvent_getListTableByStatusId } from "@/app_modules/admin/event/fun/get/get_list_table_by_status_id"; -export default async function Page() { - const listPublish = await adminEvent_funGetListPublish({page: 1}); +async function Page() { + const listPublish = await adminEvent_funGetListPublish({ page: 1 }); return ( <> @@ -11,3 +10,5 @@ export default async function Page() { ); } + +export default Page; diff --git a/src/app/dev/admin/layout.tsx b/src/app/dev/admin/layout.tsx index 212636a4..b267ac9e 100644 --- a/src/app/dev/admin/layout.tsx +++ b/src/app/dev/admin/layout.tsx @@ -5,8 +5,9 @@ import adminNotifikasi_countNotifikasi from "@/app_modules/admin/notifikasi/fun/ import adminNotifikasi_getByUserId from "@/app_modules/admin/notifikasi/fun/get/get_notifikasi_by_user_id"; import React from "react"; import versionUpdate from "../../../../package.json"; +import { redirect } from "next/navigation"; -export default async function Layout({ +export default async function Layout({ children, }: { children: React.ReactNode; @@ -14,10 +15,14 @@ export default async function Layout({ const userLoginId = await funGetUserIdByToken(); const version = versionUpdate.version; - const dataUser = await funGlobal_getUserById({ userId: userLoginId as string}); - const listNotifikasi = await adminNotifikasi_getByUserId({page: 1}); + const dataUser = await funGlobal_getUserById({ + userId: userLoginId as string, + }); + const listNotifikasi = await adminNotifikasi_getByUserId({ page: 1 }); const countNotifikasi = await adminNotifikasi_countNotifikasi(); + if (dataUser?.masterUserRoleId == "1") return redirect("/dev/home"); + return ( <> diff --git a/src/app/dev/auth/register/[id]/page.tsx b/src/app/dev/auth/register/[id]/page.tsx index ff588e30..04eebc10 100644 --- a/src/app/dev/auth/register/[id]/page.tsx +++ b/src/app/dev/auth/register/[id]/page.tsx @@ -4,5 +4,5 @@ import { auth_getCodeOtpByNumber } from "@/app_modules/auth/fun/get_kode_otp_by_ export default async function Page({ params }: { params: { id: string } }) { let otpId = params.id; const dataOtp = await auth_getCodeOtpByNumber({ kodeId: otpId }); - return ; + return ; } diff --git a/src/app/dev/auth/splash/page.tsx b/src/app/dev/auth/splash/page.tsx index a1a041c8..7ca33735 100644 --- a/src/app/dev/auth/splash/page.tsx +++ b/src/app/dev/auth/splash/page.tsx @@ -3,7 +3,7 @@ import { SplashScreen } from "@/app_modules/auth"; export default async function PageSplash() { return ( <> - + ); } diff --git a/src/app/dev/auth/validasi/[id]/page.tsx b/src/app/dev/auth/validasi/[id]/page.tsx index d81694df..eb5cb931 100644 --- a/src/app/dev/auth/validasi/[id]/page.tsx +++ b/src/app/dev/auth/validasi/[id]/page.tsx @@ -5,6 +5,5 @@ export default async function Page({ params }: { params: { id: string } }) { let kodeId = params.id; const dataOtp = await auth_getCodeOtpByNumber({ kodeId: kodeId }); - - return ; + return ; } diff --git a/src/app/dev/check-cookies/page.tsx b/src/app/dev/check-cookies/page.tsx index 39941945..b56d1956 100644 --- a/src/app/dev/check-cookies/page.tsx +++ b/src/app/dev/check-cookies/page.tsx @@ -6,16 +6,16 @@ import { CheckCookies_UiView } from "@/app_modules/check_cookies"; import { redirect } from "next/navigation"; export default async function Page() { - const userLoginId = await funGetUserIdByToken(); - const dataUser = await funGlobal_getUserById({ userId: userLoginId }); + // const userLoginId = await funGetUserIdByToken(); + // const dataUser = await funGlobal_getUserById({ userId: userLoginId }); - if (dataUser?.masterUserRoleId === "1") { - return redirect(RouterHome.main_home); - } + // if (dataUser?.masterUserRoleId === "1") { + // return redirect(RouterHome.main_home); + // } - if (dataUser?.masterUserRoleId !== "1") { - return redirect(RouterAdminDashboard.splash_admin); - } + // if (dataUser?.masterUserRoleId !== "1") { + // return redirect(RouterAdminDashboard.splash_admin); + // } // return ; } 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/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 new file mode 100644 index 00000000..3a0af55b --- /dev/null +++ b/src/app/dev/event/konfirmasi/[id]/page.tsx @@ -0,0 +1,22 @@ +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, +}: { + params: Promise<{ id: string }>; +}) { + const eventId = (await params).id; + const userLoginId = await newFunGetUserId(); + + 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/dev/forum/detail/main-detail/[id]/page.tsx b/src/app/dev/forum/detail/main-detail/[id]/page.tsx index 74eba427..c47d7783 100644 --- a/src/app/dev/forum/detail/main-detail/[id]/page.tsx +++ b/src/app/dev/forum/detail/main-detail/[id]/page.tsx @@ -16,7 +16,7 @@ export default async function Page({ params }: { params: { id: string } }) { page: 1, }); - dataPosting?.isActive === false && redirect(RouterForum.beranda); + // dataPosting?.isActive === false && redirect(RouterForum.beranda); const countKomentar = await forum_countTotalKomenById(postingId); diff --git a/src/app/dev/home/page.tsx b/src/app/dev/home/page.tsx deleted file mode 100644 index 8aae78b6..00000000 --- a/src/app/dev/home/page.tsx +++ /dev/null @@ -1,31 +0,0 @@ -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 notifikasi_countUserNotifikasi from "@/app_modules/notifikasi/fun/count/fun_count_by_id"; - -export default async function Page() { - const userLoginId = await funGetUserIdByToken(); - const dataUser = await user_getOneByUserId(userLoginId as string); - 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.splash_admin); - - return ( - <> - - - ); -} diff --git a/src/app/dev/katalog/[id]/layout.tsx b/src/app/dev/katalog/[id]/layout.tsx index fd0d7fd4..98b718f6 100644 --- a/src/app/dev/katalog/[id]/layout.tsx +++ b/src/app/dev/katalog/[id]/layout.tsx @@ -1,29 +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 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 24cccdab..98ab33e3 100644 --- a/src/app/dev/katalog/[id]/page.tsx +++ b/src/app/dev/katalog/[id]/page.tsx @@ -1,22 +1,21 @@ -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { Katalog_MainView } 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/dev/layout.tsx b/src/app/dev/layout.tsx index c568b5c5..49f4a4c7 100644 --- a/src/app/dev/layout.tsx +++ b/src/app/dev/layout.tsx @@ -1,38 +1,21 @@ -import { CheckCookies_UiLayout } from "@/app_modules/check_cookies"; import { RealtimeProvider } from "../lib"; -import { funCheckCookies } from "@/app_modules/_global/fun/get/fun_check_cookies"; -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; +import { newFunGetUserId } from "../lib/new_fun_user_id"; import { ServerEnv } from "../lib/server_env"; -import { funGlobal_getUserById } from "@/app_modules/_global/fun/get/fun_get_user_by_id"; -import { RouterHome } from "../lib/router_hipmi/router_home"; -import { RouterAdminDashboard } from "../lib/router_hipmi/router_admin"; -import { redirect } from "next/navigation"; export default async function Layout({ children, }: { children: React.ReactNode; }) { - const checkCookies = await funCheckCookies(); - if (!checkCookies) return redirect("/"); - - const userLoginId = await funGetUserIdByToken(); - const WIBU_REALTIME_TOKEN = process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN; - // console.log(WIBU_REALTIME_TOKEN, "check cookies di layout dalam"); - return ( <> {children} - {/* - {children} - */} ); } 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/dev/user-not-active/page.tsx b/src/app/dev/user-not-active/page.tsx index 5f29e41a..76d3782a 100644 --- a/src/app/dev/user-not-active/page.tsx +++ b/src/app/dev/user-not-active/page.tsx @@ -1,18 +1,5 @@ -import { RouterHome } from "@/app/lib/router_hipmi/router_home"; -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; import { Home_UserNonActive } from "@/app_modules/home"; -import { user_getOneByUserId } from "@/app_modules/home/fun/get/get_one_user_by_id"; -// import { redirect } from "next/navigation"; - export default async function Page() { - const userLoginId = await funGetUserIdByToken(); - - const dataUser = await user_getOneByUserId(userLoginId as string); - - // if (dataUser?.active === true) { - // return redirect(RouterHome.main_home); - // } - return ( <> diff --git a/src/app/dev/vote/detail/semua_riwayat/[id]/layout.tsx b/src/app/dev/vote/detail/semua_riwayat/[id]/layout.tsx index aad2aeb0..29d02c51 100644 --- a/src/app/dev/vote/detail/semua_riwayat/[id]/layout.tsx +++ b/src/app/dev/vote/detail/semua_riwayat/[id]/layout.tsx @@ -16,7 +16,7 @@ export default async function Layout({ <> {children} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index c00a706a..29bdfe8f 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,13 +1,8 @@ -import MqttLoader from "@/util/mqtt_loader"; import RootStyleRegistry from "./emotion"; // import "./globals.css"; -import { TokenProvider } from "./lib/token"; import dotenv from "dotenv"; import { ServerEnv } from "./lib/server_env"; -import { RealtimeProvider } from "./lib"; -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { funCheckCookies } from "@/app_modules/_global/fun/get/fun_check_cookies"; -import { redirect } from "next/navigation"; +import { TokenProvider } from "./lib/token"; dotenv.config({ path: ".env", }); 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..9b7094c2 --- /dev/null +++ b/src/app/lib/api_user_router/route_api_event.ts @@ -0,0 +1,10 @@ +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}`, + 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/lib/new_fun_user_id.ts b/src/app/lib/new_fun_user_id.ts new file mode 100644 index 00000000..d69660c2 --- /dev/null +++ b/src/app/lib/new_fun_user_id.ts @@ -0,0 +1,21 @@ +"use server" + +import _ from "lodash"; +import { cookies } from "next/headers"; +import { decrypt } from "../auth/_lib/decrypt"; + +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; +} \ No newline at end of file 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 6468a0a0..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,8 +72,15 @@ export default function RealtimeProvider({ gs_donasiTriggerBeranda ); + async function loadUserId() { + const userId = await newFunGetUserId(); + + setUserLoginId(userId as string); + } + useShallowEffect(() => { - // if (WIBU_REALTIME_TOKEN === undefined) return alert("gak dapet key"); + loadUserId(); + try { WibuRealtime.init({ project: "hipmi", @@ -201,7 +209,7 @@ export default function RealtimeProvider({ }, }); } catch (error) { - console.log(error); + console.log("Error!:", error); } }, []); diff --git a/src/app/page.tsx b/src/app/page.tsx index 4d6ffb92..3a1f99a2 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,24 +1,14 @@ -import { funCheckCookies } from "@/app_modules/_global/fun/get/fun_check_cookies"; -import PageSplash from "./dev/auth/splash/page"; -import { redirect } from "next/navigation"; -import { Login, SplashScreen } from "@/app_modules/auth"; -import { RouterAuth } from "./lib/router_hipmi/router_auth"; -import versionUpdate from "../../package.json"; -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { funGlobal_getUserById } from "@/app_modules/_global/fun/get/fun_get_user_by_id"; -import { RouterHome } from "./lib/router_hipmi/router_home"; -import { RouterAdminDashboard } from "./lib/router_hipmi/router_admin"; +"use client"; -export default async function Page() { - const version = versionUpdate.version; +import { SplashScreen } from "@/app_modules/auth"; +import { useShallowEffect } from "@mantine/hooks"; - const checkCookies = await funCheckCookies(); - // console.log(checkCookies, "ini check cookies di page awal"); - if (checkCookies) return redirect("/dev/check-cookies"); - return redirect("/login"); - // const WIBU_REALTIME_TOKEN = process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN; +export default function Page() { + useShallowEffect(() => { + setTimeout(() => { + window.location.replace("/dev/home"); + }, 1000); + }, []); - // return ; - // return ; - return ; + return ; } diff --git a/src/app_modules/_global/component/comp_avatar_and_username.tsx b/src/app_modules/_global/component/comp_avatar_and_username.tsx index 9269be4a..d8e419b9 100644 --- a/src/app_modules/_global/component/comp_avatar_and_username.tsx +++ b/src/app_modules/_global/component/comp_avatar_and_username.tsx @@ -51,7 +51,7 @@ export function ComponentGlobal_AvatarAndUsername({ ) : ( )} diff --git a/src/app_modules/_global/fun/generate_seeder.ts b/src/app_modules/_global/fun/generate_seeder.ts index c1f89d11..988da404 100644 --- a/src/app_modules/_global/fun/generate_seeder.ts +++ b/src/app_modules/_global/fun/generate_seeder.ts @@ -52,11 +52,13 @@ export async function generate_seeder() { nomor: i.nomor, username: i.name, masterUserRoleId: i.masterUserRoleId, + active: i.active, }, update: { nomor: i.nomor, username: i.name, masterUserRoleId: i.masterUserRoleId, + active: i.active, }, }); } diff --git a/src/app_modules/_global/fun/get/fun_check_activation_use_by_id.ts b/src/app_modules/_global/fun/get/fun_check_activation_use_by_id.ts new file mode 100644 index 00000000..010902fe --- /dev/null +++ b/src/app_modules/_global/fun/get/fun_check_activation_use_by_id.ts @@ -0,0 +1,22 @@ +"use server"; + +import { prisma } from "@/app/lib"; +import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; +import { permanentRedirect } from "next/navigation"; + +export async function funGlobal_checkActivationUseById({ + userId, +}: { + userId: string; +}) { + const data = await prisma.user.findFirst({ + where: { + id: userId, + }, + select: { + active: true, + }, + }); + + return data?.active; +} 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 ef78cbbb..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 @@ -1,20 +1,31 @@ "use server"; +import { prisma } from "@/app/lib"; import { ServerEnv } from "@/app/lib/server_env"; import { unsealData } from "iron-session"; +import { jwtVerify } from "jose"; import { cookies } from "next/headers"; export async function funGetUserIdByToken() { - const c = cookies().get("mySession"); + const SESSION_KEY = process.env.NEXT_PUBLIC_BASE_SESSION_KEY!; + // console.log("SESSION_KEY", SESSION_KEY); + const c = cookies().get("hipmi-key"); - const token = JSON.parse( - await unsealData(c?.value as string, { - password: process.env.WIBU_PWD as string, - }) - ); + const cekUser = await decrypt({ + token: c?.value as string, + encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, + }); - return token.id; - // const token = c?.value + // console.log("userid" , cekUser?.id) + + // const token = JSON.parse( + // await unsealData(c?.value as string, { + // password: process.env.WIBU_PWD as string, + // }) + // ); + // return token.id; + + // const token = c?.value; // const cekToken = await prisma.userSession.findFirst({ // where: { // token: token, @@ -22,5 +33,24 @@ export async function funGetUserIdByToken() { // }); // if (cekToken === null) return null - // return cekToken.userId; + return cekUser?.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_modules/admin/_admin_global/_component/comp_button_user_on_navbar.tsx b/src/app_modules/admin/_admin_global/_component/comp_button_user_on_navbar.tsx index ecd5d6bc..3e840a5e 100644 --- a/src/app_modules/admin/_admin_global/_component/comp_button_user_on_navbar.tsx +++ b/src/app_modules/admin/_admin_global/_component/comp_button_user_on_navbar.tsx @@ -1,14 +1,8 @@ "use client"; -import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; import { Warna } from "@/app/lib/warna"; import { AccentColor } from "@/app_modules/_global/color"; -import { - ComponentGlobal_NotifikasiBerhasil, - ComponentGlobal_NotifikasiPeringatan, -} from "@/app_modules/_global/notif_global"; -import { auth_Logout } from "@/app_modules/auth/fun/fun_logout"; -import { gs_kodeId } from "@/app_modules/auth/state/state"; +import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global"; import { MODEL_USER } from "@/app_modules/home/model/interface"; import { ActionIcon, @@ -20,12 +14,12 @@ import { Menu, Modal, Popover, + SimpleGrid, Stack, Text, Title, } from "@mantine/core"; import { IconPhone, IconUser, IconUserCircle } from "@tabler/icons-react"; -import { useAtom } from "jotai"; import { useRouter } from "next/navigation"; import { useState } from "react"; @@ -38,21 +32,18 @@ export function Admin_ComponentButtonUserCircle({ const [isOpenMenuUser, setOpenMenuUser] = useState(false); const [openPop, setOpenPop] = useState(false); const [openModal, setOpenModal] = useState(false); - const [loading, setLoading] = useState(false); - const [kodeId, setKodeId] = useAtom(gs_kodeId); const [loadingLogout, setLoadingLogout] = useState(false); async function onClickLogout() { - const res = await auth_Logout(); + setLoadingLogout(true); + const res = await fetch(`/api/auth/logout?id=${dataUser.id}`, { + method: "GET", + }); + + const result = await res.json(); if (res.status === 200) { - console.log(res); - setLoadingLogout(true); - ComponentGlobal_NotifikasiBerhasil(res.message); - setKodeId(""); - setOpenModal(false); - router.push(RouterAuth.login, { scroll: false }); - } else { - ComponentGlobal_NotifikasiPeringatan(res.message); + ComponentGlobal_NotifikasiBerhasil(result.message); + router.push("/", { scroll: false }); } } @@ -92,11 +83,21 @@ export function Admin_ComponentButtonUserCircle({ -
- + -
+ @@ -114,7 +115,6 @@ export function Admin_ComponentButtonUserCircle({ @@ -254,9 +296,17 @@ export default function AdminEvent_ComponentTableReview({ color={"red"} leftIcon={} radius={"xl"} - onClick={() => { - open(); - setEventId(e.id); + onClick={async () => { + const checkStatus = await event_checkStatus({ id: e.id }); + + if (checkStatus) { + open(); + setEventId(e.id); + } else { + ComponentAdminGlobal_NotifikasiPeringatan( + "Review di batalkan oleh user, muat kembali halaman ini !" + ); + } }} > Reject @@ -334,10 +384,10 @@ export default function AdminEvent_ComponentTableReview({
Tipe Acara
-
Tanggal
+
Tanggal & Waktu Mulai
-
Jam
+
Tanggal & Waktu Selesai
Deskripsi
diff --git a/src/app_modules/admin/event/child/riwayat.tsx b/src/app_modules/admin/event/child/riwayat.tsx index b7ab3385..1bee7757 100644 --- a/src/app_modules/admin/event/child/riwayat.tsx +++ b/src/app_modules/admin/event/child/riwayat.tsx @@ -1,19 +1,11 @@ "use client"; import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event"; -import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog"; +import { MODEL_EVENT } from "@/app_modules/event/model/interface"; import { - MODEL_EVENT, - MODEL_EVENT_PESERTA, -} from "@/app_modules/event/model/interface"; -import { - Avatar, Button, Center, - Divider, - Grid, Group, - Modal, Pagination, Paper, ScrollArea, @@ -24,7 +16,6 @@ import { TextInput, Title, } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; import { IconCircleCheck, IconSearch } from "@tabler/icons-react"; import { useRouter } from "next/navigation"; import { useState } from "react"; @@ -80,11 +71,14 @@ function DetailRiwayat({ listRiwayat }: { listRiwayat: any }) { + const TableRows = _.isEmpty(data) ? ( + + +
Belum Ada Data
- )); + ) : ( + data.map((e, i) => ( + + +
+ +
+ + +
+ { + 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} +
+ + +
+ {e.title} +
+ + +
+ {e.lokasi} +
+ + +
+ {e.EventMaster_TipeAcara.name} +
+ + + +
+ + {" "} + {new Intl.DateTimeFormat("id-ID", { + dateStyle: "full", + }).format(e?.tanggal)} + ,{" "} + + {new Intl.DateTimeFormat("id-ID", { + timeStyle: "short", + }).format(e?.tanggal)} + + +
+ + +
+ + {" "} + {new Intl.DateTimeFormat("id-ID", { + dateStyle: "full", + }).format(e?.tanggalSelesai)} + ,{" "} + + {new Intl.DateTimeFormat("id-ID", { + timeStyle: "short", + }).format(e?.tanggalSelesai)} + + +
+ + + +
+ + {e.deskripsi} + +
+ + + + + + + )) + ); return ( <> @@ -169,6 +249,13 @@ function TableStatus({ listPublish }: { listPublish: any }) { > + +
QR Code
+ + +
Download QR
+ +
Username
@@ -182,11 +269,12 @@ function TableStatus({ listPublish }: { listPublish: any }) {
Tipe Acara
-
Tanggal
+
Tanggal & Waktu Mulai
-
Jam
+
Tanggal & Waktu Selesai
+
Deskripsi
diff --git a/src/app_modules/admin/event/table_status/table_reject.tsx b/src/app_modules/admin/event/table_status/table_reject.tsx index 24e7f175..fd786fd1 100644 --- a/src/app_modules/admin/event/table_status/table_reject.tsx +++ b/src/app_modules/admin/event/table_status/table_reject.tsx @@ -11,6 +11,7 @@ import { Spoiler, Stack, Table, + Text, Textarea, TextInput, Title, @@ -106,19 +107,40 @@ function TableStatus({ listReject }: { listReject: any }) {
{e.EventMaster_TipeAcara.name}
+
- {e.tanggal.toLocaleString("id-ID", { dateStyle: "full" })} + + {" "} + {new Intl.DateTimeFormat("id-ID", { + dateStyle: "full", + }).format(e?.tanggal)} + ,{" "} + + {new Intl.DateTimeFormat("id-ID", { + timeStyle: "short", + }).format(e?.tanggal)} + +
-
- {e.tanggal.toLocaleTimeString([], { - timeStyle: "short", - hourCycle: "h24", - })} +
+ + {" "} + {new Intl.DateTimeFormat("id-ID", { + dateStyle: "full", + }).format(e?.tanggalSelesai)} + ,{" "} + + {new Intl.DateTimeFormat("id-ID", { + timeStyle: "short", + }).format(e?.tanggalSelesai)} + +
+
@@ -197,10 +219,10 @@ function TableStatus({ listReject }: { listReject: any }) {
Tipe Acara
-
Tanggal
+
Tanggal & Waktu Mulai
-
Jam
+
Tanggal & Waktu Selesai
Cacatan
diff --git a/src/app_modules/admin/new_layout.tsx b/src/app_modules/admin/new_layout.tsx index 058340f9..e7e0dfef 100644 --- a/src/app_modules/admin/new_layout.tsx +++ b/src/app_modules/admin/new_layout.tsx @@ -4,6 +4,7 @@ import { gs_admin_ntf } from "@/app/lib/global_state"; import { ActionIcon, AppShell, + Button, Divider, Drawer, Grid, @@ -18,8 +19,10 @@ import { import { useMediaQuery, useShallowEffect } from "@mantine/hooks"; import { IconBell } from "@tabler/icons-react"; import { useAtom } from "jotai"; +import { useRouter } from "next/navigation"; import { useState } from "react"; import { AccentColor } from "../_global/color"; +import { ComponentGlobal_NotifikasiBerhasil } from "../_global/notif_global"; import { MODEL_USER } from "../home/model/interface"; import { MODEL_NOTIFIKASI } from "../notifikasi/model/interface"; import { @@ -47,6 +50,7 @@ export function Admin_NewLayout({ listNotifikasi: MODEL_NOTIFIKASI[]; version: string; }) { + const router = useRouter(); const matches = useMediaQuery("(min-width: 1024px)"); const [dataUser, setDataUser] = useState(user); const userRoleId = dataUser.masterUserRoleId; @@ -72,6 +76,20 @@ export function Admin_NewLayout({ setDrawerNotifikasi(true); } + const [loadingLogout, setLoadingLogout] = useState(false); + async function onClickLogout() { + setLoadingLogout(true); + const res = await fetch(`/api/auth/logout?id=${user.id}`, { + method: "GET", + }); + + const result = await res.json(); + if (res.status === 200) { + ComponentGlobal_NotifikasiBerhasil(result.message); + router.push("/", { scroll: false }); + } + } + return ( <> View Only Available For Desktop + ) : ( children diff --git a/src/app_modules/auth/fun/fun_edit_aktivasi_kode_otp_by_id.ts b/src/app_modules/auth/fun/fun_edit_aktivasi_kode_otp_by_id.ts index 82672744..20a9ab27 100644 --- a/src/app_modules/auth/fun/fun_edit_aktivasi_kode_otp_by_id.ts +++ b/src/app_modules/auth/fun/fun_edit_aktivasi_kode_otp_by_id.ts @@ -2,12 +2,15 @@ import prisma from "@/app/lib/prisma"; -export async function auth_funDeleteAktivasiKodeOtpById({ +export async function auth_funDeleteAktivasiKodeOtpByNomor({ nomor, }: { nomor: string; }) { // console.log(otpId); + + + const updt = await prisma.kodeOtp.deleteMany({ where: { nomor: nomor, diff --git a/src/app_modules/auth/index.ts b/src/app_modules/auth/index.ts index e7f9843f..6dc3d259 100644 --- a/src/app_modules/auth/index.ts +++ b/src/app_modules/auth/index.ts @@ -2,12 +2,12 @@ import SplashScreen from "./splash/view"; import Login from "./login/view"; import Validasi from "./validasi/view"; import Register from "./register/view"; -import Component_Logout from "./logout/view"; +import Component_ButtonLogout from "./logout/view"; export { SplashScreen, Login, Validasi, Register, - Component_Logout as Logout, + Component_ButtonLogout as Logout, }; diff --git a/src/app_modules/auth/login/view.tsx b/src/app_modules/auth/login/view.tsx index 294980ca..e2b68125 100644 --- a/src/app_modules/auth/login/view.tsx +++ b/src/app_modules/auth/login/view.tsx @@ -1,6 +1,5 @@ "use client"; -import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; import { AccentColor, MainColor, @@ -8,10 +7,10 @@ import { import ComponentGlobal_ErrorInput from "@/app_modules/_global/component/error_input"; import { ComponentGlobal_NotifikasiBerhasil, + ComponentGlobal_NotifikasiGagal, ComponentGlobal_NotifikasiPeringatan, } from "@/app_modules/_global/notif_global"; import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui"; -import { auth_funLogin } from "@/app_modules/auth/fun/fun_login"; import { Box, Button, Center, Stack, Text, Title } from "@mantine/core"; import { useRouter } from "next/navigation"; import { useState } from "react"; @@ -28,23 +27,28 @@ export default function Login({ version }: { version: string }) { const nomor = phone.substring(1); if (nomor.length <= 4) return setError(true); - const res = await auth_funLogin({ nomor: nomor }); - if (res.status === 200) { - setLoading(true); - ComponentGlobal_NotifikasiBerhasil(res.message, 2000); - // router.push(RouterAuth.validasi + res.kodeId, { scroll: false }); - router.push("/validasi/" + res.kodeId, { scroll: false }); - } else { - ComponentGlobal_NotifikasiPeringatan(res.message); - } + setLoading(true); + try { + const res = await fetch("/api/auth/login", { + method: "POST", + body: JSON.stringify({ nomor: nomor }), + headers: { + "Content-Type": "application/json", + }, + }); - // await fetch(ApiHipmi.login, { - // method: "POST", - // headers: { - // "Content-Type": "application/json", - // }, - // body: JSON.stringify(body), - // }) + const result = await res.json(); + if (res.status === 200) { + localStorage.setItem("hipmi_auth_code_id", result.kodeId); + ComponentGlobal_NotifikasiBerhasil(result.message, 2000); + router.push("/validasi", { scroll: false }); + } else { + ComponentGlobal_NotifikasiPeringatan(result.message); + } + } catch (error) { + console.error(error); + ComponentGlobal_NotifikasiGagal("Terjadi Kesalahan"); + } } return ( @@ -96,16 +100,11 @@ export default function Login({ version }: { version: string }) { - V.{version} + v {version} - {/* */} ); } diff --git a/src/app_modules/auth/logout/view.tsx b/src/app_modules/auth/logout/view.tsx index f6a7900b..04346acd 100644 --- a/src/app_modules/auth/logout/view.tsx +++ b/src/app_modules/auth/logout/view.tsx @@ -11,18 +11,21 @@ import { useState } from "react"; import { auth_Logout } from "../fun/fun_logout"; import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; -export default function Component_Logout() { +export default function Component_ButtonLogout({userId}: {userId: string}) { const router = useRouter(); const [opened, setOpened] = useState(false); const [loading, setLoading] = useState(false); async function onClickLogout() { - const res = await auth_Logout(); + setLoading(true); + const res = await fetch(`/api/auth/logout?id=${userId}`, { + method: "GET", + }); + + const result = await res.json(); if (res.status === 200) { - ComponentGlobal_NotifikasiBerhasil(res.message); - router.push("/login", { scroll: false }); - } else { - ComponentGlobal_NotifikasiPeringatan(res.message); + ComponentGlobal_NotifikasiBerhasil(result.message); + router.push("/", { scroll: false }); } } @@ -49,7 +52,6 @@ export default function Component_Logout() { bg={Warna.merah} color="red" onClick={() => { - setLoading(true); onClickLogout(); }} > diff --git a/src/app_modules/auth/register/skeleton.tsx b/src/app_modules/auth/register/skeleton.tsx new file mode 100644 index 00000000..3d97a687 --- /dev/null +++ b/src/app_modules/auth/register/skeleton.tsx @@ -0,0 +1,19 @@ +import { Stack, Skeleton } from "@mantine/core"; + +export default function Register_SkeletonView() { + return ( + <> + + + + + + + + + + + + + ); +} diff --git a/src/app_modules/auth/register/view.tsx b/src/app_modules/auth/register/view.tsx index edc86465..7c1de36f 100644 --- a/src/app_modules/auth/register/view.tsx +++ b/src/app_modules/auth/register/view.tsx @@ -1,76 +1,95 @@ "use client"; -import { RouterHome } from "@/app/lib/router_hipmi/router_home"; -import { GlobalEnv } from "@/app/lib/token"; -import { - AccentColor, - MainColor, -} from "@/app_modules/_global/color/color_pallet"; +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_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui"; -import { - Button, - Center, - Stack, - Text, - TextInput, - Title -} from "@mantine/core"; -import { useFocusTrap } from "@mantine/hooks"; +import { Button, Stack, Text, TextInput, Title } from "@mantine/core"; +import { useFocusTrap, useShallowEffect } from "@mantine/hooks"; import { IconUserCircle } from "@tabler/icons-react"; import _ from "lodash"; import { useRouter } from "next/navigation"; import { useState } from "react"; -import { auth_funDeleteAktivasiKodeOtpById } from "../fun/fun_edit_aktivasi_kode_otp_by_id"; -import { Auth_funRegister } from "../fun/fun_register"; +import { auth_funDeleteAktivasiKodeOtpByNomor } from "../fun/fun_edit_aktivasi_kode_otp_by_id"; +import Register_SkeletonView from "./skeleton"; -export default function Register({ dataOtp }: { dataOtp: any }) { +export default function Register() { const router = useRouter(); - const [nomor, setNomor] = useState(dataOtp.nomor); + const [nomor, setNomor] = useState(""); const [value, setValue] = useState(""); const [isValue, setIsValue] = useState(false); const focusTrapRef = useFocusTrap(); const [loading, setLoading] = useState(false); + useShallowEffect(() => { + const kodeId = localStorage.getItem("hipmi_auth_code_id"); + if (kodeId != null) { + onCheckAuthCode({ kodeId: kodeId as string, onSetData: setNomor }); + } else { + console.log("code id not found"); + } + }, [setNomor]); + + async function onCheckAuthCode({ + kodeId, + onSetData, + }: { + kodeId: string; + onSetData: any; + }) { + const res = await fetch(`/api/auth/check?id=${kodeId}`); + const result = await res.json(); + + onSetData(result.data.nomor); + } + async function onRegistarsi() { - const body = { + const data = { username: value, nomor: nomor, }; - if (body.username === "") { - setIsValue(true); - return null; - } - if (body.username.length < 5) return null; - if (_.values(body.username).includes(" ")) return null; - - const res = await Auth_funRegister({ - data: body, - HIPMI_PWD: GlobalEnv.value?.WIBU_PWD as string, - }); - if (res.status === 200) { - await auth_funDeleteAktivasiKodeOtpById({ nomor: nomor }).then((val) => { - if (val.status === 200) { - ComponentGlobal_NotifikasiBerhasil(res.message); - setLoading(true); - router.push(RouterHome.main_home, { scroll: false }); - } else { - ComponentGlobal_NotifikasiPeringatan(val.message); - } + try { + setLoading(true); + const res = await fetch("/api/auth/register", { + method: "POST", + body: JSON.stringify({ + data, + }), + headers: { + "Content-Type": "application/json", + }, }); - } else { - ComponentGlobal_NotifikasiPeringatan(res.message); + + const result = await res.json(); + + if (res.status === 200) { + localStorage.removeItem("hipmi_auth_code_id"); + ComponentGlobal_NotifikasiBerhasil(result.message); + router.push("/dev/home", { scroll: false }); + + await auth_funDeleteAktivasiKodeOtpByNomor({ + nomor: data.nomor, + }); + } + + if (res.status === 400) { + setLoading(false); + ComponentGlobal_NotifikasiPeringatan(result.message); + } + } catch (error) { + console.log(error); } } return ( <> -
- + {nomor == "" ? ( + + ) : ( + REGISTRASI @@ -78,7 +97,7 @@ export default function Register({ dataOtp }: { dataOtp: any }) { - + Anda akan terdaftar dengan nomor berikut{" "} +{nomor} @@ -109,6 +128,11 @@ export default function Register({ dataOtp }: { dataOtp: any }) { />
+ )}
); diff --git a/src/app_modules/auth/splash/view.tsx b/src/app_modules/auth/splash/view.tsx index 9a5d888a..5108f27d 100644 --- a/src/app_modules/auth/splash/view.tsx +++ b/src/app_modules/auth/splash/view.tsx @@ -1,63 +1,22 @@ "use client"; -import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; -import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; -import { RouterHome } from "@/app/lib/router_hipmi/router_home"; -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { funGlobal_getUserById } from "@/app_modules/_global/fun/get/fun_get_user_by_id"; -import { MODEL_USER } from "@/app_modules/home/model/interface"; +import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui"; import { Avatar, BackgroundImage, Center, Image, Stack } from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; import { useRouter } from "next/navigation"; -export default function SplashScreen({ - checkCookies, -}: { - checkCookies: boolean; -}) { +export default function SplashScreen() { const router = useRouter(); - useShallowEffect(() => { - // if (!checkCookies) return router.push(RouterAuth.login, { scroll: false }); - // onCheckUser(); - - // setTimeout(() => { - // router.push(RouterAuth.login, { scroll: false }); - // }, 1000); - // if (!userLoginId) { - // setTimeout(() => { - // router.push(RouterAuth.login, { scroll: false }); - // }, 1000); - // } else { - // dataUser.masterUserRoleId === "1" - // ? setTimeout(() => { - // return router.push(RouterHome.main_home, { scroll: false }); - // }, 1000) - // : setTimeout(() => { - // return router.push(RouterAdminDashboard.splash_admin, { - // scroll: false, - // }); - // }, 1000); - // } - }, []); - - // async function onCheckUser() { - // const userLoginId = await funGetUserIdByToken(); - // const dataUser = await funGlobal_getUserById({ userId: userLoginId }); - - // if (dataUser?.masterUserRoleId == "1") - // return router.push(RouterHome.main_home); - - // return router.push(RouterAdminDashboard.splash_admin); - // } + // useShallowEffect(() => { + // setTimeout(() => { + // router.push("/dev/home", { scroll: false }); + // }, 1000); + // }, []); return ( <> - +
{/* Welcome to */} @@ -71,7 +30,7 @@ export default function SplashScreen({
-
+ ); } diff --git a/src/app_modules/auth/validasi/skeleton.tsx b/src/app_modules/auth/validasi/skeleton.tsx new file mode 100644 index 00000000..6006de6a --- /dev/null +++ b/src/app_modules/auth/validasi/skeleton.tsx @@ -0,0 +1,25 @@ +import { Stack, Skeleton, Group } from "@mantine/core"; + +export default function Validasi_SkeletonView() { + return ( + <> + + + + + + + + + {Array.from({ length: 4 }).map((_, i) => ( + + ))} + + + + + + + + ); +} diff --git a/src/app_modules/auth/validasi/view.tsx b/src/app_modules/auth/validasi/view.tsx index 8dd1a3ed..d817b00e 100644 --- a/src/app_modules/auth/validasi/view.tsx +++ b/src/app_modules/auth/validasi/view.tsx @@ -1,9 +1,7 @@ "use client"; import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; -import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; import { RouterHome } from "@/app/lib/router_hipmi/router_home"; -import { GlobalEnv } from "@/app/lib/token"; import { AccentColor, MainColor, @@ -12,107 +10,175 @@ import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_ import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui"; import { - ActionIcon, - Box, Button, Center, + Loader, PinInput, Stack, Text, Title, } from "@mantine/core"; import { useFocusTrap, useShallowEffect } from "@mantine/hooks"; -import { Prisma } from "@prisma/client"; -import { IconChevronLeft } from "@tabler/icons-react"; import { useRouter } from "next/navigation"; -import { useState } from "react"; -import { auth_funResendCode } from "../fun"; -import { auth_funDeleteAktivasiKodeOtpById } from "../fun/fun_edit_aktivasi_kode_otp_by_id"; -import { auth_funValidasi } from "../fun/fun_validasi"; +import { useEffect, useState } from "react"; -export default function Validasi({ - dataOtp, -}: { - dataOtp: Prisma.KodeOtpSelect; -}) { +import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global"; +import { auth_funDeleteAktivasiKodeOtpByNomor } from "../fun/fun_edit_aktivasi_kode_otp_by_id"; +import Validasi_SkeletonView from "./skeleton"; + +export default function Validasi() { const router = useRouter(); - const nomor = dataOtp.nomor as any; - const code = dataOtp.otp as any; const [inputCode, setInputOtp] = useState(""); const focusTrapRef = useFocusTrap(); const [loading, setLoading] = useState(false); - const [counter, setCounter] = useState(60); + const [loadingResend, setLoadingResend] = useState(false); + const [triggerOtp, setTriggerOtp] = useState(false); + + const [data, setData] = useState({ + nomor: "", + code: "", + }); useShallowEffect(() => { + const kodeId = localStorage.getItem("hipmi_auth_code_id"); + if (kodeId != null) { + onCheckAuthCode({ kodeId: kodeId as string, onSetData: setData }); + } else { + console.log("code id not found"); + } + + if (triggerOtp) { + const kodeId = localStorage.getItem("hipmi_auth_code_id"); + if (kodeId != null) { + onCheckAuthCode({ kodeId: kodeId as string, onSetData: setData }); + } else { + console.log("code id not found"); + } + setTriggerOtp(false); + } + }, [triggerOtp, setData, setTriggerOtp]); + + async function onCheckAuthCode({ + kodeId, + onSetData, + }: { + kodeId: string; + onSetData: any; + }) { + const res = await fetch(`/api/auth/check?id=${kodeId}`); + const result = await res.json(); + + onSetData({ + nomor: result.data.nomor, + code: result.data.otp, + }); + } + + useEffect(() => { counter > 0 && setTimeout(() => setCounter(counter - 1), 1000); }, [counter]); async function onVerifikasi() { if (!inputCode) return ComponentGlobal_NotifikasiPeringatan("Lengkapi Kode"); - if (code != inputCode) + if (data.code != inputCode) return ComponentGlobal_NotifikasiPeringatan("Kode Salah"); - const res = await auth_funValidasi({ - nomor: nomor, - HIPMI_PWD: GlobalEnv.value?.WIBU_PWD as string, - }); - if (res.status === 200) { - const resAktivasi = await auth_funDeleteAktivasiKodeOtpById( - dataOtp.id as any - ); - if (resAktivasi.status === 200) { - if (res.role === "1") { - ComponentGlobal_NotifikasiBerhasil(res.message); - setLoading(true); + try { + setLoading(true); + const res = await fetch("/api/auth/validasi", { + method: "POST", + body: JSON.stringify({ + nomor: data.nomor, + }), + headers: { + "Content-Type": "application/json", + }, + }); + + const result = await res.json(); + + if (res.status === 200) { + localStorage.removeItem("hipmi_auth_code_id"); + + if (result.roleId === "1") { + ComponentGlobal_NotifikasiBerhasil(result.message); router.push(RouterHome.main_home, { scroll: false }); + // if (result.active === true) { + // } else { + // ComponentGlobal_NotifikasiBerhasil(result.message); + // router.push("/waiting-room", { scroll: false }); + // } } else { ComponentGlobal_NotifikasiBerhasil("Admin Logged in"); - setLoading(true); router.push(RouterAdminDashboard.splash_admin, { scroll: false }); } - } else { - ComponentGlobal_NotifikasiPeringatan(resAktivasi.message); - } - } - if (res.status === 400) { - ComponentGlobal_NotifikasiBerhasil(res.message); - router.push("/register/" + dataOtp.id, { scroll: false }); - } - - if (res.status === 401) { - const resAktivasi = await auth_funDeleteAktivasiKodeOtpById({ - nomor: nomor, - }); - if (resAktivasi.status === 200) { - ComponentGlobal_NotifikasiPeringatan(res.message); - router.push("/login", { scroll: false }); + await auth_funDeleteAktivasiKodeOtpByNomor({ + nomor: data.nomor, + }); } + + if (res.status === 404) { + ComponentGlobal_NotifikasiBerhasil(result.message); + router.push("/register", { scroll: false }); + } + + if (res.status === 400) { + ComponentGlobal_NotifikasiPeringatan(result.message); + } + } catch (error) { + console.error(error); } } async function onBack() { - await auth_funDeleteAktivasiKodeOtpById({ nomor: nomor }); + localStorage.removeItem("hipmi_auth_code_id"); + await auth_funDeleteAktivasiKodeOtpByNomor({ nomor: data.nomor }); router.back(); } async function onResendCode() { - const res = await auth_funResendCode({ nomor: nomor }); - if (res.status === 200) { - ComponentGlobal_NotifikasiBerhasil(res.message, 2000); - router.push("/validasi/" + res.kodeId, { scroll: false }); - } else { - ComponentGlobal_NotifikasiPeringatan(res.message); + setLoadingResend(true); + localStorage.removeItem("hipmi_auth_code_id"); + + try { + const res = await fetch("/api/auth/resend", { + method: "POST", + body: JSON.stringify({ nomor: data.nomor }), + headers: { + "Content-Type": "application/json", + }, + }); + + const result = await res.json(); + + if (res.status === 200) { + localStorage.setItem("hipmi_auth_code_id", result.kodeId); + ComponentGlobal_NotifikasiBerhasil("Kode Berhasil Dikirim", 2000); + setTriggerOtp(true); + setCounter(60); + setLoadingResend(false); + // router.push("/validasi", { scroll: false }); + } else { + setLoadingResend(false); + ComponentGlobal_NotifikasiPeringatan(result.message); + } + } catch (error) { + console.error(error); + setLoadingResend(false); + ComponentGlobal_NotifikasiGagal("Terjadi Kesalahan"); } } + // console.log(data.code); + return ( <> - onBack()}> - + */} + {data.nomor == "" && data.code == "" ? ( + + ) : ( + + + Verifikasi Kode OTP + - - - Verifikasi Kode OTP - - - - - Masukan 4 digit kode otp - - Yang dikirim ke{" "} - - {" "} - +{nomor} + + + Masukan 4 digit kode otp + + Yang dikirim ke{" "} + + {" "} + +{data.nomor} + - + +
+ { + setInputOtp(val); + }} + /> +
+ + + + Tidak menerima kode ?{" "} + {counter > 0 ? ( + + {counter + "s"} + + ) : loadingResend ? ( + + ) : ( + { + onResendCode(); + }} + fw={"bold"} + > + Kirim ulang + + )} + +
-
- { - setInputOtp(val); - }} - /> -
- - - Tidak menerima kode ?{" "} - {counter > 0 ? ( - - {counter + "s"} - - ) : ( - onResendCode()}> - Kirim ulang - - )} - +
- -
+ )}
diff --git a/src/app_modules/check_cookies/layout_cek_cookies.tsx b/src/app_modules/check_cookies/layout_cek_cookies.tsx index 753bfa17..b328354d 100644 --- a/src/app_modules/check_cookies/layout_cek_cookies.tsx +++ b/src/app_modules/check_cookies/layout_cek_cookies.tsx @@ -2,7 +2,7 @@ import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; import { useShallowEffect } from "@mantine/hooks"; -import { useRouter } from "next/navigation"; +import { redirect, useRouter } from "next/navigation"; import { MODEL_USER } from "../home/model/interface"; import { RouterHome } from "@/app/lib/router_hipmi/router_home"; import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; @@ -16,6 +16,12 @@ export function CheckCookies_UiLayout({ }) { const router = useRouter(); + // if (dataUser.active == false){ + // router.push(RouterHome.home_user_non_active, { scroll: false }); + // return children + // } + + // useShallowEffect(() => { // onCheckCookies(); // }, []); @@ -38,5 +44,5 @@ export function CheckCookies_UiLayout({ // router.push(RouterAdminDashboard.splash_admin, { scroll: false }); // } - return children; + return <>{children}; } diff --git a/src/app_modules/event/_ui/konfirmasi.tsx b/src/app_modules/event/_ui/konfirmasi.tsx new file mode 100644 index 00000000..8b1814b7 --- /dev/null +++ b/src/app_modules/event/_ui/konfirmasi.tsx @@ -0,0 +1,451 @@ +"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 { + 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 { 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, + eventId, +}: { + userLoginId: string; + eventId: string; +}) { + // console.log(dataEvent); + + const router = useRouter(); + const [data, setData] = useState(null); + const [isJoin, setIsJoin] = useState(null); + const [isPresent, setIsPresent] = useState(null); + + 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); + } + + // 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(); + }, []); + + 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 (isJoin == false) { + 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 ( + <> + + + + + + Data Event Tidak Ditemukan + + + + + + + + + ); +} + +function SkeletonIsDataNull() { + return ( + <> + + + + + {" "} + {" "} + +
+ +
+
+
+
+
+ + ); +} + +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, +}: { + 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/button/button_create_event.tsx b/src/app_modules/event/component/button/button_create_event.tsx index 2e796932..74d53096 100644 --- a/src/app_modules/event/component/button/button_create_event.tsx +++ b/src/app_modules/event/component/button/button_create_event.tsx @@ -4,6 +4,7 @@ import { MainColor } from "@/app_modules/_global/color"; import { ComponentGlobal_NotifikasiBerhasil, ComponentGlobal_NotifikasiGagal, + ComponentGlobal_NotifikasiPeringatan, } from "@/app_modules/_global/notif_global"; import { notifikasiToAdmin_funCreate } from "@/app_modules/notifikasi/fun"; import { Button } from "@mantine/core"; @@ -14,13 +15,23 @@ import { useState } from "react"; import { WibuRealtime } from "wibu-pkg"; import { Event_funCreate } from "../../fun/create/fun_create"; import { gs_event_hotMenu } from "../../global_state"; +import { event_checkStatus } from "../../fun/get/fun_check_status_by_id"; -export default function Event_ComponentCreateButton({ value }: { value: any }) { +export default function Event_ComponentCreateButton({ + value, + diffTimeStart, + diffTimeEnd, +}: { + value: any; + diffTimeStart: number; + diffTimeEnd: number; +}) { const router = useRouter(); const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu); const [isLoading, setLoading] = useState(false); async function onSave() { + const res = await Event_funCreate(value); if (res.status === 201) { @@ -71,7 +82,8 @@ export default function Event_ComponentCreateButton({ value }: { value: any }) { value.deskripsi === "" || value.eventMaster_TipeAcaraId === 0 || value.tanggal === "function Date() { [native code] }" || - moment(value.tanggal).diff(moment(), "minutes") < 0 + // moment(value.tanggal).diff(moment(), "minutes") < 0 + diffTimeEnd - 1 < diffTimeStart } loaderPosition="center" loading={isLoading ? true : false} 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/detail/detail_data.tsx b/src/app_modules/event/component/detail/detail_data.tsx index b82a96ee..3e72b9b9 100644 --- a/src/app_modules/event/component/detail/detail_data.tsx +++ b/src/app_modules/event/component/detail/detail_data.tsx @@ -9,26 +9,16 @@ export default function ComponentEvent_DetailData({ }: { data: MODEL_EVENT; }) { - const tgl = data.tanggal; - const hari = tgl.toLocaleString("id-ID", { dateStyle: "full" }); - - const jam = tgl.toLocaleTimeString([], { - timeStyle: "short", - hourCycle: "h24", - }); - return ( <> - + {data ? data?.title : null} - - Lokasi - + Lokasi : @@ -37,37 +27,59 @@ export default function ComponentEvent_DetailData({ - - Tipe Acara - + Tipe Acara : {data ? data.EventMaster_TipeAcara?.name : null} - - - - Tanggal - - - : - {hari ? hari : ""} - - - - - Jam - - - : - {jam ? jam : ""} - + + Tanggal & Waktu + + + Mulai + + : + + + {" "} + {new Intl.DateTimeFormat("id-ID", { + dateStyle: "full", + }).format(data?.tanggal)} + ,{" "} + + {new Intl.DateTimeFormat("id-ID", { + timeStyle: "short", + }).format(data?.tanggal)} + + + + + + + Selesai + + : + + + {" "} + {new Intl.DateTimeFormat("id-ID", { + dateStyle: "full", + }).format(data?.tanggalSelesai)} + ,{" "} + + {new Intl.DateTimeFormat("id-ID", { + timeStyle: "short", + }).format(data?.tanggalSelesai)} + + + + + + - - Deskripsi - + Deskripsi {data ? data?.deskripsi : null} diff --git a/src/app_modules/event/component/detail/detail_main.tsx b/src/app_modules/event/component/detail/detail_main.tsx index 3e7acb65..4625b1e6 100644 --- a/src/app_modules/event/component/detail/detail_main.tsx +++ b/src/app_modules/event/component/detail/detail_main.tsx @@ -4,83 +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 - - - : - {hari} - - - - - Jam - - - : - {jam} - - - - Deskripsi - - {data ? data?.deskripsi : null} + + + {data ? data.title : null} + + + + Lokasi + + : + + {data ? data.lokasi : null} + + + + + Tipe Acara + + : + + {data ? data.EventMaster_TipeAcara.name : 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 9ae7274b..a8c53851 100644 --- a/src/app_modules/event/component/detail/list_peserta.tsx +++ b/src/app_modules/event/component/detail/list_peserta.tsx @@ -1,58 +1,202 @@ "use client"; import { + ActionIcon, + Avatar, Center, + Grid, + Group, + Skeleton, Stack, Text, - Title + Title, } from "@mantine/core"; import _ from "lodash"; import { ComponentGlobal_AvatarAndUsername, ComponentGlobal_CardStyles, + ComponentGlobal_LoaderAvatar, } from "@/app_modules/_global/component"; import { useRouter } from "next/navigation"; import { MODEL_EVENT_PESERTA } from "../../model/interface"; +import { Prisma } from "@prisma/client"; +import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog"; +import ComponentGlobal_Loader from "@/app_modules/_global/component/loader"; +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) => ( + + + + {/* */} + + ))} + + )} +
+
+ )} + + ); +} + +type IFontSize = "xs" | "sm" | "md" | "lg" | "xl"; + +function ComponentEvent_AvatarAndUsername({ + profile, + component, + sizeAvatar, + fontSize, + tanggalMulai, + tanggalSelesai, + isPresent, +}: { + profile: Prisma.ProfileSelect; + component?: React.ReactNode; + sizeAvatar?: number; + fontSize?: IFontSize | {}; + tanggalMulai?: Date; + tanggalSelesai?: Date; + isPresent?: boolean; +}) { + const router = useRouter(); + const [visible, setVisible] = useState(false); + + async function onCheckProfile() { + const res = await funGlobal_CheckProfile({ profileId: profile.id as any }); + + if (res !== null) { + setVisible(true); + router.push(RouterProfile.katalog({ id: profile.id as any })); + } else { + ComponentGlobal_NotifikasiPeringatan("Id tidak ditemukan"); + } + } + + const tglMulai = moment(tanggalMulai).diff(moment(), "minutes"); + + const tglSelesai = moment(tanggalSelesai).diff(moment(), "minutes"); + + // console.log("mulai:", tglMulai, "selesai:", tglSelesai); + + return ( + <> + + + onCheckProfile()} + > + {visible ? ( + + + + ) : ( + + )} + + + + + + onCheckProfile()} + > + {profile?.name} + + + + + {/* {component && ( + + + {component} + + + )} */} + + {tglMulai < 0 && ( + + + + + {isPresent ? "Hadir" : "-"} + + + + + )} + ); } diff --git a/src/app_modules/event/component/index.ts b/src/app_modules/event/component/index.ts index d9cc4eeb..6180e8a6 100644 --- a/src/app_modules/event/component/index.ts +++ b/src/app_modules/event/component/index.ts @@ -1,5 +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_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/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/create/create.tsx b/src/app_modules/event/create/create.tsx index 0331fe7f..a078cb80 100644 --- a/src/app_modules/event/create/create.tsx +++ b/src/app_modules/event/create/create.tsx @@ -2,7 +2,14 @@ import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown"; import { MODEL_DEFAULT_MASTER_OLD } from "@/app_modules/model_global/interface"; -import { Select, Stack, TextInput, Textarea } from "@mantine/core"; +import { + Button, + Select, + Stack, + Text, + TextInput, + Textarea, +} from "@mantine/core"; import { DateTimePicker } from "@mantine/dates"; import moment from "moment"; import { useState } from "react"; @@ -17,14 +24,18 @@ export default function Event_Create({ authorId: string; }) { const [listTipe, setListTipe] = useState(listTipeAcara); - const [isTime, setIsTime] = useState(false); + const [isTimeStart, setIsTimeStart] = useState(false); + const [diffTimeStart, setDiffTimeStart] = useState(0); + const [isTimeEnd, setIsTimeEnd] = useState(false); + const [diffTimeEnd, setDiffTimeEnd] = useState(0); const [value, setValue] = useState({ title: "", lokasi: "", deskripsi: "", tanggal: Date.toString(), + tanggalSelesai: Date.toString(), eventMaster_TipeAcaraId: 0, authorId: authorId, }); @@ -88,6 +99,8 @@ export default function Event_Create({ }); }} /> + + ) : ( "" @@ -111,9 +124,15 @@ export default function Event_Create({ // console.log( // moment(val?.toISOString().toString()).diff(moment(), "minutes" ) // ); + const diffTime = moment(val?.toISOString().toString()).diff( + moment(), + "minutes" + ); + setDiffTimeStart(diffTime); + moment(val?.toISOString().toString()).diff(moment(), "minutes") < 0 - ? setIsTime(true) - : setIsTime(false); + ? setIsTimeStart(true) + : setIsTimeStart(false); setValue({ ...value, @@ -122,6 +141,48 @@ export default function Event_Create({ }} /> + { + return moment(date).diff(Date.now(), "days") < 0; + }} + withAsterisk + label="Tanggal & Waktu Berakhir" + placeholder="Masukan tangal dan waktu " + error={ + isTimeEnd ? ( + + ) : diffTimeEnd - 1 < diffTimeStart && diffTimeEnd != 0 ? ( + + ) : ( + "" + ) + } + onChange={(val) => { + // console.log( + // moment(val?.toISOString().toString()).diff(moment(), "minutes" ) + // ); + const diffTime = moment(val?.toISOString().toString()).diff( + moment(), + "minutes" + ); + setDiffTimeEnd(diffTime); + + moment(val?.toISOString().toString()).diff(moment(), "minutes") < 0 + ? setIsTimeEnd(true) + : setIsTimeEnd(false); + + setValue({ + ...value, + tanggalSelesai: val as any, + }); + }} + /> +