Merge pull request #184 from bipproduction/staging

Merge v 1.2.23
This commit is contained in:
Bagasbanuna02
2024-12-11 16:48:23 +08:00
committed by GitHub
136 changed files with 4621 additions and 859 deletions

View File

@@ -2,6 +2,20 @@
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
## [1.2.23](https://github.com/bipproduction/hipmi/compare/v1.2.22...v1.2.23) (2024-12-11)
## [1.2.22](https://github.com/bipproduction/hipmi/compare/v1.2.21...v1.2.22) (2024-12-10)
## [1.2.21](https://github.com/bipproduction/hipmi/compare/v1.2.20...v1.2.21) (2024-12-09)
## [1.2.20](https://github.com/bipproduction/hipmi/compare/v1.2.19...v1.2.20) (2024-12-09)
## [1.2.19](https://github.com/bipproduction/hipmi/compare/v1.2.18...v1.2.19) (2024-12-06)
## [1.2.18](https://github.com/bipproduction/hipmi/compare/v1.2.17...v1.2.18) (2024-12-04)
## [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)

BIN
bun.lockb

Binary file not shown.

View File

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

View File

@@ -1,13 +1,14 @@
{
"name": "hipmi",
"version": "1.2.16",
"version": "1.2.23",
"private": true,
"prisma": {
"seed": "npx tsx prisma/seed.ts --yes"
},
"scripts": {
"dev": "bun --bun run next dev --experimental-https",
"build": "bun --bun run next build",
"build": "NODE_OPTIONS='--max-old-space-size=2048' bun --bun run next build",
"build:dev": "bun --bun run next build",
"start": "bun --bun run next start",
"lint": "bun --bun run next lint",
"ver": "bunx commit-and-tag-version -- --prerelease"
@@ -39,6 +40,7 @@
"@tiptap/pm": "^2.2.3",
"@tiptap/react": "^2.2.3",
"@tiptap/starter-kit": "^2.2.3",
"@types/bun": "^1.1.14",
"@types/lodash": "^4.17.4",
"@types/mapbox-gl": "^3.4.0",
"@types/node": "20.4.5",
@@ -47,6 +49,7 @@
"@types/uuid": "^9.0.4",
"autoprefixer": "10.4.14",
"bufferutil": "^4.0.8",
"bun": "^1.1.38",
"dayjs": "^1.11.10",
"dotenv": "^16.4.5",
"echarts": "^5.4.3",

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

View File

@@ -1,10 +1,12 @@
import { prisma } from "@/app/lib";
import { data } from "autoprefixer";
import { NextResponse } from "next/server";
import { NextRequest, NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get("id");
export async function GET(request: NextRequest) {
const id = request.nextUrl.searchParams.get("id");
// const { searchParams } = new URL(request.url);
// const id = searchParams.get("id");
try {
const data = await prisma.kodeOtp.findFirst({
@@ -12,10 +14,11 @@ export async function GET(request: Request) {
id: id as string,
},
});
return new Response(JSON.stringify({ data }), { status: 200 });
return NextResponse.json(data, { status: 200 });
} catch (error) {
console.log(error);
}
return new Response(JSON.stringify({ data: null }), { status: 404 });
return NextResponse.json(null, { status: 500 });
}

View File

@@ -18,14 +18,11 @@ export async function POST(req: Request) {
const sendWa = await res.json();
if (sendWa.status !== "success")
return new Response(
JSON.stringify({
success: false,
message: "Nomor Whatsapp Tidak Aktif",
}),
return NextResponse.json(
{ success: false, message: "Nomor Whatsapp Tidak Aktif" },
{ status: 400 }
);
const createOtpId = await prisma.kodeOtp.create({
data: {
nomor: nomor,
@@ -34,32 +31,30 @@ export async function POST(req: Request) {
});
if (!createOtpId)
return new Response(
JSON.stringify({
success: false,
message: "Gagal Membuat Kode OTP",
}),
return NextResponse.json(
{ success: false, message: "Gagal Membuat Kode OTP" },
{ status: 400 }
);
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: true,
message: "Kode Verifikasi Dikirim",
kodeId: createOtpId.id,
}),
},
{ status: 200 }
);
} catch (error) {
console.log(error);
return new Response(
JSON.stringify({
success: false,
message: "Server Whatsapp Error !!",
}),
return NextResponse.json(
{ success: false, message: "Server Whatsapp Error !! " },
{ status: 500 }
);
}
}
return NextResponse.json({ success: false });
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }
);
}

View File

@@ -1,28 +1,20 @@
import { prisma } from "@/app/lib";
import { cookies } from "next/headers";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get("id");
import { NextRequest, NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(request: NextRequest) {
const id = request.nextUrl.searchParams.get("id");
// const { searchParams } = new URL(request.url);
// const id = searchParams.get("id");
const delToken = await prisma.userSession.delete({
where: {
userId: id as string,
},
});
// const delToken = await prisma.userSession.delete({
// where: {
// userId: id as string,
// },
// });
const del = cookies().delete(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!);
return new Response(JSON.stringify({ success: true, message: "Logout Berhasil" }), {status: 200});
return NextResponse.json(
{ 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,5 +1,6 @@
import { sessionCreate } from "@/app/auth/_lib/session_create";
import prisma from "@/app/lib/prisma";
import { NextResponse } from "next/server";
export async function POST(req: Request) {
if (req.method === "POST") {
@@ -11,60 +12,38 @@ export async function POST(req: Request) {
},
});
if (cekUsername)
return new Response(
JSON.stringify({
success: false,
message: "Username sudah digunakan",
}),
{ status: 400 }
);
const createUser = await prisma.user.create({
data: {
username: data.username,
nomor: data.nomor,
active: true,
},
});
const token = await sessionCreate({
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
user: createUser as any,
});
try {
const createUserSession = await prisma.userSession.create({
if (cekUsername)
return NextResponse.json(
{ success: false, message: "Username sudah digunakan" },
{ status: 400 }
);
const createUser = await prisma.user.create({
data: {
token: token as string,
userId: createUser.id,
username: data.username,
nomor: data.nomor,
active: true,
},
});
if (!createUserSession)
return new Response(
JSON.stringify({
success: false,
message: "Gagal Membuat Session",
}),
{ status: 400 }
);
const token = await sessionCreate({
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
user: createUser as any,
});
return NextResponse.json(
{ success: true, message: "Berhasil Login", data: createUser },
{ status: 200 }
);
} catch (error) {
console.log(error);
}
return new Response(
JSON.stringify({
success: true,
message: "Berhasil Login",
}),
{ status: 200 }
);
}
return new Response(
JSON.stringify({ success: false, message: "Method Not Allowed" }),
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }
);
}

View File

@@ -18,11 +18,11 @@ export async function POST(req: Request) {
const sendWa = await res.json();
if (sendWa.status !== "success")
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: false,
message: "Nomor Whatsapp Tidak Aktif",
}),
},
{ status: 400 }
);
@@ -34,32 +34,36 @@ export async function POST(req: Request) {
});
if (!createOtpId)
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: false,
message: "Gagal Membuat Kode OTP",
}),
},
{ status: 400 }
);
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: true,
message: "Kode Verifikasi Dikirim",
kodeId: createOtpId.id,
}),
},
{ status: 200 }
);
} catch (error) {
console.log(error);
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: false,
message: "Server Whatsapp Error !!",
}),
},
{ status: 500 }
);
}
}
return NextResponse.json({ success: false });
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }
);
}

View File

