Merge pull request #257 from bipproduction/bagas/28-jan-25

Bagas/28 jan 25
This commit is contained in:
Bagasbanuna02
2025-01-30 14:38:13 +08:00
committed by GitHub
12 changed files with 393 additions and 104 deletions

View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "hipmi",
"version": "1.2.41",
"version": "1.2.42",
"private": true,
"prisma": {
"seed": "bun prisma/seed.ts"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 (
<>
<AdminEvent_Main
countPublish={countPublish as number}
countReview={countReview as number}
countDraft={countDraft as number}
countReject={countReject as number}
countTipeAcara={countTipeAcara as number}
countRiwayat={countRiwayat}
/>
<AdminEvent_Main />
</>
);
}

5
src/app/lib/limit.ts Normal file
View File

@@ -0,0 +1,5 @@
import pLimit from "p-limit";
const global_limit = pLimit(1);
export default global_limit;

View File

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

View File

@@ -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<number | null>(null);
const [countReview, setCountReview] = useState<number | null>(null);
const [countReject, setCountReject] = useState<number | null>(null);
const [countTipeAcara, setCountTipeAcara] = useState<number | null>(null);
const [countRiwayat, setCountRiwayat] = useState<number | null>(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 ? (
<CustomSkeleton height={40} width={40} />
) : countPublish ? (
countPublish
) : (
"-"
),
path: RouterAdminEvent.table_publish,
color: MainColor.green,
icon: <IconUpload size={18} color="#4CAF4F"/>,
icon: <IconUpload size={18} color="#4CAF4F" />,
},
{
id: 2,
name: "Review",
jumlah: countReview,
jumlah:
countReview == null ? (
<CustomSkeleton height={40} width={40} />
) : countReview ? (
countReview
) : (
"-"
),
path: RouterAdminEvent.table_review,
color: MainColor.orange,
icon: <IconBookmark size={18} color="#FF7043"/>
icon: <IconBookmark size={18} color="#FF7043" />,
},
// {
// id: 3,
// name: "Draft",
// jumlah: countDraft,
// path: "",
// color: "yellow",
// },
{
id: 3,
name: "Reject",
jumlah: countReject,
jumlah:
countReject == null ? (
<CustomSkeleton height={40} width={40} />
) : countReject ? (
countReject
) : (
"-"
),
path: RouterAdminEvent.table_reject,
color: MainColor.red,
icon: <IconAlertTriangle size={18} color="#FF4B4C" />
icon: <IconAlertTriangle size={18} color="#FF4B4C" />,
},
{
id: 4,
name: "Riwayat Event",
jumlah: countRiwayat,
jumlah:
countRiwayat == null ? (
<CustomSkeleton height={40} width={40} />
) : countRiwayat ? (
countRiwayat
) : (
"-"
),
path: RouterAdminEvent.table_publish,
color: AccentColor.softblue,
icon: <IconHistory size={18} color="#007CBA"/>
icon: <IconHistory size={18} color="#007CBA" />,
},
];
const listBox2 = [
{
id: 1,
name: "Tipe Acara",
jumlah: countTipeAcara,
jumlah:
countTipeAcara == null ? (
<CustomSkeleton height={40} width={40} />
) : countTipeAcara ? (
countTipeAcara
) : (
"-"
),
path: RouterAdminEvent.table_publish,
color: "#A888E2",
icon: <IconBriefcase size={18} color="#A888E2" />
icon: <IconBriefcase size={18} color="#A888E2" />,
},
];
@@ -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" }}
>
<Stack spacing={0}>
<Text fw={"bold"} color={AccentColor.white}>{e.name}</Text>
<Text fw={"bold"} color={AccentColor.white}>
{e.name}
</Text>
<Flex align={"center"} justify={"space-between"}>
<Title c={AccentColor.white}>{e.jumlah}</Title>
<ThemeIcon radius={"xl"} size={"md"} color={AccentColor.white}>
<ThemeIcon
radius={"xl"}
size={"md"}
color={AccentColor.white}
>
{e.icon}
</ThemeIcon>
</Flex>
</Stack>
</Paper>
))}
</SimpleGrid>
@@ -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" }}
>
<Stack spacing={0}>
<Text fw={"bold"} color={AccentColor.white}>{e.name}</Text>
<Flex align={"center"} justify={"space-between"}>
<Title c={AccentColor.white}>{e.jumlah}</Title>
<ThemeIcon radius={"xl"} size={"md"} bg={AccentColor.white}>
{e.icon}
</ThemeIcon>
</Flex>
</Stack>
<Stack spacing={0}>
<Text fw={"bold"} color={AccentColor.white}>
{e.name}
</Text>
<Flex align={"center"} justify={"space-between"}>
<Title c={AccentColor.white}>{e.jumlah}</Title>
<ThemeIcon radius={"xl"} size={"md"} bg={AccentColor.white}>
{e.icon}
</ThemeIcon>
</Flex>
</Stack>
</Paper>
))}
</SimpleGrid>

View File

@@ -37,6 +37,7 @@ const middlewareConfig: MiddlewareConfig = {
// "/api/user/*",
// "/api/new/*",
// ADMIN API
// "/api/admin/event/*",
// Akses awal