From abfa16339f01771a371c70ce3edd0d1787ee397d Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Wed, 29 Jan 2025 23:43:14 +0800 Subject: [PATCH 1/4] fix event deskripsi: - fix database event sponsor & event transaksi --- prisma/schema.prisma | 22 +- src/app/api/master/bank/route.ts | 41 ++++ src/app/api/master/status_transaksi/route.ts | 41 ++++ .../metode_pembayaran/{ => [id]}/layout.tsx | 0 .../metode_pembayaran/{ => [id]}/page.tsx | 2 - .../dev/event/invoice/{ => [id]}/layout.tsx | 0 src/app/dev/event/invoice/[id]/page.tsx | 14 ++ src/app/dev/event/invoice/page.tsx | 12 -- src/app/lib/router_hipmi/router_event.ts | 6 +- src/app_modules/_global/lib/api_master.ts | 19 ++ .../event/detail/invoice/index.tsx | 60 ++++-- .../sponsor/metode_pembayaran/index.tsx | 188 +++++++++++------- .../detail/sponsor/nominal_sponsor/index.tsx | 80 ++++++-- src/app_modules/event/global_state/index.ts | 15 +- src/middleware.ts | 4 + 15 files changed, 377 insertions(+), 127 deletions(-) create mode 100644 src/app/api/master/bank/route.ts create mode 100644 src/app/api/master/status_transaksi/route.ts rename src/app/dev/event/detail/sponsor/metode_pembayaran/{ => [id]}/layout.tsx (100%) rename src/app/dev/event/detail/sponsor/metode_pembayaran/{ => [id]}/page.tsx (66%) rename src/app/dev/event/invoice/{ => [id]}/layout.tsx (100%) create mode 100644 src/app/dev/event/invoice/[id]/page.tsx delete mode 100644 src/app/dev/event/invoice/page.tsx create mode 100644 src/app_modules/_global/lib/api_master.ts diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8fcbf136..6d41ff20 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -11,7 +11,6 @@ datasource db { url = env("DATABASE_URL") } - model User { id String @id @default(cuid()) username String @unique @@ -182,6 +181,14 @@ model MasterStatus { Job Job[] } +model MasterStatusTransaksi { + id String @id @default(cuid()) + name String + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + // -------------------- INVESTASI --------------------- // // Table investasi / saham model Investasi { @@ -983,16 +990,17 @@ model EventSponsor { } model EventTransaksi { - id String @id @default(cuid()) - isActive Boolean @default(true) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt nominal Int - MasterBank MasterBank? @relation(fields: [masterBankId], references: [id]) - masterBankId String? status String transferImageId String? + MasterBank MasterBank? @relation(fields: [masterBankId], references: [id]) + masterBankId String? + AuthorId User? @relation(fields: [authorId], references: [id]) authorId String? diff --git a/src/app/api/master/bank/route.ts b/src/app/api/master/bank/route.ts new file mode 100644 index 00000000..2ce3228b --- /dev/null +++ b/src/app/api/master/bank/route.ts @@ -0,0 +1,41 @@ +import { prisma } from "@/app/lib"; +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" }, + { status: 405 } + ); + } + + try { + const res = await prisma.masterBank.findMany({ + orderBy: { + updatedAt: "asc", + }, + where: { + isActive: true, + }, + }); + + 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( + { + success: false, + message: "API Error Get Data", + reason: (error as Error).message, + }, + { status: 500 } + ); + } +} diff --git a/src/app/api/master/status_transaksi/route.ts b/src/app/api/master/status_transaksi/route.ts new file mode 100644 index 00000000..99dc035e --- /dev/null +++ b/src/app/api/master/status_transaksi/route.ts @@ -0,0 +1,41 @@ +import { prisma } from "@/app/lib"; +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" }, + { status: 405 } + ); + } + + try { + // const res = await prisma.masterBank.findMany({ + // orderBy: { + // updatedAt: "asc", + // }, + // where: { + // isActive: true, + // }, + // }); + + await prisma.$disconnect(); + return NextResponse.json( + { success: true, message: "Berhasil mendapatkan data", data: "" }, + { status: 200 } + ); + } catch (error) { + await prisma.$disconnect(); + backendLogger.error("Error Get Master Status Transaksi >>", error); + return NextResponse.json( + { + success: false, + message: "API Error Get Data", + reason: (error as Error).message, + }, + { status: 500 } + ); + } +} diff --git a/src/app/dev/event/detail/sponsor/metode_pembayaran/layout.tsx b/src/app/dev/event/detail/sponsor/metode_pembayaran/[id]/layout.tsx similarity index 100% rename from src/app/dev/event/detail/sponsor/metode_pembayaran/layout.tsx rename to src/app/dev/event/detail/sponsor/metode_pembayaran/[id]/layout.tsx diff --git a/src/app/dev/event/detail/sponsor/metode_pembayaran/page.tsx b/src/app/dev/event/detail/sponsor/metode_pembayaran/[id]/page.tsx similarity index 66% rename from src/app/dev/event/detail/sponsor/metode_pembayaran/page.tsx rename to src/app/dev/event/detail/sponsor/metode_pembayaran/[id]/page.tsx index 7ebc92bf..9e749bdd 100644 --- a/src/app/dev/event/detail/sponsor/metode_pembayaran/page.tsx +++ b/src/app/dev/event/detail/sponsor/metode_pembayaran/[id]/page.tsx @@ -1,7 +1,5 @@ import Event_MetodePembayaran from '@/app_modules/event/detail/sponsor/metode_pembayaran'; -import { MODEL_MASTER_BANK } from '@/app_modules/investasi/_lib/interface'; -import React from 'react'; function Page() { return ( diff --git a/src/app/dev/event/invoice/layout.tsx b/src/app/dev/event/invoice/[id]/layout.tsx similarity index 100% rename from src/app/dev/event/invoice/layout.tsx rename to src/app/dev/event/invoice/[id]/layout.tsx diff --git a/src/app/dev/event/invoice/[id]/page.tsx b/src/app/dev/event/invoice/[id]/page.tsx new file mode 100644 index 00000000..7574ae8b --- /dev/null +++ b/src/app/dev/event/invoice/[id]/page.tsx @@ -0,0 +1,14 @@ +import { funGetUserIdByToken } from '@/app_modules/_global/fun/get'; +import Event_Invoice from '@/app_modules/event/detail/invoice'; +import React from 'react'; + +async function Page() { + const userLoginId = await funGetUserIdByToken(); + return ( + <> + + + ); +} + +export default Page; diff --git a/src/app/dev/event/invoice/page.tsx b/src/app/dev/event/invoice/page.tsx deleted file mode 100644 index 9c6a990b..00000000 --- a/src/app/dev/event/invoice/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import Event_Invoice from '@/app_modules/event/detail/invoice'; -import React from 'react'; - -function Page() { - return ( - <> - - - ); -} - -export default Page; diff --git a/src/app/lib/router_hipmi/router_event.ts b/src/app/lib/router_hipmi/router_event.ts index c98a3b9e..41154204 100644 --- a/src/app/lib/router_hipmi/router_event.ts +++ b/src/app/lib/router_hipmi/router_event.ts @@ -43,7 +43,11 @@ export const RouterEvent = { `/dev/event/detail/sponsor/tambah_sponsor/${id}`, detail_sponsor: ({ id }: { id: string }) => `/dev/event/detail/detail_sponsor/${id}`, - nominal_sponsor: ({ id }: { id: string }) => `/dev/event/detail/sponsor/nominal_sponsor/${id}`, + + metode_pembayaran: ({ id }: { id: string }) => + `/dev/event/detail/sponsor/metode_pembayaran/${id}`, + invoice: ({ id }: { id: string }) => + `/dev/event/invoice/${id}`, }; diff --git a/src/app_modules/_global/lib/api_master.ts b/src/app_modules/_global/lib/api_master.ts new file mode 100644 index 00000000..7443c12e --- /dev/null +++ b/src/app_modules/_global/lib/api_master.ts @@ -0,0 +1,19 @@ +export { apiGetMasterBank }; + +const apiGetMasterBank = 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/bank`, { + 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/event/detail/invoice/index.tsx b/src/app_modules/event/detail/invoice/index.tsx index 127b1fd5..d3a4ee70 100644 --- a/src/app_modules/event/detail/invoice/index.tsx +++ b/src/app_modules/event/detail/invoice/index.tsx @@ -1,10 +1,23 @@ -'use client'; -import { AccentColor, MainColor } from '@/app_modules/_global/color'; -import { ActionIcon, Button, Grid, Group, Paper, Stack, Text, Title } from '@mantine/core'; -import { IconCamera } from '@tabler/icons-react'; -import React from 'react'; +"use client"; + +import { AccentColor, MainColor } from "@/app_modules/_global/color"; +import { Button, Grid, Group, Paper, Stack, Text, Title } from "@mantine/core"; +import { IconCamera } from "@tabler/icons-react"; +import { useAtom } from "jotai"; +import { useParams, useRouter } from "next/navigation"; +import { gs_nominal_sponsor, gs_event_bank_id } from "../../global_state"; + +function Event_Invoice({ userLoginId }: { userLoginId: string }) { + const router = useRouter(); + const params = useParams<{ id: string }>(); + const sponsorId = params.id; + + const [nominal, setNominal] = useAtom(gs_nominal_sponsor); + const [bankId, setBankId] = useAtom(gs_event_bank_id); + + console.log("nominal >>", nominal); + console.log("bankId >>", bankId); -function Event_Invoice() { return ( <> @@ -54,17 +67,19 @@ function Event_Invoice() { > - + 9065456754325643 - - @@ -101,15 +116,19 @@ function Event_Invoice() { > - + Rp. 100.000 - - @@ -131,15 +150,22 @@ function Event_Invoice() { }} > - - - Upload bukti transfer anda + + Upload bukti transfer anda + - diff --git a/src/app_modules/event/detail/sponsor/metode_pembayaran/index.tsx b/src/app_modules/event/detail/sponsor/metode_pembayaran/index.tsx index 365af7dc..18ad624e 100644 --- a/src/app_modules/event/detail/sponsor/metode_pembayaran/index.tsx +++ b/src/app_modules/event/detail/sponsor/metode_pembayaran/index.tsx @@ -1,84 +1,130 @@ -'use client'; +"use client"; -import { AccentColor, MainColor } from '@/app_modules/_global/color'; -import { MODEL_MASTER_BANK } from '@/app_modules/investasi/_lib/interface'; -import { Button, Paper, Radio, Stack, Title } from '@mantine/core'; -import { useRouter } from 'next/navigation'; -import React, { useState } from 'react'; - -const bank = [ - { - id: 1, - namaBank: "BRI", - }, - { - id: 2, - namaBank: "BCA", - }, - { - id: 3, - namaBank: "BNI", - }, - { - id: 4, - namaBank: "BSI", - } -] +import { RouterEvent } from "@/app/lib/router_hipmi/router_event"; +import { AccentColor, MainColor } from "@/app_modules/_global/color"; +import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; +import { apiGetMasterBank } from "@/app_modules/_global/lib/api_master"; +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; +import { + gs_event_bank_id, + gs_nominal_sponsor, +} from "@/app_modules/event/global_state"; +import { MODEL_MASTER_BANK } from "@/app_modules/investasi/_lib/interface"; +import { clientLogger } from "@/util/clientLogger"; +import { Button, Paper, Radio, Stack, Title } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { useAtom } from "jotai"; +import _ from "lodash"; +import { useParams, useRouter } from "next/navigation"; +import { useState } from "react"; function Event_MetodePembayaran() { + const params = useParams<{ id: string }>(); const [pilihBank, setPilihBank] = useState(""); const router = useRouter(); + const [nominal, setNominal] = useAtom(gs_nominal_sponsor); + const [bankId, setBankId] = useAtom(gs_event_bank_id); + const [isLoading, setIsLoading] = useState(false); + console.log("nominal >>", nominal); + + const [data, setData] = useState(null); + useShallowEffect(() => { + onLoadBank(); + }, []); + + async function onLoadBank() { + try { + const respone = await apiGetMasterBank(); + + if (respone) { + setData(respone.data); + } + } catch (error) { + clientLogger.error("Error get data bank", error); + } + } + + if (!data) { + return ( + <> + + {Array.from({ length: 2 }).map((e, i) => ( + + ))} + + + ); + } + return ( <> - - - {bank.map((e) => ( - + ) : ( + + + {data.map((e) => ( + + + {e.namaBank} + + } + /> + + ))} + + + - + Pilih + + + )} ); } -export default Event_MetodePembayaran; \ No newline at end of file +export default Event_MetodePembayaran; diff --git a/src/app_modules/event/detail/sponsor/nominal_sponsor/index.tsx b/src/app_modules/event/detail/sponsor/nominal_sponsor/index.tsx index 846ec486..3f437159 100644 --- a/src/app_modules/event/detail/sponsor/nominal_sponsor/index.tsx +++ b/src/app_modules/event/detail/sponsor/nominal_sponsor/index.tsx @@ -1,5 +1,7 @@ "use client"; +import { RouterEvent } from "@/app/lib/router_hipmi/router_event"; import { AccentColor, MainColor } from "@/app_modules/_global/color"; +import { gs_nominal_sponsor } from "@/app_modules/event/global_state"; import { Box, Button, @@ -9,6 +11,7 @@ import { Text, TextInput, Title, + Loader, } from "@mantine/core"; import { IconChevronRight, @@ -17,35 +20,42 @@ import { IconMoodSmileDizzy, IconMoodXd, } from "@tabler/icons-react"; +import { useAtom } from "jotai"; import { useParams, useRouter } from "next/navigation"; -import React from "react"; +import { useState } from "react"; const listNominal = [ { id: 1, - jumlah: " 25.000", + value: 25000, icon: , }, { id: 2, - jumlah: " 50.000", + value: 50000, icon: , }, { id: 3, - jumlah: " 75.000", + value: 75000, icon: , }, { id: 4, - jumlah: " 100.000", + value: 100000, icon: , }, ]; function Event_PilihNominalSponsor() { const params = useParams<{ id: string }>(); const router = useRouter(); - + const [inputNominal, setInputNominal] = useState(""); + const [valueNominal, setValueNominal] = useState(0); + const [fixNominal, setFixNominal] = useAtom(gs_nominal_sponsor); + const [isLoading, setLoading] = useState(false); + const [isLoadingPaper, setLoadingPaper] = useState(false); + const [chooseId, setChooseId] = useState(0); + return ( <> @@ -54,6 +64,7 @@ function Event_PilihNominalSponsor() { { + try { + setChooseId(e.id); + setLoadingPaper(true); + setFixNominal(e.value); + router.push(RouterEvent.metode_pembayaran({ id: params.id })); + } catch (error) { + console.error(error); + } + }} > {e.icon} - Rp.{e.jumlah} + + Rp. + {new Intl.NumberFormat("id-ID", { currency: "IDR" }).format( + e.value + )} + - + {isLoadingPaper && e.id === chooseId ? ( + + ) : ( + + )} ))} @@ -89,21 +119,41 @@ function Event_PilihNominalSponsor() { icon={Rp.} placeholder="0" min={0} + value={inputNominal} + onChange={(val) => { + const match = val.currentTarget.value + .replace(/\./g, "") + .match(/^[0-9]+$/); + + if (val.currentTarget.value === "") + return setInputNominal(0 + ""); + + if (!match?.[0]) return null; + + const nilai = val.currentTarget.value.replace(/\./g, ""); + const target = Intl.NumberFormat("id-ID").format(+nilai); + + setValueNominal(+nilai); + setInputNominal(target); + }} /> - - Minimal Donasi Rp. 10.000 - + diff --git a/src/app_modules/event/global_state/index.ts b/src/app_modules/event/global_state/index.ts index 310e4a91..2574ed23 100644 --- a/src/app_modules/event/global_state/index.ts +++ b/src/app_modules/event/global_state/index.ts @@ -1,13 +1,24 @@ +import { atom } from "jotai"; import { atomWithStorage } from "jotai/utils"; /** * @param index | 0 - 3 | 0: Beranda, 1: Status, 2: Kontibusi, 3: Riwayat * @type number */ -export const gs_event_hotMenu = atomWithStorage("gs_event_hotMenu", 0) +export const gs_event_hotMenu = atomWithStorage("gs_event_hotMenu", 0); /** * @param status | "Publish", "Review", "Draft", "Reject" * @type string */ -export const gs_event_status = atomWithStorage("gs_status_event", "Publish") +export const gs_event_status = atomWithStorage( + "gs_status_event", + "Publish" +); + +export const gs_nominal_sponsor = atomWithStorage( + "gs_nominal_sponsor", + 0 +); + +export const gs_event_bank_id = atomWithStorage("gs_event_bank_id", ""); diff --git a/src/middleware.ts b/src/middleware.ts index dc993068..65b3d06c 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -32,9 +32,13 @@ const middlewareConfig: MiddlewareConfig = { "/api/auth/*", "/api/origin-url", "/api/event/*", + // "/api/master/*", // "/api/image/*", // "/api/user/*", // "/api/new/*", + // ADMIN API + + // Akses awal "/api/get-cookie", "/api/user/activation", From a5b9258da7c7f0b62eb8dc569ef0135323a0deb3 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Thu, 30 Jan 2025 10:23:42 +0800 Subject: [PATCH 2/4] fix event deskripsi: - fix database event --- prisma/schema.prisma | 14 +++++++----- src/app/api/master/status_transaksi/route.ts | 18 +++++++-------- .../_global/fun/generate_seeder.ts | 22 +++++++++++++++++++ src/bin/seeder/master/index.ts | 2 ++ .../master/master_status_transaksi.json | 18 +++++++++++++++ src/middleware.ts | 2 +- 6 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 src/bin/seeder/master/master_status_transaksi.json diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6d41ff20..eab897c0 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -182,11 +182,12 @@ model MasterStatus { } model MasterStatusTransaksi { - id String @id @default(cuid()) - name String - isActive Boolean @default(true) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + name String + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + EventTransaksi EventTransaksi[] } // -------------------- INVESTASI --------------------- // @@ -1009,4 +1010,7 @@ model EventTransaksi { EventSponsor EventSponsor? @relation(fields: [eventSponsorId], references: [id]) eventSponsorId String? @unique + + MasterStatusTransaksi MasterStatusTransaksi? @relation(fields: [masterStatusTransaksiId], references: [id]) + masterStatusTransaksiId String? } diff --git a/src/app/api/master/status_transaksi/route.ts b/src/app/api/master/status_transaksi/route.ts index 99dc035e..e7abd5e0 100644 --- a/src/app/api/master/status_transaksi/route.ts +++ b/src/app/api/master/status_transaksi/route.ts @@ -12,18 +12,18 @@ export async function GET(request: Request) { } try { - // const res = await prisma.masterBank.findMany({ - // orderBy: { - // updatedAt: "asc", - // }, - // where: { - // isActive: true, - // }, - // }); + const res = await prisma.masterStatusTransaksi.findMany({ + orderBy: { + updatedAt: "asc", + }, + where: { + isActive: true, + }, + }); await prisma.$disconnect(); return NextResponse.json( - { success: true, message: "Berhasil mendapatkan data", data: "" }, + { success: true, message: "Berhasil mendapatkan data", data: res }, { status: 200 } ); } catch (error) { diff --git a/src/app_modules/_global/fun/generate_seeder.ts b/src/app_modules/_global/fun/generate_seeder.ts index 3704edf4..3e549c78 100644 --- a/src/app_modules/_global/fun/generate_seeder.ts +++ b/src/app_modules/_global/fun/generate_seeder.ts @@ -25,6 +25,7 @@ import voting_status from "../../../bin/seeder/voting/master_status.json"; import { master_kategori_app } from "@/bin/seeder/master"; import { new_status_transaksi_investasi } from "@/bin/seeder/investasi"; import { master_nama_bank } from "@/bin/seeder/master"; +import { master_status_transaksi } from "@/bin/seeder/master"; import pLimit from "p-limit"; async function masterUserRole() { @@ -543,6 +544,26 @@ async function masterInvestasiNewTransaksiStatus() { console.log("masterInvestasiNewTransaksiStatus success"); } +async function masterStatusTransaksi() { + for (let a of master_status_transaksi) { + await prisma.masterStatusTransaksi.upsert({ + where: { + id: a.id, + }, + create: { + id: a.id, + name: a.name, + }, + update: { + id: a.id, + name: a.name, + }, + }); + } + + console.log("masterStatusTransaksi success"); +} + const listSeederQueue = [ masterUserRole, seederUser, @@ -570,6 +591,7 @@ const listSeederQueue = [ seederNomorAdmin, masterKategoriApp, masterInvestasiNewTransaksiStatus, + masterStatusTransaksi, ]; const limit = pLimit(1); diff --git a/src/bin/seeder/master/index.ts b/src/bin/seeder/master/index.ts index b2a301c4..8cb000b1 100644 --- a/src/bin/seeder/master/index.ts +++ b/src/bin/seeder/master/index.ts @@ -1,5 +1,7 @@ import master_kategori_app from "./master_kategori_app.json"; import master_nama_bank from "./master_nama_bank.json"; +import master_status_transaksi from "./master_status_transaksi.json"; export { master_kategori_app }; export { master_nama_bank }; +export { master_status_transaksi }; diff --git a/src/bin/seeder/master/master_status_transaksi.json b/src/bin/seeder/master/master_status_transaksi.json new file mode 100644 index 00000000..6093bdd0 --- /dev/null +++ b/src/bin/seeder/master/master_status_transaksi.json @@ -0,0 +1,18 @@ +[ + { + "id": "1", + "name": "Berhasil" + }, + { + "id": "2", + "name": "Proses" + }, + { + "id": "3", + "name": "Menunggu" + }, + { + "id": "4", + "name": "Gagal" + } +] diff --git a/src/middleware.ts b/src/middleware.ts index 65b3d06c..82fae375 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -32,7 +32,7 @@ const middlewareConfig: MiddlewareConfig = { "/api/auth/*", "/api/origin-url", "/api/event/*", - // "/api/master/*", + "/api/master/*", // "/api/image/*", // "/api/user/*", // "/api/new/*", From 34293124ed0c05629756d0141d6e96f7df571501 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Thu, 30 Jan 2025 14:36:37 +0800 Subject: [PATCH 3/4] fix admin event deskripsi: - fix server action to API --- .../api/admin/event/dashboard/[name]/route.ts | 53 ++++ .../admin/event/dashboard/riwayat/route.ts | 47 ++++ .../admin/event/dashboard/tipe-acara/route.ts | 44 ++++ src/app/api/event/[id]/route.ts | 8 +- .../admin/event/_lib/api_fecth_admin_event.ts | 60 +++++ src/app/dev/admin/event/main/page.tsx | 19 +- src/app/lib/limit.ts | 5 + src/app/lib/new_fun_user_id.ts | 28 --- src/app_modules/admin/event/main/index.tsx | 228 ++++++++++++++---- src/middleware.ts | 1 + 10 files changed, 390 insertions(+), 103 deletions(-) create mode 100644 src/app/api/admin/event/dashboard/[name]/route.ts create mode 100644 src/app/api/admin/event/dashboard/riwayat/route.ts create mode 100644 src/app/api/admin/event/dashboard/tipe-acara/route.ts create mode 100644 src/app/dev/admin/event/_lib/api_fecth_admin_event.ts create mode 100644 src/app/lib/limit.ts delete mode 100644 src/app/lib/new_fun_user_id.ts diff --git a/src/app/api/admin/event/dashboard/[name]/route.ts b/src/app/api/admin/event/dashboard/[name]/route.ts new file mode 100644 index 00000000..9ebc3310 --- /dev/null +++ b/src/app/api/admin/event/dashboard/[name]/route.ts @@ -0,0 +1,53 @@ +import { prisma } from "@/app/lib"; +import backendLogger from "@/util/backendLogger"; +import _ from "lodash"; +import { NextResponse } from "next/server"; + +export async function GET( + request: Request, + { params }: { params: { name: string } } +) { + const method = request.method; + if (method !== "GET") { + return NextResponse.json( + { success: false, message: "Method not allowed" }, + { status: 405 } + ); + } + + const { name } = params; + + try { + let fixData; + const fixStatus = _.startCase(name); + fixData = await prisma.event.count({ + where: { + EventMaster_Status: { + name: fixStatus, + }, + isArsip: false, + }, + }); + + return NextResponse.json( + { + success: true, + message: "Success get data event dashboard", + data: fixData, + }, + { status: 200 } + ); + } catch (error) { + backendLogger.error("Error get data event dashboard >>", error); + return NextResponse.json( + { + success: false, + message: "Failed to get data", + reason: (error as Error).message, + }, + { status: 500 } + ); + } finally { + await prisma.$disconnect(); + } +} diff --git a/src/app/api/admin/event/dashboard/riwayat/route.ts b/src/app/api/admin/event/dashboard/riwayat/route.ts new file mode 100644 index 00000000..377d371d --- /dev/null +++ b/src/app/api/admin/event/dashboard/riwayat/route.ts @@ -0,0 +1,47 @@ +import { prisma } from "@/app/lib"; +import backendLogger from "@/util/backendLogger"; +import _ from "lodash"; +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" }, + { status: 405 } + ); + } + + try { + let fixData; + fixData = await prisma.event.count({ + where: { + EventMaster_Status: { + name: "Publish", + }, + isArsip: true, + }, + }); + + return NextResponse.json( + { + success: true, + message: "Success get data riwayat event dashboard", + data: fixData, + }, + { status: 200 } + ); + } catch (error) { + backendLogger.error("Error get data riwayat event dashboard >>", error); + return NextResponse.json( + { + success: false, + message: "Failed to get data", + reason: (error as Error).message, + }, + { status: 500 } + ); + } finally { + await prisma.$disconnect(); + } +} diff --git a/src/app/api/admin/event/dashboard/tipe-acara/route.ts b/src/app/api/admin/event/dashboard/tipe-acara/route.ts new file mode 100644 index 00000000..e4d22fdf --- /dev/null +++ b/src/app/api/admin/event/dashboard/tipe-acara/route.ts @@ -0,0 +1,44 @@ +import { prisma } from "@/app/lib"; +import backendLogger from "@/util/backendLogger"; +import _ from "lodash"; +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" }, + { status: 405 } + ); + } + + try { + let fixData; + fixData = await prisma.eventMaster_TipeAcara.count({ + where: { + active: true, + }, + }); + + return NextResponse.json( + { + success: true, + message: "Success get data riwayat event dashboard", + data: fixData, + }, + { status: 200 } + ); + } catch (error) { + backendLogger.error("Error get data riwayat event dashboard >>", error); + return NextResponse.json( + { + success: false, + message: "Failed to get data", + reason: (error as Error).message, + }, + { status: 500 } + ); + } finally { + await prisma.$disconnect(); + } +} diff --git a/src/app/api/event/[id]/route.ts b/src/app/api/event/[id]/route.ts index 516b15d0..0d7214c7 100644 --- a/src/app/api/event/[id]/route.ts +++ b/src/app/api/event/[id]/route.ts @@ -32,21 +32,17 @@ export async function GET( }, }); - await prisma.$disconnect(); - return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: fixData, }); } catch (error) { - await prisma.$disconnect(); - return NextResponse.json( { success: false, message: "Gagal mendapatkan data" }, { status: 500 } ); + } finally { + await prisma.$disconnect(); } } - - diff --git a/src/app/dev/admin/event/_lib/api_fecth_admin_event.ts b/src/app/dev/admin/event/_lib/api_fecth_admin_event.ts new file mode 100644 index 00000000..0fe61529 --- /dev/null +++ b/src/app/dev/admin/event/_lib/api_fecth_admin_event.ts @@ -0,0 +1,60 @@ +export { + apiGetEventStatusCountDashboard, + apiGetEventTipeAcara, + apiGetEventRiwayatCount, +}; + +const apiGetEventStatusCountDashboard = async ({ + name, +}: { + name: "Publish" | "Review" | "Reject"; +}) => { + 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/event/dashboard/${name}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }); + + return await response.json().catch(() => null); +}; + +const apiGetEventRiwayatCount = 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/event/dashboard/riwayat`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }); + + return await response.json().catch(() => null); +} + +const apiGetEventTipeAcara = 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/event/dashboard/tipe-acara`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }); + + return await response.json().catch(() => null); +}; diff --git a/src/app/dev/admin/event/main/page.tsx b/src/app/dev/admin/event/main/page.tsx index abd71c1e..21e83625 100644 --- a/src/app/dev/admin/event/main/page.tsx +++ b/src/app/dev/admin/event/main/page.tsx @@ -1,26 +1,9 @@ import { AdminEvent_Main } from "@/app_modules/admin/event"; -import AdminEvent_funCountByStatusId from "@/app_modules/admin/event/fun/count/fun_count_event_by_status_id"; -import { AdminEvent_funCountRiwayat } from "@/app_modules/admin/event/fun/count/fun_count_riwayat"; -import { AdminEvent_funCountTipeAcara } from "@/app_modules/admin/event/fun/count/fun_count_tipe_acara"; export default async function Page() { - const countPublish = await AdminEvent_funCountByStatusId("1"); - const countReview = await AdminEvent_funCountByStatusId("2"); - const countDraft = await AdminEvent_funCountByStatusId("3"); - const countReject = await AdminEvent_funCountByStatusId("4"); - const countTipeAcara = await AdminEvent_funCountTipeAcara(); - const countRiwayat = await AdminEvent_funCountRiwayat(); - return ( <> - + ); } diff --git a/src/app/lib/limit.ts b/src/app/lib/limit.ts new file mode 100644 index 00000000..1be48f04 --- /dev/null +++ b/src/app/lib/limit.ts @@ -0,0 +1,5 @@ +import pLimit from "p-limit"; + +const global_limit = pLimit(1); + +export default global_limit; \ No newline at end of file diff --git a/src/app/lib/new_fun_user_id.ts b/src/app/lib/new_fun_user_id.ts deleted file mode 100644 index c147ff22..00000000 --- a/src/app/lib/new_fun_user_id.ts +++ /dev/null @@ -1,28 +0,0 @@ -"use server"; - -import _ from "lodash"; -import { cookies } from "next/headers"; -import { decrypt } from "../auth/_lib/decrypt"; -import backendLogger from "@/util/backendLogger"; - -export async function newFunGetUserId() { - try { - const key = process.env.NEXT_PUBLIC_BASE_SESSION_KEY; - const c = cookies().get("hipmi-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; - } catch (error) { - backendLogger.log("Gagal mendapatkan user id", error); - return null; - } -} diff --git a/src/app_modules/admin/event/main/index.tsx b/src/app_modules/admin/event/main/index.tsx index 0f4db2b9..468d25d3 100644 --- a/src/app_modules/admin/event/main/index.tsx +++ b/src/app_modules/admin/event/main/index.tsx @@ -2,7 +2,16 @@ import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event"; +import { + apiGetEventRiwayatCount, + apiGetEventStatusCountDashboard, + apiGetEventTipeAcara, +} from "@/app/dev/admin/event/_lib/api_fecth_admin_event"; +import global_limit from "@/app/lib/limit"; import { AccentColor, MainColor } from "@/app_modules/_global/color"; +import { AdminColor } from "@/app_modules/_global/color/color_pallet"; +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; +import { clientLogger } from "@/util/clientLogger"; import { Flex, Paper, @@ -10,81 +19,192 @@ import { Stack, Text, ThemeIcon, - Title + Title, } from "@mantine/core"; -import { IconAlertTriangle, IconBookmark, IconBriefcase, IconHistory, IconUpload } from "@tabler/icons-react"; +import { useShallowEffect } from "@mantine/hooks"; +import { + IconAlertTriangle, + IconBookmark, + IconBriefcase, + IconHistory, + IconUpload, +} from "@tabler/icons-react"; import { useRouter } from "next/navigation"; +import { useState } from "react"; import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate"; -import { AdminColor } from "@/app_modules/_global/color/color_pallet"; -export default function AdminEvent_Main({ - countPublish, - countReview, - countDraft, - countReject, - countTipeAcara, - countRiwayat, -}: { - countPublish: number; - countReview: number; - countDraft: number; - countReject: number; - countTipeAcara: number; - countRiwayat: number -}) { +export default function AdminEvent_Main() { const router = useRouter(); + const [countPublish, setCountPublish] = useState(null); + const [countReview, setCountReview] = useState(null); + const [countReject, setCountReject] = useState(null); + const [countTipeAcara, setCountTipeAcara] = useState(null); + const [countRiwayat, setCountRiwayat] = useState(null); + + useShallowEffect(() => { + handlerLoadData(); + }, []); + + async function handlerLoadData() { + try { + const listLoadData = [ + global_limit(() => onLoadCountPublish()), + global_limit(() => onLoadCountReview()), + global_limit(() => onLoadCountReject()), + global_limit(() => onLoadCountRiwayat()), + global_limit(() => onLoadCountTipeAcara()), + ]; + const result = await Promise.all(listLoadData); + } catch (error) { + clientLogger.error("Error handler load data", error); + } + } + + async function onLoadCountPublish() { + try { + const respone = await apiGetEventStatusCountDashboard({ + name: "Publish", + }); + + if (respone) { + setCountPublish(respone.data); + } + } catch (error) { + clientLogger.error("Error get count publish", error); + } + } + + async function onLoadCountReview() { + try { + const respone = await apiGetEventStatusCountDashboard({ + name: "Review", + }); + + if (respone) { + setCountReview(respone.data); + } + } catch (error) { + clientLogger.error("Error get count review", error); + } + } + + async function onLoadCountReject() { + try { + const respone = await apiGetEventStatusCountDashboard({ + name: "Reject", + }); + + if (respone) { + setCountReject(respone.data); + } + } catch (error) { + clientLogger.error("Error get count reject", error); + } + } + + async function onLoadCountRiwayat() { + try { + const respone = await apiGetEventRiwayatCount(); + + if (respone) { + setCountRiwayat(respone.data); + } + } catch (error) { + clientLogger.error("Error get count riwayat", error); + } + } + + async function onLoadCountTipeAcara() { + try { + const respone = await apiGetEventTipeAcara(); + + if (respone) { + setCountTipeAcara(respone.data); + } + } catch (error) { + clientLogger.error("Error get count tipe acara", error); + } + } const listStatus = [ { id: 1, name: "Publish", - jumlah: countPublish, + jumlah: + countPublish == null ? ( + + ) : countPublish ? ( + countPublish + ) : ( + "-" + ), path: RouterAdminEvent.table_publish, color: MainColor.green, - icon: , + icon: , }, { id: 2, name: "Review", - jumlah: countReview, + jumlah: + countReview == null ? ( + + ) : countReview ? ( + countReview + ) : ( + "-" + ), path: RouterAdminEvent.table_review, color: MainColor.orange, - icon: + icon: , }, - // { - // id: 3, - // name: "Draft", - // jumlah: countDraft, - // path: "", - // color: "yellow", - // }, + { id: 3, name: "Reject", - jumlah: countReject, + jumlah: + countReject == null ? ( + + ) : countReject ? ( + countReject + ) : ( + "-" + ), path: RouterAdminEvent.table_reject, color: MainColor.red, - icon: + icon: , }, { id: 4, name: "Riwayat Event", - jumlah: countRiwayat, + jumlah: + countRiwayat == null ? ( + + ) : countRiwayat ? ( + countRiwayat + ) : ( + "-" + ), path: RouterAdminEvent.table_publish, color: AccentColor.softblue, - icon: + icon: , }, ]; const listBox2 = [ - { id: 1, name: "Tipe Acara", - jumlah: countTipeAcara, + jumlah: + countTipeAcara == null ? ( + + ) : countTipeAcara ? ( + countTipeAcara + ) : ( + "-" + ), path: RouterAdminEvent.table_publish, color: "#A888E2", - icon: + icon: , }, ]; @@ -109,19 +229,23 @@ export default function AdminEvent_Main({ shadow="md" radius="md" p="md" - // sx={{ borderColor: e.color, borderStyle: "solid" }} + // sx={{ borderColor: e.color, borderStyle: "solid" }} > - - {e.name} + + {e.name} + {e.jumlah} - + {e.icon} - ))} @@ -141,17 +265,19 @@ export default function AdminEvent_Main({ shadow="md" radius="md" p="md" - // sx={{ borderColor: e.color, borderStyle: "solid" }} + // sx={{ borderColor: e.color, borderStyle: "solid" }} > - - {e.name} - - {e.jumlah} - - {e.icon} - - - + + + {e.name} + + + {e.jumlah} + + {e.icon} + + + ))} diff --git a/src/middleware.ts b/src/middleware.ts index 82fae375..5f1afd7f 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -37,6 +37,7 @@ const middlewareConfig: MiddlewareConfig = { // "/api/user/*", // "/api/new/*", // ADMIN API + // "/api/admin/event/*", // Akses awal From fceea008293a71ee1c60ce057ed6b26574e8b965 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Thu, 30 Jan 2025 14:36:52 +0800 Subject: [PATCH 4/4] chore(release): 1.2.42 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e93ff79..b08dbab9 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.42](https://github.com/bipproduction/hipmi/compare/v1.2.41...v1.2.42) (2025-01-30) + ## [1.2.41](https://github.com/bipproduction/hipmi/compare/v1.2.40...v1.2.41) (2025-01-21) ## [1.2.40](https://github.com/bipproduction/hipmi/compare/v1.2.39...v1.2.40) (2025-01-16) diff --git a/package.json b/package.json index 81b515cf..20f4c0f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hipmi", - "version": "1.2.41", + "version": "1.2.42", "private": true, "prisma": { "seed": "bun prisma/seed.ts"