Merge pull request #164 from bipproduction/join

First merge to staging
This commit is contained in:
Bagasbanuna02
2024-12-06 13:55:36 +08:00
committed by GitHub
167 changed files with 4843 additions and 9546 deletions

View File

@@ -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. 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) ## [1.2.5](https://github.com/bipproduction/hipmi/compare/v1.2.4...v1.2.5) (2024-11-28)

BIN
bun.lockb Executable file

Binary file not shown.

View File

@@ -1,10 +1,10 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
reactStrictMode: false, reactStrictMode: false,
experimental: { experimental: {
serverActions: true serverActions: true,
}, },
output: "standalone"
};
} module.exports = nextConfig;
module.exports = nextConfig

View File

@@ -1,16 +1,17 @@
{ {
"name": "hipmi", "name": "hipmi",
"version": "1.2.5", "version": "1.2.19",
"private": true, "private": true,
"prisma": { "prisma": {
"seed": "npx tsx prisma/seed.ts --yes" "seed": "npx tsx prisma/seed.ts --yes"
}, },
"scripts": { "scripts": {
"dev": "next dev --experimental-https", "dev": "bun --bun run next dev --experimental-https",
"build": "next build", "build": "NODE_OPTIONS='--max-old-space-size=2048' bun --bun run next build",
"start": "next start", "build:dev": "bun --bun run next build",
"lint": "next lint", "start": "bun --bun run next start",
"ver": "npx commit-and-tag-version -- --prerelease" "lint": "bun --bun run next lint",
"ver": "bunx commit-and-tag-version -- --prerelease"
}, },
"dependencies": { "dependencies": {
"@bounceapp/iframe": "^0.3.0", "@bounceapp/iframe": "^0.3.0",
@@ -79,6 +80,7 @@
"react-international-phone": "^4.2.6", "react-international-phone": "^4.2.6",
"react-map-gl": "^7.1.7", "react-map-gl": "^7.1.7",
"react-pdf": "^9.1.0", "react-pdf": "^9.1.0",
"react-qr-code": "^2.0.15",
"react-quill": "^2.0.0", "react-quill": "^2.0.0",
"react-responsive-carousel": "^3.2.23", "react-responsive-carousel": "^3.2.23",
"react-toastify": "^9.1.3", "react-toastify": "^9.1.3",
@@ -89,6 +91,7 @@
"utf-8-validate": "^6.0.3", "utf-8-validate": "^6.0.3",
"uuid": "^9.0.1", "uuid": "^9.0.1",
"wibu": "bipproduction/wibu", "wibu": "bipproduction/wibu",
"wibu-cli": "^1.0.91",
"wibu-pkg": "^1.0.3", "wibu-pkg": "^1.0.3",
"yaml": "^2.3.2" "yaml": "^2.3.2"
} }

View File

@@ -15,7 +15,7 @@ model User {
id String @id @default(cuid()) id String @id @default(cuid())
username String @unique username String @unique
nomor String @unique nomor String @unique
active Boolean @default(true) active Boolean @default(false)
createdAt DateTime? @default(now()) createdAt DateTime? @default(now())
updatedAt DateTime? @updatedAt updatedAt DateTime? @updatedAt
MasterUserRole MasterUserRole @relation(fields: [masterUserRoleId], references: [id]) MasterUserRole MasterUserRole @relation(fields: [masterUserRoleId], references: [id])
@@ -573,16 +573,19 @@ model Donasi_PencairanDana {
// ========================================= EVENT ========================================= // // ========================================= EVENT ========================================= //
model Event { model Event {
id String @id @default(cuid()) id String @id @default(cuid())
title String title String
lokasi String lokasi String
tanggal DateTime tanggal DateTime?
deskripsi String deskripsi String
active Boolean @default(true) active Boolean @default(true)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
catatan String? catatan String?
tanggalSelesai DateTime?
isArsip Boolean? @default(false)
Author User? @relation(fields: [authorId], references: [id]) Author User? @relation(fields: [authorId], references: [id])
authorId String? authorId String?
EventMaster_Status EventMaster_Status? @relation(fields: [eventMaster_StatusId], references: [id]) EventMaster_Status EventMaster_Status? @relation(fields: [eventMaster_StatusId], references: [id])
@@ -615,6 +618,7 @@ model Event_Peserta {
active Boolean @default(true) active Boolean @default(true)
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
isPresent Boolean @default(false)
Event Event? @relation(fields: [eventId], references: [id]) Event Event? @relation(fields: [eventId], references: [id])
eventId String? eventId String?

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

View File

@@ -1,4 +1,4 @@
import { funCheckCookies } from "@/app_modules/_global/fun/get/fun_check_cookies";
import { Login } from "@/app_modules/auth"; import { Login } from "@/app_modules/auth";
import versionUpdate from "../../../../package.json"; import versionUpdate from "../../../../package.json";

View File

@@ -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 <Register dataOtp={dataOtp} />;
}

View File

@@ -0,0 +1,5 @@
import { Register } from "@/app_modules/auth";
export default async function Page() {
return <Register />;
}

View File

@@ -0,0 +1,7 @@
import { SplashScreen } from "@/app_modules/auth";
export default async function Page() {
return <>
<SplashScreen/>
</>
}

View File

@@ -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 <Validasi dataOtp={dataOtp as any} />;
}

View File

@@ -0,0 +1,5 @@
import { Validasi } from "@/app_modules/auth";
export default async function Page() {
return <Validasi />;
}

View File

@@ -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 (
<>
<WaitingRoom_View
activationUser={activationUser as boolean}
userLoginId={userLoginId as string}
/>
</>
);
}

View File

@@ -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 });
}

View File

@@ -1,31 +1,64 @@
import { prisma } from "@/app/lib";
import { randomOTP } from "@/app_modules/auth/fun/rondom_otp";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
export async function POST(req: Request) { export async function POST(req: Request) {
if (req.method === "POST") { if (req.method === "POST") {
const codeOtp = randomOTP();
const body = await req.json(); const body = await req.json();
// console.log(body); const { nomor } = body;
if (body.nomor === "1234567890") { try {
return NextResponse.json({ const res = await fetch(
success: true, `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.
status: 200, \n
message: "Login Success", >> Kode OTP anda: ${codeOtp}.
}); `
} else { );
try {
await fetch( const sendWa = await res.json();
`https://wa.wibudev.com/code?nom=${body.nomor}&text=Masukan Kode OTP:${body.otp}` if (sendWa.status !== "success")
return new Response(
JSON.stringify({
success: false,
message: "Nomor Whatsapp Tidak Aktif",
}),
{ status: 400 }
); );
return NextResponse.json({
body, const createOtpId = await prisma.kodeOtp.create({
status: 200, data: {
message: "Login Success", nomor: nomor,
}); otp: codeOtp,
} catch (error) { },
return NextResponse.json({ status: 500, message: "Server Error !!!" }); });
}
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 }); return NextResponse.json({ success: false });

View File

@@ -1,12 +1,28 @@
import { prisma } from "@/app/lib";
import { cookies } from "next/headers"; 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() { const delToken = await prisma.userSession.delete({
cookies().set({ where: {
name: "mySession", userId: id as string,
value: "", },
maxAge: 0, });
});
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" });
// }

View File

@@ -1,51 +1,70 @@
import { sessionCreate } from "@/app/auth/_lib/session_create";
import prisma from "@/app/lib/prisma"; 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) { export async function POST(req: Request) {
if (req.method === "POST") { if (req.method === "POST") {
const body = await req.json(); const { data } = await req.json();
// MyConsole(body);
const cekUsername = await prisma.user.findUnique({ const cekUsername = await prisma.user.findUnique({
where: { where: {
username: body.username, username: data.username,
}, },
}); });
if (cekUsername) 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: { data: {
username: body.username, username: data.username,
nomor: body.nomor, nomor: data.nomor,
active: true,
}, },
}); });
if (data) { const token = await sessionCreate({
const seal = await sealData( sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
JSON.stringify({ encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
id: data.id, user: createUser as any,
username: data.username, });
}),
{
password: ServerEnv.value?.WIBU_PWD as string,
}
);
cookies().set({ try {
name: "mySession", const createUserSession = await prisma.userSession.create({
value: seal, data: {
maxAge: 60 * 60 * 24 * 7, 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 }
);
} }

View File

@@ -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 });
}

View File

@@ -1,3 +1,4 @@
import { sessionCreate } from "@/app/auth/_lib/session_create";
import prisma from "@/app/lib/prisma"; import prisma from "@/app/lib/prisma";
import { ServerEnv } from "@/app/lib/server_env"; import { ServerEnv } from "@/app/lib/server_env";
import { sealData } from "iron-session"; import { sealData } from "iron-session";
@@ -7,45 +8,100 @@ import { NextResponse } from "next/server";
export async function POST(req: Request) { export async function POST(req: Request) {
if (req.method === "POST") { 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: { where: {
nomor: body.nomor, nomor: nomor,
}, },
select: { select: {
id: true, id: true,
nomor: true, nomor: true,
username: true, username: true,
active: true, active: true,
masterUserRoleId: true,
}, },
}); });
if (!data) return NextResponse.json({ status: 404 });
if (data) { if (dataUser === null)
const res = await sealData( return new Response(
JSON.stringify({ JSON.stringify({ success: false, message: "Nomor Belum Terdaftar" }),
id: data.id, { status: 404 }
username: data.username,
}),
{
password: ServerEnv.value?.WIBU_PWD as string,
}
); );
cookies().set({ const token = await sessionCreate({
name: "mySession", sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
value: res, encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
maxAge: 60 * 60 * 24 * 7, 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 }
);
} }

View File

@@ -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 });
}

View File

@@ -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 });
}

View File

@@ -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 });
}

View File

@@ -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 }
);
}

View File

@@ -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 });
}

View File

@@ -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 });
}
}

View File

@@ -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 });
}
}

View File

@@ -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 });
}
}

View File

@@ -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 }));
}

41
src/app/api/user/route.ts Normal file
View File

@@ -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<Record<string, any> | null> {
try {
const enc = new TextEncoder().encode(encodedKey);
const { payload } = await jwtVerify(token, enc, {
algorithms: ["HS256"],
});
return (payload.user as Record<string, any>) || null;
} catch (error) {
console.error("Gagal verifikasi session", error);
return null;
}
}

View File

@@ -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 }));
}

View File

@@ -0,0 +1,22 @@
import { jwtVerify } from "jose";
export async function decrypt({
token,
encodedKey,
}: {
token: string;
encodedKey: string;
}): Promise<Record<string, any> | null> {
try {
const enc = new TextEncoder().encode(encodedKey);
const { payload } = await jwtVerify(token, enc, {
algorithms: ["HS256"],
});
return (payload.user as Record<string, any>) || null;
} catch (error) {
console.error("Gagal verifikasi session", error);
return null;
}
}
// wibu:0.2.82

View File

@@ -0,0 +1,25 @@
import { SignJWT } from "jose";
export async function encrypt({
user,
exp = "7 year",
encodedKey,
}: {
user: Record<string, any>;
exp?: string;
encodedKey: string;
}): Promise<string | null> {
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

View File

@@ -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<string, unknown>;
}) {
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

View File

@@ -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 }));
}

View File

@@ -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 }));
}

View File

@@ -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 (
<>
<Button loading={loading} onClick={login}>
Login
</Button>
</>
);
}

View File

@@ -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 (
<>
{/* <HomeView
dataUser={dataUser as any}
dataJob={dataJob as any}
countNotifikasi={countNotifikasi}
/> */}
<HomeViewNew countNotifikasi={countNotifikasi} />
</>
);
}

View File

