fix admin event

- detail event publish
This commit is contained in:
2025-03-25 15:05:33 +08:00
parent c9eabe5a30
commit db3994142f
12 changed files with 376 additions and 240 deletions

View File

@@ -2,50 +2,54 @@ import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
import prisma from "@/lib/prisma";
export async function GET(req: Request,
{ params }: { params: { id: string } }) {
try {
const { id } = params;
const data = await prisma.event.findUnique({
where: {
id: id
export async function GET(
req: Request,
{ params }: { params: { id: string } }
) {
try {
const { id } = params;
const data = await prisma.event.findUnique({
where: {
id: id,
},
include: {
Author: {
select: {
username: true,
nomor: true,
Profile: {
select: {
name: true,
alamat: true,
},
},
include: {
Author: {
select: {
username: true,
nomor: true,
Profile: {
select: {
name: true,
alamat: true
}
}
}
},
EventMaster_TipeAcara: {
select: {
name: true
}
}
}
})
return NextResponse.json({
success: true,
message: "Success get data event detail",
data: data,
},
},
{ status: 200 }
)
} catch (error) {
backendLogger.error("Error get data event detail >>", error);
return NextResponse.json({
success: false,
message: "Error get data event detail",
reason: (error as Error).message
EventMaster_TipeAcara: {
select: {
name: true,
},
},
{ status: 500 }
)
}
}
EventMaster_Status: true,
},
});
return NextResponse.json(
{
success: true,
message: "Success get data event detail",
data: data,
},
{ status: 200 }
);
} catch (error) {
backendLogger.error("Error get data event detail >>", error);
return NextResponse.json(
{
success: false,
message: "Error get data event detail",
reason: (error as Error).message,
},
{ status: 500 }
);
}
}

View File

@@ -0,0 +1,11 @@
import { AdminEvent_UiNewDetail } from "@/app_modules/admin/event/_ui/ui_new_detail";
async function Page() {
return (
<>
<AdminEvent_UiNewDetail />
</>
);
}
export default Page;

View File

@@ -0,0 +1,74 @@
import { MODEL_EVENT } from "@/app_modules/event/_lib/interface";
import { Badge, Grid, Stack, Text } from "@mantine/core";
import moment from "moment";
import "moment/locale/id";
import { Admin_ComponentBoxStyle } from "../../_admin_global/_component/comp_admin_boxstyle";
function AdminEvent_ComponentDetailData({
data,
}: {
data: MODEL_EVENT | null;
}) {
const listData = [
{
label: "Nama",
value: data?.Author.Profile.name,
},
{
label: "Username",
value: data?.Author.username,
},
{
label: "Nomor",
value: `+ ${data?.Author.nomor}`,
},
{
label: "Status",
value: <Badge>{data?.EventMaster_Status.name}</Badge>,
},
{
label: "Judul",
value: data?.title,
},
{
label: "Lokasi",
value: data?.lokasi,
},
{
label: "Tipe acara",
value: data?.EventMaster_TipeAcara.name,
},
{
label: "Tanggal & Waktu mulai",
value: moment(data?.tanggal).format("LLLL"),
},
{
label: "Tanggal & Waktu selesai",
value: moment(data?.tanggalSelesai).format("LLLL"),
},
{
label: "Deskripsi",
value: data?.deskripsi,
},
];
return (
<>
{listData.map((item, index) => (
<Grid key={index}>
<Grid.Col span={3}>
<Text fw={"bold"}>{item.label}</Text>
</Grid.Col>
<Grid.Col span={1}>
<Text>:</Text>
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>{item.value}</Text>
</Grid.Col>
</Grid>
))}
</>
);
}
export default AdminEvent_ComponentDetailData;

View File

@@ -0,0 +1,67 @@
import { MODEL_EVENT } from "@/app_modules/event/_lib/interface";
import { Button, Grid, Stack, Text } from "@mantine/core";
import { Admin_ComponentBoxStyle } from "../../_admin_global/_component/comp_admin_boxstyle";
import AdminEvent_ComponentDetailData from "./comp_detail_data";
import QRCode from "react-qr-code";
function AdminEvent_ComponentDetailPublish({ data }: { data: MODEL_EVENT }) {
const handleDownloadQR = () => {
const svg: any = document.getElementById(data.id);
const svgData = new XMLSerializer().serializeToString(svg);
const canvas = document.createElement("canvas");
const ctx: any = canvas.getContext("2d");
const img = new Image();
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
const pngFile = canvas.toDataURL("image/png");
const downloadLink = document.createElement("a");
downloadLink.download = `QRCode ${data.title}`;
downloadLink.href = `${pngFile}`;
downloadLink.click();
};
img.src = `data:image/svg+xml;base64,${btoa(svgData)}`;
};
const donwloadButton = () => {
return (
<>
<Grid>
<Grid.Col span={3}>
<Text fw={"bold"}>QR Code</Text>
</Grid.Col>
<Grid.Col span={1}>
<Text>:</Text>
</Grid.Col>
<Grid.Col span={"auto"}>
{/* <Button onClick={handleDownloadQR}>Download QR</Button> */}
<QRCode
id={data.id}
style={{ height: 100, width: 100 }}
value={`${origin}/dev/event/konfirmasi/${data.id}`}
/>
</Grid.Col>
</Grid>
</>
);
};
return (
<>
<Grid>
<Grid.Col span={9}>
<Admin_ComponentBoxStyle>
<Stack>
<AdminEvent_ComponentDetailData data={data} />
{donwloadButton()}
</Stack>
</Admin_ComponentBoxStyle>
</Grid.Col>
</Grid>
{/* <ComponentEvent_DetailDataEvent data={data} /> */}
</>
);
}
export default AdminEvent_ComponentDetailPublish;

View File

@@ -1,74 +0,0 @@
import { AdminColor } from '@/app_modules/_global/color/color_pallet';
import CustomSkeleton from '@/app_modules/components/CustomSkeleton';
import { MODEL_EVENT } from '@/app_modules/event/_lib/interface';
import { Grid, Paper, Stack, Text, Title } from '@mantine/core';
import React from 'react';
function ComponentEvent_DetailDataAuthor({ data }: { data: MODEL_EVENT | null }) {
return (
<>
{/* {!data ? (
<CustomSkeleton height={"40vh"} width={"100%"} />
) : (
)} */}
<Paper bg={AdminColor.softBlue} p={"lg"}>
<Stack c={AdminColor.white}>
<Title order={3}>Data User</Title>
<Stack spacing={"xs"}>
<Grid>
<Grid.Col span={6}>
<Text fw={"bold"}>Nama:</Text>
</Grid.Col>
<Grid.Col span={6}>
{data ?
<Text>{data?.Author?.Profile?.name}</Text>
:
<CustomSkeleton height={30} width={"100%"} />
}
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={6}>
<Text fw={"bold"}>Username:</Text>
</Grid.Col>
<Grid.Col span={6}>
{data ?
<Text>{data?.Author?.username}</Text>
:
<CustomSkeleton height={30} width={"100%"} />
}
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={6}>
<Text fw={"bold"}>Nomor:</Text>
</Grid.Col>
<Grid.Col span={6}>
{data ?
<Text>{data?.Author?.nomor}</Text>
:
<CustomSkeleton height={30} width={"100%"} />
}
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={6}>
<Text fw={"bold"}>Alamat:</Text>
</Grid.Col>
<Grid.Col span={6}>
{data ?
<Text>{data?.Author?.Profile?.alamat}</Text>
:
<CustomSkeleton height={30} width={"100%"} />
}
</Grid.Col>
</Grid>
</Stack>
</Stack>
</Paper >
</>
);
}
export default ComponentEvent_DetailDataAuthor;

View File

@@ -0,0 +1,68 @@
"use client";
import { MODEL_EVENT } from "@/app_modules/event/_lib/interface";
import { clientLogger } from "@/util/clientLogger";
import { SimpleGrid, Stack } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useParams } from "next/navigation";
import { useState } from "react";
import AdminGlobal_ComponentBackButton from "../../_admin_global/back_button";
import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate";
import { apiGetAdminDetailEventById } from "../_lib/api_fecth_admin_event";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
import ComponentAdminGlobal_IsEmptyData from "../../_admin_global/is_empty_data";
import { AdminEvent_ViewDetailPublish } from "../_view/view_detail_publish";
export function AdminEvent_UiNewDetail() {
const params = useParams<{ id: string }>();
const [loading, setLoading] = useState(true);
const [data, setData] = useState<MODEL_EVENT | null>();
useShallowEffect(() => {
getDetailData();
}, []);
async function getDetailData() {
try {
setLoading(true);
const response = await apiGetAdminDetailEventById({
id: params.id,
});
if (response?.success && response?.data) {
console.log("res >>", response.data);
setData(response.data);
} else {
console.error("Invalid data format received:", response);
setData(null);
}
} catch (error) {
clientLogger.error("Error get data table detail publish", error);
setData(null);
}
}
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Detail event" />
<AdminGlobal_ComponentBackButton />
{data === undefined ? (
<SimpleGrid cols={2}>
<CustomSkeleton h={500} />
</SimpleGrid>
) : !data ? (
<ComponentAdminGlobal_IsEmptyData />
) : data.EventMaster_Status.name === "Publish" ? (
<AdminEvent_ViewDetailPublish data={data}/>
) : data.EventMaster_Status.name === "Review" ? (
"Detail Review"
) : data.EventMaster_Status.name === "Reject" ? (
"Detail Reject"
) : (
""
)}
</Stack>
</>
);
}

