From 075d4809697348172abfccc08993a9817e291b33 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Mon, 10 Feb 2025 12:15:43 +0800 Subject: [PATCH 1/5] fix error server --- .env.build | 9 +++ build.wibu | 3 + src/app/(auth)/_lib/decrypt.back.txt | 22 +++++ src/app/(auth)/_lib/decrypt.ts | 35 +++++++- .../admin/voting/dashboard/riwayat/route.ts | 80 ++++++++++--------- src/app/api/auth/logout/route.ts | 49 ++++++++---- src/app/api/auth/validasi/route.ts | 19 ++++- src/app/api/master/bank/route.ts | 4 +- src/app/dev/check-cookies/page.tsx | 21 ----- src/app_modules/check_cookies/index.ts | 5 -- .../check_cookies/layout_cek_cookies.tsx | 48 ----------- .../check_cookies/ui_check_cookies.tsx | 22 ----- src/middleware.ts | 20 ++++- 13 files changed, 177 insertions(+), 160 deletions(-) create mode 100644 .env.build create mode 100644 build.wibu create mode 100644 src/app/(auth)/_lib/decrypt.back.txt delete mode 100644 src/app/dev/check-cookies/page.tsx delete mode 100644 src/app_modules/check_cookies/index.ts delete mode 100644 src/app_modules/check_cookies/layout_cek_cookies.tsx delete mode 100644 src/app_modules/check_cookies/ui_check_cookies.tsx diff --git a/.env.build b/.env.build new file mode 100644 index 00000000..4529a401 --- /dev/null +++ b/.env.build @@ -0,0 +1,9 @@ +DATABASE_URL="postgresql://bip:Production_123@localhost:5433/hipmi_build?schema=public" +WIBU_PWD="QWERTYUIOPLKJHGFDSAZXCVBNMQAZWSXEDCRFVTGBYHNUJMIKOLPPOIUYTREWQLKJHGFDSAMNBVCXZlghvftyguhijknhbgvcfytguu8okjnhbgvfty7u8oilkjnhgvtygu7u8ojilnkhbgvhujnkhghvjhukjnhb" +Client_KEY="SB-Mid-client-9NDTxltqdZrEB9m-" +Server_KEY="SB-Mid-server-NyltU-U7fLVQd1nv1LWBKylr" +MAPBOX_TOKEN="pk.eyJ1IjoibWFsaWtrdXJvc2FraSIsImEiOiJjbHppZHh2enYwZnQ3MmlyMWc2Y2RlMzZoIn0.XssvJvq_iniclf8UhvXaIg" +WS_APIKEY="eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjp7ImlkIjoiY20wdXIxeXh3MDAwMDU2bnNqbHI2MTg3cCIsIm5hbWUiOiJiYWdhcyIsImVtYWlsIjoiYmFnYXNAZ21haWwuY29tIiwiQXBpS2V5IjpbeyJpZCI6ImNtMHVyMXl5MzAwMDI1Nm5zazNia2xyc28iLCJuYW1lIjoiZGVmYXVsdCJ9XX0sImlhdCI6MTcyNTk1NjMyMSwiZXhwIjo0ODgxNzE2MzIxfQ.9D3YszZA_ljrkTKMcgo03u7PL5mo9OaoM41rbUrOsz8" +NEXT_PUBLIC_WIBU_REALTIME_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inp5aml4c2J1c2diYnR2am9namhvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MjY3Mzk1NDUsImV4cCI6MjA0MjMxNTU0NX0.jHNW5Pwhj-KXUQOMqzILaAz62k3xlKEL5XKE4xoR7Xc" +NEXT_PUBLIC_BASE_TOKEN_KEY="QWERTYUIOPLKJHGFDSAZXCVBNMQAZWSXEDCRFVTGBYHNUJMIKOLPPOIUYTREWQLKJHGFDSAMNBVCXZlghvftyguhijknhbgvcfytguu8okjnhbgvfty7u8oilkjnhgvtygu7u8ojilnkhbgvhujnkhghvjhukjnhb" +NEXT_PUBLIC_BASE_SESSION_KEY="hipmi-key" \ No newline at end of file diff --git a/build.wibu b/build.wibu new file mode 100644 index 00000000..62d352e1 --- /dev/null +++ b/build.wibu @@ -0,0 +1,3 @@ +bun --env-file=.env.build prisma db push +bun --env-file=.env.build prisma db seed +bun --env-file=.env.build run build \ No newline at end of file diff --git a/src/app/(auth)/_lib/decrypt.back.txt b/src/app/(auth)/_lib/decrypt.back.txt new file mode 100644 index 00000000..410a7369 --- /dev/null +++ b/src/app/(auth)/_lib/decrypt.back.txt @@ -0,0 +1,22 @@ +import { jwtVerify } from "jose"; + +export async function decrypt({ + token, + encodedKey, +}: { + token: string; + encodedKey: string; +}): Promise | null> { + try { + const enc = new TextEncoder().encode(encodedKey); + const { payload } = await jwtVerify(token, enc, { + algorithms: ["HS256"], + }); + return (payload.user as Record) || null; + } catch (error) { + console.error("Gagal verifikasi session", error); + return null; + } +} + +// wibu:0.2.82 diff --git a/src/app/(auth)/_lib/decrypt.ts b/src/app/(auth)/_lib/decrypt.ts index 410a7369..0883f2b3 100644 --- a/src/app/(auth)/_lib/decrypt.ts +++ b/src/app/(auth)/_lib/decrypt.ts @@ -7,16 +7,43 @@ export async function decrypt({ token: string; encodedKey: string; }): Promise | null> { + if (!token || !encodedKey) { + console.error("Missing required parameters:", { + hasToken: !!token, + hasEncodedKey: !!encodedKey, + }); + return null; + } + try { const enc = new TextEncoder().encode(encodedKey); const { payload } = await jwtVerify(token, enc, { algorithms: ["HS256"], }); - return (payload.user as Record) || null; + + if (!payload || !payload.user) { + console.error("Invalid payload structure:", { + hasPayload: !!payload, + hasUser: payload ? !!payload.user : false, + }); + return null; + } + + // Logging untuk debug + // console.log("Decrypt successful:", { + // payloadExists: !!payload, + // userExists: !!payload.user, + // tokenPreview: token.substring(0, 10) + "...", + // }); + + return payload.user as Record; } catch (error) { - console.error("Gagal verifikasi session", error); + console.error("Token verification failed:", { + error, + tokenLength: token?.length, + errorName: error instanceof Error ? error.name : "Unknown error", + errorMessage: error instanceof Error ? error.message : String(error), + }); return null; } } - -// wibu:0.2.82 diff --git a/src/app/api/admin/voting/dashboard/riwayat/route.ts b/src/app/api/admin/voting/dashboard/riwayat/route.ts index 3857af0e..c377c3de 100644 --- a/src/app/api/admin/voting/dashboard/riwayat/route.ts +++ b/src/app/api/admin/voting/dashboard/riwayat/route.ts @@ -3,42 +3,46 @@ import backendLogger from "@/util/backendLogger"; import { NextResponse } from "next/server"; export async function GET(request: Request) { - const method = request.method; - if (method !== "GET") { - return NextResponse.json({ - success: false, - message: "Method not allowed", + if (request.method !== "GET") { + return NextResponse.json( + { + success: false, + message: "Method not allowed", + }, + { status: 405 } + ); + } + + try { + let fixData; + fixData = await prisma.voting.count({ + where: { + Voting_Status: { + name: "Publish", }, - { status: 405 } - ) - } - try { - let fixData; - fixData = await prisma.voting.count({ - where: { - Voting_Status: { - name: "Publish", - }, - isArsip: true, - } - }) - return NextResponse.json({ - success: true, - message: 'Success get data voting dashboard', - data: fixData - }, - { status: 200 } - ) - } catch (error) { - backendLogger.error('Error get data voting dashboard >>', error); - NextResponse.json({ - success: false, - message: 'Error get data voting dashboard', - reason: (error as Error).message - }, - { status: 500 } - ) - } finally { - await prisma.$disconnect(); - } -} \ No newline at end of file + isArsip: true, + }, + }); + + return NextResponse.json( + { + success: true, + message: "Success get data voting dashboard", + data: fixData, + }, + { status: 200 } + ); + } catch (error) { + backendLogger.error("Error get data voting dashboard >>", error); + return NextResponse.json( + { + success: false, + message: "Error get data voting dashboard", + reason: (error as Error).message, + }, + { status: 500 } + ); + } finally { + await prisma.$disconnect(); + } +} diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts index 44a4a2ab..a3e0304a 100644 --- a/src/app/api/auth/logout/route.ts +++ b/src/app/api/auth/logout/route.ts @@ -1,20 +1,39 @@ +import { decrypt } from "@/app/(auth)/_lib/decrypt"; import { cookies } from "next/headers"; -import { NextRequest, NextResponse } from "next/server"; +import { 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, - // }, - // }); +export async function GET() { + const sessionKey = process.env.NEXT_PUBLIC_BASE_SESSION_KEY!; // Gunakan environment variable yang tidak diekspos ke client-side + if (!sessionKey) { + return NextResponse.json( + { success: false, message: "Session key tidak ditemukan" }, + { status: 500 } + ); + } - const del = cookies().delete(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!); - return NextResponse.json( - { success: true, message: "Logout Berhasil" }, - { status: 200 } - ); + const cookieStore = cookies(); + const sessionCookie = cookieStore.get(sessionKey); + + if (!sessionCookie) { + return NextResponse.json( + { success: false, message: "Session tidak ditemukan" }, + { status: 400 } + ); + } + + try { + cookieStore.delete(sessionKey); + return NextResponse.json( + { success: true, message: "Logout berhasil" }, + { status: 200 } + ); + } catch (error) { + console.error("Gagal menghapus cookie:", error); + return NextResponse.json( + { success: false, message: "Gagal melakukan logout" }, + { status: 500 } + ); + } } diff --git a/src/app/api/auth/validasi/route.ts b/src/app/api/auth/validasi/route.ts index c9f9814e..6df13d37 100644 --- a/src/app/api/auth/validasi/route.ts +++ b/src/app/api/auth/validasi/route.ts @@ -38,7 +38,14 @@ export async function POST(req: Request) { user: dataUser as any, }); - return NextResponse.json( + if (!token) { + return NextResponse.json( + { success: false, message: "Gagal membuat session" }, + { status: 500 } + ); + } + // Buat response dengan token dalam cookie + const response = NextResponse.json( { success: true, message: "Berhasil Login", @@ -47,6 +54,16 @@ export async function POST(req: Request) { }, { status: 200 } ); + + // Set cookie dengan token yang sudah dipastikan tidak null + response.cookies.set(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!, token, { + path: "/", + sameSite: "lax", + secure: process.env.NODE_ENV === "production", + maxAge: 30 * 24 * 60 * 60, // 30 hari dalam detik (1 bulan) + }); + + return response; } catch (error) { backendLogger.log("API Error or Server Error", error); return NextResponse.json( diff --git a/src/app/api/master/bank/route.ts b/src/app/api/master/bank/route.ts index 2ce3228b..146ac8d9 100644 --- a/src/app/api/master/bank/route.ts +++ b/src/app/api/master/bank/route.ts @@ -21,13 +21,11 @@ export async function GET(request: Request) { }, }); - await prisma.$disconnect(); return NextResponse.json( { success: true, message: "Berhasil mendapatkan data", data: res }, { status: 200 } ); } catch (error) { - await prisma.$disconnect(); backendLogger.error("Error Get Master Bank >>", error); return NextResponse.json( { @@ -37,5 +35,7 @@ export async function GET(request: Request) { }, { status: 500 } ); + } finally { + await prisma.$disconnect(); } } diff --git a/src/app/dev/check-cookies/page.tsx b/src/app/dev/check-cookies/page.tsx deleted file mode 100644 index b56d1956..00000000 --- a/src/app/dev/check-cookies/page.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; -import { RouterHome } from "@/app/lib/router_hipmi/router_home"; -import { funGetUserIdByToken } from "@/app_modules/_global/fun/get"; -import { funGlobal_getUserById } from "@/app_modules/_global/fun/get/fun_get_user_by_id"; -import { CheckCookies_UiView } from "@/app_modules/check_cookies"; -import { redirect } from "next/navigation"; - -export default async function Page() { - // const userLoginId = await funGetUserIdByToken(); - // const dataUser = await funGlobal_getUserById({ userId: userLoginId }); - - // if (dataUser?.masterUserRoleId === "1") { - // return redirect(RouterHome.main_home); - // } - - // if (dataUser?.masterUserRoleId !== "1") { - // return redirect(RouterAdminDashboard.splash_admin); - // } - - // return ; -} diff --git a/src/app_modules/check_cookies/index.ts b/src/app_modules/check_cookies/index.ts deleted file mode 100644 index c5fdd44c..00000000 --- a/src/app_modules/check_cookies/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { CheckCookies_UiLayout } from "./layout_cek_cookies"; -import { CheckCookies_UiView } from "./ui_check_cookies"; - -export { CheckCookies_UiView }; -export { CheckCookies_UiLayout }; diff --git a/src/app_modules/check_cookies/layout_cek_cookies.tsx b/src/app_modules/check_cookies/layout_cek_cookies.tsx deleted file mode 100644 index b328354d..00000000 --- a/src/app_modules/check_cookies/layout_cek_cookies.tsx +++ /dev/null @@ -1,48 +0,0 @@ -"use client"; - -import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; -import { useShallowEffect } from "@mantine/hooks"; -import { redirect, useRouter } from "next/navigation"; -import { MODEL_USER } from "../home/model/interface"; -import { RouterHome } from "@/app/lib/router_hipmi/router_home"; -import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; - -export function CheckCookies_UiLayout({ - children, - dataUser, -}: { - children: React.ReactNode; - dataUser: MODEL_USER; -}) { - const router = useRouter(); - - // if (dataUser.active == false){ - // router.push(RouterHome.home_user_non_active, { scroll: false }); - // return children - // } - - - // useShallowEffect(() => { - // onCheckCookies(); - // }, []); - - // async function onCheckCookies() { - // const cek = await fetch("/api/check-cookies"); - - // const result = await cek.json(); - - // if (result.success === false) { - // router.push(RouterAuth.login, { scroll: false }); - // } - // } - - // if (dataUser.masterUserRoleId === "1") { - // router.push(RouterHome.main_home, { scroll: false }); - // } - - // if (dataUser.masterUserRoleId !== "1") { - // router.push(RouterAdminDashboard.splash_admin, { scroll: false }); - // } - - return <>{children}; -} diff --git a/src/app_modules/check_cookies/ui_check_cookies.tsx b/src/app_modules/check_cookies/ui_check_cookies.tsx deleted file mode 100644 index f7a18b31..00000000 --- a/src/app_modules/check_cookies/ui_check_cookies.tsx +++ /dev/null @@ -1,22 +0,0 @@ -"use client"; - -import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; -import { Button, Center } from "@mantine/core"; -import { useRouter } from "next/navigation"; -import { UIGlobal_LayoutDefault } from "../_global/ui"; - -export function CheckCookies_UiView() { - const router = useRouter(); - - return ( - <> - -
- -
-
- - ); -} diff --git a/src/middleware.ts b/src/middleware.ts index 83574b35..d0d05c35 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,6 +1,5 @@ -import { NextRequest, NextResponse } from "next/server"; import { jwtVerify } from "jose"; -import { apies, pages } from "./lib/routes"; +import { NextRequest, NextResponse } from "next/server"; type MiddlewareConfig = { apiPath: string; @@ -110,7 +109,7 @@ export const middleware = async (req: NextRequest) => { // Preserve token in cookie when redirecting if (token) { response.cookies.set(sessionKey, token, { - httpOnly: true, + // httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "lax", path: "/", @@ -145,6 +144,19 @@ export const middleware = async (req: NextRequest) => { const userValidateJson = await userValidate.json(); + if (userValidateJson.success == true && userValidateJson.data == null) { + const logout = await fetch(new URL("/api/auth/logout", req.url), { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + }); + + if (!logout.ok) { + throw new Error("Failed to logout user"); + } + } + if (!userValidateJson.data.active) { return setCorsHeaders( NextResponse.redirect(new URL("/waiting-room", req.url)) @@ -186,7 +198,7 @@ export const middleware = async (req: NextRequest) => { // Ensure token is preserved in cookie if (token) { response.cookies.set(sessionKey, token, { - httpOnly: true, + // httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "lax", path: "/", From 1ca1042c44698d61c72ed89a4c790ab64e0d9aa2 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Mon, 10 Feb 2025 12:15:57 +0800 Subject: [PATCH 2/5] chore(release): 1.2.50 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 392cab00..a2e79c67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [1.2.50](https://github.com/bipproduction/hipmi/compare/v1.2.49...v1.2.50) (2025-02-10) + ## [1.2.49](https://github.com/bipproduction/hipmi/compare/v1.2.48...v1.2.49) (2025-02-07) ## [1.2.48](https://github.com/bipproduction/hipmi/compare/v1.2.47...v1.2.48) (2025-02-07) diff --git a/package.json b/package.json index 5a153c7f..70dcda96 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hipmi", - "version": "1.2.49", + "version": "1.2.50", "private": true, "prisma": { "seed": "bun prisma/seed.ts" From 6b493b755495aa647a6dde712f51fb1c4a72fe61 Mon Sep 17 00:00:00 2001 From: nico Date: Mon, 10 Feb 2025 12:17:49 +0800 Subject: [PATCH 3/5] Tambahan Hari Ini --- src/app/api/admin/forum/komentar/route.ts | 116 +++++++ src/app/api/admin/forum/posting/route.ts | 150 +++++++++ src/app/api/admin/forum/publish/route.ts | 38 ++- .../admin/voting/dashboard/riwayat/route.ts | 2 +- .../admin/forum/lib/api_fetch_admin_forum.ts | 55 +++- .../admin/forum/main/dashboard.tsx | 6 +- .../admin/forum/sub_menu/table_posting.tsx | 301 ++++++++++-------- src/middleware.ts | 3 +- 8 files changed, 532 insertions(+), 139 deletions(-) create mode 100644 src/app/api/admin/forum/komentar/route.ts create mode 100644 src/app/api/admin/forum/posting/route.ts diff --git a/src/app/api/admin/forum/komentar/route.ts b/src/app/api/admin/forum/komentar/route.ts new file mode 100644 index 00000000..4fac2a60 --- /dev/null +++ b/src/app/api/admin/forum/komentar/route.ts @@ -0,0 +1,116 @@ +import { count } from 'console'; +import { prisma } from "@/app/lib"; +import backendLogger from "@/util/backendLogger"; +import { NextResponse } from "next/server"; +import _ from 'lodash'; + +export async function GET(request: Request, { komentarId }: { komentarId: string }) { + const method = request.method; + if (method !== "GET") { + return NextResponse.json({ + success: false, + message: "Method not allowed" + }, + { status: 405 } + ); + } + + const { searchParams } = new URL(request.url); + const search = searchParams.get("search"); + const page = searchParams.get("page"); + const takeData = 10; + const skipData = Number(page) * takeData - takeData; + + console.log("Ini page", page) + + try { + let fixData; + + + + if (!page) { + fixData = await prisma.forum_ReportKomentar.findMany({ + + orderBy: { + createdAt: "desc" + }, + where: { + forum_KomentarId: komentarId, + }, + select: { + id: true, + isActive: true, + createdAt: true, + deskripsi: true, + ForumMaster_KategoriReport: true, + User: { + select: { + Profile: { + select: { + id: true, + name: true, + }, + }, + }, + }, + }, + }) + } else { + const data = await prisma.forum_ReportKomentar.findMany({ + take: takeData, + skip: skipData, + orderBy: { + createdAt: "desc", + }, + where: { + forum_KomentarId: komentarId, + }, + select: { + id: true, + isActive: true, + createdAt: true, + deskripsi: true, + ForumMaster_KategoriReport: true, + User: { + select: { + Profile: { + select: { + id: true, + name: true, + }, + }, + }, + }, + }, + }) + const nCount = await prisma.forum_ReportKomentar.count({ + where: { + forum_KomentarId: komentarId, + } + }) + + fixData = { + data: data, + nCount: _.ceil(nCount / takeData) + } + } + console.log("Ini fixData", fixData) + return NextResponse.json({ + success: true, + message: "Success get data forum komentar", + data: fixData, + }, + { status: 200 } + ) + } catch (error) { + backendLogger.error("Error get data forum komentar", error); + return NextResponse.json({ + success: false, + message: "Error get data forum komentar", + reason: (error as Error).message + }, + ) + } finally { + await prisma.$disconnect(); + } +} \ No newline at end of file diff --git a/src/app/api/admin/forum/posting/route.ts b/src/app/api/admin/forum/posting/route.ts new file mode 100644 index 00000000..b2a21dba --- /dev/null +++ b/src/app/api/admin/forum/posting/route.ts @@ -0,0 +1,150 @@ +import { prisma } from "@/app/lib"; +import backendLogger from "@/util/backendLogger"; +import _ from "lodash"; +import { NextResponse } from "next/server"; + +export async function GET(request: Request, + { postingId }: { postingId: string }) { + const method = request.method; + if (method !== "GET") { + return NextResponse.json({ + success: false, + message: "Method not allowed", + }, + { status: 405 } + ) + } + + + const { searchParams } = new URL(request.url); + const search = searchParams.get('search'); + const page = searchParams.get('page'); + const takeData = 10; + const skipData = Number(page) * takeData - takeData; + + try { + let fixData; + + if (!page) { + fixData = await prisma.forum_ReportPosting.findMany({ + + orderBy: { + createdAt: "desc", + }, + where: { + forum_PostingId: postingId, + }, + select: { + id: true, + deskripsi: true, + createdAt: true, + User: { + select: { + id: true, + username: true, + Profile: { + select: { + name: true, + }, + }, + }, + }, + ForumMaster_KategoriReport: { + select: { + id: true, + title: true, + deskripsi: true, + }, + }, + }, + }); + } else { + const data = await prisma.forum_ReportPosting.findMany({ + take: takeData, + skip: skipData, + orderBy: { + createdAt: "desc", + }, + where: { + Forum_Posting: { + isActive: true, + diskusi: { + contains: search ? search : '', + mode: "insensitive" + } + }, + + }, + select: { + id: true, + isActive: true, + createdAt: true, + deskripsi: true, + forumMaster_KategoriReportId: true, + ForumMaster_KategoriReport: { + select: { + id: true, + title: true, + deskripsi: true, + }, + }, + + forum_PostingId: true, + Forum_Posting: { + select: { + id: true, + diskusi: true, + ForumMaster_StatusPosting: { + select: { + id: true, + status: true, + } + }, + Author: { + select: { + id: true, + username: true + } + } + }, + }, + userId: true, + User: { + select: { + id: true, + username: true, + }, + }, + }, + }); + const nCount = await prisma.forum_ReportPosting.count({ + where: { + isActive: true, + } + }) + + + fixData = { + data: data, + nCount: _.ceil(nCount / takeData) + } + } + return NextResponse.json({ + success: true, + data: fixData, + message: "Success get data forum posting" + }, + { status: 200 } + ) + } catch (error) { + backendLogger.error("Error get data forum posting >>", error); + return NextResponse.json({ + success: false, + message: "Error get data forum posting", + }, + { status: 500 } + ) + } finally { + await prisma.$disconnect(); + } +} \ No newline at end of file diff --git a/src/app/api/admin/forum/publish/route.ts b/src/app/api/admin/forum/publish/route.ts index d1f19d8e..7a848e61 100644 --- a/src/app/api/admin/forum/publish/route.ts +++ b/src/app/api/admin/forum/publish/route.ts @@ -24,6 +24,41 @@ export async function GET(request: Request) { let fixData; if (!page) { + fixData = await prisma.forum_Posting.findMany({ + + orderBy: { + createdAt: "desc", + }, + where: { + isActive: true, + diskusi: { + contains: search ? search : "", + mode: "insensitive", + }, + }, + select: { + id: true, + diskusi: true, + isActive: true, + createdAt: true, + Author: { + select: { + id: true, + username: true, + Profile: true, + }, + }, + Forum_ReportPosting: true, + Forum_Komentar: { + where: { + isActive: true, + }, + }, + ForumMaster_StatusPosting: true, + }, + }); + + } else { const data = await prisma.forum_Posting.findMany({ take: takeData, skip: skipData, @@ -73,7 +108,6 @@ export async function GET(request: Request) { data: data, nCount: _.ceil(nCount / takeData) } - } return NextResponse.json({ success: true, @@ -91,5 +125,7 @@ export async function GET(request: Request) { }, { status: 500 } ) + } finally { + await prisma.$disconnect() } } \ No newline at end of file diff --git a/src/app/api/admin/voting/dashboard/riwayat/route.ts b/src/app/api/admin/voting/dashboard/riwayat/route.ts index 3857af0e..c0411274 100644 --- a/src/app/api/admin/voting/dashboard/riwayat/route.ts +++ b/src/app/api/admin/voting/dashboard/riwayat/route.ts @@ -31,7 +31,7 @@ export async function GET(request: Request) { ) } catch (error) { backendLogger.error('Error get data voting dashboard >>', error); - NextResponse.json({ + return NextResponse.json({ success: false, message: 'Error get data voting dashboard', reason: (error as Error).message diff --git a/src/app_modules/admin/forum/lib/api_fetch_admin_forum.ts b/src/app_modules/admin/forum/lib/api_fetch_admin_forum.ts index 18d7741f..9c6fef07 100644 --- a/src/app_modules/admin/forum/lib/api_fetch_admin_forum.ts +++ b/src/app_modules/admin/forum/lib/api_fetch_admin_forum.ts @@ -1,7 +1,10 @@ export { apiGetAdminForumPublishCountDasboard, + apiGetAdminCountForumReportPosting , + apiGetAdminCountForumReportKomentar, apiGetAdminForumReportPosting, - apiGetAdminForumReportKomentar + apiGetAdminForumReportKomentar, + apiGetAdminForumPublish } const apiGetAdminForumPublishCountDasboard = async () => { @@ -21,7 +24,7 @@ const apiGetAdminForumPublishCountDasboard = async () => { return await response.json().catch(() => null); } -const apiGetAdminForumReportPosting = async () => { +const apiGetAdminCountForumReportPosting = async () => { const { token } = await fetch("/api/get-cookie").then((res) => res.json()); if (!token) return await token.json().catch(() => null); @@ -38,6 +41,38 @@ const apiGetAdminForumReportPosting = async () => { return await response.json().catch(() => null); } +const apiGetAdminCountForumReportKomentar = async () => { + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) return await token.json().catch(() => null); + + const response = await fetch(`/api/admin/forum/dashboard/report_komentar`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + + return await response.json().catch(() => null); +} +const apiGetAdminForumReportPosting = async () => { + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) return await token.json().catch(() => null); + + const response = await fetch(`/api/admin/forum/dashboard/report_posting`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + + return await response.json().catch(() => null); +} const apiGetAdminForumReportKomentar = async () => { const { token } = await fetch("/api/get-cookie").then((res) => res.json()); if (!token) return await token.json().catch(() => null); @@ -52,5 +87,21 @@ const apiGetAdminForumReportKomentar = async () => { }, }) + return await response.json().catch(() => null); +} +const apiGetAdminForumPublish = async () => { + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) return await token.json().catch(() => null); + + const response = await fetch(`/api/admin/forum/dashboard/publish`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + return await response.json().catch(() => null); } \ No newline at end of file diff --git a/src/app_modules/admin/forum/main/dashboard.tsx b/src/app_modules/admin/forum/main/dashboard.tsx index 433fa323..92f99431 100644 --- a/src/app_modules/admin/forum/main/dashboard.tsx +++ b/src/app_modules/admin/forum/main/dashboard.tsx @@ -8,7 +8,7 @@ import { AdminColor } from "@/app_modules/_global/color/color_pallet"; import { useShallowEffect } from "@mantine/hooks"; import { clientLogger } from "@/util/clientLogger"; import global_limit from "@/app/lib/limit"; -import { apiGetAdminForumPublishCountDasboard } from "../lib/api_fetch_admin_forum"; +import { apiGetAdminCountForumReportKomentar, apiGetAdminCountForumReportPosting, apiGetAdminForumPublishCountDasboard } from "../lib/api_fetch_admin_forum"; import { useState } from "react"; import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; @@ -63,7 +63,7 @@ function ForumMain() { async function onLoadCountReportPosting() { try { - const response = await apiGetAdminForumPublishCountDasboard() + const response = await apiGetAdminCountForumReportPosting() if (response) { setCountLaporanPosting(response.data) } @@ -74,7 +74,7 @@ function ForumMain() { async function onLoadCountReportKomentar() { try { - const response = await apiGetAdminForumPublishCountDasboard() + const response = await apiGetAdminCountForumReportKomentar() if (response) { setCountLaporanKomentar(response.data) } diff --git a/src/app_modules/admin/forum/sub_menu/table_posting.tsx b/src/app_modules/admin/forum/sub_menu/table_posting.tsx index a367e1bf..24aeda9d 100644 --- a/src/app_modules/admin/forum/sub_menu/table_posting.tsx +++ b/src/app_modules/admin/forum/sub_menu/table_posting.tsx @@ -1,5 +1,6 @@ "use client"; + import { RouterAdminForum } from "@/app/lib/router_admin/router_admin_forum"; import { RouterForum } from "@/app/lib/router_hipmi/router_forum"; import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/_admin_global/header_tamplate"; @@ -30,13 +31,17 @@ import { useState } from "react"; import { adminForum_funDeletePostingById } from "../fun/delete/fun_delete_posting_by_id"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal"; -import { useDisclosure } from "@mantine/hooks"; +import { useDisclosure, useShallowEffect } from "@mantine/hooks"; import { adminForum_getListPosting } from "../fun/get/get_list_publish"; import adminJob_getListPublish from "@/app_modules/admin/job/fun/get/get_list_publish"; import ComponentAdminForum_ButtonDeletePosting from "../component/button_delete"; import ComponentAdminGlobal_IsEmptyData from "../../_admin_global/is_empty_data"; import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component"; import { AdminColor } from "@/app_modules/_global/color/color_pallet"; +import { apiGetAdminForumPublish } from "../lib/api_fetch_admin_forum"; +import { clientLogger } from "@/util/clientLogger"; +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; + export default function AdminForum_TablePosting({ listPublish, @@ -47,125 +52,150 @@ export default function AdminForum_TablePosting({ <> - + {/*
{JSON.stringify(listPublish, null, 2)}
*/}
); } -function TablePublish({ listPublish }: { listPublish: any }) { + +function TablePublish() { const router = useRouter(); - const [data, setData] = useState(listPublish.data); - const [nPage, setNPage] = useState(listPublish.nPage); + const [data, setData] = useState(null); + const [nPage, setNPage] = useState(1); const [activePage, setActivePage] = useState(1); const [isSearch, setSearch] = useState(""); - async function onSearch(s: string) { - setSearch(s); - setActivePage(1); - const loadData = await adminForum_getListPosting({ - page: 1, - search: s, - }); - setData(loadData.data as any); - setNPage(loadData.nPage); - } - async function onPageClick(p: any) { - setActivePage(p); - const loadData = await adminForum_getListPosting({ - search: isSearch, - page: p, - }); - setData(loadData.data as any); - setNPage(loadData.nPage); + useShallowEffect(() => { + const loadInitialData = async () => { + try { + const response = await apiGetAdminForumPublish() + + + if (response?.success && response?.data.data) { + setData(response.data.data); + setNPage(response.data.nPage || 1); + } else { + console.error("Invalid data format recieved:", response); + setData([]); + } + } catch (error) { + clientLogger.error("Invlid data format recieved:", error); + setData([]); + } + } + loadInitialData(); + }, [activePage, isSearch]); + const onSearch = async (searchTerm: string) => { + setSearch(searchTerm); + setActivePage(1); } async function onLoadData() { - const loadData = await adminForum_getListPosting({ - page: 1, - }); - setData(loadData.data as any); - setNPage(loadData.nPage); + const loadData = await adminForum_getListPosting({ + page: 1, + }); + setData(loadData.data as any); + setNPage(loadData.nPage); } - const TableRows = data?.map((e, i) => ( - - -
- {e?.Author?.username} -
- - -
- - {e?.ForumMaster_StatusPosting?.status} - -
- - - - -
{ + setActivePage(page); + } + + + const renderTableBody = () => { + if (!Array.isArray(data) || data.length === 0) { + return ( + + +
+ Tidak ada data +
+ + + ) + } + return data?.map((e, i) => ( + + +
+ {e?.Author?.username} +
+ + +
+ + {e?.ForumMaster_StatusPosting?.status} + +
+ + + + +
+ + + + +
+ + {new Intl.DateTimeFormat(["id-ID"], { dateStyle: "medium" }).format( + e.createdAt + )} + +
+ + +
+ + {e?.Forum_Komentar.length} + +
+ + +
+ = 3 ? "red" : "black"} + fw={"bold"} + fz={"lg"} + > + {e?.Forum_ReportPosting.length} + +
+ + + + + { + if (val) { + onLoadData(); + } }} /> - - - - -
- - {new Intl.DateTimeFormat(["id-ID"], { dateStyle: "medium" }).format( - e.createdAt - )} - -
- - -
- - {e?.Forum_Komentar.length} - -
- - -
- = 3 ? "red" : "black"} - fw={"bold"} - fz={"lg"} - > - {e?.Forum_ReportPosting.length} - -
- - - - - { - if (val) { - onLoadData(); - } - }} - /> - - - - )); +
+ + + )); + } + return ( <> @@ -175,36 +205,37 @@ function TablePublish({ listPublish }: { listPublish: any }) { color={AdminColor.softBlue} component={ } - radius={"xl"} - placeholder="Cari postingan" - onChange={(val) => { - onSearch(val.currentTarget.value); - }} - /> + icon={} + radius={"xl"} + placeholder="Cari postingan" + onChange={(val) => { + onSearch(val.currentTarget.value); + }} + /> } /> {/* - - Posting - - } - radius={"xl"} - placeholder="Cari postingan" - onChange={(val) => { - onSearch(val.currentTarget.value); - }} - /> - */} - - {isEmpty(data) ? ( - + position="apart" + bg={"green.4"} + p={"xs"} + style={{ borderRadius: "6px" }} + > + + Posting + + } + radius={"xl"} + placeholder="Cari postingan" + onChange={(val) => { + onSearch(val.currentTarget.value); + }} + /> + */} + + + {!data ? ( + ) : ( @@ -214,7 +245,8 @@ function TablePublish({ listPublish }: { listPublish: any }) { p={"md"} w={"100%"} h={"100%"} - + + > @@ -241,7 +273,7 @@ function TablePublish({ listPublish }: { listPublish: any }) { - {TableRows} + {renderTableBody()}
@@ -260,11 +292,13 @@ function TablePublish({ listPublish }: { listPublish: any }) { ); } + function ButtonAction({ postingId }: { postingId: string }) { const router = useRouter(); const [loadingKomentar, setLoadingKomentar] = useState(false); const [loadingReport, setLoadingReport] = useState(false); + return ( <> + + + + ); +} diff --git a/src/middleware.ts b/src/middleware.ts index d0d05c35..f9eb9318 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -54,6 +54,7 @@ const middlewareConfig: MiddlewareConfig = { "/register", "/validasi", "/splash", + "/invalid-user", "/job-vacancy", "/preview-image", "/auth/login", @@ -145,16 +146,9 @@ export const middleware = async (req: NextRequest) => { const userValidateJson = await userValidate.json(); if (userValidateJson.success == true && userValidateJson.data == null) { - const logout = await fetch(new URL("/api/auth/logout", req.url), { - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}`, - }, - }); - - if (!logout.ok) { - throw new Error("Failed to logout user"); - } + return setCorsHeaders( + NextResponse.redirect(new URL("/invalid-user", req.url)) + ); } if (!userValidateJson.data.active) { From 1c31943c95dd9ddecdf6323ef4e75c55c5626532 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Mon, 10 Feb 2025 17:12:03 +0800 Subject: [PATCH 5/5] fix portofolio deskripsi: - fix server to API --- src/app/api/master/bidang-bisnis/route.ts | 41 ++++++++++++++ src/app/api/portofolio/[id]/route.ts | 53 +++++++++++++++++++ src/app/dev/portofolio/create/[id]/page.tsx | 8 ++- src/app_modules/_global/lib/api_master.ts | 16 +++++- .../component/api_fetch_portofolio.ts | 21 ++++++++ .../button/comp_button_selanjutnya.tsx | 48 +++++++++++++---- .../katalog/portofolio/create/view.tsx | 44 +++++++++++---- src/middleware.ts | 13 +---- 8 files changed, 208 insertions(+), 36 deletions(-) create mode 100644 src/app/api/master/bidang-bisnis/route.ts create mode 100644 src/app/api/portofolio/[id]/route.ts create mode 100644 src/app_modules/katalog/portofolio/component/api_fetch_portofolio.ts diff --git a/src/app/api/master/bidang-bisnis/route.ts b/src/app/api/master/bidang-bisnis/route.ts new file mode 100644 index 00000000..aa73de99 --- /dev/null +++ b/src/app/api/master/bidang-bisnis/route.ts @@ -0,0 +1,41 @@ +import { prisma } from "@/app/lib"; +import backendLogger from "@/util/backendLogger"; +import { clientLogger } from "@/util/clientLogger"; +import { NextResponse } from "next/server"; + +export async function GET(request: Request) { + if (request.method !== "GET") { + return NextResponse.json( + { success: false, message: "Method not allowed" }, + { status: 405 } + ); + } + + try { + let fixData; + fixData = await prisma.masterBidangBisnis.findMany({ + where: { + active: true, + }, + }); + + return NextResponse.json( + { + success: true, + message: "Berhasil mendapatkan data", + data: fixData, + }, + { status: 200 } + ); + } catch (error) { + backendLogger.error("Error Get Master Bidang Bisnis >>", error); + return NextResponse.json( + { + success: false, + message: "API Error Get Data", + reason: (error as Error).message, + }, + { status: 500 } + ); + } +} diff --git a/src/app/api/portofolio/[id]/route.ts b/src/app/api/portofolio/[id]/route.ts new file mode 100644 index 00000000..deea8fd8 --- /dev/null +++ b/src/app/api/portofolio/[id]/route.ts @@ -0,0 +1,53 @@ +import { prisma } from "@/app/lib"; +import { NextResponse } from "next/server"; + +export { POST }; + +async function POST(request: Request, { params }: { params: { id: string } }) { + if (request.method !== "POST") { + return NextResponse.json( + { + success: false, + message: "Method not allowed", + }, + { status: 405 } + ); + } + + try { + const { id } = params; + const { data } = await request.json(); + + // const createPortofolio = await prisma.portofolio.create({ + // data: { + // profileId: id, + // id_Portofolio: "Porto" + Date.now().toString(), + // namaBisnis: data.namaBisnis, + // deskripsi: data.deskripsi, + // tlpn: data.tlpn, + // alamatKantor: data.alamatKantor, + // masterBidangBisnisId: data.masterBidangBisnisId, + // logoId: data.fileId, + // }, + // }); + + return NextResponse.json( + { + success: true, + message: "Berhasil mendapatkan data", + id, + data, + }, + { status: 200 } + ); + } catch (error) { + return NextResponse.json( + { + success: false, + message: "API Error Post Data", + reason: (error as Error).message, + }, + { status: 500 } + ); + } +} diff --git a/src/app/dev/portofolio/create/[id]/page.tsx b/src/app/dev/portofolio/create/[id]/page.tsx index 652a81d1..fcc6bef3 100644 --- a/src/app/dev/portofolio/create/[id]/page.tsx +++ b/src/app/dev/portofolio/create/[id]/page.tsx @@ -1,15 +1,13 @@ import { CreatePortofolio } from "@/app_modules/katalog/portofolio"; import { Portofolio_getMasterBidangBisnis } from "@/app_modules/katalog/portofolio/fun/master/get_bidang_bisnis"; -export default async function Page({ params }: { params: { id: string } }) { - const profileId = params.id; - const bidangBisnis = await Portofolio_getMasterBidangBisnis(); +export default async function Page() { + // const profileId = params.id; + // const bidangBisnis = await Portofolio_getMasterBidangBisnis(); return ( <> ); diff --git a/src/app_modules/_global/lib/api_master.ts b/src/app_modules/_global/lib/api_master.ts index 7443c12e..3b3522d9 100644 --- a/src/app_modules/_global/lib/api_master.ts +++ b/src/app_modules/_global/lib/api_master.ts @@ -1,4 +1,4 @@ -export { apiGetMasterBank }; +export { apiGetMasterBank, apiGetMasterBidangBisnis }; const apiGetMasterBank = async () => { const { token } = await fetch("/api/get-cookie").then((res) => res.json()); @@ -12,8 +12,22 @@ const apiGetMasterBank = async () => { Authorization: `Bearer ${token}`, }, }); + return await respone.json().catch(() => null); }; +const apiGetMasterBidangBisnis = async () => { + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) return await token.json().catch(() => null); + const respone = await fetch(`/api/master/bidang-bisnis`, { + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }); + return await respone.json().catch(() => null); +}; diff --git a/src/app_modules/katalog/portofolio/component/api_fetch_portofolio.ts b/src/app_modules/katalog/portofolio/component/api_fetch_portofolio.ts new file mode 100644 index 00000000..398ea490 --- /dev/null +++ b/src/app_modules/katalog/portofolio/component/api_fetch_portofolio.ts @@ -0,0 +1,21 @@ +export { + apiCreatePortofolio, +}; + +const apiCreatePortofolio = async ({ data }: { data: any }) => { + const { token } = await fetch("/api/get-cookie").then((res) => res.json()); + if (!token) return await token.json().catch(() => null); + + const res = await fetch(`/api/portofolio`, { + method: "POST", + body: JSON.stringify({ data }), + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }); + + return await res.json().catch(() => null); +}; diff --git a/src/app_modules/katalog/portofolio/component/button/comp_button_selanjutnya.tsx b/src/app_modules/katalog/portofolio/component/button/comp_button_selanjutnya.tsx index ccf7c19a..fad34c13 100644 --- a/src/app_modules/katalog/portofolio/component/button/comp_button_selanjutnya.tsx +++ b/src/app_modules/katalog/portofolio/component/button/comp_button_selanjutnya.tsx @@ -15,6 +15,21 @@ import { clientLogger } from "@/util/clientLogger"; import { useRouter } from "next/navigation"; import { useState } from "react"; import funCreatePortofolio from "../../fun/fun_create_portofolio"; +import { apiCreatePortofolio } from "../api_fetch_portofolio"; + +interface ICreatePortofolio { + namaBisnis: string; + masterBidangBisnisId: string; + alamatKantor: string; + tlpn: string; + deskripsi: string; + fileId: string; + facebook: string; + twitter: string; + instagram: string; + tiktok: string; + youtube: string; +} export function Portofolio_ComponentButtonSelanjutnya({ profileId, @@ -31,15 +46,7 @@ export function Portofolio_ComponentButtonSelanjutnya({ const [loading, setLoading] = useState(false); async function onSubmit() { - const porto = { - namaBisnis: dataPortofolio.namaBisnis, - masterBidangBisnisId: dataPortofolio.masterBidangBisnisId, - alamatKantor: dataPortofolio.alamatKantor, - tlpn: dataPortofolio.tlpn, - deskripsi: dataPortofolio.deskripsi, - }; - - if (_.values(porto).includes("")) { + if (_.values(dataPortofolio).includes("")) { ComponentGlobal_NotifikasiPeringatan("Lengkapi Data"); return; } @@ -65,6 +72,29 @@ export function Portofolio_ComponentButtonSelanjutnya({ const fileId = uploadFile.data.id; + const newData: ICreatePortofolio = { + namaBisnis: dataPortofolio.namaBisnis, + masterBidangBisnisId: dataPortofolio.masterBidangBisnisId, + alamatKantor: dataPortofolio.alamatKantor, + tlpn: dataPortofolio.tlpn, + deskripsi: dataPortofolio.deskripsi, + facebook: dataMedsos.facebook, + twitter: dataMedsos.twitter, + instagram: dataMedsos.instagram, + tiktok: dataMedsos.tiktok, + youtube: dataMedsos.youtube, + fileId: fileId, + }; + + // const responeCreated = await apiCreatePortofolio({ + // data: newData, + // }); + + // if (responeCreated.success) { + // ComponentGlobal_NotifikasiBerhasil("Berhasil disimpan"); + // router.replace(RouterMap.create + responeCreated.id, { scroll: false }); + // } + const res = await funCreatePortofolio({ profileId: profileId, data: dataPortofolio as any, diff --git a/src/app_modules/katalog/portofolio/create/view.tsx b/src/app_modules/katalog/portofolio/create/view.tsx index ee633266..46c9966a 100644 --- a/src/app_modules/katalog/portofolio/create/view.tsx +++ b/src/app_modules/katalog/portofolio/create/view.tsx @@ -35,14 +35,16 @@ import { useState } from "react"; import { PhoneInput } from "react-international-phone"; import "react-international-phone/style.css"; import { Portofolio_ComponentButtonSelanjutnya } from "../component"; +import { useParams } from "next/navigation"; +import { useShallowEffect } from "@mantine/hooks"; +import { apiGetMasterBidangBisnis } from "@/app_modules/_global/lib/api_master"; +import { MODEL_PORTOFOLIO_BIDANG_BISNIS } from "../model/interface"; +import { clientLogger } from "@/util/clientLogger"; + +export default function CreatePortofolio() { + const params = useParams<{ id: string }>(); + const profileId = params.id; -export default function CreatePortofolio({ - bidangBisnis, - profileId, -}: { - bidangBisnis: BIDANG_BISNIS_OLD; - profileId: any; -}) { const [dataPortofolio, setDataPortofolio] = useState({ namaBisnis: "", masterBidangBisnisId: "", @@ -62,6 +64,25 @@ export default function CreatePortofolio({ const [file, setFile] = useState(null); const [img, setImg] = useState(null); const [imageId, setImageId] = useState(""); + const [listBidangBisnis, setListBidangBisnis] = useState< + MODEL_PORTOFOLIO_BIDANG_BISNIS[] | null + >(null); + + useShallowEffect(() => { + onLoadMaster(); + }, []); + + async function onLoadMaster() { + try { + const respone = await apiGetMasterBidangBisnis(); + + if (respone.success) { + setListBidangBisnis(respone.data); + } + } catch (error) { + clientLogger.error("Error on load master bidang bisnis", error); + } + } return ( <> @@ -91,6 +112,7 @@ export default function CreatePortofolio({ }); }} /> +