@@ -1,9 +1,8 @@
import { AdminEvent_TablePublish } from "@/app_modules/admin/event"; import { AdminEvent_TablePublish } from "@/app_modules/admin/event";
import { adminEvent_funGetListPublish } from "@/app_modules/admin/event/fun"; 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() { async function Page() {
const listPublish = await adminEvent_funGetListPublish({page: 1}); const listPublish = await adminEvent_funGetListPublish({ page: 1 });
return ( return (
<> <>
@@ -11,3 +10,5 @@ export default async function Page() {
</> </>
); );
} }
export default Page;

View File

@@ -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 adminNotifikasi_getByUserId from "@/app_modules/admin/notifikasi/fun/get/get_notifikasi_by_user_id";
import React from "react"; import React from "react";
import versionUpdate from "../../../../package.json"; import versionUpdate from "../../../../package.json";
import { redirect } from "next/navigation";
export default async function Layout({ export default async function Layout({
children, children,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
@@ -14,10 +15,14 @@ export default async function Layout({
const userLoginId = await funGetUserIdByToken(); const userLoginId = await funGetUserIdByToken();
const version = versionUpdate.version; const version = versionUpdate.version;
const dataUser = await funGlobal_getUserById({ userId: userLoginId as string}); const dataUser = await funGlobal_getUserById({
const listNotifikasi = await adminNotifikasi_getByUserId({page: 1}); userId: userLoginId as string,
});
const listNotifikasi = await adminNotifikasi_getByUserId({ page: 1 });
const countNotifikasi = await adminNotifikasi_countNotifikasi(); const countNotifikasi = await adminNotifikasi_countNotifikasi();
if (dataUser?.masterUserRoleId == "1") return redirect("/dev/home");
return ( return (
<> <>
<Admin_NewLayout <Admin_NewLayout

View File

@@ -6,9 +6,9 @@ import { redirect } from "next/navigation";
export default async function Page() { export default async function Page() {
const version = versionUpdate.version; const version = versionUpdate.version;
const checkCookies = await funCheckCookies(); // const checkCookies = await funCheckCookies();
console.log(checkCookies, "ini halaman login"); // console.log(checkCookies, "ini halaman login");
if (!checkCookies) return redirect("/"); // if (!checkCookies) return redirect("/");
return ( return (
<> <>

View File

@@ -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 } }) { export default async function Page({ params }: { params: { id: string } }) {
let otpId = params.id; let otpId = params.id;
const dataOtp = await auth_getCodeOtpByNumber({ kodeId: otpId }); const dataOtp = await auth_getCodeOtpByNumber({ kodeId: otpId });
return <Register dataOtp={dataOtp} />; return <Register />;
} }

View File

@@ -3,7 +3,7 @@ import { SplashScreen } from "@/app_modules/auth";
export default async function PageSplash() { export default async function PageSplash() {
return ( return (
<> <>
<SplashScreen checkCookies/> <SplashScreen />
</> </>
); );
} }

View File

@@ -5,6 +5,5 @@ export default async function Page({ params }: { params: { id: string } }) {
let kodeId = params.id; let kodeId = params.id;
const dataOtp = await auth_getCodeOtpByNumber({ kodeId: kodeId }); const dataOtp = await auth_getCodeOtpByNumber({ kodeId: kodeId });
return <Validasi />;
return <Validasi dataOtp={dataOtp as any} />;
} }

View File

@@ -6,16 +6,16 @@ import { CheckCookies_UiView } from "@/app_modules/check_cookies";
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
export default async function Page() { export default async function Page() {
const userLoginId = await funGetUserIdByToken(); // const userLoginId = await funGetUserIdByToken();
const dataUser = await funGlobal_getUserById({ userId: userLoginId }); // const dataUser = await funGlobal_getUserById({ userId: userLoginId });
if (dataUser?.masterUserRoleId === "1") { // if (dataUser?.masterUserRoleId === "1") {
return redirect(RouterHome.main_home); // return redirect(RouterHome.main_home);
} // }
if (dataUser?.masterUserRoleId !== "1") { // if (dataUser?.masterUserRoleId !== "1") {
return redirect(RouterAdminDashboard.splash_admin); // return redirect(RouterAdminDashboard.splash_admin);
} // }
// return <CheckCookies_UiView />; // return <CheckCookies_UiView />;
} }

View File

@@ -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_Create } from "@/app_modules/event";
import { Event_getMasterTipeAcara } from "@/app_modules/event/fun/master/get_tipe_acara"; import { Event_getMasterTipeAcara } from "@/app_modules/event/fun/master/get_tipe_acara";
export default async function Page() { export default async function Page() {
const userLoginId = await funGetUserIdByToken(); const userLoginId = await newFunGetUserId();
const listTipeAcara = await Event_getMasterTipeAcara(); const listTipeAcara = await Event_getMasterTipeAcara();
return ( return (

View File

@@ -11,8 +11,7 @@ export default async function Page({ params }: { params: { id: string } }) {
return ( return (
<> <>
<Event_DetailKontribusi <Event_DetailKontribusi
dataEvent={dataEvent as any} eventId={eventId}
listKontributor={listKontributor as any}
totalPeserta={totalPeserta} totalPeserta={totalPeserta}
/> />
</> </>

View File

@@ -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_DetailMain } from "@/app_modules/event";
import { Event_countTotalPesertaById } from "@/app_modules/event/fun/count/count_total_peserta_by_id"; 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 } }) { export default async function Page({ params }: { params: { id: string } }) {
let eventId = params.id; let eventId = params.id;
const userLoginId : any= await funGetUserIdByToken(); const userLoginId = await newFunGetUserId();
const dataEvent = await event_getOneById(eventId);
const listPeserta = await Event_getListPesertaById(eventId);
const isJoin = await Event_CekUserJoinById(eventId, userLoginId);
const totalPeserta = await Event_countTotalPesertaById(eventId); const totalPeserta = await Event_countTotalPesertaById(eventId);
return ( return (
<> <>
<Event_DetailMain <Event_DetailMain
dataEvent={dataEvent as any}
listPeserta={listPeserta as any}
userLoginId={userLoginId as string} userLoginId={userLoginId as string}
isJoin={isJoin}
totalPeserta={totalPeserta as any} totalPeserta={totalPeserta as any}
eventId={eventId}
/> />
</> </>
); );

View File

@@ -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 } }) { export default async function Page({ params }: { params: { id: string } }) {
let eventId = params.id; let eventId = params.id;
const dataEvent = await event_getOneById(eventId); const dataEvent = await event_getOneById(eventId);
const listPeserta = await Event_getListPesertaById(eventId);
const totalPeserta = await Event_countTotalPesertaById(eventId); const totalPeserta = await Event_countTotalPesertaById(eventId);
return ( return (
<Event_DetailPublish <Event_DetailPublish
dataEvent={dataEvent as any} dataEvent={dataEvent as any}
listPeserta={listPeserta}
totalPeserta={totalPeserta} totalPeserta={totalPeserta}
eventId={eventId}
/> />
); );
} }

View File

@@ -1,21 +1,15 @@
import { Event_DetailRiwayat } from "@/app_modules/event"; import { Event_DetailRiwayat } from "@/app_modules/event";
import { Event_countTotalPesertaById } from "@/app_modules/event/fun/count/count_total_peserta_by_id"; 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 } }) { export default async function Page({ params }: { params: { id: string } }) {
let eventId = params.id; let eventId = params.id;
const dataEvent = await event_getOneById(eventId);
const listPeserta = await Event_getListPesertaById(eventId);
const totalPeserta = await Event_countTotalPesertaById(eventId); const totalPeserta = await Event_countTotalPesertaById(eventId);
return ( return (
<> <>
<Event_DetailRiwayat <Event_DetailRiwayat
dataEvent={dataEvent as any}
listPeserta={listPeserta as any}
totalPeserta={totalPeserta as any} totalPeserta={totalPeserta as any}
eventId={eventId}
/> />
</> </>
); );

View File

@@ -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 (
<>
<Ui_Konfirmasi userLoginId={userLoginId as string} eventId={eventId} />
</>
);
}

View File

@@ -1,12 +1,10 @@
import { Event_Beranda } from "@/app_modules/event"; 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() { export default async function Page() {
const dataEvent = await event_getListAllPublish({ page: 1 });
return ( return (
<> <>
<Event_Beranda dataEvent={dataEvent as any} /> <Event_Beranda />
</> </>
); );
} }

View File

@@ -16,7 +16,7 @@ export default async function Page({ params }: { params: { id: string } }) {
page: 1, page: 1,
}); });
dataPosting?.isActive === false && redirect(RouterForum.beranda); // dataPosting?.isActive === false && redirect(RouterForum.beranda);
const countKomentar = await forum_countTotalKomenById(postingId); const countKomentar = await forum_countTotalKomenById(postingId);

View File

@@ -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 (
<>
<HomeView
dataUser={dataUser as any}
dataJob={dataJob as any}
countNotifikasi={countNotifikasi}
/>
</>
);
}

View File

@@ -1,29 +1,24 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; import { LayoutKatalogNew } from "@/app_modules/katalog/main";
import { KatalogLayout } from "@/app_modules/katalog/main";
import { Profile_getOneProfileAndUserById } from "@/app_modules/katalog/profile/fun/get/get_one_user_profile";
export default async function Layout({ export default async function Layout({ children, params, }: { children: any; params: { id: string } }) {
children, // const profileId = params.id;
params, // const dataProfile = await Profile_getOneProfileAndUserById(profileId);
}: { // const authorId = dataProfile?.userId;
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 ( return (
<> <>
<KatalogLayout {/* <KatalogLayout
profileId={profileId} profileId={profileId}
userLoginId={userLoginId as string} userLoginId={userLoginId as string}
authorId={authorId as any} authorId={authorId as any}
userRoleId={userRoleId as string}
> >
{children} {children}
</KatalogLayout> </KatalogLayout> */}
<LayoutKatalogNew>{children}</LayoutKatalogNew>
</> </>
); );
} }

View File

@@ -1,22 +1,21 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; import { ViewKatalogNew } from "@/app_modules/katalog";
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";
export default async function Page({ params }: { params: { id: string } }) { export default async function Page({ params }: { params: { id: string } }) {
let profileId = params.id; // let profileId = params.id;
const userLoginId = await funGetUserIdByToken(); // const userLoginId = await funGetUserIdByToken();
const listPorto = await funGetListPortofolio(profileId); // const listPorto = await funGetListPortofolio(profileId);
const dataProfile = await Profile_getOneProfileAndUserById(profileId); // const dataProfile = await Profile_getOneProfileAndUserById(profileId);
return ( return (
<> <>
<Katalog_MainView {/* <Katalog_MainView
profile={dataProfile as any} profile={dataProfile as any}
listPorto={listPorto as any} listPorto={listPorto as any}
userLoginId={userLoginId as any} userLoginId={userLoginId as any}
/> /> */}
<ViewKatalogNew />
</> </>
); );
} }

View File

@@ -1,38 +1,21 @@
import { CheckCookies_UiLayout } from "@/app_modules/check_cookies";
import { RealtimeProvider } from "../lib"; import { RealtimeProvider } from "../lib";
import { funCheckCookies } from "@/app_modules/_global/fun/get/fun_check_cookies"; import { newFunGetUserId } from "../lib/new_fun_user_id";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { ServerEnv } from "../lib/server_env"; 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({ export default async function Layout({
children, children,
}: { }: {
children: React.ReactNode; 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 ( return (
<> <>
<RealtimeProvider <RealtimeProvider
userLoginId={userLoginId as string}
WIBU_REALTIME_TOKEN={ WIBU_REALTIME_TOKEN={
ServerEnv.value?.NEXT_PUBLIC_WIBU_REALTIME_TOKEN as string ServerEnv.value?.NEXT_PUBLIC_WIBU_REALTIME_TOKEN as string
} }
/> />
{children} {children}
{/* <CheckCookies_UiLayout dataUser={dataUser as any}>
{children}
</CheckCookies_UiLayout> */}
</> </>
); );
} }

View File

@@ -1,17 +1,17 @@
import { Portofolio_ViewListDetail } from "@/app_modules/katalog/portofolio"; import { ListDetailPortofolioNew } from "@/app_modules/katalog/portofolio";
import { portofolio_funGetAllDaftarByid } from "@/app_modules/katalog/portofolio/fun/get/get_all_portofolio";
export default async function Page({ params }: { params: { id: string } }) { export default async function Page({ params }: { params: { id: string } }) {
const profileId = params.id; // const profileId = params.id;
const dataPortofolio = await portofolio_funGetAllDaftarByid({ // const dataPortofolio = await portofolio_funGetAllDaftarByid({
profileId, // profileId,
page: 1, // page: 1,
}); // });
return ( return (
<> <>
<Portofolio_ViewListDetail dataPortofolio={dataPortofolio as any} profileId={profileId} /> {/* <Portofolio_ViewListDetail dataPortofolio={dataPortofolio as any} profileId={profileId} /> */}
<ListDetailPortofolioNew />
</> </>
); );
} }

View File

@@ -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 { 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() { 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 ( return (
<> <>
<Home_UserNonActive /> <Home_UserNonActive />

View File

@@ -16,7 +16,7 @@ export default async function Layout({
<> <>
<LayoutVote_DetailSemuaRiwayat <LayoutVote_DetailSemuaRiwayat
votingId={votingId} votingId={votingId}
userLoginId={userLoginId} userLoginId={userLoginId as string}
> >
{children} {children}
</LayoutVote_DetailSemuaRiwayat> </LayoutVote_DetailSemuaRiwayat>

View File

@@ -1,13 +1,8 @@
import MqttLoader from "@/util/mqtt_loader";
import RootStyleRegistry from "./emotion"; import RootStyleRegistry from "./emotion";
// import "./globals.css"; // import "./globals.css";
import { TokenProvider } from "./lib/token";
import dotenv from "dotenv"; import dotenv from "dotenv";
import { ServerEnv } from "./lib/server_env"; import { ServerEnv } from "./lib/server_env";
import { RealtimeProvider } from "./lib"; import { TokenProvider } from "./lib/token";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { funCheckCookies } from "@/app_modules/_global/fun/get/fun_check_cookies";
import { redirect } from "next/navigation";
dotenv.config({ dotenv.config({
path: ".env", path: ".env",
}); });

View File

@@ -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}`,
};

View File

@@ -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;
}

View File

@@ -1,17 +1,26 @@
import { PrismaClient } from '@prisma/client' import { PrismaClient } from '@prisma/client';
const prismaClientSingleton = () => {
return new PrismaClient()
}
type PrismaClientSingleton = ReturnType<typeof prismaClientSingleton>
// Singleton PrismaClient untuk pengembangan
const globalForPrisma = globalThis as unknown as { 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 export default prisma;
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma

View File

@@ -17,6 +17,8 @@ import {
gs_votingTiggerBeranda, gs_votingTiggerBeranda,
IRealtimeData, IRealtimeData,
} from "./global_state"; } from "./global_state";
import { newFunGetUserId } from "./new_fun_user_id";
import { useState } from "react";
// const WIBU_REALTIME_TOKEN: string | undefined = // const WIBU_REALTIME_TOKEN: string | undefined =
// process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN; // process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN;
@@ -30,12 +32,11 @@ export type TypeNotification = {
}; };
export default function RealtimeProvider({ export default function RealtimeProvider({
userLoginId,
WIBU_REALTIME_TOKEN, WIBU_REALTIME_TOKEN,
}: { }: {
userLoginId: string;
WIBU_REALTIME_TOKEN: string; WIBU_REALTIME_TOKEN: string;
}) { }) {
const [userLoginId, setUserLoginId] = useState("");
const [dataRealtime, setDataRealtime] = useAtom(gs_realtimeData); const [dataRealtime, setDataRealtime] = useAtom(gs_realtimeData);
const [newAdminNtf, setNewAdminNtf] = useAtom(gs_admin_ntf); const [newAdminNtf, setNewAdminNtf] = useAtom(gs_admin_ntf);
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf); const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
@@ -71,8 +72,15 @@ export default function RealtimeProvider({
gs_donasiTriggerBeranda gs_donasiTriggerBeranda
); );
async function loadUserId() {
const userId = await newFunGetUserId();
setUserLoginId(userId as string);
}
useShallowEffect(() => { useShallowEffect(() => {
// if (WIBU_REALTIME_TOKEN === undefined) return alert("gak dapet key"); loadUserId();
try { try {
WibuRealtime.init({ WibuRealtime.init({
project: "hipmi", project: "hipmi",
@@ -201,7 +209,7 @@ export default function RealtimeProvider({
}, },
}); });
} catch (error) { } catch (error) {
console.log(error); console.log("Error!:", error);
} }
}, []); }, []);

View File

@@ -1,24 +1,14 @@
import { funCheckCookies } from "@/app_modules/_global/fun/get/fun_check_cookies"; "use client";
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";
export default async function Page() { import { SplashScreen } from "@/app_modules/auth";
const version = versionUpdate.version; import { useShallowEffect } from "@mantine/hooks";
const checkCookies = await funCheckCookies(); export default function Page() {
// console.log(checkCookies, "ini check cookies di page awal"); useShallowEffect(() => {
if (checkCookies) return redirect("/dev/check-cookies"); setTimeout(() => {
return redirect("/login"); window.location.replace("/dev/home");
// const WIBU_REALTIME_TOKEN = process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN; }, 1000);
}, []);
// return <Login version={version} />; return <SplashScreen />;
// return <SplashScreen checkCookies={checkCookies} />;
return <PageSplash />;
} }

View File

@@ -51,7 +51,7 @@ export function ComponentGlobal_AvatarAndUsername({
</Avatar> </Avatar>
) : ( ) : (
<ComponentGlobal_LoaderAvatar <ComponentGlobal_LoaderAvatar
fileId={profile.imageId as any} fileId={profile?.imageId as any}
sizeAvatar={sizeAvatar} sizeAvatar={sizeAvatar}
/> />
)} )}

View File

@@ -52,11 +52,13 @@ export async function generate_seeder() {
nomor: i.nomor, nomor: i.nomor,
username: i.name, username: i.name,
masterUserRoleId: i.masterUserRoleId, masterUserRoleId: i.masterUserRoleId,
active: i.active,
}, },
update: { update: {
nomor: i.nomor, nomor: i.nomor,
username: i.name, username: i.name,
masterUserRoleId: i.masterUserRoleId, masterUserRoleId: i.masterUserRoleId,
active: i.active,
}, },
}); });
} }

View File

@@ -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;
}

View File

@@ -1,20 +1,31 @@
"use server"; "use server";
import { prisma } from "@/app/lib";
import { ServerEnv } from "@/app/lib/server_env"; import { ServerEnv } from "@/app/lib/server_env";
import { unsealData } from "iron-session"; import { unsealData } from "iron-session";
import { jwtVerify } from "jose";
import { cookies } from "next/headers"; import { cookies } from "next/headers";
export async function funGetUserIdByToken() { 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( const cekUser = await decrypt({
await unsealData(c?.value as string, { token: c?.value as string,
password: process.env.WIBU_PWD as string, encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
}) });
);
return token.id; // console.log("userid" , cekUser?.id)
// const token = c?.value
// 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({ // const cekToken = await prisma.userSession.findFirst({
// where: { // where: {
// token: token, // token: token,
@@ -22,5 +33,24 @@ export async function funGetUserIdByToken() {
// }); // });
// if (cekToken === null) return null // if (cekToken === null) return null
// return cekToken.userId; return cekUser?.id;
}
async function decrypt({
token,
encodedKey,
}: {
token: string;
encodedKey: string;
}): Promise<Record<string, any> | null> {
try {
const enc = new TextEncoder().encode(encodedKey);
const { payload } = await jwtVerify(token, enc, {
algorithms: ["HS256"],
});
return (payload.user as Record<string, any>) || null;
} catch (error) {
console.error("Gagal verifikasi session", error);
return null;
}
} }

View File

@@ -1,14 +1,8 @@
"use client"; "use client";
import { RouterAuth } from "@/app/lib/router_hipmi/router_auth";
import { Warna } from "@/app/lib/warna"; import { Warna } from "@/app/lib/warna";
import { AccentColor } from "@/app_modules/_global/color"; import { AccentColor } from "@/app_modules/_global/color";
import { import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global";
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 { MODEL_USER } from "@/app_modules/home/model/interface"; import { MODEL_USER } from "@/app_modules/home/model/interface";
import { import {
ActionIcon, ActionIcon,
@@ -20,12 +14,12 @@ import {
Menu, Menu,
Modal, Modal,
Popover, Popover,
SimpleGrid,
Stack, Stack,
Text, Text,
Title, Title,
} from "@mantine/core"; } from "@mantine/core";
import { IconPhone, IconUser, IconUserCircle } from "@tabler/icons-react"; import { IconPhone, IconUser, IconUserCircle } from "@tabler/icons-react";
import { useAtom } from "jotai";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
@@ -38,21 +32,18 @@ export function Admin_ComponentButtonUserCircle({
const [isOpenMenuUser, setOpenMenuUser] = useState(false); const [isOpenMenuUser, setOpenMenuUser] = useState(false);
const [openPop, setOpenPop] = useState(false); const [openPop, setOpenPop] = useState(false);
const [openModal, setOpenModal] = useState(false); const [openModal, setOpenModal] = useState(false);
const [loading, setLoading] = useState(false);
const [kodeId, setKodeId] = useAtom(gs_kodeId);
const [loadingLogout, setLoadingLogout] = useState(false); const [loadingLogout, setLoadingLogout] = useState(false);
async function onClickLogout() { 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) { if (res.status === 200) {
console.log(res); ComponentGlobal_NotifikasiBerhasil(result.message);
setLoadingLogout(true); router.push("/", { scroll: false });
ComponentGlobal_NotifikasiBerhasil(res.message);
setKodeId("");
setOpenModal(false);
router.push(RouterAuth.login, { scroll: false });
} else {
ComponentGlobal_NotifikasiPeringatan(res.message);
} }
} }
@@ -92,11 +83,21 @@ export function Admin_ComponentButtonUserCircle({
<Divider /> <Divider />
<Center> <SimpleGrid cols={2}>
<Button radius={"xl"} onClick={() => setOpenModal(true)}> <Button
radius={"xl"}
onClick={() => router.push("/dev/home", { scroll: false })}
>
User Access
</Button>
<Button
radius={"xl"}
color="red"
onClick={() => setOpenModal(true)}
>
Keluar Keluar
</Button> </Button>
</Center> </SimpleGrid>
</Stack> </Stack>
</Popover.Dropdown> </Popover.Dropdown>
</Popover> </Popover>
@@ -114,7 +115,6 @@ export function Admin_ComponentButtonUserCircle({
<Button <Button
onClick={() => { onClick={() => {
setOpenModal(false); setOpenModal(false);
setLoading(false);
}} }}
radius={50} radius={50}
> >

View File

@@ -45,6 +45,8 @@ import adminNotifikasi_funCreateToUser from "../../notifikasi/fun/create/fun_cre
import { adminEvent_funGetListReview } from "../fun"; import { adminEvent_funGetListReview } from "../fun";
import { AdminEvent_funEditStatusPublishById } from "../fun/edit/fun_edit_status_publish_by_id"; import { AdminEvent_funEditStatusPublishById } from "../fun/edit/fun_edit_status_publish_by_id";
import { AdminEvent_funEditCatatanById } from "../fun/edit/fun_edit_status_reject_by_id"; import { AdminEvent_funEditCatatanById } from "../fun/edit/fun_edit_status_reject_by_id";
import { event_checkStatus } from "@/app_modules/event/fun/get/fun_check_status_by_id";
import { ComponentAdminGlobal_NotifikasiPeringatan } from "../../_admin_global/admin_notifikasi/notifikasi_peringatan";
export default function AdminEvent_ComponentTableReview({ export default function AdminEvent_ComponentTableReview({
listData, listData,
@@ -104,51 +106,65 @@ export default function AdminEvent_ComponentTableReview({
setIsAdminTriggerReview(false); setIsAdminTriggerReview(false);
} }
async function onPublish(eventId: string, tanggal: Date) { async function onPublish({
if (moment(tanggal).diff(Date.now(), "minutes") < 0) eventId,
return ComponentGlobal_NotifikasiPeringatan( tanggal,
"Waktu acara telah lewat, Report untuk memberitahu user !" }: {
); eventId: string;
tanggal: Date;
}) {
const checkStatus = await event_checkStatus({ id: eventId });
const res = await AdminEvent_funEditStatusPublishById(eventId, "1"); if (checkStatus) {
if (res.status === 200) { if (moment(tanggal).diff(Date.now(), "minutes") < 0)
const dataNotifikasi: IRealtimeData = { return ComponentGlobal_NotifikasiPeringatan(
appId: res.data?.id as any, "Waktu acara telah lewat, Report untuk memberitahu user !"
status: res.data?.EventMaster_Status?.name as any, );
userId: res.data?.authorId as any,
pesan: res.data?.title as any,
kategoriApp: "EVENT",
title: "Event publish",
};
const notif = await adminNotifikasi_funCreateToUser({ const res = await AdminEvent_funEditStatusPublishById(eventId, "1");
data: dataNotifikasi as any, if (res.status === 200) {
}); const dataNotifikasi: IRealtimeData = {
appId: res.data?.id as any,
status: res.data?.EventMaster_Status?.name as any,
userId: res.data?.authorId as any,
pesan: res.data?.title as any,
kategoriApp: "EVENT",
title: "Event publish",
};
if (notif.status === 201) { const notif = await adminNotifikasi_funCreateToUser({
WibuRealtime.setData({ data: dataNotifikasi as any,
type: "notification",
pushNotificationTo: "USER",
dataMessage: dataNotifikasi,
}); });
WibuRealtime.setData({ if (notif.status === 201) {
type: "trigger", WibuRealtime.setData({
pushNotificationTo: "USER", type: "notification",
dataMessage: dataNotifikasi, pushNotificationTo: "USER",
dataMessage: dataNotifikasi,
});
WibuRealtime.setData({
type: "trigger",
pushNotificationTo: "USER",
dataMessage: dataNotifikasi,
});
}
const loadData = await adminEvent_funGetListReview({
search: isSearch,
page: isActivePage,
}); });
setData(loadData.data as any);
setNPage(loadData.nPage);
ComponentAdminGlobal_NotifikasiBerhasil("Berhasil update status");
} else {
ComponentAdminGlobal_NotifikasiGagal(res.message);
} }
const loadData = await adminEvent_funGetListReview({
search: isSearch,
page: isActivePage,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
ComponentAdminGlobal_NotifikasiBerhasil("Berhasil update status");
} else { } else {
ComponentAdminGlobal_NotifikasiGagal(res.message); ComponentAdminGlobal_NotifikasiPeringatan(
"Review di batalkan oleh user, reload halaman review !"
);
} }
} }
@@ -218,19 +234,40 @@ export default function AdminEvent_ComponentTableReview({
<Text>{e.EventMaster_TipeAcara.name}</Text> <Text>{e.EventMaster_TipeAcara.name}</Text>
</Center> </Center>
</td> </td>
<td> <td>
<Center w={200}> <Center w={200}>
{e.tanggal.toLocaleString("id-ID", { dateStyle: "full" })} <Text align="center">
{" "}
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(e?.tanggal)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.tanggal)}
</Text>
</Text>
</Center> </Center>
</td> </td>
<td> <td>
<Center w={200}> <Center w={200}>
{e.tanggal.toLocaleTimeString([], { <Text align="center">
timeStyle: "short", {" "}
hourCycle: "h24", {new Intl.DateTimeFormat("id-ID", {
})} dateStyle: "full",
}).format(e?.tanggalSelesai)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.tanggalSelesai)}
</Text>
</Text>
</Center> </Center>
</td> </td>
<td> <td>
<Center w={400}> <Center w={400}>
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan"> <Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan">
@@ -246,7 +283,12 @@ export default function AdminEvent_ComponentTableReview({
color={"green"} color={"green"}
leftIcon={<IconCircleCheck />} leftIcon={<IconCircleCheck />}
radius={"xl"} radius={"xl"}
onClick={() => onPublish(e.id, e.tanggal)} onClick={() =>
onPublish({
eventId: e.id,
tanggal: e.tanggal,
})
}
> >
Publish Publish
</Button> </Button>
@@ -254,9 +296,17 @@ export default function AdminEvent_ComponentTableReview({
color={"red"} color={"red"}
leftIcon={<IconBan />} leftIcon={<IconBan />}
radius={"xl"} radius={"xl"}
onClick={() => { onClick={async () => {
open(); const checkStatus = await event_checkStatus({ id: e.id });
setEventId(e.id);
if (checkStatus) {
open();
setEventId(e.id);
} else {
ComponentAdminGlobal_NotifikasiPeringatan(
"Review di batalkan oleh user, muat kembali halaman ini !"
);
}
}} }}
> >
Reject Reject
@@ -334,10 +384,10 @@ export default function AdminEvent_ComponentTableReview({
<Center>Tipe Acara</Center> <Center>Tipe Acara</Center>
</th> </th>
<th> <th>
<Center>Tanggal</Center> <Center>Tanggal & Waktu Mulai</Center>
</th> </th>
<th> <th>
<Center>Jam</Center> <Center>Tanggal & Waktu Selesai</Center>
</th> </th>
<th> <th>
<Center>Deskripsi</Center> <Center>Deskripsi</Center>

View File

@@ -1,19 +1,11 @@
"use client"; "use client";
import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event"; 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 { import {
MODEL_EVENT,
MODEL_EVENT_PESERTA,
} from "@/app_modules/event/model/interface";
import {
Avatar,
Button, Button,
Center, Center,
Divider,
Grid,
Group, Group,
Modal,
Pagination, Pagination,
Paper, Paper,
ScrollArea, ScrollArea,
@@ -24,7 +16,6 @@ import {
TextInput, TextInput,
Title, Title,
} from "@mantine/core"; } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { IconCircleCheck, IconSearch } from "@tabler/icons-react"; import { IconCircleCheck, IconSearch } from "@tabler/icons-react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
@@ -80,11 +71,14 @@ function DetailRiwayat({ listRiwayat }: { listRiwayat: any }) {
<tr key={i}> <tr key={i}>
<td> <td>
<Button <Button
loaderPosition="center"
loading={e.id === eventId && loading ? true : false} loading={e.id === eventId && loading ? true : false}
color={"green"} color={"green"}
leftIcon={<IconCircleCheck />} leftIcon={<IconCircleCheck />}
radius={"xl"} radius={"xl"}
onClick={() => { onClick={() => {
setEventId(e.id);
setLoading(true);
router.push(RouterAdminEvent.detail_peserta + e.id); router.push(RouterAdminEvent.detail_peserta + e.id);
}} }}
> >
@@ -112,19 +106,40 @@ function DetailRiwayat({ listRiwayat }: { listRiwayat: any }) {
<Text>{e.EventMaster_TipeAcara.name}</Text> <Text>{e.EventMaster_TipeAcara.name}</Text>
</Center> </Center>
</td> </td>
<td> <td>
<Center w={200}> <Center w={200}>
{e.tanggal.toLocaleString("id-ID", { dateStyle: "full" })} <Text align="center">
{" "}
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(e?.tanggal)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.tanggal)}
</Text>
</Text>
</Center> </Center>
</td> </td>
<td> <td>
<Center w={200}> <Center w={200}>
{e.tanggal.toLocaleTimeString([], { <Text align="center">
timeStyle: "short", {" "}
hourCycle: "h24", {new Intl.DateTimeFormat("id-ID", {
})} dateStyle: "full",
}).format(e?.tanggalSelesai)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.tanggalSelesai)}
</Text>
</Text>
</Center> </Center>
</td> </td>
<td> <td>
<Center w={400}> <Center w={400}>
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan"> <Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan">
@@ -183,10 +198,10 @@ function DetailRiwayat({ listRiwayat }: { listRiwayat: any }) {
<Center>Tipe Acara</Center> <Center>Tipe Acara</Center>
</th> </th>
<th> <th>
<Center>Tanggal</Center> <Center>Tanggal & Waktu Mulai</Center>
</th> </th>
<th> <th>
<Center>Jam</Center> <Center>Tanggal & Waktu Selesai</Center>
</th> </th>
<th> <th>
<Center>Deskripsi</Center> <Center>Deskripsi</Center>

View File

@@ -12,9 +12,7 @@ export default async function AdminEvent_funCountByStatusId(statusId: string) {
const count = await prisma.event.count({ const count = await prisma.event.count({
where: { where: {
eventMaster_StatusId: "1", eventMaster_StatusId: "1",
tanggal: { isArsip: false
gte: new Date
}
}, },
}); });
return count; return count;

View File

@@ -6,9 +6,7 @@ export async function AdminEvent_funCountRiwayat() {
const data = await prisma.event.count({ const data = await prisma.event.count({
where: { where: {
eventMaster_StatusId: "1", eventMaster_StatusId: "1",
tanggal: { isArsip: true,
lte: new Date(),
},
}, },
}); });

View File

@@ -21,9 +21,7 @@ export async function adminEvent_funGetListAllRiwayat({
}, },
where: { where: {
eventMaster_StatusId: "1", eventMaster_StatusId: "1",
tanggal: { isArsip: true,
lte: new Date(),
},
title: { title: {
contains: search, contains: search,
mode: "insensitive", mode: "insensitive",
@@ -49,9 +47,7 @@ export async function adminEvent_funGetListAllRiwayat({
const nCount = await prisma.event.count({ const nCount = await prisma.event.count({
where: { where: {
eventMaster_StatusId: "1", eventMaster_StatusId: "1",
tanggal: { isArsip: true,
lte: new Date(),
},
title: { title: {
contains: search, contains: search,
mode: "insensitive", mode: "insensitive",

View File

@@ -1,146 +0,0 @@
"use server";
import prisma from "@/app/lib/prisma";
export async function AdminEvent_getListTableByStatusId(statudId: string) {
if (statudId === "1") {
const getPublish = await prisma.event.findMany({
orderBy: {
tanggal: "desc",
},
where: {
eventMaster_StatusId: "1",
tanggal: {
gte: new Date(),
},
},
select: {
id: true,
title: true,
lokasi: true,
tanggal: true,
deskripsi: true,
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: {
select: {
id: true,
name: true,
},
},
EventMaster_TipeAcara: {
select: {
id: true,
name: true,
},
},
Event_Peserta: true,
},
});
return getPublish;
}
if (statudId === "2") {
const getReview = await prisma.event.findMany({
orderBy: {
updatedAt: "desc",
},
where: {
eventMaster_StatusId: "2",
active: true,
},
select: {
id: true,
title: true,
lokasi: true,
tanggal: true,
deskripsi: true,
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: {
select: {
id: true,
name: true,
},
},
EventMaster_TipeAcara: {
select: {
id: true,
name: true,
},
},
},
});
return getReview;
}
if (statudId === "3") {
const getDraft = await prisma.event.findMany({
orderBy: {
updatedAt: "desc",
},
where: {
eventMaster_StatusId: "3",
},
});
return getDraft;
}
if (statudId === "4") {
const getReject = await prisma.event.findMany({
orderBy: {
updatedAt: "desc",
},
where: {
eventMaster_StatusId: "4",
},
select: {
id: true,
title: true,
lokasi: true,
tanggal: true,
deskripsi: true,
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
name: true,
},
},
},
},
EventMaster_Status: {
select: {
id: true,
name: true,
},
},
EventMaster_TipeAcara: {
select: {
id: true,
name: true,
},
},
catatan: true,
},
});
return getReject;
}
}

View File

@@ -1,7 +1,9 @@
"use server"; "use server";
import prisma from "@/app/lib/prisma"; import prisma from "@/app/lib/prisma";
import { ComponentAdminGlobal_NotifikasiPeringatan } from "@/app_modules/admin/_admin_global/admin_notifikasi/notifikasi_peringatan";
import { ceil } from "lodash"; import { ceil } from "lodash";
import moment from "moment";
export async function adminEvent_funGetListPublish({ export async function adminEvent_funGetListPublish({
page, page,
@@ -10,6 +12,27 @@ export async function adminEvent_funGetListPublish({
page: number; page: number;
search?: string; search?: string;
}) { }) {
const getAllData = await prisma.event.findMany({
where: {
active: true,
eventMaster_StatusId: "1",
isArsip: false,
},
});
for (let i of getAllData) {
if (moment(i.tanggalSelesai).diff(moment(), "minutes") < 0) {
await prisma.event.update({
where: {
id: i.id,
},
data: {
isArsip: true,
},
});
}
}
let takeData = 10; let takeData = 10;
let skipData = page * takeData - takeData; let skipData = page * takeData - takeData;
@@ -21,9 +44,7 @@ export async function adminEvent_funGetListPublish({
}, },
where: { where: {
eventMaster_StatusId: "1", eventMaster_StatusId: "1",
tanggal: { isArsip: false,
gte: new Date(),
},
title: { title: {
contains: search, contains: search,
mode: "insensitive", mode: "insensitive",
@@ -49,9 +70,7 @@ export async function adminEvent_funGetListPublish({
const nCount = await prisma.event.count({ const nCount = await prisma.event.count({
where: { where: {
eventMaster_StatusId: "1", eventMaster_StatusId: "1",
tanggal: { isArsip: false,
gte: new Date(),
},
title: { title: {
contains: search, contains: search,
mode: "insensitive", mode: "insensitive",

View File

@@ -1,14 +1,12 @@
"use client"; "use client";
import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event";
import { MODEL_EVENT } from "@/app_modules/event/model/interface";
import { import {
Avatar,
Box, Box,
Button, Button,
Center, Center,
Divider,
Grid,
Group, Group,
Modal,
Pagination, Pagination,
Paper, Paper,
ScrollArea, ScrollArea,
@@ -19,20 +17,14 @@ import {
TextInput, TextInput,
Title, Title,
} from "@mantine/core"; } from "@mantine/core";
import { IconCircleCheck, IconEyeShare, IconSearch } from "@tabler/icons-react"; import { IconCircleCheck, IconSearch } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useDisclosure } from "@mantine/hooks";
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import {
MODEL_EVENT,
MODEL_EVENT_PESERTA,
} from "@/app_modules/event/model/interface";
import _ from "lodash"; import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate"; import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate";
import { adminEvent_getListPesertaById } from "../fun/get/get_list_peserta_by_id";
import { adminEvent_funGetListPublish } from "../fun"; import { adminEvent_funGetListPublish } from "../fun";
import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event"; import QRCode from "react-qr-code";
import { useShallowEffect } from "@mantine/hooks";
export default function AdminEvent_TablePublish({ export default function AdminEvent_TablePublish({
listPublish, listPublish,
@@ -58,6 +50,21 @@ function TableStatus({ listPublish }: { listPublish: any }) {
const [eventId, setEventId] = useState(""); const [eventId, setEventId] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [origin, setOrigin] = useState("");
useShallowEffect(() => {
if (typeof window !== "undefined") {
console.log(window.location.origin);
setOrigin(window.location.origin);
}
}, [setOrigin]);
// async function onLoadOrigin(setOrigin: any) {
// const res = await fetch("/api/origin-url");
// const result = await res.json();
// setOrigin(result.origin);
// }
async function onSearch(s: string) { async function onSearch(s: string) {
setSearch(s); setSearch(s);
const loadData = await adminEvent_funGetListPublish({ const loadData = await adminEvent_funGetListPublish({
@@ -78,64 +85,137 @@ function TableStatus({ listPublish }: { listPublish: any }) {
setNPage(loadData.nPage); setNPage(loadData.nPage);
} }
const TableRows = data.map((e, i) => ( const TableRows = _.isEmpty(data) ? (
<tr key={i}> <tr>
<td> <td colSpan={12}>
<Center w={200}> <Center>Belum Ada Data</Center>
<Text>{e?.Author?.username}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text lineClamp={2}>{e.title}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.lokasi}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.EventMaster_TipeAcara.name}</Text>
</Center>
</td>
<td>
<Center w={200}>
{e.tanggal.toLocaleString("id-ID", { dateStyle: "full" })}
</Center>
</td>
<td>
<Center w={200}>
{e.tanggal.toLocaleTimeString([], {
timeStyle: "short",
hourCycle: "h24",
})}
</Center>
</td>
<td>
<Center w={400}>
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan">
{e.deskripsi}
</Spoiler>
</Center>
</td>
<td>
<Button
loading={e.id === eventId ? (loading === true ? true : false) : false}
color={"green"}
leftIcon={<IconCircleCheck />}
radius={"xl"}
onClick={async () => {
router.push(RouterAdminEvent.detail_peserta + e.id);
}}
>
Lihat Peserta
</Button>
</td> </td>
</tr> </tr>
)); ) : (
data.map((e, i) => (
<tr key={i}>
<td>
<Center w={200}>
<QRCode
id={e.id}
style={{ height: 70, width: 70 }}
value={`${origin}/dev/event/konfirmasi/${e.id}`}
/>
</Center>
</td>
<td>
<Center w={200}>
<input
type="button"
value="Download QR"
onClick={() => {
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)}`;
}}
/>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e?.Author?.username}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text lineClamp={2}>{e.title}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.lokasi}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text>{e.EventMaster_TipeAcara.name}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text align="center">
{" "}
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(e?.tanggal)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.tanggal)}
</Text>
</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text align="center">
{" "}
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(e?.tanggalSelesai)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.tanggalSelesai)}
</Text>
</Text>
</Center>
</td>
<td>
<Center w={400}>
<Spoiler
hideLabel="sembunyikan"
maxHeight={50}
showLabel="tampilkan"
>
{e.deskripsi}
</Spoiler>
</Center>
</td>
<td>
<Button
loaderPosition="center"
loading={
e.id === eventId ? (loading === true ? true : false) : false
}
color={"green"}
leftIcon={<IconCircleCheck />}
radius={"xl"}
onClick={async () => {
setEventId(e.id);
setLoading(true);
router.push(RouterAdminEvent.detail_peserta + e.id);
}}
>
Lihat Peserta
</Button>
</td>
</tr>
))
);
return ( return (
<> <>
@@ -169,6 +249,13 @@ function TableStatus({ listPublish }: { listPublish: any }) {
> >
<thead> <thead>
<tr> <tr>
<th>
<Center>QR Code</Center>
</th>
<th>
<Center>Download QR</Center>
</th>
<th> <th>
<Center>Username</Center> <Center>Username</Center>
</th> </th>
@@ -182,11 +269,12 @@ function TableStatus({ listPublish }: { listPublish: any }) {
<Center>Tipe Acara</Center> <Center>Tipe Acara</Center>
</th> </th>
<th> <th>
<Center>Tanggal</Center> <Center>Tanggal & Waktu Mulai</Center>
</th> </th>
<th> <th>
<Center>Jam</Center> <Center>Tanggal & Waktu Selesai</Center>
</th> </th>
<th> <th>
<Center>Deskripsi</Center> <Center>Deskripsi</Center>
</th> </th>

View File

@@ -11,6 +11,7 @@ import {
Spoiler, Spoiler,
Stack, Stack,
Table, Table,
Text,
Textarea, Textarea,
TextInput, TextInput,
Title, Title,
@@ -106,19 +107,40 @@ function TableStatus({ listReject }: { listReject: any }) {
<td> <td>
<Center w={200}>{e.EventMaster_TipeAcara.name}</Center> <Center w={200}>{e.EventMaster_TipeAcara.name}</Center>
</td> </td>
<td> <td>
<Center w={200}> <Center w={200}>
{e.tanggal.toLocaleString("id-ID", { dateStyle: "full" })} <Text align="center">
{" "}
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(e?.tanggal)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.tanggal)}
</Text>
</Text>
</Center> </Center>
</td> </td>
<td> <td>
<Center w={100}> <Center w={200}>
{e.tanggal.toLocaleTimeString([], { <Text align="center">
timeStyle: "short", {" "}
hourCycle: "h24", {new Intl.DateTimeFormat("id-ID", {
})} dateStyle: "full",
}).format(e?.tanggalSelesai)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.tanggalSelesai)}
</Text>
</Text>
</Center> </Center>
</td> </td>
<td> <td>
<Center w={500}> <Center w={500}>
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan"> <Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan">
@@ -197,10 +219,10 @@ function TableStatus({ listReject }: { listReject: any }) {
<Center>Tipe Acara</Center> <Center>Tipe Acara</Center>
</th> </th>
<th> <th>
<Center>Tanggal</Center> <Center>Tanggal & Waktu Mulai</Center>
</th> </th>
<th> <th>
<Center>Jam</Center> <Center>Tanggal & Waktu Selesai</Center>
</th> </th>
<th> <th>
<Center>Cacatan</Center> <Center>Cacatan</Center>

View File

@@ -4,6 +4,7 @@ import { gs_admin_ntf } from "@/app/lib/global_state";
import { import {
ActionIcon, ActionIcon,
AppShell, AppShell,
Button,
Divider, Divider,
Drawer, Drawer,
Grid, Grid,
@@ -18,8 +19,10 @@ import {
import { useMediaQuery, useShallowEffect } from "@mantine/hooks"; import { useMediaQuery, useShallowEffect } from "@mantine/hooks";
import { IconBell } from "@tabler/icons-react"; import { IconBell } from "@tabler/icons-react";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
import { AccentColor } from "../_global/color"; import { AccentColor } from "../_global/color";
import { ComponentGlobal_NotifikasiBerhasil } from "../_global/notif_global";
import { MODEL_USER } from "../home/model/interface"; import { MODEL_USER } from "../home/model/interface";
import { MODEL_NOTIFIKASI } from "../notifikasi/model/interface"; import { MODEL_NOTIFIKASI } from "../notifikasi/model/interface";
import { import {
@@ -47,6 +50,7 @@ export function Admin_NewLayout({
listNotifikasi: MODEL_NOTIFIKASI[]; listNotifikasi: MODEL_NOTIFIKASI[];
version: string; version: string;
}) { }) {
const router = useRouter();
const matches = useMediaQuery("(min-width: 1024px)"); const matches = useMediaQuery("(min-width: 1024px)");
const [dataUser, setDataUser] = useState(user); const [dataUser, setDataUser] = useState(user);
const userRoleId = dataUser.masterUserRoleId; const userRoleId = dataUser.masterUserRoleId;
@@ -72,6 +76,20 @@ export function Admin_NewLayout({
setDrawerNotifikasi(true); 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 ( return (
<> <>
<AppShell <AppShell
@@ -168,6 +186,7 @@ export function Admin_NewLayout({
<Title order={4} align="center"> <Title order={4} align="center">
View Only Available For Desktop View Only Available For Desktop
</Title> </Title>
<Button onClick={() => onClickLogout()}>Logout</Button>
</Stack> </Stack>
) : ( ) : (
children children

View File

@@ -2,12 +2,15 @@
import prisma from "@/app/lib/prisma"; import prisma from "@/app/lib/prisma";
export async function auth_funDeleteAktivasiKodeOtpById({ export async function auth_funDeleteAktivasiKodeOtpByNomor({
nomor, nomor,
}: { }: {
nomor: string; nomor: string;
}) { }) {
// console.log(otpId); // console.log(otpId);
const updt = await prisma.kodeOtp.deleteMany({ const updt = await prisma.kodeOtp.deleteMany({
where: { where: {
nomor: nomor, nomor: nomor,

View File

@@ -2,12 +2,12 @@ import SplashScreen from "./splash/view";
import Login from "./login/view"; import Login from "./login/view";
import Validasi from "./validasi/view"; import Validasi from "./validasi/view";
import Register from "./register/view"; import Register from "./register/view";
import Component_Logout from "./logout/view"; import Component_ButtonLogout from "./logout/view";
export { export {
SplashScreen, SplashScreen,
Login, Login,
Validasi, Validasi,
Register, Register,
Component_Logout as Logout, Component_ButtonLogout as Logout,
}; };

View File

@@ -1,6 +1,5 @@
"use client"; "use client";
import { RouterAuth } from "@/app/lib/router_hipmi/router_auth";
import { import {
AccentColor, AccentColor,
MainColor, MainColor,
@@ -8,10 +7,10 @@ import {
import ComponentGlobal_ErrorInput from "@/app_modules/_global/component/error_input"; import ComponentGlobal_ErrorInput from "@/app_modules/_global/component/error_input";
import { import {
ComponentGlobal_NotifikasiBerhasil, ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan, ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global"; } from "@/app_modules/_global/notif_global";
import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui"; 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 { Box, Button, Center, Stack, Text, Title } from "@mantine/core";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
@@ -28,23 +27,28 @@ export default function Login({ version }: { version: string }) {
const nomor = phone.substring(1); const nomor = phone.substring(1);
if (nomor.length <= 4) return setError(true); if (nomor.length <= 4) return setError(true);
const res = await auth_funLogin({ nomor: nomor }); setLoading(true);
if (res.status === 200) { try {
setLoading(true); const res = await fetch("/api/auth/login", {
ComponentGlobal_NotifikasiBerhasil(res.message, 2000); method: "POST",
// router.push(RouterAuth.validasi + res.kodeId, { scroll: false }); body: JSON.stringify({ nomor: nomor }),
router.push("/validasi/" + res.kodeId, { scroll: false }); headers: {
} else { "Content-Type": "application/json",
ComponentGlobal_NotifikasiPeringatan(res.message); },
} });
// await fetch(ApiHipmi.login, { const result = await res.json();
// method: "POST", if (res.status === 200) {
// headers: { localStorage.setItem("hipmi_auth_code_id", result.kodeId);
// "Content-Type": "application/json", ComponentGlobal_NotifikasiBerhasil(result.message, 2000);
// }, router.push("/validasi", { scroll: false });
// body: JSON.stringify(body), } else {
// }) ComponentGlobal_NotifikasiPeringatan(result.message);
}
} catch (error) {
console.error(error);
ComponentGlobal_NotifikasiGagal("Terjadi Kesalahan");
}
} }
return ( return (
@@ -96,16 +100,11 @@ export default function Login({ version }: { version: string }) {
<Box pos={"fixed"} bottom={10}> <Box pos={"fixed"} bottom={10}>
<Text fw={"bold"} c={"white"} fs={"italic"} fz={"xs"}> <Text fw={"bold"} c={"white"} fs={"italic"} fz={"xs"}>
V.{version} v {version}
</Text> </Text>
</Box> </Box>
</Stack> </Stack>
</UIGlobal_LayoutDefault> </UIGlobal_LayoutDefault>
{/* <BackgroundImage
src={"/aset/global/main_background.png"}
h={"100vh"}
// pos={"static"}
></BackgroundImage> */}
</> </>
); );
} }

View File

@@ -11,18 +11,21 @@ import { useState } from "react";
import { auth_Logout } from "../fun/fun_logout"; import { auth_Logout } from "../fun/fun_logout";
import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; 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 router = useRouter();
const [opened, setOpened] = useState(false); const [opened, setOpened] = useState(false);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
async function onClickLogout() { 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) { if (res.status === 200) {
ComponentGlobal_NotifikasiBerhasil(res.message); ComponentGlobal_NotifikasiBerhasil(result.message);
router.push("/login", { scroll: false }); router.push("/", { scroll: false });
} else {
ComponentGlobal_NotifikasiPeringatan(res.message);
} }
} }
@@ -49,7 +52,6 @@ export default function Component_Logout() {
bg={Warna.merah} bg={Warna.merah}
color="red" color="red"
onClick={() => { onClick={() => {
setLoading(true);
onClickLogout(); onClickLogout();
}} }}
> >

View File

@@ -0,0 +1,19 @@
import { Stack, Skeleton } from "@mantine/core";
export default function Register_SkeletonView() {
return (
<>
<Stack h={"100vh"} align="center" justify="center" spacing={50}>
<Skeleton h={30} w={250} radius={"xl"} />
<Skeleton h={100} w={100} radius={"50%"} />
<Stack spacing={"sm"}>
<Skeleton h={20} w={300} radius={"xl"} />
<Skeleton h={50} w={300} radius={"sm"} />
<Skeleton h={50} w={300} radius={"sm"} />
</Stack>
</Stack>
</>
);
}

View File

@@ -1,76 +1,95 @@
"use client"; "use client";
import { RouterHome } from "@/app/lib/router_hipmi/router_home"; import { MainColor } from "@/app_modules/_global/color/color_pallet";
import { GlobalEnv } from "@/app/lib/token";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_ErrorInput from "@/app_modules/_global/component/error_input"; import ComponentGlobal_ErrorInput from "@/app_modules/_global/component/error_input";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui"; import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui";
import { import { Button, Stack, Text, TextInput, Title } from "@mantine/core";
Button, import { useFocusTrap, useShallowEffect } from "@mantine/hooks";
Center,
Stack,
Text,
TextInput,
Title
} from "@mantine/core";
import { useFocusTrap } from "@mantine/hooks";
import { IconUserCircle } from "@tabler/icons-react"; import { IconUserCircle } from "@tabler/icons-react";
import _ from "lodash"; import _ from "lodash";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
import { auth_funDeleteAktivasiKodeOtpById } from "../fun/fun_edit_aktivasi_kode_otp_by_id"; import { auth_funDeleteAktivasiKodeOtpByNomor } from "../fun/fun_edit_aktivasi_kode_otp_by_id";
import { Auth_funRegister } from "../fun/fun_register"; import Register_SkeletonView from "./skeleton";
export default function Register({ dataOtp }: { dataOtp: any }) { export default function Register() {
const router = useRouter(); const router = useRouter();
const [nomor, setNomor] = useState(dataOtp.nomor); const [nomor, setNomor] = useState("");
const [value, setValue] = useState(""); const [value, setValue] = useState("");
const [isValue, setIsValue] = useState(false); const [isValue, setIsValue] = useState(false);
const focusTrapRef = useFocusTrap(); const focusTrapRef = useFocusTrap();
const [loading, setLoading] = useState(false); 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() { async function onRegistarsi() {
const body = { const data = {
username: value, username: value,
nomor: nomor, nomor: nomor,
}; };
if (body.username === "") { try {
setIsValue(true); setLoading(true);
return null; const res = await fetch("/api/auth/register", {
} method: "POST",
if (body.username.length < 5) return null; body: JSON.stringify({
if (_.values(body.username).includes(" ")) return null; data,
}),
const res = await Auth_funRegister({ headers: {
data: body, "Content-Type": "application/json",
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);
}
}); });
} 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 ( return (
<> <>
<UIGlobal_LayoutDefault> <UIGlobal_LayoutDefault>
<Center h={"100vh"}> {nomor == "" ? (
<Stack h={"100%"} align="center" justify="center" spacing={70}> <Register_SkeletonView />
) : (
<Stack h={"100vh"} align="center" justify="center" spacing={50}>
<Title order={2} c={MainColor.yellow}> <Title order={2} c={MainColor.yellow}>
REGISTRASI REGISTRASI
</Title> </Title>
@@ -78,7 +97,7 @@ export default function Register({ dataOtp }: { dataOtp: any }) {
<IconUserCircle size={100} color="white" /> <IconUserCircle size={100} color="white" />
<Stack spacing={"sm"} w={300}> <Stack spacing={"sm"} w={300}>
<Text fz={10} c={"white"}> <Text align="center" c={"white"}>
Anda akan terdaftar dengan nomor berikut{" "} Anda akan terdaftar dengan nomor berikut{" "}
<Text inherit span fw={"bold"}> <Text inherit span fw={"bold"}>
+{nomor} +{nomor}
@@ -109,6 +128,11 @@ export default function Register({ dataOtp }: { dataOtp: any }) {
/> />
<Stack> <Stack>
<Button <Button
disabled={
value === "" ||
value.length < 5 ||
_.values(value).includes(" ")
}
loading={loading ? true : false} loading={loading ? true : false}
loaderPosition="center" loaderPosition="center"
radius={"md"} radius={"md"}
@@ -117,9 +141,6 @@ export default function Register({ dataOtp }: { dataOtp: any }) {
c={"black"} c={"black"}
bg={MainColor.yellow} bg={MainColor.yellow}
color={"yellow"} color={"yellow"}
style={{
borderColor: AccentColor.yellow,
}}
onClick={() => { onClick={() => {
onRegistarsi(); onRegistarsi();
}} }}
@@ -129,7 +150,7 @@ export default function Register({ dataOtp }: { dataOtp: any }) {
</Stack> </Stack>
</Stack> </Stack>
</Stack> </Stack>
</Center> )}
</UIGlobal_LayoutDefault> </UIGlobal_LayoutDefault>
</> </>
); );

View File

@@ -1,63 +1,22 @@
"use client"; "use client";
import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui";
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 { Avatar, BackgroundImage, Center, Image, Stack } from "@mantine/core"; import { Avatar, BackgroundImage, Center, Image, Stack } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks"; import { useShallowEffect } from "@mantine/hooks";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
export default function SplashScreen({ export default function SplashScreen() {
checkCookies,
}: {
checkCookies: boolean;
}) {
const router = useRouter(); const router = useRouter();
useShallowEffect(() => { // useShallowEffect(() => {
// if (!checkCookies) return router.push(RouterAuth.login, { scroll: false }); // setTimeout(() => {
// onCheckUser(); // router.push("/dev/home", { scroll: false });
// }, 1000);
// 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);
// }
return ( return (
<> <>
<BackgroundImage <UIGlobal_LayoutDefault>
src={"/aset/global/main_background.png"}
h={"100vh"}
// pos={"static"}
>
<Center h={"100vh"}> <Center h={"100vh"}>
<Stack align="center" justify="center" p={"md"}> <Stack align="center" justify="center" p={"md"}>
{/* <Title c={"#002e59"}>Welcome to</Title> */} {/* <Title c={"#002e59"}>Welcome to</Title> */}
@@ -71,7 +30,7 @@ export default function SplashScreen({
</Avatar> </Avatar>
</Stack> </Stack>
</Center> </Center>
</BackgroundImage> </UIGlobal_LayoutDefault>
</> </>
); );
} }

View File

@@ -0,0 +1,25 @@
import { Stack, Skeleton, Group } from "@mantine/core";
export default function Validasi_SkeletonView() {
return (
<>
<Stack align="center" justify="center" h={"100vh"} spacing={50}>
<Skeleton h={30} w={250} radius={"xl"} />
<Stack>
<Skeleton h={20} w={250} radius={"xl"} />
<Skeleton h={20} w={250} radius={"xl"} />
</Stack>
<Group>
{Array.from({ length: 4 }).map((_, i) => (
<Skeleton key={i} h={50} w={50} radius={"sm"} />
))}
</Group>
<Skeleton h={20} w={250} radius={"xl"} />
<Skeleton h={50} w={250} radius={"sm"} />
</Stack>
</>
);
}

View File

@@ -1,9 +1,7 @@
"use client"; "use client";
import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; 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 { RouterHome } from "@/app/lib/router_hipmi/router_home";
import { GlobalEnv } from "@/app/lib/token";
import { import {
AccentColor, AccentColor,
MainColor, 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 { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui"; import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui";
import { import {
ActionIcon,
Box,
Button, Button,
Center, Center,
Loader,
PinInput, PinInput,
Stack, Stack,
Text, Text,
Title, Title,
} from "@mantine/core"; } from "@mantine/core";
import { useFocusTrap, useShallowEffect } from "@mantine/hooks"; import { useFocusTrap, useShallowEffect } from "@mantine/hooks";
import { Prisma } from "@prisma/client";
import { IconChevronLeft } from "@tabler/icons-react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useState } from "react"; import { useEffect, 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";
export default function Validasi({ import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global";
dataOtp, import { auth_funDeleteAktivasiKodeOtpByNomor } from "../fun/fun_edit_aktivasi_kode_otp_by_id";
}: { import Validasi_SkeletonView from "./skeleton";
dataOtp: Prisma.KodeOtpSelect;
}) { export default function Validasi() {
const router = useRouter(); const router = useRouter();
const nomor = dataOtp.nomor as any;
const code = dataOtp.otp as any;
const [inputCode, setInputOtp] = useState(""); const [inputCode, setInputOtp] = useState("");
const focusTrapRef = useFocusTrap(); const focusTrapRef = useFocusTrap();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [counter, setCounter] = useState(60); const [counter, setCounter] = useState(60);
const [loadingResend, setLoadingResend] = useState(false);
const [triggerOtp, setTriggerOtp] = useState(false);
const [data, setData] = useState({
nomor: "",
code: "",
});
useShallowEffect(() => { 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 > 0 && setTimeout(() => setCounter(counter - 1), 1000);
}, [counter]); }, [counter]);
async function onVerifikasi() { async function onVerifikasi() {
if (!inputCode) if (!inputCode)
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Kode"); return ComponentGlobal_NotifikasiPeringatan("Lengkapi Kode");
if (code != inputCode) if (data.code != inputCode)
return ComponentGlobal_NotifikasiPeringatan("Kode Salah"); return ComponentGlobal_NotifikasiPeringatan("Kode Salah");
const res = await auth_funValidasi({ try {
nomor: nomor, setLoading(true);
HIPMI_PWD: GlobalEnv.value?.WIBU_PWD as string, const res = await fetch("/api/auth/validasi", {
}); method: "POST",
if (res.status === 200) { body: JSON.stringify({
const resAktivasi = await auth_funDeleteAktivasiKodeOtpById( nomor: data.nomor,
dataOtp.id as any }),
); headers: {
if (resAktivasi.status === 200) { "Content-Type": "application/json",
if (res.role === "1") { },
ComponentGlobal_NotifikasiBerhasil(res.message); });
setLoading(true);
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 }); router.push(RouterHome.main_home, { scroll: false });
// if (result.active === true) {
// } else {
// ComponentGlobal_NotifikasiBerhasil(result.message);
// router.push("/waiting-room", { scroll: false });
// }
} else { } else {
ComponentGlobal_NotifikasiBerhasil("Admin Logged in"); ComponentGlobal_NotifikasiBerhasil("Admin Logged in");
setLoading(true);
router.push(RouterAdminDashboard.splash_admin, { scroll: false }); router.push(RouterAdminDashboard.splash_admin, { scroll: false });
} }
} else {
ComponentGlobal_NotifikasiPeringatan(resAktivasi.message);
}
}
if (res.status === 400) { await auth_funDeleteAktivasiKodeOtpByNomor({
ComponentGlobal_NotifikasiBerhasil(res.message); nomor: data.nomor,
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 });
} }
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() { async function onBack() {
await auth_funDeleteAktivasiKodeOtpById({ nomor: nomor }); localStorage.removeItem("hipmi_auth_code_id");
await auth_funDeleteAktivasiKodeOtpByNomor({ nomor: data.nomor });
router.back(); router.back();
} }
async function onResendCode() { async function onResendCode() {
const res = await auth_funResendCode({ nomor: nomor }); setLoadingResend(true);
if (res.status === 200) { localStorage.removeItem("hipmi_auth_code_id");
ComponentGlobal_NotifikasiBerhasil(res.message, 2000);
router.push("/validasi/" + res.kodeId, { scroll: false }); try {
} else { const res = await fetch("/api/auth/resend", {
ComponentGlobal_NotifikasiPeringatan(res.message); 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 ( return (
<> <>
<UIGlobal_LayoutDefault> <UIGlobal_LayoutDefault>
<Stack h={"100vh"}> <Stack h={"100vh"}>
<Box {/* <Box
pt={"md"} pt={"md"}
px={"md"} px={"md"}
style={{ style={{
@@ -123,70 +189,84 @@ export default function Validasi({
<ActionIcon variant="transparent" onClick={() => onBack()}> <ActionIcon variant="transparent" onClick={() => onBack()}>
<IconChevronLeft color="white" /> <IconChevronLeft color="white" />
</ActionIcon> </ActionIcon>
</Box> </Box> */}
{data.nomor == "" && data.code == "" ? (
<Validasi_SkeletonView />
) : (
<Stack align="center" justify="center" h={"100vh"} spacing={50}>
<Title order={2} color={MainColor.yellow}>
Verifikasi Kode OTP
</Title>
<Stack align="center" justify="center" h={"100vh"} spacing={50}> <Stack spacing={"md"} align="center">
<Title order={2} color={MainColor.yellow}> <Stack spacing={0} align="center">
Verifikasi Kode OTP <Text c={"white"}>Masukan 4 digit kode otp</Text>
</Title> <Text c={"white"}>
Yang dikirim ke{" "}
<Stack spacing={"md"} align="center"> <Text span inherit fw={"bold"}>
<Stack spacing={0} align="center"> {" "}
<Text c={"white"}>Masukan 4 digit kode otp</Text> +{data.nomor}
<Text c={"white"}> </Text>
Yang dikirim ke{" "}
<Text span inherit fw={"bold"}>
{" "}
+{nomor}
</Text> </Text>
</Text> </Stack>
<Center>
<PinInput
size="xl"
type={"number"}
ref={focusTrapRef}
spacing={"md"}
mt={"md"}
onChange={(val) => {
setInputOtp(val);
}}
/>
</Center>
<Stack h={"5vh"} align="center" justify="center">
<Text fs="italic" c={"white"}>
Tidak menerima kode ?{" "}
{counter > 0 ? (
<Text fw={"bold"} inherit span>
{counter + "s"}
</Text>
) : loadingResend ? (
<Loader ml={"sm"} size={"xs"} color="yellow" />
) : (
<Text
inherit
span
onClick={() => {
onResendCode();
}}
fw={"bold"}
>
Kirim ulang
</Text>
)}
</Text>
</Stack>
</Stack> </Stack>
<Center> <Button
<PinInput w={300}
size="xl" loading={loading ? true : false}
type={"number"} loaderPosition="center"
ref={focusTrapRef} radius={"md"}
spacing={"md"} compact
mt={"md"} h={40}
onChange={(val) => { c={"black"}
setInputOtp(val); bg={MainColor.yellow}
}} color={"yellow"}
/> style={{
</Center> borderColor: AccentColor.yellow,
}}
<Text fs="italic" mt={"sm"} c={"white"}> onClick={() => {
Tidak menerima kode ?{" "} onVerifikasi();
{counter > 0 ? ( }}
<Text fw={"bold"} inherit span> >
{counter + "s"} <Text>VERIFIKASI</Text>
</Text> </Button>
) : (
<Text inherit span onClick={() => onResendCode()}>
Kirim ulang
</Text>
)}
</Text>
</Stack> </Stack>
<Button )}
w={300}
loading={loading ? true : false}
loaderPosition="center"
radius={"md"}
compact
h={40}
c={"black"}
bg={MainColor.yellow}
color={"yellow"}
style={{
borderColor: AccentColor.yellow,
}}
onClick={() => {
onVerifikasi();
}}
>
<Text>VERIFIKASI</Text>
</Button>
</Stack>
</Stack> </Stack>
</UIGlobal_LayoutDefault> </UIGlobal_LayoutDefault>
</> </>

View File

@@ -2,7 +2,7 @@
import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; import { RouterAuth } from "@/app/lib/router_hipmi/router_auth";
import { useShallowEffect } from "@mantine/hooks"; import { useShallowEffect } from "@mantine/hooks";
import { useRouter } from "next/navigation"; import { redirect, useRouter } from "next/navigation";
import { MODEL_USER } from "../home/model/interface"; import { MODEL_USER } from "../home/model/interface";
import { RouterHome } from "@/app/lib/router_hipmi/router_home"; import { RouterHome } from "@/app/lib/router_hipmi/router_home";
import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin";
@@ -16,6 +16,12 @@ export function CheckCookies_UiLayout({
}) { }) {
const router = useRouter(); const router = useRouter();
// if (dataUser.active == false){
// router.push(RouterHome.home_user_non_active, { scroll: false });
// return children
// }
// useShallowEffect(() => { // useShallowEffect(() => {
// onCheckCookies(); // onCheckCookies();
// }, []); // }, []);
@@ -38,5 +44,5 @@ export function CheckCookies_UiLayout({
// router.push(RouterAdminDashboard.splash_admin, { scroll: false }); // router.push(RouterAdminDashboard.splash_admin, { scroll: false });
// } // }
return children; return <>{children}</>;
} }

View File

@@ -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<MODEL_EVENT | null>(null);
const [isJoin, setIsJoin] = useState<boolean | null>(null);
const [isPresent, setIsPresent] = useState<boolean | null>(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 <SkeletonIsDataNull />;
}
if (data == null) {
return (
<>
<DataNotFound />
</>
);
}
if (moment(data?.tanggal).diff(moment(), "minute") < 0) {
return (
<>
<EventAlreadyDone title={data?.title} eventId={eventId} />
</>
);
}
if (isJoin == false) {
return (
<>
<UserNotJoin
title={data?.title}
eventId={eventId}
userLoginId={userLoginId}
/>
</>
);
}
if (isPresent && data) {
return <UserAlreadyConfirm title={data.title} />;
}
if (isPresent == false && data) {
return (
<UserNotConfirm
title={data.title}
eventId={eventId}
userLoginId={userLoginId}
/>
);
}
// const tgl = moment(data?.tanggal).diff(moment(), "minute") < 0;
// return (
// <>
// <UIGlobal_LayoutDefault>
// <Stack h={"100vh"} justify="center" c={"white"}>
// {JSON.stringify(tgl)}
// </Stack>
// </UIGlobal_LayoutDefault>
// </>
// );
}
function DataNotFound() {
const router = useRouter();
const [isLoading, setLoading] = useState(false);
const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu);
return (
<>
<UIGlobal_LayoutDefault>
<Stack h={"100vh"} justify="center">
<ComponentGlobal_CardStyles>
<Stack>
<Text fw={"bold"} align="center">
Data Event Tidak Ditemukan
</Text>
<Button
loading={isLoading}
loaderPosition="center"
radius={"xl"}
color="green"
c={"black"}
onClick={() => {
setHotMenu(0);
setLoading(true);
router.push(RouterEvent.beranda, { scroll: false });
}}
>
Kembali Ke Beranda
</Button>
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</UIGlobal_LayoutDefault>
</>
);
}
function SkeletonIsDataNull() {
return (
<>
<UIGlobal_LayoutDefault>
<Stack h={"100vh"} justify="center">
<ComponentGlobal_CardStyles>
<Stack>
<Skeleton height={20} width={"100%"} radius={"xl"} />{" "}
<Skeleton height={20} width={"100%"} radius={"xl"} />{" "}
<Skeleton height={20} width={"100%"} radius={"xl"} />
<Center>
<Skeleton height={40} width={"40%"} radius={"sm"} />
</Center>
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</UIGlobal_LayoutDefault>
</>
);
}
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 (
<>
<UIGlobal_LayoutDefault>
<Stack h={"100vh"} justify="center">
<ComponentGlobal_CardStyles>
<Stack align="center" justify="center">
<Text align="center">
Halo, Bapak/Ibu. Kami mencatat bahwa Anda belum melakukan
registrasi melalui aplikasi untuk mengikuti acara{" "}
<Text inherit span fw={"bold"}>
{title}.
</Text>{" "}
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.
</Text>
<Button
loading={isLoading}
loaderPosition="center"
radius={"xs"}
bg={MainColor.yellow}
color="yellow"
c={"black"}
onClick={() => {
onJoinAndKonfirmasi();
}}
>
Join & Konfirmasi
</Button>
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</UIGlobal_LayoutDefault>
</>
);
}
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 (
<>
<UIGlobal_LayoutDefault>
<Stack h={"100vh"} justify="center">
<ComponentGlobal_CardStyles>
<Stack align="center" justify="center">
<Text align="center">
Kami mohon maaf, Bapak/Ibu, acara{" "}
<Text inherit span fw={"bold"}>
{title}
</Text>{" "}
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.
</Text>
</Stack>
<Group grow mt={"lg"}>
<Button
loading={isLoading}
loaderPosition="center"
radius={"xl"}
color="green"
c={"black"}
onClick={() => {
setHotMenu(0);
setLoading(true);
router.push(RouterEvent.beranda, { scroll: false });
}}
>
Beranda
</Button>
<Button
loading={isLoadingDetail}
loaderPosition="center"
radius={"xl"}
c={"black"}
onClick={() => {
setHotMenu(3);
setLoadingDetail(true);
router.push(RouterEvent.detail_riwayat + eventId, {
scroll: false,
});
}}
>
Riwayat Event
</Button>
</Group>
</ComponentGlobal_CardStyles>
</Stack>
</UIGlobal_LayoutDefault>
</>
);
}
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 (
<>
<UIGlobal_LayoutDefault>
<Stack h={"100vh"} justify="center">
<ComponentGlobal_CardStyles>
<Stack align="center" justify="center">
<Text align="center">
Terima kasih atas kehadiran Anda di acara{" "}
<Text inherit span fw={"bold"}>
{title}
</Text>{" "}
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.
</Text>
<Button
loading={isLoading}
loaderPosition="center"
radius={"xs"}
bg={MainColor.yellow}
color="yellow"
c={"black"}
onClick={() => {
onUpdateKonfirmasi();
}}
>
HADIR
</Button>
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</UIGlobal_LayoutDefault>
</>
);
}
function UserAlreadyConfirm({ title }: { title: string }) {
const router = useRouter();
const [isLoading, setLoading] = useState(false);
const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu);
return (
<>
<UIGlobal_LayoutDefault>
<Stack h={"100vh"} justify="center">
<ComponentGlobal_CardStyles>
<Stack align="center" justify="center">
<Text align="center">
Terima kasih, Bapak/Ibu, kehadiran Anda di acara{" "}
<Text inherit span fw={"bold"}>
{title}
</Text>{" "}
telah berhasil dikonfirmasi. Kami senang menyambut Anda dan
semoga acara ini memberikan manfaat yang maksimal. Selamat
mengikuti kegiatan.
</Text>
<Button
loading={isLoading}
loaderPosition="center"
radius={"xl"}
color="green"
c={"black"}
onClick={() => {
setHotMenu(0);
setLoading(true);
router.push(RouterEvent.beranda, { scroll: false });
}}
>
Beranda
</Button>
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</UIGlobal_LayoutDefault>
</>
);
}

View File

@@ -4,6 +4,7 @@ import { MainColor } from "@/app_modules/_global/color";
import { import {
ComponentGlobal_NotifikasiBerhasil, ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal, ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global"; } from "@/app_modules/_global/notif_global";
import { notifikasiToAdmin_funCreate } from "@/app_modules/notifikasi/fun"; import { notifikasiToAdmin_funCreate } from "@/app_modules/notifikasi/fun";
import { Button } from "@mantine/core"; import { Button } from "@mantine/core";
@@ -14,13 +15,23 @@ import { useState } from "react";
import { WibuRealtime } from "wibu-pkg"; import { WibuRealtime } from "wibu-pkg";
import { Event_funCreate } from "../../fun/create/fun_create"; import { Event_funCreate } from "../../fun/create/fun_create";
import { gs_event_hotMenu } from "../../global_state"; 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 router = useRouter();
const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu); const [hotMenu, setHotMenu] = useAtom(gs_event_hotMenu);
const [isLoading, setLoading] = useState(false); const [isLoading, setLoading] = useState(false);
async function onSave() { async function onSave() {
const res = await Event_funCreate(value); const res = await Event_funCreate(value);
if (res.status === 201) { if (res.status === 201) {
@@ -71,7 +82,8 @@ export default function Event_ComponentCreateButton({ value }: { value: any }) {
value.deskripsi === "" || value.deskripsi === "" ||
value.eventMaster_TipeAcaraId === 0 || value.eventMaster_TipeAcaraId === 0 ||
value.tanggal === "function Date() { [native code] }" || 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" loaderPosition="center"
loading={isLoading ? true : false} loading={isLoading ? true : false}

View File

@@ -34,11 +34,11 @@ export function ComponentEvent_CardBeranda({ data }: { data: any }) {
<Title order={5} lineClamp={1}> <Title order={5} lineClamp={1}>
{data.title} {data.title}
</Title> </Title>
<Text align="right" fz={"sm"} lineClamp={1}> {/* <Text align="right" fz={"sm"} lineClamp={1}>
{new Intl.DateTimeFormat("id-ID", { {new Intl.DateTimeFormat("id-ID", {
dateStyle: "medium", dateStyle: "medium",
}).format(data.tanggal)} }).format(data?.tanggal)}
</Text> </Text> */}
</Group> </Group>
<Text fz={"sm"} lineClamp={2}> <Text fz={"sm"} lineClamp={2}>

View File

@@ -9,26 +9,16 @@ export default function ComponentEvent_DetailData({
}: { }: {
data: MODEL_EVENT; data: MODEL_EVENT;
}) { }) {
const tgl = data.tanggal;
const hari = tgl.toLocaleString("id-ID", { dateStyle: "full" });
const jam = tgl.toLocaleTimeString([], {
timeStyle: "short",
hourCycle: "h24",
});
return ( return (
<> <>
<ComponentGlobal_CardStyles marginBottom={"16px"}> <ComponentGlobal_CardStyles marginBottom={"16px"}>
<Stack px={"sm"} spacing={"lg"}> <Stack px={"sm"} spacing={"xl"}>
<Title lineClamp={2} align="center" w={"100%"} order={4}> <Title lineClamp={2} align="center" w={"100%"} order={4}>
{data ? data?.title : null} {data ? data?.title : null}
</Title> </Title>
<Grid> <Grid>
<Grid.Col span={4}> <Grid.Col span={4}>
<Text fw={"bold"} fz={"sm"}> <Text fw={"bold"}>Lokasi</Text>
Lokasi
</Text>
</Grid.Col> </Grid.Col>
<Grid.Col span={1}>:</Grid.Col> <Grid.Col span={1}>:</Grid.Col>
<Grid.Col span={"auto"}> <Grid.Col span={"auto"}>
@@ -37,37 +27,59 @@ export default function ComponentEvent_DetailData({
</Grid> </Grid>
<Grid> <Grid>
<Grid.Col span={4}> <Grid.Col span={4}>
<Text fw={"bold"} fz={"sm"}> <Text fw={"bold"}>Tipe Acara</Text>
Tipe Acara
</Text>
</Grid.Col> </Grid.Col>
<Grid.Col span={1}>:</Grid.Col> <Grid.Col span={1}>:</Grid.Col>
<Grid.Col span={"auto"}> <Grid.Col span={"auto"}>
<Text>{data ? data.EventMaster_TipeAcara?.name : null}</Text> <Text>{data ? data.EventMaster_TipeAcara?.name : null}</Text>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
<Grid> <Stack spacing={"xs"}>
<Grid.Col span={4}> <Text fw={"bold"}>Tanggal & Waktu</Text>
<Text fw={"bold"} fz={"sm"}> <Grid>
Tanggal <Grid.Col span={4}>
</Text> <Text fw={"bold"}>Mulai</Text>
</Grid.Col> </Grid.Col>
<Grid.Col span={1}>:</Grid.Col> <Grid.Col span={1}>:</Grid.Col>
<Grid.Col span={"auto"}>{hari ? hari : ""}</Grid.Col> <Grid.Col span={"auto"}>
</Grid> <Text>
<Grid> {" "}
<Grid.Col span={4}> {new Intl.DateTimeFormat("id-ID", {
<Text fw={"bold"} fz={"sm"}> dateStyle: "full",
Jam }).format(data?.tanggal)}
</Text> ,{" "}
</Grid.Col> <Text span inherit>
<Grid.Col span={1}>:</Grid.Col> {new Intl.DateTimeFormat("id-ID", {
<Grid.Col span={"auto"}>{jam ? jam : ""}</Grid.Col> timeStyle: "short",
</Grid> }).format(data?.tanggal)}
</Text>
</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={4}>
<Text fw={"bold"}>Selesai</Text>
</Grid.Col>
<Grid.Col span={1}>:</Grid.Col>
<Grid.Col span={"auto"}>
<Text>
{" "}
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(data?.tanggalSelesai)}
,{" "}
<Text span inherit>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(data?.tanggalSelesai)}
</Text>
</Text>
</Grid.Col>
</Grid>
</Stack>
<Stack spacing={2}> <Stack spacing={2}>
<Text fw={"bold"} fz={"sm"}> <Text fw={"bold"}>Deskripsi</Text>
Deskripsi
</Text>
<Text>{data ? data?.deskripsi : null}</Text> <Text>{data ? data?.deskripsi : null}</Text>
</Stack> </Stack>
</Stack> </Stack>

View File

@@ -4,83 +4,110 @@ import {
ComponentGlobal_AvatarAndUsername, ComponentGlobal_AvatarAndUsername,
ComponentGlobal_CardStyles, ComponentGlobal_CardStyles,
} from "@/app_modules/_global/component"; } 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 { 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({ export default function ComponentEvent_DetailMainData({
data, eventId,
}: { }: {
data: MODEL_EVENT; eventId: string;
}) { }) {
const tgl = data.tanggal; const [data, setData] = useState<MODEL_EVENT | null>(null);
const hari = tgl.toLocaleString("id-ID", { dateStyle: "full" });
const jam = tgl.toLocaleTimeString([], { useShallowEffect(() => {
timeStyle: "short", onLoadData();
hourCycle: "h24", }, []);
});
async function onLoadData() {
const data = await fetch(
API_RouteEvent.get_one_by_id({ eventId: eventId })
);
const res = await data.json();
setData(res.data);
}
return ( return (
<> <>
<ComponentGlobal_CardStyles> {data == null ? (
<Stack px={"xs"} spacing={"xl"}> <Event_ComponentSkeletonDetail />
<ComponentGlobal_AvatarAndUsername ) : (
profile={data?.Author?.Profile as any} <ComponentGlobal_CardStyles>
/> <Stack px={"xs"} spacing={"xl"}>
<ComponentGlobal_AvatarAndUsername
profile={data?.Author?.Profile as any}
/>
<Stack> <Stack spacing={"xl"}>
<Title align="center" order={4}> <Title align="center" order={4}>
{data ? data.title : null} {data ? data.title : null}
</Title> </Title>
<Grid> <Grid>
<Grid.Col span={4}> <Grid.Col span={4}>
<Text fw={"bold"} fz={"sm"}> <Text fw={"bold"}>Lokasi</Text>
Lokasi </Grid.Col>
</Text> <Grid.Col span={1}>:</Grid.Col>
</Grid.Col> <Grid.Col span={"auto"}>
<Grid.Col span={1}>:</Grid.Col> <Text>{data ? data.lokasi : null}</Text>
<Grid.Col span={"auto"}> </Grid.Col>
<Text>{data ? data.lokasi : null}</Text> </Grid>
</Grid.Col> <Grid>
</Grid> <Grid.Col span={4}>
<Grid> <Text fw={"bold"}>Tipe Acara</Text>
<Grid.Col span={4}> </Grid.Col>
<Text fw={"bold"} fz={"sm"}> <Grid.Col span={1}>:</Grid.Col>
Tipe Acara <Grid.Col span={"auto"}>
</Text> <Text>{data ? data.EventMaster_TipeAcara.name : null}</Text>
</Grid.Col> </Grid.Col>
<Grid.Col span={1}>:</Grid.Col> </Grid>
<Grid.Col span={"auto"}>
<Text>{data ? data.EventMaster_TipeAcara.name : null}</Text> <Stack spacing={"xs"}>
</Grid.Col> <Text fw={"bold"}>Tanggal & Waktu</Text>
</Grid> <Grid>
<Grid> <Grid.Col span={4}>
<Grid.Col span={4}> <Text fw={"bold"}>Mulai</Text>
<Text fw={"bold"} fz={"sm"}> </Grid.Col>
Tanggal <Grid.Col span={1}>:</Grid.Col>
</Text> <Grid.Col span={"auto"}>
</Grid.Col> <Text>
<Grid.Col span={1}>:</Grid.Col> {moment(
<Grid.Col span={"auto"}>{hari}</Grid.Col> data.tanggal?.toLocaleString("id-ID", {
</Grid> dateStyle: "full",
<Grid> })
<Grid.Col span={4}> ).format("dddd, DD MMMM YYYY, LT")}
<Text fw={"bold"} fz={"sm"}> </Text>
Jam </Grid.Col>
</Text> </Grid>
</Grid.Col> <Grid>
<Grid.Col span={1}>:</Grid.Col> <Grid.Col span={4}>
<Grid.Col span={"auto"}>{jam}</Grid.Col> <Text fw={"bold"}>Selesai</Text>
</Grid> </Grid.Col>
<Stack spacing={2}> <Grid.Col span={1}>:</Grid.Col>
<Text fw={"bold"} fz={"sm"}> <Grid.Col span={"auto"}>
Deskripsi <Text>
</Text> {moment(
<Text>{data ? data?.deskripsi : null}</Text> data.tanggalSelesai?.toLocaleString("id-ID", {
dateStyle: "full",
})
).format("dddd, DD MMMM YYYY, LT")}
</Text>
</Grid.Col>
</Grid>
</Stack>
<Stack spacing={2}>
<Text fw={"bold"}>Deskripsi</Text>
<Text>{data ? data?.deskripsi : null}</Text>
</Stack>
</Stack> </Stack>
</Stack> </Stack>
</Stack> </ComponentGlobal_CardStyles>
</ComponentGlobal_CardStyles> )}
</> </>
); );
} }

View File

@@ -1,58 +1,202 @@
"use client"; "use client";
import { import {
ActionIcon,
Avatar,
Center, Center,
Grid,
Group,
Skeleton,
Stack, Stack,
Text, Text,
Title Title,
} from "@mantine/core"; } from "@mantine/core";
import _ from "lodash"; import _ from "lodash";
import { import {
ComponentGlobal_AvatarAndUsername, ComponentGlobal_AvatarAndUsername,
ComponentGlobal_CardStyles, ComponentGlobal_CardStyles,
ComponentGlobal_LoaderAvatar,
} from "@/app_modules/_global/component"; } from "@/app_modules/_global/component";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { MODEL_EVENT_PESERTA } from "../../model/interface"; 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({ export default function ComponentEvent_ListPeserta({
listPeserta,
total, total,
eventId,
isNewPeserta,
}: { }: {
listPeserta: MODEL_EVENT_PESERTA[];
total: number; total: number;
eventId: string;
isNewPeserta?: boolean | null;
}) { }) {
const router = useRouter(); const router = useRouter();
const [data, setData] = useState<MODEL_EVENT_PESERTA[] | null>(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 ( return (
<> <>
<ComponentGlobal_CardStyles> {data === null ? (
<Stack spacing={"md"} px={"sm"}> <Event_ComponentSkeletonListPeserta />
<Center> ) : (
<Title order={5}>Daftar Peserta ({total})</Title> <ComponentGlobal_CardStyles>
</Center> <Stack spacing={"md"} px={"sm"}>
{_.isEmpty(listPeserta) ? (
<Center> <Center>
<Text fz={"xs"} fw={"bold"}> <Title order={5}>Daftar Peserta ({total})</Title>
- Tidak ada peserta -
</Text>
</Center> </Center>
) : (
<Stack> {_.isEmpty(data) ? (
{listPeserta.map((e, i) => ( <Center>
<Stack key={i} spacing={"sm"}> <Text fz={"xs"} fw={"bold"}>
<ComponentGlobal_AvatarAndUsername - Tidak ada peserta -
profile={e.User.Profile as any} </Text>
sizeAvatar={30} </Center>
fontSize={"sm"} ) : (
/> <Stack>
{/* <Divider /> */} {data.map((e, i) => (
</Stack> <Stack key={i} spacing={"sm"}>
))} <ComponentEvent_AvatarAndUsername
</Stack> profile={e?.User?.Profile as any}
)} sizeAvatar={30}
</Stack> fontSize={"sm"}
</ComponentGlobal_CardStyles> tanggalMulai={e?.Event?.tanggal}
tanggalSelesai={e?.Event?.tanggalSelesai}
isPresent={e?.isPresent}
/>
{/* <Divider /> */}
</Stack>
))}
</Stack>
)}
</Stack>
</ComponentGlobal_CardStyles>
)}
</>
);
}
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 (
<>
<Grid align="flex-start" justify="space-around">
<Grid.Col span={2} style={{ minHeight: 50 }}>
<ActionIcon
radius={"xl"}
variant="transparent"
onClick={() => onCheckProfile()}
>
{visible ? (
<Avatar radius={"xl"} size={40}>
<ComponentGlobal_Loader />
</Avatar>
) : (
<ComponentGlobal_LoaderAvatar
fileId={profile?.imageId as any}
sizeAvatar={sizeAvatar}
/>
)}
</ActionIcon>
</Grid.Col>
<Grid.Col span={"auto"} style={{ minHeight: 50 }}>
<Stack justify="center" h={30}>
<Text
fw={"bold"}
fz={fontSize ? fontSize : "sm"}
lineClamp={1}
onClick={() => onCheckProfile()}
>
{profile?.name}
</Text>
</Stack>
</Grid.Col>
{/* {component && (
<Grid.Col span={"auto"} style={{ minHeight: 50 }}>
<Stack justify="center" h={30}>
{component}
</Stack>
</Grid.Col>
)} */}
{tglMulai < 0 && (
<Grid.Col span={3} style={{ minHeight: 50 }}>
<Group position="right">
<Stack justify="center" h={30}>
<Text fw={"bold"} fz={fontSize ? fontSize : "sm"}>
{isPresent ? "Hadir" : "-"}
</Text>
</Stack>
</Group>
</Grid.Col>
)}
</Grid>
</> </>
); );
} }

View File

@@ -1,5 +1,11 @@
import Event_ComponentCreateButton from "./button/button_create_event"; 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_ComponentSkeletonDetailData } from "./skeleton/comp_skeleton_detail_data";
import Event_ComponentSkeletonListPeserta from "./skeleton/comp_skeleton_list_peserta";
export { Event_ComponentSkeletonDetailData }; export { Event_ComponentSkeletonDetailData };
export { Event_ComponentCreateButton }; export { Event_ComponentCreateButton };
export { Event_ComponentSkeletonBeranda };
export { Event_ComponentSkeletonDetail };
export { Event_ComponentSkeletonListPeserta };

View File

@@ -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) => (
<ComponentGlobal_CardStyles key={index} marginBottom={"16px"}>
<Stack>
<Grid align="center">
<Grid.Col span={"content"}>
<Skeleton radius={"100%"} h={50} w={50} />
</Grid.Col>
<Grid.Col span={"auto"}>
<Skeleton h={20} w={"50%"} />
</Grid.Col>
</Grid>
<Stack>
<Skeleton h={20} w={"100%"} />
<Skeleton h={20} w={"100%"} />
</Stack>
</Stack>
</ComponentGlobal_CardStyles>
))}
</>
);
}

View File

@@ -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 (
<>
<ComponentGlobal_CardStyles>
<Stack>
<Grid align="center">
<Grid.Col span={"content"}>
<Skeleton radius={"100%"} h={50} w={50} />
</Grid.Col>
<Grid.Col span={"auto"}>
<Skeleton h={20} w={"50%"} />
</Grid.Col>
</Grid>
</Stack>
<Stack spacing={"xl"}>
<Center>
<Skeleton h={20} w={"50%"} />
</Center>
<Skeleton h={20} w={"100%"} />
<Skeleton h={20} w={"100%"} />
<Skeleton h={20} w={"50%"} />
<Skeleton h={20} w={"100%"} />
<Skeleton h={20} w={"100%"} />
<Stack>
<Skeleton h={20} w={"50%"} />
<Skeleton h={20} w={"100%"} />
<Skeleton h={20} w={"100%"} />
</Stack>
</Stack>
</ComponentGlobal_CardStyles>
</>
);
}

View File

@@ -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 (
<>
<ComponentGlobal_CardStyles>
<Stack spacing={"lg"}>
<Center>
<Skeleton height={20} width={"50%"} />
</Center>
<Stack>
{Array.from(new Array(3)).map((e, i) => (
<Grid key={i} align="center">
<Grid.Col span={"content"}>
<Skeleton radius={"100%"} h={30} w={30} />
</Grid.Col>
<Grid.Col span={"auto"}>
<Skeleton h={20} w={"50%"} />
</Grid.Col>
<Grid.Col span={2}>
<Skeleton h={20} w={"50%"} />
</Grid.Col>
</Grid>
))}
</Stack>
</Stack>
</ComponentGlobal_CardStyles>
</>
);
}

Some files were not shown because too many files have changed in this diff Show More