View File

@@ -158,14 +158,6 @@ export function AdminEvent_ViewDetailPeserta() {
</thead>
<tbody>{renderTableBody()}</tbody>
</Table>
{_.isEmpty(data) ? (
<ComponentAdminGlobal_IsEmptyData
text="Tidak ada peserta"
marginTop={100}
/>
) : (
""
)}
</ScrollArea>
<Center mt={"xl"}>

View File

@@ -0,0 +1,48 @@
import { MODEL_EVENT } from "@/app_modules/event/_lib/interface";
import { IconCircleCheck } from "@tabler/icons-react";
import { useAtom } from "jotai";
import { gs_admin_event_menu_publish } from "../_lib/global_state";
import { Stack, Group, Button } from "@mantine/core";
import AdminGlobal_ComponentBackButton from "../../_admin_global/back_button";
import AdminEvent_ComponentDetailPublish from "../_component/comp_detail_publish";
import { AdminEvent_ViewDetailPeserta } from "./view_detail_peserta";
export function AdminEvent_ViewDetailPublish({ data }: { data: MODEL_EVENT }) {
const [selectPage, setSelectPage] = useAtom(gs_admin_event_menu_publish);
const listPage = [
{
id: "1",
name: "Detail Event",
icon: <IconCircleCheck />,
},
{
id: "2",
name: "Daftar Peserta",
icon: <IconCircleCheck />,
},
];
return (
<>
<Stack mt={"lg"}>
<Group>
{listPage.map((e) => (
<Button
radius={"xl"}
key={e.id}
color={selectPage == e.id ? "green" : "gray"}
onClick={() => setSelectPage(e.id)}
style={{
transition: "all 0.5s",
}}
>
{e.name}
</Button>
))}
</Group>
{selectPage == "1" && <AdminEvent_ComponentDetailPublish data={data} />}
{selectPage == "2" && <AdminEvent_ViewDetailPeserta />}
</Stack>
</>
);
}

View File

@@ -1,59 +0,0 @@
import { SimpleGrid } from '@mantine/core';
import React, { useState } from 'react';
import ComponentEvent_DetailDataAuthor from '../_component/detail_data_author';
import ComponentEvent_DetailDataEvent from '../_component/detail_data_event';
import { useParams } from 'next/navigation';
import { apiGetAdminDetailEventById } from '../_lib/api_fecth_admin_event';
import { MODEL_EVENT } from '@/app_modules/event/_lib/interface';
import { clientLogger } from '@/util/clientLogger';
import { useShallowEffect } from '@mantine/hooks';
function AdminEvent_ViewDetailData({ }) {
const params = useParams<{ id: string }>();
const [loading, setLoading] = useState(true);
const [data, setData] = useState<MODEL_EVENT | null>(null);
useShallowEffect(() => {
getDetailData();
}, [])
async function getDetailData() {
try {
setLoading(true);
const response = await apiGetAdminDetailEventById({
id: params.id,
})
if (response?.success && response?.data) {
setTimeout(() => {
setData(response.data);
}, 1000)
} else {
console.error("Invalid data format received:", response);
setData(null);
}
} catch (error) {
clientLogger.error("Error get data table detail publish", error);
setData(null);
}
}
return (
<>
<SimpleGrid
cols={2}
breakpoints={[
{ maxWidth: "48rem", cols: 2, spacing: "sm" },
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
]}
>
{/* //Data Author */}
<ComponentEvent_DetailDataAuthor data={data}/>
{/* Data Event */}
<ComponentEvent_DetailDataEvent data={data} />
</SimpleGrid>
</>
);
}
export default AdminEvent_ViewDetailData;

View File

@@ -6,7 +6,7 @@ import { IconCircleCheck } from '@tabler/icons-react';
import { Button, Group, Stack } from '@mantine/core';
import AdminGlobal_ComponentBackButton from '../../_admin_global/back_button';
import { AdminEvent_ViewDetailPeserta } from '../_view';
import AdminEvent_ViewDetailData from '../detail/view_detail_data';
import AdminEvent_ComponentDetailPublish from '../_component/comp_detail_publish';
import AdminEvent_DetailDataSponsor from '../_component/detail_data_sponsor';
function AdminEvent_DetailPublish() {
@@ -22,11 +22,11 @@ function AdminEvent_DetailPublish() {
name: "Daftar Peserta",
icon: <IconCircleCheck />,
},
{
id: "3",
name: "Daftar Sponsor",
icon: <IconCircleCheck />,
}
// {
// id: "3",
// name: "Daftar Sponsor",
// icon: <IconCircleCheck />,
// }
]
return (
<>
@@ -50,14 +50,14 @@ function AdminEvent_DetailPublish() {
))}
</Group>
{selectPage == "1" ? (
<AdminEvent_ViewDetailData />
<AdminEvent_ComponentDetailPublish data={{} as any} />
) : null}
{selectPage == "2" ? (
<AdminEvent_ViewDetailPeserta />
) : null}
{selectPage == "3" ? (
{/* {selectPage == "3" ? (
<AdminEvent_DetailDataSponsor />
) : null}
) : null} */}
</Stack>
</>
);

View File

@@ -6,6 +6,7 @@ import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
import { MODEL_EVENT } from "@/app_modules/event/_lib/interface";
import { clientLogger } from "@/util/clientLogger";
import {
Box,
Button,
Center,
Pagination,
@@ -18,13 +19,14 @@ import {
TextInput,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconEyeCheck, IconSearch } from "@tabler/icons-react";
import { IconDownload, IconEyeCheck, IconSearch } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import QRCode from "react-qr-code";
import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate";
import { AdminColor } from "@/app_modules/_global/color/color_pallet";
import Admin_DetailButton from "../../_admin_global/_component/button/detail_button";
export default function AdminEvent_TablePublish() {
return (
@@ -119,33 +121,31 @@ function TableStatus() {
return data.map((e, i) => (
<tr key={i}>
<td>
<Center w={200}>
{/* <td>
<Center>
<QRCode
id={e.id}
style={{ height: 70, width: 70 }}
value={`${origin}/dev/event/konfirmasi/${e.id}`}
/>
</Center>
</td>
</td> */}
<td>
<Center w={200}>
<Button onClick={() => handleDownloadQR(e.id, e.title)}>
Download QR
</Button>
<Center c={AdminColor.white}>
<Box w={100}>
<Text lineClamp={1}>{e?.Author?.username} dasdsasdasdsa sadasd</Text>
</Box>
</Center>
</td>
<td>
<Center c={AdminColor.white} w={200}>
<Text>{e?.Author?.username}</Text>
<Center c={AdminColor.white} >
<Box w={100}>
<Text lineClamp={2}>{e.title}</Text>
</Box>
</Center>
</td>
<td>
<Center c={AdminColor.white} w={200}>
<Text lineClamp={2}>{e.title}</Text>
</Center>
</td>
<td>
{/* <td>
<Center c={AdminColor.white} w={200}>
<Text>{e.lokasi}</Text>
</Center>
@@ -154,10 +154,10 @@ function TableStatus() {
<Center c={AdminColor.white} w={200}>
<Text>{e.EventMaster_TipeAcara?.name}</Text>
</Center>
</td>
</td> */}
<td>
<Center c={AdminColor.white} w={200}>
<Center c={AdminColor.white}>
<Text align="center">
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
@@ -172,7 +172,7 @@ function TableStatus() {
</Center>
</td>
<td>
<Center c={AdminColor.white} w={200}>
<Center c={AdminColor.white}>
<Text align="center">
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
@@ -187,7 +187,7 @@ function TableStatus() {
</Center>
</td>
<td>
{/* <td>
<Center c={AdminColor.white} w={400}>
<Spoiler
hideLabel="sembunyikan"
@@ -197,9 +197,9 @@ function TableStatus() {
{e.deskripsi}
</Spoiler>
</Center>
</td>
</td> */}
<td>
{/* <td>
<Button
loaderPosition="center"
loading={loading && e.id === eventId}
@@ -214,6 +214,26 @@ function TableStatus() {
>
Detail
</Button>
</td> */}
<td>
<Center>
<Button
leftIcon={<IconDownload />}
radius="xl"
onClick={() => handleDownloadQR(e.id, e.title)}
>
Download QR
</Button>
</Center>
</td>
<td>
<Center>
<Admin_DetailButton
path={RouterAdminEvent.new_detail({ id: e.id })}
/>
</Center>
</td>
</tr>
));
@@ -241,40 +261,25 @@ function TableStatus() {
) : (
<Paper p="md" bg={AdminColor.softBlue} h="80vh">
<ScrollArea w="100%" h="90%">
<Table
verticalSpacing="md"
horizontalSpacing="md"
p="md"
w={1500}
>
<Table verticalSpacing="md" horizontalSpacing="md" p="md">
<thead>
<tr>
<th>
<Center c={AdminColor.white}>QR Code</Center>
</th>
<th>
<Center c={AdminColor.white}>Download QR</Center>
</th>
<th>
<Center c={AdminColor.white}>Username</Center>
</th>
<th>
<Center c={AdminColor.white}>Judul</Center>
</th>
<th>
<Center c={AdminColor.white}>Lokasi</Center>
</th>
<th>
<Center c={AdminColor.white}>Tipe Acara</Center>
</th>
<th>
<Center c={AdminColor.white}>Tanggal & Waktu Mulai</Center>
</th>
<th>
<Center c={AdminColor.white}>Tanggal & Waktu Selesai</Center>
<Center c={AdminColor.white}>
Tanggal & Waktu Selesai
</Center>
</th>
<th>
<Center c={AdminColor.white}>Deskripsi</Center>
<Center c={AdminColor.white}>QR Code</Center>
</th>
<th>
<Center c={AdminColor.white}>Aksi</Center>

View File

@@ -3,7 +3,10 @@ export const RouterAdminEvent = {
// detail
detail_peserta: "/dev/admin/event/detail/peserta/",
detail_publish: "/dev/admin/event/detail/publish/",
detail_publish: ({ id }: { id: string }) =>
`/dev/admin/event/detail/publish/${id}`,
new_detail: ({ id }: { id: string }) =>
`/dev/admin/event/${id}`,
detail_sponsor: "/dev/admin/event/detail/detail_sponsor/",
// child
@@ -14,7 +17,4 @@ export const RouterAdminEvent = {
table_review: "/dev/admin/event/table/review",
table_publish: "/dev/admin/event/table/publish",
table_reject: "/dev/admin/event/table/reject",
};