@@ -1,107 +1,52 @@
import { sessionCreate } from "@/app/auth/_lib/session_create";
import prisma from "@/app/lib/prisma";
import { ServerEnv } from "@/app/lib/server_env";
import { sealData } from "iron-session";
import { revalidatePath } from "next/cache";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
export async function POST(req: Request) {
if (req.method === "POST") {
const { nomor } = await req.json();
const dataUser = await prisma.user.findUnique({
where: {
nomor: nomor,
},
select: {
id: true,
nomor: true,
username: true,
active: true,
masterUserRoleId: true,
},
});
if (dataUser === null)
return new Response(
JSON.stringify({ success: false, message: "Nomor Belum Terdaftar" }),
{ status: 404 }
);
const token = await sessionCreate({
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
user: dataUser as any,
});
const cekSessionUser = await prisma.userSession.findFirst({
where: {
userId: dataUser.id,
},
});
if (cekSessionUser !== null) {
await prisma.userSession.delete({
where: {
userId: dataUser.id,
},
});
}
try {
const createUserSession = await prisma.userSession.create({
data: {
token: token as string,
userId: dataUser.id,
const dataUser = await prisma.user.findUnique({
where: {
nomor: nomor,
},
select: {
id: true,
nomor: true,
username: true,
active: true,
masterUserRoleId: true,
},
});
if (!createUserSession)
return new Response(
JSON.stringify({ success: false, message: "Gagal Membuat Session" }),
{ status: 400 }
if (dataUser == null)
return NextResponse.json(
{ success: false, message: "Nomor Belum Terdaftar" },
{ status: 404 }
);
const token = await sessionCreate({
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
user: dataUser as any,
});
return NextResponse.json(
{
success: true,
message: "Berhasil Login",
roleId: dataUser.masterUserRoleId,
active: dataUser.active,
},
{ status: 200 }
);
} 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 new Response(
JSON.stringify({ success: false, message: "Method Not Allowed" }),
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }
);
}

View File

@@ -8,7 +8,7 @@ export async function GET(req: Request) {
if (!c || !c?.value || _.isEmpty(c?.value) || _.isUndefined(c?.value)) {
return NextResponse.json({ success: false });
// return new Response(JSON.stringify({ success: false }));
}
return NextResponse.json({ success: true });
}

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,17 @@
import { event_newGetListPesertaById } from "@/app_modules/event/fun";
import { Event_getListPesertaById } from "@/app_modules/event/fun/get/get_list_peserta_by_id";
import { toNumber } from "lodash";
import { NextResponse } from "next/server";
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,67 @@
import { prisma } from "@/app/lib"
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// GET ALL DATA PORTOFOLIO BY PROFILE ID
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url)
const page = searchParams.get("page")
const search = searchParams.get("search")
const dataSkip = Number(page) * 5 - 5;
const data = await prisma.forum_Posting.findMany({
take: 5,
skip: dataSkip,
orderBy: {
createdAt: "desc",
},
where: {
isActive: true,
diskusi: {
mode: "insensitive",
contains: (search == undefined || search == "null") ? "" : search,
},
},
select: {
id: true,
diskusi: true,
createdAt: true,
isActive: true,
authorId: true,
Author: {
select: {
id: true,
username: true,
Profile: {
select: {
id: true,
name: true,
imageId: true,
},
},
},
},
Forum_Komentar: {
where: {
isActive: true,
},
},
ForumMaster_StatusPosting: {
select: {
id: true,
status: true,
},
},
forumMaster_StatusPostingId: true,
},
});
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data }, { status: 200 });
}
catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,69 @@
import { prisma } from "@/app/lib";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// GET DATA HOME
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,76 @@
import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const data = await prisma.businessMaps.findUnique({
where: {
id: id,
},
select: {
namePin: true,
latitude: true,
longitude: true,
pinId: true,
imageId: true,
Author: {
select: {
Profile: {
select: {
id: true,
name: true,
imageId: true,
}
}
}
},
Portofolio: {
select: {
id: true,
alamatKantor: true,
tlpn: true,
deskripsi: true,
namaBisnis: true,
MasterBidangBisnis: {
select: {
name: true,
},
},
},
},
}
});
const dataLokasi = {
namePin: data?.namePin,
latitude: data?.latitude,
longitude: data?.longitude,
pinId: data?.pinId,
imageId: data?.imageId,
}
const dataAuthor = {
id: data?.Author?.Profile?.id,
name: data?.Author?.Profile?.name,
imageId: data?.Author?.Profile?.imageId,
}
const dataBisnis = {
id: data?.Portofolio?.id,
alamatKantor: data?.Portofolio?.alamatKantor,
tlpn: data?.Portofolio?.tlpn,
deskripsi: data?.Portofolio?.deskripsi,
namaBisnis: data?.Portofolio?.namaBisnis,
bidangBisnis: data?.Portofolio?.MasterBidangBisnis?.name,
}
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", dataLokasi, dataAuthor, dataBisnis }, { status: 200 });
}
catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,40 @@
import { prisma } from "@/app/lib";
import _ from "lodash";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// GET ALL DATA MAP
export async function GET(request: Request) {
try {
const data = await prisma.businessMaps.findMany({
where: {
isActive: true,
},
select: {
id: true,
namePin: true,
latitude: true,
longitude: true,
pinId: true,
Portofolio: {
select: {
logoId: true,
}
}
}
});
const dataFix = data.map((v: any) => ({
..._.omit(v, ["Portofolio"]),
logoId: v.Portofolio.logoId
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
}
catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,173 @@
import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
import fs from "fs";
export const dynamic = "force-dynamic";
// GET ONE DATA PORTOFOLIO BY ID PORTOFOLIO
export async function GET(request: Request, context: { params: { id: string } }) {
try {
let dataFix
const { id } = context.params;
const { searchParams } = new URL(request.url);
const kategori = searchParams.get('cat');
if (kategori == "bisnis") {
const data = await prisma.portofolio.findUnique({
where: {
id: id,
},
select: {
id_Portofolio: true,
namaBisnis: true,
alamatKantor: true,
tlpn: true,
deskripsi: true,
logoId: true,
MasterBidangBisnis: {
select: {
name: true
}
},
Profile: {
select: {
userId: true
}
}
}
});
dataFix = {
id_Portofolio: data?.id_Portofolio,
namaBisnis: data?.namaBisnis,
alamatKantor: data?.alamatKantor,
tlpn: data?.tlpn,
deskripsi: data?.deskripsi,
logoId: data?.logoId,
bidangBisnis: data?.MasterBidangBisnis?.name,
authorId: data?.Profile?.userId
}
} else if (kategori == "lokasi") {
const data = await prisma.portofolio.findUnique({
where: {
id: id,
},
select: {
logoId: true,
BusinessMaps: {
select: {
id: true,
namePin: true,
latitude: true,
longitude: true,
imageId: true,
pinId: true
}
}
}
});
dataFix = {
mapId: data?.BusinessMaps?.id,
logoId: data?.logoId,
namePin: data?.BusinessMaps?.namePin,
latitude: data?.BusinessMaps?.latitude,
longitude: data?.BusinessMaps?.longitude,
imageId: data?.BusinessMaps?.imageId,
pinId: data?.BusinessMaps?.pinId
}
} else if (kategori == "sosmed") {
const data = await prisma.portofolio.findUnique({
where: {
id: id,
},
select: {
Portofolio_MediaSosial: {
select: {
facebook: true,
twitter: true,
instagram: true,
tiktok: true,
youtube: true
}
}
}
});
dataFix = {
facebook: data?.Portofolio_MediaSosial?.facebook,
twitter: data?.Portofolio_MediaSosial?.twitter,
instagram: data?.Portofolio_MediaSosial?.instagram,
tiktok: data?.Portofolio_MediaSosial?.tiktok,
youtube: data?.Portofolio_MediaSosial?.youtube
}
}
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// DELETE ONE DATA PORTOFOLIO
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const data = await prisma.portofolio.findUnique({
where: {
id: id
}
})
const findLogo = await prisma.images.findFirst({
where: {
id: String(data?.logoId),
},
select: {
id: true,
url: true,
},
});
if (findLogo) {
fs.unlinkSync(`./public/portofolio/logo/${findLogo.url}`)
const deleteLogo = await prisma.images.delete({
where: {
id: String(findLogo?.id),
},
});
}
const deletePortoMedsos = await prisma.portofolio_MediaSosial.delete({
where: {
portofolioId: id,
},
});
const deleteMap = await prisma.businessMaps.delete({
where: {
portofolioId: id
}
})
const deletePortofolio = await prisma.portofolio.delete({
where: {
id: id,
},
});
return NextResponse.json({ success: true, message: "Berhasil menghapus data" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menghapus data, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,60 @@
import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// GET ALL DATA PORTOFOLIO BY PROFILE ID
export async function GET(request: Request) {
try {
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,59 @@
import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// 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

@@ -1,6 +1,7 @@
import { headers } from "next/headers";
import { NextResponse } from "next/server";
export async function GET(req: Request) {
const origin = new URL(req.url).origin;
return new Response(JSON.stringify({ success: true, origin }));
return NextResponse.json({ success: true, origin });
}

View File

@@ -1,8 +1,11 @@
import prisma from "@/app/lib/prisma";
import { NextResponse } from "next/server";
export async function GET(req: Request) {
const page = new URL(req.url).searchParams.get("page");
if (!page) return new Response("page require", { status: 400 });
if (!page)
return NextResponse.json({ message: "Page not found" }, { status: 400 });
const res = await prisma.projectCollaboration_Message.findMany({
take: 5,
skip: +page * 5 - 5,

View File

@@ -0,0 +1,51 @@
import { NextResponse } from "next/server";
export async function POST(request: Request) {
const WS_APIKEY = process.env.WS_APIKEY;
console.log(WS_APIKEY);
try {
const formData = await request.formData();
const res = await fetch("https://wibu-storage.wibudev.com/api/upload", {
method: "POST",
body: formData,
headers: {
Authorization: `Bearer ${process.env.WS_APIKEY}`,
},
});
// if (res.ok) {
// console.log("Berhasil");
// const hasil = await res.json();
// return { success: true, data: hasil.data };
// } else {
// const errorText = await res.text();
// return { success: false, data: {} };
// }
} catch (error) {
console.log(error);
}
// try {
// const res = await fetch("https://wibu-storage.wibudev.com/api/upload", {
// method: "POST",
// body: formData,
// headers: {
// Authorization: `Bearer ${process.env.WS_APIKEY}`,
// },
// });
// if (res.ok) {
// const hasil = await res.json();
// return { success: true, data: hasil.data };
// } else {
// const errorText = await res.text();
// return { success: false, data: {} };
// }
// } catch (error) {
// console.error("Upload error:", error);
// return { success: false, data: {} };
// }
return NextResponse.json({ success: true });
}

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

@@ -1,7 +1,9 @@
import { NextResponse } from "next/server";
export async function GET(req: Request) {
const auth = req.headers.get("Authorization");
const token = auth?.split(" ")[1];
if (!token)
return new Response(JSON.stringify({ success: false }), { status: 401 });
return new Response(JSON.stringify({ success: true }));
if (!token) return NextResponse.json({ success: false }, { status: 401 });
return NextResponse.json({ success: true });
}

View File

@@ -1,7 +1,8 @@
import { headers } from "next/headers";
import { NextResponse } from "next/server";
export async function GET(
req: Request) {
const origin = new URL(req.url).origin;
return new Response(JSON.stringify({ success: true, origin }));
return NextResponse.json({ success: true, origin });
}

View File

@@ -1,5 +1,6 @@
import { prisma } from "@/app/lib";
import { sessionCreate } from "../../_lib/session_create";
import { NextResponse } from "next/server";
export async function POST(req: Request) {
const user = await prisma.user.findUnique({
@@ -12,10 +13,7 @@ export async function POST(req: Request) {
},
});
if (!user)
return new Response(
JSON.stringify({ success: false, message: "User not found" }), {status: 404}
);
if (!user) return NextResponse.json({ success: false }, { status: 404 });
const token = await sessionCreate({
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
@@ -23,5 +21,5 @@ export async function POST(req: Request) {
user: user as any,
});
return new Response(JSON.stringify({ success: true, token }));
return NextResponse.json({ success: true, token });
}

View File

@@ -1,5 +1,8 @@
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
export async function GET() {
const del = cookies().delete(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!);
return new Response(JSON.stringify({ success: true }));
return NextResponse.json({ success: true, message: "Logout Berhasil" });
}

View File

@@ -1,32 +1,21 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { HomeView } from "@/app_modules/home";
import { user_getOneByUserId } from "@/app_modules/home/fun/get/get_one_user_by_id";
import { job_getTwoForHomeView } from "@/app_modules/job/fun/get/get_two_for_home_view";
import { HomeViewNew } from "@/app_modules/home";
import notifikasi_countUserNotifikasi from "@/app_modules/notifikasi/fun/count/fun_count_by_id";
export default async function PageHome() {
const userLoginId = await funGetUserIdByToken();
const dataUser = await user_getOneByUserId(userLoginId as string);
const dataJob = await job_getTwoForHomeView();
// const userLoginId = await funGetUserIdByToken();
// const dataUser = await user_getOneByUserId(userLoginId as string);
// const dataJob = await job_getTwoForHomeView();
const countNotifikasi = await notifikasi_countUserNotifikasi();
// console.log(userLoginId, "ini di home");
// console.log(dataUser, "ini di home");
// if (dataUser?.active === false) {
// return redirect(RouterHome.home_user_non_active);
// }
// if (dataUser?.masterUserRoleId === "2" || dataUser?.masterUserRoleId === "3")
// return redirect(RouterAdminDashboard.main_admin);
return (
<>
<HomeView
{/* <HomeView
dataUser={dataUser as any}
dataJob={dataJob as any}
countNotifikasi={countNotifikasi}
/>
/> */}
<HomeViewNew countNotifikasi={countNotifikasi} />
</>
);
}

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

View File

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

View File

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

View File

@@ -1,40 +1,17 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { newFunGetUserId } from "@/app/lib/new_fun_user_id";
import Ui_Konfirmasi from "@/app_modules/event/_ui/konfirmasi";
import {
event_funCheckKehadiran,
event_funCheckPesertaByUserId,
} from "@/app_modules/event/fun";
import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id";
import { redirect } from "next/navigation";
export default async function Page({ params }: { params: { id: string } }) {
const eventId = params.id;
const userLoginId = await funGetUserIdByToken();
const dataEvent = await event_getOneById(eventId);
const checkPeserta = await event_funCheckPesertaByUserId({
eventId: eventId,
userId: userLoginId as string,
});
if (dataEvent?.isArsip)
return redirect(`/dev/event/detail/riwayat/${dataEvent.id}`);
if (checkPeserta == false)
return redirect(`/dev/event/detail/main/${eventId}`);
// if (checkKehadiran) {
// return redirect(`/dev/event/main/beranda`);
// }
export default async function Page({
params,
}: {
params: Promise<{ id: string }>;
}) {
const eventId = (await params).id;
const userLoginId = await newFunGetUserId();
return (
<>
<Ui_Konfirmasi
dataEvent={dataEvent as any}
userLoginId={userLoginId as string}
/>
<Ui_Konfirmasi userLoginId={userLoginId as string} eventId={eventId} />
</>
);
}

View File

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

View File

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

View File

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

View File

@@ -1,42 +1,21 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { funGlobal_getUserById } from "@/app_modules/_global/fun/get/fun_get_user_by_id";
import { redirect } from "next/navigation";
import { RealtimeProvider } from "../lib";
import { newFunGetUserId } from "../lib/new_fun_user_id";
import { ServerEnv } from "../lib/server_env";
import { RouterAdminDashboard } from "../lib/router_hipmi/router_admin";
import { funGlobal_checkActivationUseById } from "@/app_modules/_global/fun/get/fun_check_activation_use_by_id";
export default async function Layout({
children,
}: {
children: React.ReactNode;
}) {
const userLoginId = await funGetUserIdByToken();
// const dataUser = await funGlobal_getUserById({
// userId: userLoginId as string,
// });
// if (dataUser?.masterUserRoleId != "1") return redirect("/dev/home");
// const activationUser = await funGlobal_checkActivationUseById({
// userId: userLoginId as string,
// });
// if (activationUser == false) return redirect("/waiting-room");
return (
<>
<RealtimeProvider
userLoginId={userLoginId as string}
WIBU_REALTIME_TOKEN={
ServerEnv.value?.NEXT_PUBLIC_WIBU_REALTIME_TOKEN as string
}
/>
{children}
{/* <CheckCookies_UiLayout dataUser={dataUser as any}>
{children}
</CheckCookies_UiLayout> */}
</>
);
}

View File

@@ -1,13 +1,13 @@
import { map_funGetAllMap } from "@/app_modules/map/fun/get/fun_get_all_map";
import { Map_View } from "@/app_modules/map/view";
import { Map_ViewNew } from "@/app_modules/map/view/main_view_new";
const mapboxToken = process.env.MAPBOX_TOKEN!;
export default async function Page() {
const dataMap = await map_funGetAllMap();
// const dataMap = await map_funGetAllMap();
return (
<>
<Map_View mapboxToken={mapboxToken} dataMap={dataMap} />
{/* <Map_View mapboxToken={mapboxToken} dataMap={dataMap} /> */}
<Map_ViewNew mapboxToken={mapboxToken} />
</>
);
}

View File

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

View File

@@ -1,27 +1,20 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { PortofolioLayout } from "@/app_modules/katalog/portofolio";
import { portofolio_getOneById } from "@/app_modules/katalog/portofolio/fun/get/get_one_portofolio";
import { PortofolioLayoutNew } from "@/app_modules/katalog/portofolio";
export default async function Layout({
children,
params,
}: {
children: any;
params: { id: string };
}) {
let portoId = params.id;
const getPorto = await portofolio_getOneById(portoId);
const userLoginId = await funGetUserIdByToken();
export default async function Layout({ children, params, }: { children: any; params: { id: string }; }) {
// let portoId = params.id;
// const getPorto = await portofolio_getOneById(portoId);
// const userLoginId = await funGetUserIdByToken();
return (
<>
<PortofolioLayout
{/* <PortofolioLayout
portoId={portoId}
userLoginId={userLoginId as string}
authorId={getPorto?.Profile?.User?.id as any}
>
{children}
</PortofolioLayout>
</PortofolioLayout> */}
<PortofolioLayoutNew>{children}</PortofolioLayoutNew>
</>
);
}

View File

@@ -1,20 +1,19 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { ViewPortofolio } from "@/app_modules/katalog/portofolio";
import { portofolio_getOneById } from "@/app_modules/katalog/portofolio/fun/get/get_one_portofolio";
import { Portofolio_UiDetailNew } from "@/app_modules/katalog/portofolio";
const mapboxToken = process.env.MAPBOX_TOKEN!;
export default async function Page({ params }: { params: { id: string } }) {
const portofolioId = params.id;
const dataPortofolio = await portofolio_getOneById(portofolioId);
const userLoginId = await funGetUserIdByToken();
// const portofolioId = params.id;
// const dataPortofolio = await portofolio_getOneById(portofolioId);
// const userLoginId = await funGetUserIdByToken();
return (
<>
<ViewPortofolio
{/* <ViewPortofolio
dataPorto={dataPortofolio as any}
userLoginId={userLoginId as any}
mapboxToken={mapboxToken}
/>
/> */}
<Portofolio_UiDetailNew mapboxToken={mapboxToken} />
</>
);
}

View File

@@ -1,14 +1,12 @@
import EditProfile from "@/app_modules/katalog/profile/edit/view";
import { Profile_getOneProfileAndUserById } from "@/app_modules/katalog/profile/fun/get/get_one_user_profile";
export default async function Page({ params }: { params: { id: string } }) {
let profileId = params.id
const dataProfile = await Profile_getOneProfileAndUserById(profileId)
let profileId = params.id;
const dataProfile = await Profile_getOneProfileAndUserById(profileId);
return (
<>
{/* {JSON.stringify(data)} */}
<EditProfile data={dataProfile as any} />
</>
);

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'
const prismaClientSingleton = () => {
return new PrismaClient()
}
type PrismaClientSingleton = ReturnType<typeof prismaClientSingleton>
import { PrismaClient } from '@prisma/client';
// Singleton PrismaClient untuk pengembangan
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClientSingleton | undefined
__prisma__: PrismaClient | undefined;
};
export const prisma = globalForPrisma.__prisma__ ?? new PrismaClient({
// log: process.env.NODE_ENV === 'development' ? ['query', 'info', 'warn', 'error'] : [],
});
// Gunakan PrismaClient yang sama jika sudah ada
if (process.env.NODE_ENV !== 'production') {
if (!globalForPrisma.__prisma__) {
console.log('PrismaClient initialized in development mode');
}
globalForPrisma.__prisma__ = prisma;
}
const prisma = globalForPrisma.prisma ?? prismaClientSingleton()
process.on('SIGINT', async () => {
console.log('Disconnecting PrismaClient...');
await prisma.$disconnect();
process.exit(0);
});
export default prisma
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
export default prisma;

View File

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

View File

@@ -1,18 +1,111 @@
"use client";
import { MainColor } from "@/app_modules/_global/color";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import Coba_TestLoading from "@/app_modules/zCoba";
import {
Avatar,
Button,
Center,
FileButton,
Paper,
Stack,
} from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
import { useState } from "react";
import { DIRECTORY_ID } from "../lib";
import { TokenStorage } from "../lib/token";
import { envs } from "@/lib/envs";
export default async function Page() {
await new Promise((a, b) => {
setTimeout(a, 3000);
});
export default function Page() {
const [filePP, setFilePP] = useState<File | null>(null);
const [imgPP, setImgPP] = useState<any | null>();
const userLoginId = await funGetUserIdByToken();
async function onSave() {
const body = {
file: filePP,
dirId: DIRECTORY_ID.profile_foto,
};
const token =
"QWERTYUIOPLKJHGFDSAZXCVBNMQAZWSXEDCRFVTGBYHNUJMIKOLPPOIUYTREWQLKJHGFDSAMNBVCXZlghvftyguhijknhbgvcfytguu8okjnhbgvfty7u8oilkjnhgvtygu7u8ojilnkhbgvhujnkhghvjhukjnhb";
const formData = new FormData();
formData.append("file", filePP as any);
const res = await fetch("/api/upload", {
method: "POST",
body: formData,
});
console.log(await res.json());
}
return (
<>
{/* <CobaRealtime userLoginId={userLoginId} /> */}
<Coba_TestLoading userLoginId={userLoginId as string} />
{/* <ComponentGlobal_UI_LayoutTamplate /> */}
<Stack>
<Center>
{imgPP ? (
<Paper shadow="lg" radius={"100%"}>
<Avatar
color={"cyan"}
sx={{
borderStyle: "solid",
borderColor: "gray",
borderWidth: "0.5px",
}}
src={imgPP ? imgPP : "/aset/global/avatar.png"}
size={150}
radius={"100%"}
/>
</Paper>
) : (
<Paper shadow="lg" radius={"100%"}>
<Avatar
variant="light"
color="blue"
size={150}
radius={"100%"}
sx={{
borderStyle: "solid",
borderColor: MainColor.darkblue,
borderWidth: "0.5px",
}}
/>
</Paper>
)}
</Center>
<FileButton
onChange={async (files: any | null) => {
try {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
setImgPP(buffer);
setFilePP(files);
} catch (error) {
console.log(error);
}
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
radius={"xl"}
leftIcon={<IconCamera />}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload
</Button>
)}
</FileButton>
<Button onClick={() => onSave()}>Upload</Button>
</Stack>
</>
);
}

View File

@@ -3,6 +3,8 @@
import { Button, FileButton } from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
import { MainColor } from "../color";
import { MAX_SIZE } from "../lib";
import { ComponentGlobal_NotifikasiPeringatan } from "../notif_global";
export function ComponentGlobal_ButtonUploadFileImage({
onSetFile,
@@ -19,8 +21,14 @@ export function ComponentGlobal_ButtonUploadFileImage({
new Blob([new Uint8Array(await files.arrayBuffer())])
);
onSetFile(files);
onSetImage(buffer);
if (files.size > MAX_SIZE) {
ComponentGlobal_NotifikasiPeringatan(
"Ukuran file terlalu besar. Maksimal 2 MB."
);
} else {
onSetFile(files);
onSetImage(buffer);
}
} catch (error) {
console.log(error);
}

View File

@@ -7,13 +7,16 @@ import { jwtVerify } from "jose";
import { cookies } from "next/headers";
export async function funGetUserIdByToken() {
const c = cookies().get(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!);
const SESSION_KEY = process.env.NEXT_PUBLIC_BASE_SESSION_KEY!;
// console.log("SESSION_KEY", SESSION_KEY);
const c = cookies().get("hipmi-key");
const cekUser = await decrypt({
token: c?.value as string,
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
});
// console.log("userid" , cekUser?.id)
// const token = JSON.parse(
// await unsealData(c?.value as string, {

View File

@@ -54,6 +54,4 @@ export async function funGlobal_UploadToStorage({
console.error("Error:", error);
return { success: false, data: {} };
}
return { success: false, data: { id: "" } };
}

View File

@@ -0,0 +1,3 @@
import { MAX_SIZE } from "./max_size";
export { MAX_SIZE };

View File

@@ -0,0 +1,2 @@
// Maksimal ukuran file dalam byte (2 MB)
export const MAX_SIZE = 2 * 1024 * 1024; // 2 MB

View File

@@ -28,13 +28,13 @@ export default function UIGlobal_Drawer({
opened: boolean;
close: () => void;
component:
| {
id: string;
name: string;
icon: string;
path: string;
}[]
| any[];
| {
id: string;
name: string;
icon: string;
path: string;
}[]
| any[];
}) {
const router = useRouter();
const [isLoading, setIsLoading] = useState(false);
@@ -77,21 +77,28 @@ export default function UIGlobal_Drawer({
</Group>
<SimpleGrid cols={component.length < 4 ? component.length : 4}>
{component.map((e, i) => (
<Stack key={i} align="center" spacing={"xs"}>
<Stack key={i} align="center" spacing={"xs"}
onClick={() => {
setPageId(e?.id);
setIsLoading(true);
router.push(e?.path, { scroll: false });
}}
>
<ActionIcon
variant="transparent"
c="white"
onClick={() => {
setPageId(e?.id);
setIsLoading(true);
router.push(e?.path, {scroll: false});
}}
>
{isLoading && e?.id === pageId ? (
{/* PAKE LOADING */}
{/* {isLoading && e?.id === pageId ? (
<ComponentGlobal_Loader />
) : (
e?.icon
)}
)} */}
{/* GA PAKE LOADING */}
{e?.icon}
</ActionIcon>
<Text fz={"sm"} align="center" color="white">
{e?.name}

View File

@@ -77,12 +77,21 @@ export default function UIGlobal_LayoutHeaderTamplate({
: router.push(routerLeft, { scroll: false });
}}
>
{isLoading ? (
{/* PAKE LOADING SAAT KLIK BACK */}
{/* {isLoading ? (
<Loader color={AccentColor.yellow} size={20} />
) : iconLeft ? (
iconLeft
) : (
<IconChevronLeft />
)} */}
{/* GA PAKE LOADING SAAT KLIK BACK */}
{iconLeft ? (
iconLeft
) : (
<IconChevronLeft />
)}
</ActionIcon>
)}

View File

@@ -28,7 +28,7 @@ export function UIGlobal_ImagePreview({ fileId }: { fileId: string }) {
const [isImage, setIsImage] = useState<boolean | null>(null);
const [isLoading, setIsLoading] = useState(false);
const url = APIs.GET({ fileId: fileId });
const url = APIs.GET({ fileId: fileId, size: "500" });
useShallowEffect(() => {
onLoadImage();

View File

@@ -2,6 +2,7 @@
import { MODEL_EVENT_PESERTA } from "@/app_modules/event/model/interface";
import {
Badge,
Button,
Center,
Pagination,
@@ -26,6 +27,7 @@ export function AdminEvent_ViewDetailPeserta({
const [isNPage, setNPage] = useState(dataPeserta.nPage);
const [isActivePage, setActivePage] = useState(1);
async function onPageClick(p: any) {
setActivePage(p);
const loadData = await adminEvent_getListPesertaById({
@@ -52,6 +54,15 @@ export function AdminEvent_ViewDetailPeserta({
<td>
<Center>{e?.User?.Profile?.email}</Center>
</td>
<td>
<Center>
{e.isPresent ? (
<Badge color="green">Hadir</Badge>
) : (
<Badge color="red">Tidak Hadir</Badge>
)}
</Center>
</td>
</tr>
));
@@ -81,6 +92,9 @@ export function AdminEvent_ViewDetailPeserta({
<th>
<Center>Email</Center>
</th>
<th>
<Center>Konfirmasi Kehadiran</Center>
</th>
</tr>
</thead>
<tbody>{tableRow}</tbody>

View File

@@ -108,15 +108,15 @@ export default function AdminEvent_ComponentTableReview({
async function onPublish({
eventId,
tanggalSelesai,
tanggal,
}: {
eventId: string;
tanggalSelesai: Date;
tanggal: Date;
}) {
const checkStatus = await event_checkStatus({ id: eventId });
if (checkStatus) {
if (moment(tanggalSelesai).diff(Date.now(), "minutes") < 0)
if (moment(tanggal).diff(Date.now(), "minutes") < 0)
return ComponentGlobal_NotifikasiPeringatan(
"Waktu acara telah lewat, Report untuk memberitahu user !"
);
@@ -267,7 +267,7 @@ export default function AdminEvent_ComponentTableReview({
</Text>
</Center>
</td>
<td>
<Center w={400}>
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan">
@@ -286,7 +286,7 @@ export default function AdminEvent_ComponentTableReview({
onClick={() =>
onPublish({
eventId: e.id,
tanggalSelesai: e.tanggalSelesai,
tanggal: e.tanggal,
})
}
>
@@ -297,7 +297,7 @@ export default function AdminEvent_ComponentTableReview({
leftIcon={<IconBan />}
radius={"xl"}
onClick={async () => {
const checkStatus = await event_checkStatus({ id: eventId });
const checkStatus = await event_checkStatus({ id: e.id });
if (checkStatus) {
open();

View File

@@ -22,6 +22,7 @@ export async function adminEvent_getListPesertaById({
eventId: eventId,
},
select: {
isPresent: true,
User: {
include: {
Profile: true,

View File

@@ -50,20 +50,20 @@ function TableStatus({ listPublish }: { listPublish: any }) {
const [eventId, setEventId] = useState("");
const [loading, setLoading] = useState(false);
const [origin, setOrigin] = useState("");
const [origin, setOrigin] = useState("");
useShallowEffect(() => {
onLoadOrigin(setOrigin);
// if (typeof window !== "undefined") {
// setOrigin(window.location.origin);
// }
}, [setOrigin]);
useShallowEffect(() => {
if (typeof window !== "undefined") {
// console.log(window.location.origin);
setOrigin(window.location.origin);
}
}, [setOrigin]);
async function onLoadOrigin(setOrigin: any) {
const res = await fetch("/api/origin-url");
const result = await res.json();
setOrigin(result.origin);
}
// async function onLoadOrigin(setOrigin: any) {
// const res = await fetch("/api/origin-url");
// const result = await res.json();
// setOrigin(result.origin);
// }
async function onSearch(s: string) {
setSearch(s);
@@ -97,11 +97,38 @@ function TableStatus({ listPublish }: { listPublish: any }) {
<td>
<Center w={200}>
<QRCode
id={e.id}
style={{ height: 70, width: 70 }}
value={`${origin}/dev/event/konfirmasi/${e.id}`}
/>
</Center>
</td>
</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>
@@ -225,6 +252,9 @@ function TableStatus({ listPublish }: { listPublish: any }) {
<th>
<Center>QR Code</Center>
</th>
<th>
<Center>Download QR</Center>
</th>
<th>
<Center>Username</Center>

View File

@@ -41,7 +41,7 @@ export default function Register() {
const res = await fetch(`/api/auth/check?id=${kodeId}`);
const result = await res.json();
onSetData(result.data.nomor);
onSetData(result.nomor);
}
async function onRegistarsi() {
@@ -64,6 +64,11 @@ export default function Register() {
const result = await res.json();
if (res.status === 400) {
setLoading(false);
ComponentGlobal_NotifikasiPeringatan(result.message);
}
if (res.status === 200) {
localStorage.removeItem("hipmi_auth_code_id");
ComponentGlobal_NotifikasiBerhasil(result.message);
@@ -73,11 +78,6 @@ export default function Register() {
nomor: data.nomor,
});
}
if (res.status === 400) {
setLoading(false);
ComponentGlobal_NotifikasiPeringatan(result.message);
}
} catch (error) {
console.log(error);
}

View File

@@ -43,7 +43,7 @@ export default function Validasi() {
useShallowEffect(() => {
const kodeId = localStorage.getItem("hipmi_auth_code_id");
if (kodeId != null) {
onCheckAuthCode({ kodeId: kodeId as string, onSetData: setData });
onCheckAuthCode({ kodeId: kodeId as string });
} else {
console.log("code id not found");
}
@@ -51,27 +51,25 @@ export default function Validasi() {
if (triggerOtp) {
const kodeId = localStorage.getItem("hipmi_auth_code_id");
if (kodeId != null) {
onCheckAuthCode({ kodeId: kodeId as string, onSetData: setData });
onCheckAuthCode({ kodeId: kodeId as string });
} else {
console.log("code id not found");
}
setTriggerOtp(false);
}
}, [triggerOtp, setData, setTriggerOtp]);
}, [triggerOtp]);
async function onCheckAuthCode({
kodeId,
onSetData,
}: {
kodeId: string;
onSetData: any;
}) {
const res = await fetch(`/api/auth/check?id=${kodeId}`);
const result = await res.json();
onSetData({
nomor: result.data.nomor,
code: result.data.otp,
setData({
nomor: result.nomor,
code: result.otp,
});
}

View File

@@ -17,7 +17,7 @@ export default function Colab_Splash() {
setHotMenu(1);
// setStatus("Publish");
router.replace(RouterColab.beranda, {scroll: false});
}, 1000);
}, 500);
}, []);
return (

View File

@@ -10,7 +10,7 @@ export default function SplashCrowd() {
const router = useRouter();
useShallowEffect(() => {
setTimeout(() => router.push(RouterCrowd.main), 1000);
setTimeout(() => router.push(RouterCrowd.main), 500);
}, []);
return (
<>

View File

@@ -1,134 +1,592 @@
"use client";
import {
UIGlobal_LayoutDefault,
UIGlobal_LayoutTamplate,
} from "@/app_modules/_global/ui";
import { Button, Paper, Skeleton, Stack, Text, Title } from "@mantine/core";
import { MODEL_EVENT } from "../model/interface";
import { useShallowEffect } from "@mantine/hooks";
import { AccentColor, MainColor } from "@/app_modules/_global/color";
import { event_funCheckKehadiran, event_funUpdateKehadiran } from "../fun";
import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event";
import { RouterEvent } from "@/app/lib/router_hipmi/router_event";
import { MainColor } from "@/app_modules/_global/color";
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
} from "@/app_modules/_global/notif_global";
import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui";
import { Button, Center, Group, Skeleton, Stack, Text } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useAtom } from "jotai";
import moment from "moment";
import { useRouter } from "next/navigation";
import { RouterEvent } from "@/app/lib/router_hipmi/router_event";
import { useState } from "react";
import { event_funUpdateKehadiran } from "../fun";
import { Event_funJoinAndConfirmEvent } from "../fun/create/fun_join_and_confirm";
import { gs_event_hotMenu } from "../global_state";
import { MODEL_EVENT } from "../model/interface";
import { Event_funJoinEvent } from "../fun/create/fun_join_event";
import "moment/locale/id";
export default function Ui_Konfirmasi({
dataEvent,
userLoginId,
eventId,
}: {
dataEvent: MODEL_EVENT;
userLoginId: string;
eventId: string;
}) {
// console.log(dataEvent);
const router = useRouter();
const [isLoading, setLoading] = useState(false);
const [data, setData] = useState<MODEL_EVENT | null>(null);
const [isJoin, setIsJoin] = useState<boolean | null>(null);
const [isPresent, setIsPresent] = useState<boolean | null>(null);
// useShallowEffect(() => {
// onLoadData({
// onPublish(val) {
// setData(val);
// },
// });
// }, [setData]);
useShallowEffect(() => {
onLoadKehadiran({
onChange(val) {
setIsPresent(val);
},
});
}, [setIsPresent]);
onLoadData();
}, []);
async function onLoadKehadiran({
onChange,
}: {
onChange: (val: boolean) => void;
}) {
const checkKehadiran = await event_funCheckKehadiran({
eventId: dataEvent.id,
userId: userLoginId as string,
});
onChange(checkKehadiran);
async function onLoadData() {
const data = await fetch(
API_RouteEvent.get_one_by_id({ eventId: eventId })
);
const res = await data.json();
setData(res.data);
}
async function onUpdateKonfirmasi() {
setLoading(true);
const res = await event_funUpdateKehadiran({
eventId: dataEvent.id,
userId: userLoginId,
});
// CEK PESERTA
useShallowEffect(() => {
onCheckPeserta();
}, []);
async function onCheckPeserta() {
const res = await fetch(
API_RouteEvent.check_peserta({ eventId: eventId, userId: userLoginId })
);
const data = await res.json();
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);
}
// =========== CEK KEHADIRAN ===========//
// Jika data kosong
if (data == null && isPresent == null) {
return <SkeletonIsDataNull />;
}
// Jika data tidak ada
if (data == null) {
return (
<>
<DataNotFound />
</>
);
}
// Jika tanggal acara sudah lewat
if (moment(data?.tanggalSelesai).diff(moment(), "minute") < 0) {
return (
<>
<EventAlreadyDone title={data?.title} eventId={eventId} />
</>
);
}
// Jika join true
if (isJoin == true && moment(data?.tanggal).diff(moment(), "minute") > 0) {
return (
<>
<UserJoinTrue title={data?.title} tanggal={data?.tanggal} />
</>
);
}
// Jika belum join dan tanggal mulai acara belum lewat
if (isJoin == false && moment(data?.tanggal).diff(moment(), "minute") > 0) {
return (
<>
<UserAllowToJoin
title={data?.title}
tanggal={data?.tanggal}
lokasi={data.lokasi}
eventId={eventId}
userLoginId={userLoginId}
/>
</>
);
}
// Jika belum join dan tanggal mulai acara sudah lewat
if (isJoin == false && moment(data?.tanggal).diff(moment(), "minute") < 0) {
return (
<>
<UserNotJoinAndEventReady
title={data?.title}
eventId={eventId}
userLoginId={userLoginId}
/>
</>
);
}
if (isPresent == false && data) {
return (
<UserNotConfirm
title={data.title}
eventId={eventId}
userLoginId={userLoginId}
/>
);
}
// Jika sudah join, sudah konfirmasi dan tanggal mulai acara sudah lewat
// if (isPresent && moment(data?.tanggal).diff(moment(), "minute") < 0)
if (
isPresent &&
isJoin &&
moment(data?.tanggal).diff(moment(), "minute") < 0
) {
return <UserAlreadyConfirm title={data.title} />;
}
}
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 UserJoinTrue({ title, tanggal }: { title: string; tanggal: Date }) {
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, Anda telah berhasil bergabung dalam
acara{" "}
<Text inherit span fw={"bold"}>
{title}
</Text>{" "}
. Mohon ditunggu hingga tanggal{" "}
<Text inherit span fw={"bold"}>
{moment(tanggal).format("DD-MM-YYYY")}
</Text>{" "}
untuk melakukan konfirmasi kehadiran melalui aplikasi HIPMI APP.
</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>
</>
);
}
function UserAllowToJoin({
title,
tanggal,
lokasi,
eventId,
userLoginId,
}: {
title: string;
tanggal: Date;
lokasi: string;
eventId: string;
userLoginId: string;
}) {
const router = useRouter();
const [isLoading, setLoading] = useState(false);
async function onJoinEvent() {
setLoading(true);
const data = {
userId: userLoginId,
eventId: eventId,
};
const res = await Event_funJoinEvent(data as any);
if (res.status === 200) {
ComponentGlobal_NotifikasiBerhasil(res.message, 2000);
router.push(RouterEvent.detail_main + dataEvent.id);
router.push(RouterEvent.detail_main + eventId);
} else {
setLoading(false);
ComponentGlobal_NotifikasiGagal(res.message);
}
}
if (isPresent === null) {
return <></>;
}
return (
<>
<UIGlobal_LayoutDefault>
<Stack h={"100vh"} align="center" justify="center">
{isPresent == null ? (
<Skeleton h={200} w={300} radius={"sm"} />
) : isPresent ? (
<Paper p={"md"} withBorder bg={AccentColor.softblue}>
<Stack align="center" justify="center">
<Text fw={"bold"} align="center">
Anda telah terkonfirmasi silahkan kembali ke beranda !
</Text>
<Title order={3}>{dataEvent.title}</Title>
<Button
loading={isLoading}
loaderPosition="center"
radius={"md"}
color="green"
c={"black"}
onClick={() => {
router.push(RouterEvent.beranda, { scroll: false });
}}
>
Beranda
</Button>
</Stack>
</Paper>
) : (
<Paper p={"md"} withBorder bg={AccentColor.softblue}>
<Stack align="center" justify="center">
<Text fw={"bold"} align="center">
Anda mengkonfirmasi bahwa anda telah datang & ikut menghadir
di event
</Text>
<Title order={3}>{dataEvent.title}</Title>
<Button
loading={isLoading}
loaderPosition="center"
radius={"xs"}
bg={MainColor.yellow}
color="yellow"
c={"black"}
onClick={() => {
onUpdateKonfirmasi();
}}
>
YA
</Button>
</Stack>
</Paper>
)}
<Stack h={"100vh"} justify="center">
<ComponentGlobal_CardStyles>
<Stack align="center" justify="center">
<Text align="center">
Halo, Bapak/Ibu. Kami dengan senang hati mengundang Anda untuk
bergabung dalam acara
<Text inherit span fw={"bold"}>
{title}
</Text>{" "}
yang akan diselenggarakan pada{" "}
<Text inherit span fw={"bold"}>
{moment(tanggal).format("LL")}
</Text>{" "}
pukul
<Text inherit span fw={"bold"}>
{moment(tanggal).format("LT")}
</Text>{" "}
di
<Text inherit span fw={"bold"}>
{lokasi}
</Text>{" "}
. Pastikan Anda sudah melakukan registrasi melalui aplikasi
[Nama Aplikasi] agar dapat berpartisipasi. Kami sangat
menantikan kehadiran Anda. Sampai jumpa di acara ini.
</Text>
<Button
loading={isLoading}
loaderPosition="center"
radius={"xs"}
bg={MainColor.yellow}
color="yellow"
c={"black"}
onClick={() => {
onJoinEvent();
}}
>
Join Event
</Button>
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</UIGlobal_LayoutDefault>
</>
);
}
function UserNotJoinAndEventReady({
title,
eventId,
userLoginId,
}: {
title: string;
eventId: string;
userLoginId: string;
}) {
const router = useRouter();
const [isLoading, setLoading] = useState(false);
async function onJoinAndKonfirmasi() {
setLoading(true);
const body = {
eventId: eventId,
userId: userLoginId,
};
const res = await Event_funJoinAndConfirmEvent(body as any);
if (res.status === 200) {
ComponentGlobal_NotifikasiBerhasil(res.message, 2000);
router.push(RouterEvent.detail_main + eventId);
} else {
setLoading(false);
ComponentGlobal_NotifikasiGagal(res.message);
}
}
return (
<>
<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{" "}
<Text inherit span fw={"bold"}>
Konfirmasi Kehadiran
</Text>{" "}
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();
}}
>
Konfirmasi Kehadiran
</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

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

View File

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

View File

@@ -3,9 +3,12 @@
import {
ActionIcon,
Avatar,
Badge,
Center,
Grid,
Group,
Loader,
Skeleton,
Stack,
Text,
Title,
@@ -26,55 +29,112 @@ 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";
import { ScrollOnly } from "next-scroll-loader";
import { event_newGetListPesertaById } from "../../fun";
export default function ComponentEvent_ListPeserta({
listPeserta,
total,
eventId,
isNewPeserta,
}: {
listPeserta: MODEL_EVENT_PESERTA[];
total: number;
eventId: string;
isNewPeserta?: boolean | null;
}) {
const router = useRouter();
const [data, setData] = useState<MODEL_EVENT_PESERTA[] | null>(null);
const [activePage, setActivePage] = useState<number>(1);
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 (
<>
<ComponentGlobal_CardStyles>
<Stack spacing={"md"} px={"sm"}>
<Center>
<Title order={5}>Daftar Peserta ({total})</Title>
</Center>
{_.isEmpty(listPeserta) ? (
{data === null ? (
<Event_ComponentSkeletonListPeserta />
) : (
<ComponentGlobal_CardStyles>
<Stack spacing={"md"} px={"sm"}>
<Center>
<Text fz={"xs"} fw={"bold"}>
- Tidak ada peserta -
</Text>
<Title order={5}>Daftar Peserta ({total})</Title>
</Center>
) : (
<Stack>
{listPeserta.map((e, i) => (
<Stack key={i} spacing={"sm"}>
{/* <ComponentGlobal_AvatarAndUsername
profile={e?.User?.Profile as any}
sizeAvatar={30}
fontSize={"sm"}
/> */}
{_.isEmpty(data) ? (
<Center>
<Text fz={"xs"} fw={"bold"}>
- Tidak ada peserta -
</Text>
</Center>
) : (
// <Stack>
// {data.map((e, i) => (
// <Stack key={i} spacing={"sm"}>
// <ComponentEvent_AvatarAndUsername
// profile={e?.User?.Profile as any}
// sizeAvatar={30}
// fontSize={"sm"}
// tanggalMulai={e?.Event?.tanggal}
// tanggalSelesai={e?.Event?.tanggalSelesai}
// isPresent={e?.isPresent}
// />
// {/* <Divider /> */}
// </Stack>
// ))}
// </Stack>
<ScrollOnly
height="90vh"
renderLoading={() => (
<Center mt={"lg"}>
<Loader color={"yellow"} />
</Center>
)}
data={data}
setData={setData as any}
moreData={async () => {
const loadData = await event_newGetListPesertaById({
eventId: eventId as string,
page: activePage + 1,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentEvent_AvatarAndUsername
profile={e?.User?.Profile as any}
profile={item?.User?.Profile as any}
sizeAvatar={30}
fontSize={"sm"}
tanggalMulai={e?.Event?.tanggal}
tanggalSelesai={e?.Event?.tanggalSelesai}
isPresent={e?.isPresent}
tanggalMulai={item?.Event?.tanggal}
tanggalSelesai={item?.Event?.tanggalSelesai}
isPresent={item?.isPresent}
/>
{/* <Divider /> */}
</Stack>
))}
</Stack>
)}
</Stack>
</ComponentGlobal_CardStyles>
)}
</ScrollOnly>
)}
</Stack>
</ComponentGlobal_CardStyles>
)}
</>
);
}
@@ -112,11 +172,7 @@ function ComponentEvent_AvatarAndUsername({
}
}
const tglMulai = moment(tanggalMulai).diff(moment(), "minutes");
const tglSelesai = moment(tanggalSelesai).diff(moment(), "minutes");
// console.log("mulai:", tglMulai, "selesai:", tglSelesai);
const tglMulai = moment(tanggalMulai).diff(moment(), "minutes") < 0;
return (
<>
@@ -153,20 +209,16 @@ function ComponentEvent_AvatarAndUsername({
</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 }}>
{tglMulai && (
<Grid.Col span={4} style={{ minHeight: 50 }}>
<Group position="right">
<Stack justify="center" h={30}>
<Text fw={"bold"} fz={fontSize ? fontSize : "sm"}>
{isPresent ? "Hadir" : "-"}
{isPresent ? (
<Badge color="green">Hadir</Badge>
) : (
<Badge>-</Badge>
)}
</Text>
</Stack>
</Group>

View File

@@ -1,5 +1,11 @@
import Event_ComponentCreateButton from "./button/button_create_event";
import Event_ComponentSkeletonBeranda from "./skeleton/comp_skeleton_beranda";
import { Event_ComponentSkeletonDetail } from "./skeleton/comp_skeleton_detail";
import { Event_ComponentSkeletonDetailData } from "./skeleton/comp_skeleton_detail_data";
import Event_ComponentSkeletonListPeserta from "./skeleton/comp_skeleton_list_peserta";
export { Event_ComponentSkeletonDetailData };
export { Event_ComponentCreateButton };
export { Event_ComponentSkeletonBeranda };
export { Event_ComponentSkeletonDetail };
export { Event_ComponentSkeletonListPeserta };

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

View File

@@ -3,25 +3,19 @@
import { Stack } from "@mantine/core";
import ComponentEvent_DetailMainData from "../../component/detail/detail_main";
import ComponentEvent_ListPeserta from "../../component/detail/list_peserta";
import { MODEL_EVENT, MODEL_EVENT_PESERTA } from "../../model/interface";
export default function Event_DetailKontribusi({
dataEvent,
listKontributor,
eventId,
totalPeserta,
}: {
dataEvent: MODEL_EVENT;
listKontributor: MODEL_EVENT_PESERTA[];
eventId: string;
totalPeserta: number;
}) {
return (
<>
<Stack spacing={"lg"} mb={"md"}>
<ComponentEvent_DetailMainData data={dataEvent} />
<ComponentEvent_ListPeserta
listPeserta={listKontributor}
total={totalPeserta}
/>
<ComponentEvent_DetailMainData eventId={eventId} />
<ComponentEvent_ListPeserta eventId={eventId} total={totalPeserta} />
</Stack>
</>
);

View File

@@ -1,11 +1,12 @@
"use client";
import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event";
import { IRealtimeData } from "@/app/lib/global_state";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import notifikasiToUser_funCreate from "@/app_modules/notifikasi/fun/create/create_notif_to_user";
import { Button, Stack } from "@mantine/core";
import { useRouter } from "next/navigation";
import { Button, Skeleton, Stack } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useState } from "react";
import { WibuRealtime } from "wibu-pkg";
import ComponentEvent_DetailMainData from "../../component/detail/detail_main";
@@ -13,31 +14,43 @@ import ComponentEvent_ListPeserta from "../../component/detail/list_peserta";
import { Event_countTotalPesertaById } from "../../fun/count/count_total_peserta_by_id";
import { Event_funJoinEvent } from "../../fun/create/fun_join_event";
import { Event_getListPesertaById } from "../../fun/get/get_list_peserta_by_id";
import { MODEL_EVENT, MODEL_EVENT_PESERTA } from "../../model/interface";
export default function Event_DetailMain({
dataEvent,
listPeserta,
userLoginId,
isJoin,
totalPeserta,
eventId,
}: {
dataEvent: MODEL_EVENT;
listPeserta: MODEL_EVENT_PESERTA[];
userLoginId: string;
isJoin: boolean;
totalPeserta: number;
eventId: string;
}) {
const router = useRouter();
const [total, setTotal] = useState(totalPeserta);
const [peserta, setPeserta] = useState(listPeserta);
const [isLoading, setLoading] = useState(false);
const [isJoinSuccess, setIsJoinSuccess] = useState<boolean | null>(null);
const [isNewPeserta, setIsNewPeserta] = useState<boolean | null>(null);
useShallowEffect(() => {
onCheckPeserta();
}, []);
async function onCheckPeserta() {
const res = await fetch(
API_RouteEvent.check_peserta({ eventId: eventId, userId: userLoginId })
);
const data = await res.json();
setIsJoinSuccess(data);
}
return (
<>
<Stack spacing={"lg"} pb={"md"}>
<ComponentEvent_DetailMainData data={dataEvent} />
{isJoin ? (
<ComponentEvent_DetailMainData
eventId={eventId}
/>
{isJoinSuccess == null ? (
<Skeleton radius={"xl"} h={40} />
) : isJoinSuccess ? (
<Button disabled radius={"xl"} color="green">
Anda Telah Ikut Serta
</Button>
@@ -50,10 +63,11 @@ export default function Event_DetailMain({
onClick={() => {
onJoin(
userLoginId,
dataEvent.id,
setPeserta,
eventId,
setTotal,
setLoading
setLoading,
setIsJoinSuccess,
setIsNewPeserta
);
}}
>
@@ -61,7 +75,11 @@ export default function Event_DetailMain({
</Button>
)}
<ComponentEvent_ListPeserta listPeserta={listPeserta} total={total} />
<ComponentEvent_ListPeserta
total={total}
eventId={eventId}
isNewPeserta={isNewPeserta}
/>
</Stack>
</>
);
@@ -70,9 +88,11 @@ export default function Event_DetailMain({
async function onJoin(
userId: string,
eventId: string,
setPeserta: any,
setTotal: any,
setLoading: any
setLoading: any,
setIsJoinSuccess: (val: boolean | null) => void,
setIsNewPeserta: any
) {
const body = {
userId: userId,
@@ -84,7 +104,7 @@ async function onJoin(
const res = await Event_funJoinEvent(body as any);
if (res.status === 200) {
const resPeserta = await Event_getListPesertaById(eventId);
setPeserta(resPeserta);
setIsNewPeserta(true);
const resTotal = await Event_countTotalPesertaById(eventId);
setTotal(resTotal);
@@ -111,7 +131,7 @@ async function onJoin(
});
}
}
setIsJoinSuccess(true);
setLoading(true);
ComponentGlobal_NotifikasiBerhasil(res.message, 2000);
} else {

View File

@@ -6,20 +6,17 @@ import { MODEL_EVENT } from "../../model/interface";
export default function Event_DetailPublish({
dataEvent,
listPeserta,
totalPeserta,
eventId,
}: {
dataEvent: MODEL_EVENT;
listPeserta: any[];
totalPeserta: number;
eventId: string;
}) {
return (
<>
<ComponentEvent_DetailData data={dataEvent} />
<ComponentEvent_ListPeserta
listPeserta={listPeserta}
total={totalPeserta}
/>
<ComponentEvent_ListPeserta eventId={eventId} total={totalPeserta} />
</>
);
}

View File

@@ -1,63 +1,27 @@
"use client";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import {
Stack
} from "@mantine/core";
import { Stack } from "@mantine/core";
import { useRouter } from "next/navigation";
import { useState } from "react";
import ComponentEvent_DetailMainData from "../../component/detail/detail_main";
import ComponentEvent_ListPeserta from "../../component/detail/list_peserta";
import { Event_countTotalPesertaById } from "../../fun/count/count_total_peserta_by_id";
import { Event_funJoinEvent } from "../../fun/create/fun_join_event";
import { Event_getListPesertaById } from "../../fun/get/get_list_peserta_by_id";
import { MODEL_EVENT, MODEL_EVENT_PESERTA } from "../../model/interface";
export default function Event_DetailRiwayat({
dataEvent,
listPeserta,
totalPeserta,
eventId,
}: {
dataEvent: MODEL_EVENT;
listPeserta: MODEL_EVENT_PESERTA[];
totalPeserta: number;
eventId: string;
}) {
const router = useRouter();
const [total, setTotal] = useState(totalPeserta);
const [peserta, setPeserta] = useState(listPeserta);
return (
<>
<Stack spacing={"lg"} py={"md"}>
<ComponentEvent_DetailMainData data={dataEvent} />
<ComponentEvent_ListPeserta listPeserta={listPeserta} total={total} />
<ComponentEvent_DetailMainData eventId={eventId} />
<ComponentEvent_ListPeserta eventId={eventId} total={total} />
</Stack>
</>
);
}
async function onJoin(
userId: string,
eventId: string,
setPeserta: any,
setTotal: any
) {
const body = {
userId: userId,
eventId: eventId,
};
await Event_funJoinEvent(body as any).then(async (res) => {
if (res.status === 200) {
await Event_getListPesertaById(eventId).then(async (val) => {
await Event_countTotalPesertaById(eventId).then((ttl) => {
setPeserta(val);
setTotal(ttl);
ComponentGlobal_NotifikasiBerhasil(res.message, 2000);
});
});
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
});
}

View File

@@ -0,0 +1,23 @@
"use server";
import prisma from "@/app/lib/prisma";
import { MODEL_EVENT_PESERTA } from "../../model/interface";
import { revalidatePath } from "next/cache";
export async function Event_funJoinAndConfirmEvent(data: MODEL_EVENT_PESERTA) {
const join = await prisma.event_Peserta.create({
data: {
eventId: data.eventId,
userId: data.userId,
isPresent: true,
},
});
if (!join) return { status: 400, message: "Gagal Join & Konfirmasi" };
revalidatePath("/dev/event/detail/main");
return {
status: 200,
message: "Berhasil Join & Konfirmasi",
};
}

View File

@@ -0,0 +1,43 @@
"use server";
import prisma from "@/app/lib/prisma";
export async function event_newGetListPesertaById({
eventId,
page,
}: {
eventId: string;
page: number;
}) {
const takeData = 10;
const skipData = page * takeData - takeData;
const data = await prisma.event_Peserta.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
eventId: eventId,
},
select: {
id: true,
active: true,
createdAt: true,
updatedAt: true,
userId: true,
isPresent: true,
User: {
select: {
Profile: true,
},
},
Event: true,
eventId: true,
},
});
return data;
}

View File

@@ -1,6 +1,7 @@
import { event_funUpdateKehadiran } from "./edit/fun_update_konfirmasi_by_user_id";
import { event_funCheckKehadiran } from "./get/fun_check_kehadiran";
import { event_funCheckPesertaByUserId } from "./get/fun_check_peserta_by_user_id";
import { event_newGetListPesertaById } from "./get/new_get_list_peserta";
import { event_getAllByStatusId } from "./get/status/get_all_by_status_id";
import { event_getMasterStatus } from "./master/get_status_event";
@@ -9,3 +10,4 @@ export { event_getMasterStatus };
export { event_funCheckPesertaByUserId };
export { event_funUpdateKehadiran };
export { event_funCheckKehadiran };
export { event_newGetListPesertaById };

View File

@@ -5,7 +5,16 @@ import { RouterEvent } from "@/app/lib/router_hipmi/router_event";
import { AccentColor } from "@/app_modules/_global/color";
import ComponentGlobal_CreateButton from "@/app_modules/_global/component/button_create";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { Affix, Box, Button, Center, Loader, rem } from "@mantine/core";
import {
Affix,
Box,
Button,
Center,
Loader,
rem,
Skeleton,
Paper,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useAtom } from "jotai";
import _ from "lodash";
@@ -14,13 +23,11 @@ import { useState } from "react";
import { ComponentEvent_CardBeranda } from "../component/card_view/card_beranda";
import { event_getListAllPublish } from "../fun/get/get_list_all_publish";
import { MODEL_EVENT } from "../model/interface";
import { Event_ComponentSkeletonBeranda } from "../component";
import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event";
export default function Event_Beranda({
dataEvent,
}: {
dataEvent: MODEL_EVENT[];
}) {
const [data, setData] = useState(dataEvent);
export default function Event_Beranda() {
const [data, setData] = useState<MODEL_EVENT[] | null>(null);
const [activePage, setActivePage] = useState(1);
const [isLoading, setIsLoading] = useState(false);
@@ -31,23 +38,27 @@ export default function Event_Beranda({
const [isShowUpdate, setIsShowUpdate] = useState(false);
useShallowEffect(() => {
onLoadData({
onPublish(val) {
setData(val);
},
});
}, [setData]);
setIsShowUpdate(false);
loadData();
}, []);
useShallowEffect(() => {
if (isTriggerEventBeranda) {
setIsShowUpdate(true);
}
}, [isTriggerEventBeranda, setIsShowUpdate]);
}, [isTriggerEventBeranda]);
async function onLoadData({ onPublish }: { onPublish: (val: any) => void }) {
async function loadData() {
const res = await fetch(API_RouteEvent.get_all({ page: activePage }));
const data = await res.json();
setData(data.data as any);
}
async function onLoadNewData() {
setIsLoading(true);
const loadData = await event_getListAllPublish({ page: 1 });
onPublish(loadData);
const res = await fetch(API_RouteEvent.get_all({ page: 1 }));
const data = await res.json();
setData(data.data as any);
setIsShowUpdate(false);
setIsTriggerEventBeranca(false);
@@ -71,13 +82,7 @@ export default function Event_Beranda({
radius={"xl"}
opacity={0.8}
onClick={() => {
onLoadData({
onPublish(val) {
setData(val);
},
});
onLoadNewData();
}}
>
Update beranda
@@ -87,7 +92,10 @@ export default function Event_Beranda({
)}
<ComponentGlobal_CreateButton path={RouterEvent.create} />
{_.isEmpty(data) ? (
{data == null ? (
<Event_ComponentSkeletonBeranda />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
<Box>
@@ -99,7 +107,7 @@ export default function Event_Beranda({
</Center>
)}
data={data}
setData={setData}
setData={setData as any}
moreData={async () => {
const loadData = await event_getListAllPublish({
page: activePage + 1,

View File

@@ -16,7 +16,7 @@ export default function Event_SplashScreen() {
setTimeout(() => {
router.replace(RouterEvent.beranda);
setHotMenu(0);
}, 1000);
}, 500);
}, []);
return (
<>

View File

@@ -11,7 +11,7 @@ export default function Forum_Splash() {
useShallowEffect(() => {
setTimeout(() => {
router.replace(RouterForum.beranda, { scroll: false });
}, 1000);
}, 500);
}, []);
return (

View File

@@ -0,0 +1,193 @@
import { AccentColor, MainColor } from "@/app_modules/_global/color";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
import { ActionIcon, Box, Group, Image, Paper, SimpleGrid, Skeleton, Stack, Text } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconUserSearch } from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { apiGetDataHome } from "../fun/get/api_home";
import { listMenuHomeBody, menuHomeJob } from "./list_menu_home";
export default function BodyHome() {
const router = useRouter()
const [dataUser, setDataUser] = useState<any>({})
const [dataJob, setDataJob] = useState<any[]>([])
const [loadingJob, setLoadingJob] = useState(true)
useShallowEffect(() => {
cekUserLogin()
getHomeJob()
}, []);
async function cekUserLogin() {
try {
const response = await apiGetDataHome("?cat=cek_profile")
if (response.success) {
setDataUser(response.data);
}
} catch (error) {
console.error(error);
}
}
async function getHomeJob() {
try {
setLoadingJob(true)
const response = await apiGetDataHome("?cat=job")
if (response.success) {
setDataJob(response.data);
}
} catch (error) {
console.error(error);
} finally {
setLoadingJob(false)
}
}
return (
<Box>
<Paper
radius={"xl"}
mb={"xs"}
style={{
borderRadius: "10px 10px 10px 10px",
border: `2px solid ${AccentColor.blue}`,
}}
>
<Image radius={"lg"} alt="logo" src={"/aset/home/home-hipmi-new.png"} />
</Paper>
<Stack my={"sm"}>
<SimpleGrid
cols={2}
spacing="md"
>
{listMenuHomeBody.map((e, i) => (
<Paper
key={e.id}
h={150}
bg={MainColor.darkblue}
style={{
borderRadius: "10px 10px 10px 10px",
border: `2px solid ${AccentColor.blue}`,
}}
onClick={() => {
if (dataUser.profile === undefined || dataUser?.profile === null) {
return ComponentGlobal_NotifikasiPeringatan(
"Lengkapi Profile"
);
} else {
if (e.link === "") {
return ComponentGlobal_NotifikasiPeringatan(
"Cooming Soon !!"
);
} else {
router.push(e.link, { scroll: false });
}
}
}}
>
<Stack align="center" justify="center" h={"100%"}>
<ActionIcon
size={50}
variant="transparent"
c={e.link === "" ? "gray.3" : "white"}
>
{e.icon}
</ActionIcon>
<Text c={e.link === "" ? "gray.3" : "white"} fz={"xs"}>
{e.name}
</Text>
</Stack>
</Paper>
))}
</SimpleGrid>
{/* Job View */}
<Paper
p={"md"}
w={"100%"}
bg={MainColor.darkblue}
style={{
borderRadius: "10px 10px 10px 10px",
border: `2px solid ${AccentColor.blue}`,
}}
>
<Stack
onClick={() => {
if (dataUser.profile === undefined || dataUser?.profile === null) {
return ComponentGlobal_NotifikasiPeringatan(
"Lengkapi Profile"
);
} else {
if (menuHomeJob.link === "") {
return ComponentGlobal_NotifikasiPeringatan(
"Cooming Soon !!"
);
} else {
return router.push(menuHomeJob.link, { scroll: false });
}
}
}}
>
<Group>
<ActionIcon
variant="transparent"
size={40}
c={menuHomeJob.link === "" ? "gray.3" : "white"}
>
{menuHomeJob.icon}
</ActionIcon>
<Text c={menuHomeJob.link === "" ? "gray.3" : "white"}>
{menuHomeJob.name}
</Text>
</Group>
{
loadingJob ?
Array(2)
.fill(null)
.map((_, i) => (
<Box key={i} mb={"md"}>
<Skeleton height={10} mt={0} radius="xl" width={"50%"} />
<Skeleton height={10} mt={10} radius="xl" />
<Skeleton height={10} mt={10} radius="xl" />
</Box>
))
: _.isEmpty(dataJob) ?
(<ComponentGlobal_IsEmptyData text="Tidak ada data" height={10} />)
: (
<SimpleGrid cols={2} spacing="md">
{dataJob.map((e, i) => (
<Stack key={e.id}>
<Group spacing={"xs"}>
<Stack h={"100%"} align="center" justify="flex-start">
<IconUserSearch size={20} color="white" />
</Stack>
<Stack spacing={0} w={"60%"}>
<Text
lineClamp={1}
fz={"sm"}
c={MainColor.yellow}
fw={"bold"}
>
{e?.Author.username}
</Text>
<Text fz={"sm"} c={"white"} lineClamp={2}>
{e?.title}
</Text>
</Stack>
</Group>
</Stack>
))}
</SimpleGrid>
)
}
</Stack>
</Paper>
</Stack>
</Box>
);
}

View File

@@ -0,0 +1,113 @@
import { APIs } from "@/app/lib";
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
import { ActionIcon, Box, Center, SimpleGrid, Stack, Text } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconUserCircle } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { apiGetDataHome } from "../fun/get/api_home";
import { Home_ComponentAvatarProfile } from "./comp_avatar_profile";
import { listMenuHomeFooter } from "./list_menu_home";
export default function FooterHome() {
const router = useRouter()
const [dataUser, setDataUser] = useState<any>({})
useShallowEffect(() => {
cekUserLogin();
}, []);
async function cekUserLogin() {
try {
const response = await apiGetDataHome("?cat=cek_profile")
if (response.success) {
setDataUser(response.data);
}
} catch (error) {
console.error(error);
}
}
return (
<Box
style={{
zIndex: 99,
borderRadius: "20px 20px 0px 0px",
}}
w={"100%"}
bottom={0}
h={"9vh"}
>
<SimpleGrid cols={listMenuHomeFooter.length + 1}>
{listMenuHomeFooter.map((e) => (
<Center h={"9vh"} key={e.id}>
<Stack align="center" spacing={0}
onClick={() => {
if (dataUser.profile === undefined || dataUser?.profile === null) {
ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile");
} else {
if (e.link == "") {
ComponentGlobal_NotifikasiPeringatan("Cooming Soon")
} else {
router.push(e.link, { scroll: false })
}
}
}}
>
<ActionIcon
radius={"xl"}
c={e.link === "" ? "gray" : "white"}
variant="transparent"
>
{e.icon}
</ActionIcon>
<Text
lineClamp={1}
c={e.link === "" ? "gray" : "white"}
fz={12}
>
{e.name}
</Text>
</Stack>
</Center>
))}
<Center h={"9vh"}>
<Stack
align="center"
spacing={2}
onClick={() => {
if (dataUser.profile === undefined || dataUser?.profile === null) {
router.push(RouterProfile.create, { scroll: false });
} else {
router.push(
RouterProfile.katalogOLD + `${dataUser?.profile}`,
{ scroll: false }
);
}
}}
>
<ActionIcon variant={"transparent"}>
{dataUser.profile === undefined || dataUser?.profile === null
?
<IconUserCircle color="white" />
:
<Home_ComponentAvatarProfile
url={APIs.GET({
fileId: dataUser?.imageId as string,
size: "50"
})}
/>
}
</ActionIcon>
<Text fz={10} c={"white"}>
Profile
</Text>
</Stack>
</Center>
</SimpleGrid>
</Box>
);
}

View File

@@ -0,0 +1,67 @@
import { RouterColab } from '@/app/lib/router_hipmi/router_colab';
import { RouterEvent } from '@/app/lib/router_hipmi/router_event';
import { RouterForum } from '@/app/lib/router_hipmi/router_forum';
import { RouterJob } from '@/app/lib/router_hipmi/router_job';
import { RouterMap } from '@/app/lib/router_hipmi/router_map';
import { RouterVote } from '@/app/lib/router_hipmi/router_vote';
import { IconAffiliate, IconBriefcase, IconHeartHandshake, IconMap2, IconMessages, IconPackageImport, IconPresentation, IconShoppingBag } from '@tabler/icons-react';
// yg ada di footer home
export const listMenuHomeFooter = [
{
id: 1,
name: "Forums",
icon: <IconMessages />,
link: RouterForum.splash,
},
{
id: 2,
name: "MarketPlace",
icon: <IconShoppingBag />,
link: "",
},
{
id: 3,
name: "Business Maps",
icon: <IconMap2 />,
link: RouterMap.splash,
},
];
// yg ada di kotak2 home (body)
export const listMenuHomeBody = [
{
id: 1,
name: "Event",
icon: <IconPresentation size={50} />,
link: RouterEvent.splash,
},
{
id: 2,
name: "Collaboration",
icon: <IconAffiliate size={50} />,
link: RouterColab.splash,
},
{
id: 3,
name: "Voting",
icon: <IconPackageImport size={50} />,
link: RouterVote.splash,
},
{
id: 4,
name: "Crowd Funding",
icon: <IconHeartHandshake size={50} />,
link: `/dev/crowd/splash`,
},
];
export const menuHomeJob = {
name: "Job Vacancy",
icon: <IconBriefcase size={50} />,
link: RouterJob.spalsh,
};

View File

@@ -104,7 +104,7 @@ export function Home_UiView({
border: `2px solid ${AccentColor.blue}`,
}}
>
<Image radius={"lg"} alt="logo" src={"/aset/home/home-hipmi.png"} />
<Image radius={"lg"} alt="logo" src={"/aset/home/home-hipmi-new.png"} />
</Paper>
<Stack my={"sm"}>

View File

@@ -0,0 +1,4 @@
export const apiGetDataHome = async (path?: string) => {
const response = await fetch(`/api/new/home${(path) ? path : ''}`)
return await response.json().catch(() => null)
}

View File

@@ -1,4 +1,6 @@
import { listMenuHomeFooter } from './component/list_menu_home';
import HomeView from "./view_home";
import HomeViewNew from "./view_home_new";
import Home_UserNotActive from "./user_non_active";
export { HomeView, Home_UserNotActive as Home_UserNonActive };
export { HomeView, HomeViewNew, listMenuHomeFooter, Home_UserNotActive as Home_UserNonActive };

View File

@@ -1,21 +1,15 @@
"use client";
import { useEffect, useState } from "react";
import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state";
import { useShallowEffect } from "@mantine/hooks";
import { useAtom } from "jotai";
import { useState } from "react";
import UIGlobal_LayoutHeaderTamplate from "../_global/ui/ui_header_tamplate";
import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate";
import { MODEL_JOB } from "../job/model/interface";
import {
ComponentHome_ButtonHeaderLeft,
ComponentHome_ButtonHeaderRight,
} from "./component/button_header";
import notifikasi_countUserNotifikasi from "../notifikasi/fun/count/fun_count_by_id";
import { ComponentHome_ButtonHeaderLeft, ComponentHome_ButtonHeaderRight, } from "./component/button_header";
import { Home_UiFooter, Home_UiView } from "./component/ui_home";
import { MODEL_USER } from "./model/interface";
import { useShallowEffect } from "@mantine/hooks";
import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state";
import { useAtom } from "jotai";
import notifikasi_countUserNotifikasi from "../notifikasi/fun/count/fun_count_by_id";
import { Center, Text, Title } from "@mantine/core";
import { useRouter } from "next/navigation";
export default function HomeView({
dataUser,
@@ -26,7 +20,6 @@ export default function HomeView({
dataJob: MODEL_JOB[];
countNotifikasi: number;
}) {
const router = useRouter();
const [countNtf, setCountNtf] = useState(countNotifikasi);
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
const [countLoadNtf, setCountLoadNtf] = useAtom(gs_count_ntf);
@@ -60,15 +53,11 @@ export default function HomeView({
onLoad(loadNotif);
}
// console.log(dataUser, "dipage")
return (
<>
<UIGlobal_LayoutTamplate
header={
// <Center>
// <Title order={3}>HIPMI</Title>
// </Center>
<UIGlobal_LayoutHeaderTamplate
title="HIPMI"
customButtonLeft={

View File

@@ -0,0 +1,127 @@
"use client";
import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state";
import { RouterNotifikasi } from "@/app/lib/router_hipmi/router_notifikasi";
import { RouterUserSearch } from "@/app/lib/router_hipmi/router_user_search";
import { ActionIcon, Indicator, Text } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconBell, IconUserSearch } from "@tabler/icons-react";
import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { MainColor } from "../_global/color";
import { ComponentGlobal_NotifikasiPeringatan } from "../_global/notif_global";
import UIGlobal_LayoutHeaderTamplate from "../_global/ui/ui_header_tamplate";
import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate";
import notifikasi_countUserNotifikasi from "../notifikasi/fun/count/fun_count_by_id";
import BodyHome from "./component/body_home";
import FooterHome from "./component/footer_home";
import { apiGetDataHome } from "./fun/get/api_home";
export default function HomeViewNew({ countNotifikasi }: { countNotifikasi: number; }) {
const [countNtf, setCountNtf] = useState(countNotifikasi);
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
const [countLoadNtf, setCountLoadNtf] = useAtom(gs_count_ntf);
const [dataUser, setDataUser] = useState<any>({})
const router = useRouter();
useShallowEffect(() => {
onLoadNotifikasi({
onLoad(val) {
setCountNtf(val);
},
});
setCountNtf(countLoadNtf as any);
}, [countLoadNtf, setCountNtf]);
useShallowEffect(() => {
setCountNtf(countNtf + newUserNtf);
setNewUserNtf(0);
}, [newUserNtf, setCountNtf]);
async function onLoadNotifikasi({ onLoad }: { onLoad: (val: any) => void }) {
const loadNotif = await notifikasi_countUserNotifikasi();
onLoad(loadNotif);
}
useShallowEffect(() => {
cekUserLogin();
}, []);
async function cekUserLogin() {
try {
const response = await apiGetDataHome("?cat=cek_profile")
if (response.success) {
setDataUser(response.data);
}
} catch (error) {
console.error(error);
}
}
return (
<>
<UIGlobal_LayoutTamplate
header={
<UIGlobal_LayoutHeaderTamplate
title="HIPMI"
customButtonLeft={
<ActionIcon
radius={"xl"}
variant={"transparent"}
onClick={() => {
if (dataUser.profile === undefined || dataUser?.profile === null) {
ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile");
} else {
router.push(RouterUserSearch.main, { scroll: false });
}
}}
>
<IconUserSearch color="white" />
</ActionIcon>
}
customButtonRight={
<ActionIcon
variant="transparent"
onClick={() => {
if (dataUser.profile === undefined || dataUser?.profile === null) {
ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile");
} else {
router.push(RouterNotifikasi.categoryApp({ name: "semua" }), {
scroll: false,
});
}
}}
>
{
countNotifikasi > 0
?
<Indicator
processing
color={MainColor.yellow}
label={
<Text fz={10} c={MainColor.darkblue}>
{countNotifikasi > 99 ? "99+" : countNotifikasi}
</Text>
}
>
<IconBell color="white" />
</Indicator>
:
<IconBell color="white" />
}
</ActionIcon>
}
/>
}
footer={<FooterHome />}
>
<BodyHome />
</UIGlobal_LayoutTamplate>
</>
);
}

View File

@@ -0,0 +1,151 @@
import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin";
import {
RouterPortofolio,
RouterProfile,
} from "@/app/lib/router_hipmi/router_katalog";
import { AccentColor } from "@/app_modules/_global/color";
import {
gs_admin_navbar_menu,
gs_admin_navbar_subMenu,
} from "@/app_modules/admin/_admin_global/new_global_state";
import Component_ButtonLogout from "@/app_modules/auth/logout/view";
import {
ActionIcon,
Drawer,
Group,
SimpleGrid,
Stack,
Text,
} from "@mantine/core";
import { IconDashboard } from "@tabler/icons-react";
import {
IconEdit,
IconPencilPlus,
IconPhotoEdit,
IconPolaroid,
IconX,
} from "@tabler/icons-react";
import { useAtom } from "jotai";
import { useParams, useRouter } from "next/navigation";
export default function DrawerKatalogNew({
opened,
close,
userRoleId,
userId,
}: {
opened: boolean;
close: () => void;
userRoleId: string;
userId: string;
}) {
const param = useParams<{ id: string }>();
const router = useRouter();
const [activeId, setActiveId] = useAtom(gs_admin_navbar_menu);
const [activeChildId, setActiveChildId] = useAtom(gs_admin_navbar_subMenu);
const listPage = [
{
id: "1",
name: "Edit profile",
icon: <IconEdit />,
path: RouterProfile.edit + param.id,
},
{
id: "2",
name: "Ubah foto profile",
icon: <IconPhotoEdit />,
path: RouterProfile.update_foto_profile + param.id,
},
{
id: "3",
name: "Ubah latar belakang",
icon: <IconPolaroid />,
path: RouterProfile.update_foto_background + param.id,
},
{
id: "4",
name: "Tambah portofolio",
icon: <IconPencilPlus />,
path: RouterPortofolio.create + param.id,
},
];
return (
<>
<Drawer
opened={opened}
onClose={() => close()}
position={"bottom"}
size={"auto"}
withCloseButton={false}
styles={{
content: {
padding: 0,
position: "absolute",
margin: "auto",
backgroundColor: "transparent",
left: 0,
right: 0,
width: 500,
},
body: {
backgroundColor: AccentColor.darkblue,
borderTop: `2px solid ${AccentColor.blue}`,
borderRight: `1px solid ${AccentColor.blue}`,
borderLeft: `1px solid ${AccentColor.blue}`,
borderRadius: "20px 20px 0px 0px",
color: "white",
paddingBottom: "5%",
},
}}
>
<Stack spacing={"xs"}>
<Group position="right">
<ActionIcon onClick={close} variant="transparent">
<IconX color="white" />
</ActionIcon>
</Group>
<SimpleGrid cols={4}>
{listPage.map((e, i) => (
<Stack key={i} align="center" spacing={"xs"}
onClick={() => {
router.push(e.path, { scroll: false });
}}
>
<ActionIcon variant="transparent" c="white" >
{e.icon}
</ActionIcon>
<Text align="center" color="white">
{e.name}
</Text>
</Stack>
))}
<Component_ButtonLogout userId={userId} />
{userRoleId != "1" && userRoleId != "" && (
<Stack align="center" spacing={"xs"}>
<ActionIcon
variant="transparent"
c="white"
onClick={() => {
setActiveId("Main");
setActiveChildId("");
router.push(RouterAdminDashboard.main_admin, {
scroll: false,
});
}}
>
<IconDashboard />
</ActionIcon>
<Text align="center" color="white">
Dashboard Admin
</Text>
</Stack>
)}
</SimpleGrid>
</Stack>
</Drawer>
</>
);
}

View File

@@ -1,2 +1,3 @@
export var validRegex =
/^([a-zA-Z0-9\.!#$%&'*+/=?^_`{|}~-]+)@([a-zA-Z0-9])+.([a-z]+)(.[a-z]+)?$/;
export const gmailRegex = /^[a-zA-Z0-9._%+-]+@gmail\.com$/;

View File

@@ -1,2 +1,4 @@
import ViewKatalogNew from "./view_katalog_new";
export { Katalog_MainView } from "./view_katalog";
export { ViewKatalogNew }

View File

@@ -1,3 +1,5 @@
import KatalogLayout from "./layout";
import LayoutKatalogNew from "./layout_new";
export { KatalogLayout };
export { LayoutKatalogNew }

View File

@@ -0,0 +1,66 @@
'use client'
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { UIGlobal_LayoutHeaderTamplate, UIGlobal_LayoutTamplate } from "@/app_modules/_global/ui";
import { apiGetUserProfile } from "@/app_modules/user";
import { ActionIcon } from "@mantine/core";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { IconDotsVertical } from "@tabler/icons-react";
import { useParams } from "next/navigation";
import { useState } from "react";
import DrawerKatalogNew from "../component/drawer_katalog_new";
export default function LayoutKatalogNew({ children }: { children: any }) {
const param = useParams<{ id: string }>()
const [authorId, setAuthorId] = useState("")
const [userRoleId, setUserRoleId] = useState("")
const [userLoginId, setUserLoginId] = useState("")
const [opened, { open, close }] = useDisclosure()
const [loading, setLoading] = useState(true);
async function getProfile() {
try {
setLoading(true)
const response = await apiGetUserProfile(`?profile=${param.id}`)
const response2 = await funGetUserIdByToken()
if (response.success) {
setAuthorId(response.data.id)
setUserRoleId(response.data.masterUserRoleId)
setUserLoginId(response2)
}
} catch (error) {
console.error(error);
} finally {
setLoading(false)
}
}
useShallowEffect(() => {
getProfile()
}, [])
return (
<>
<UIGlobal_LayoutTamplate
header={
<UIGlobal_LayoutHeaderTamplate
title="KATALOG"
customButtonRight={
loading ?
<ActionIcon disabled variant="transparent"></ActionIcon> :
authorId == userLoginId ? (
<ActionIcon c="white" variant="transparent" onClick={() => open()}>
<IconDotsVertical />
</ActionIcon>
) : (
<ActionIcon disabled variant="transparent"></ActionIcon>
)
}
/>
}
>
{children}
<DrawerKatalogNew opened={opened} close={() => close()} userRoleId={userRoleId} userId={userLoginId} />
</UIGlobal_LayoutTamplate>
</>
)
}

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