API Dashboard Investasi & Event

This commit is contained in:
2025-01-30 17:44:18 +08:00
36 changed files with 1070 additions and 288 deletions

View File

@@ -0,0 +1,16 @@
const apiGetDonasiStatusCountDashboard = 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/donasi/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);
};

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

@@ -0,0 +1,22 @@
const apiGetInvestasiCountDashboard = 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/investasi/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);
};
export default apiGetInvestasiCountDashboard;

View File

@@ -46,49 +46,129 @@ import TablePublikasiProgresInvestasi from "./table_publikasi_progres";
import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate";
import { AccentColor, MainColor } from "@/app_modules/_global/color";
import { AdminColor } from "@/app_modules/_global/color/color_pallet";
import { clientLogger } from "@/util/clientLogger";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
import global_limit from "@/app/lib/limit";
import { useShallowEffect } from "@mantine/hooks";
import apiGetInvestasiCountDashboard from "../_lib/api_fetch_count_status";
export default function Admin_Investasi({
listInvestasi,
countDraft,
countReview,
countPublish,
countReject,
totalInvestasiByUser,
publishProgres,
}: {
listInvestasi: MODEL_INVESTASI[];
countDraft: number | any;
countReview: number | any;
countPublish: number | any;
countReject: number | any;
totalInvestasiByUser: any[];
publishProgres: any[];
}) {
const [investasi, setInvestasi] = useState(listInvestasi);
const router = useRouter();
const [countPublish, setCountPublish] = useState<number | null>(null);
const [countReview, setCountReview] = useState<number | null>(null);
const [countReject, setCountReject] = useState<number | null>(null);
useShallowEffect(() => {
handlerLoadData();
}, [])
async function handlerLoadData() {
try {
const listLoadData = [
global_limit(() => onLoadCountPublish()),
global_limit(() => onLoadCountReview()),
global_limit(() => onLoadCountReject()),
];
const result = await Promise.all(listLoadData);
} catch (error) {
clientLogger.error("Error handler load data", error);
}
}
async function onLoadCountPublish() {
try {
const response = await apiGetInvestasiCountDashboard({
name: "Publish",
});
console.log("Response Publish", response);
if (response) {
setCountPublish(response.data);
}
} catch (error) {
clientLogger.error("Error get count publish", error);
}
}
async function onLoadCountReview() {
try {
const response = await apiGetInvestasiCountDashboard({
name: "Review",
});
if (response) {
setCountReview(response.data);
}
} catch (error) {
clientLogger.error("Error get count review", error);
}
}
async function onLoadCountReject() {
try {
const response = await apiGetInvestasiCountDashboard({
name: "Reject",
});
if (response) {
setCountReject(response.data);
}
} catch (error) {
clientLogger.error("Error get count reject", error);
}
}
const listBox = [
{
id: 1,
name: "Publish",
jumlah: countPublish,
link: RouterAdminInvestasi_OLD.table_status_publish,
jumlah:
countPublish == null ? (
<CustomSkeleton height={40} width={40} />
) : countPublish ? (
countPublish
) : (
"-"
),
path: RouterAdminInvestasi_OLD.table_status_publish,
color: MainColor.green,
icon: <IconUpload size={18} color="#4CAF4F" />,
},
{
id: 2,
name: "Review",
jumlah: countReview,
link: RouterAdminInvestasi_OLD.table_status_review,
jumlah: countReview == null ? (
<CustomSkeleton height={40} width={40} />
) : countReview ? (
countReview
) : (
"-"
),
path: RouterAdminInvestasi_OLD.table_status_review,
color: MainColor.orange,
icon: <IconBookmark size={18} color="#FF7043" />
},
{
id: 3,
name: "Reject",
jumlah: countReject,
link: RouterAdminInvestasi_OLD.table_status_reject,
jumlah: countReject == null ? (
<CustomSkeleton height={40} width={40} />
) : countReject ? (
countReject
) : (
"-"
),
path: RouterAdminInvestasi_OLD.table_status_reject,
color: MainColor.red,
icon: <IconAlertTriangle size={18} color="#FF4B4C" />

View File

@@ -10,6 +10,7 @@ import { apiGetCountPortofolio, apiGetCountUserActive } from "../lib/api_fetch_m
import { NextResponse } from "next/server";
import { clientLogger } from "@/util/clientLogger";
import MainDashboardSkeleton from "../../_admin_global/_component/skeleton/main_dashboard_skeleton";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
export default function AdminMain() {
const [countUser, setCountUser] = useState<number | null>(null);
@@ -34,7 +35,7 @@ export default function AdminMain() {
clientLogger.error("Error get count user data", error);
}
}
async function onLoadDataPortofolio() {
try {
const response = await apiGetCountPortofolio();
@@ -52,14 +53,26 @@ export default function AdminMain() {
{
id: 1,
name: "User",
jumlah: countUser,
jumlah:
countUser == null ? (<CustomSkeleton height={40} width={40} />
) : countUser ? (
countUser
) : (
"-"
),
link: "",
icon: <IconUsers size={18} color="#0066CCFF" />
},
{
id: 2,
name: "Portofolio",
jumlah: countPortofolio,
jumlah:
countPortofolio == null ? (<CustomSkeleton height={40} width={40} />
) : countPortofolio ? (
countPortofolio
) : (
"-"
),
link: "",
icon: <IconFileText size={18} color={"#B6A22EFF"} />
},
@@ -68,35 +81,31 @@ export default function AdminMain() {
return (
<>
{!countUser && !countPortofolio ? (
<MainDashboardSkeleton />
) : (
<Stack spacing={"sm"}>
<ComponentAdminGlobal_HeaderTamplate name="Main Dashboard" />
{/* <Title c={AdminColor.white}>Main Dashboard</Title>
<Stack spacing={"sm"}>
<ComponentAdminGlobal_HeaderTamplate name="Main Dashboard" />
{/* <Title c={AdminColor.white}>Main Dashboard</Title>
<Divider c={AdminColor.dividerWhite} mb={"md"} size={"xs"} /> */}
<Grid>
{listBox.map((e) => (
<Grid.Col md={4} lg={4} key={e.id}>
<Paper style={{ borderColor: "transparent" }} bg={AdminColor.softBlue} withBorder shadow="md" radius="md" p="md">
<Stack spacing={0}>
<Text fw={"bold"} c={MainColor.white}>{e.name}</Text>
<Flex align={"center"} justify={"space-between"}>
<Title c={MainColor.white}>{e.jumlah}</Title>
<ThemeIcon radius={"xl"} size={"md"} color={AccentColor.white}>{e.icon}</ThemeIcon>
</Flex>
</Stack>
</Paper>
</Grid.Col>
))}
<Grid.Col md={4} lg={4}>
{/* <PieChart /> */}
<Grid>
{listBox.map((e) => (
<Grid.Col md={4} lg={4} key={e.id}>
<Paper style={{ borderColor: "transparent" }} bg={AdminColor.softBlue} withBorder shadow="md" radius="md" p="md">
<Stack spacing={0}>
<Text fw={"bold"} c={MainColor.white}>{e.name}</Text>
<Flex align={"center"} justify={"space-between"}>
<Title c={MainColor.white}>{e.jumlah}</Title>
<ThemeIcon radius={"xl"} size={"md"} color={AccentColor.white}>{e.icon}</ThemeIcon>
</Flex>
</Stack>
</Paper>
</Grid.Col>
</Grid>
</Stack>
)}
))}
<Grid.Col md={4} lg={4}>
{/* <PieChart /> */}
</Grid.Col>
</Grid>
</Stack>
</>
);
}