Merge pull request #151 from bipproduction/event/qrcode

Event/qrcode
This commit is contained in:
Bagasbanuna02
2024-12-03 10:28:23 +08:00
committed by GitHub
19 changed files with 439 additions and 13 deletions

View File

@@ -2,6 +2,14 @@
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.13](https://github.com/bipproduction/hipmi/compare/v1.2.12...v1.2.13) (2024-12-03)
### Bug Fixes
* event ([fc38813](https://github.com/bipproduction/hipmi/commit/fc388133a638d4288314dd3faeddfcce61fe7292))
* version 1.2.12 ([932735f](https://github.com/bipproduction/hipmi/commit/932735f9238db07b331b1b26328624247371c3d6))
## [1.2.12](https://github.com/bipproduction/hipmi/compare/v1.2.11...v1.2.12) (2024-12-02)

View File

@@ -1,6 +1,6 @@
{
"name": "hipmi",
"version": "1.2.12",
"version": "1.2.13",
"private": true,
"prisma": {
"seed": "npx tsx prisma/seed.ts --yes"

View File

@@ -618,6 +618,7 @@ model Event_Peserta {
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
isPresent Boolean @default(false)
Event Event? @relation(fields: [eventId], references: [id])
eventId String?

View File

@@ -0,0 +1,6 @@
import { headers } from "next/headers";
export async function GET(req: Request) {
const origin = new URL(req.url).origin;
return new Response(JSON.stringify({ success: true, origin }));
}

View File

@@ -0,0 +1,40 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import Ui_Konfirmasi from "@/app_modules/event/_ui/konfirmasi";
import {
event_funCheckKehadiran,
event_funCheckPesertaByUserId,
} from "@/app_modules/event/fun";
import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id";
import { redirect } from "next/navigation";
export default async function Page({ params }: { params: { id: string } }) {
const eventId = params.id;
const userLoginId = await funGetUserIdByToken();
const dataEvent = await event_getOneById(eventId);
const checkPeserta = await event_funCheckPesertaByUserId({
eventId: eventId,
userId: userLoginId as string,
});
if (dataEvent?.isArsip)
return redirect(`/dev/event/detail/riwayat/${dataEvent.id}`);
if (checkPeserta == false)
return redirect(`/dev/event/detail/main/${eventId}`);
// if (checkKehadiran) {
// return redirect(`/dev/event/main/beranda`);
// }
return (
<>
<Ui_Konfirmasi
dataEvent={dataEvent as any}
userLoginId={userLoginId as string}
/>
</>
);
}

View File

@@ -4,8 +4,6 @@ import { HomeView } from "@/app_modules/home";
import { user_getOneByUserId } from "@/app_modules/home/fun/get/get_one_user_by_id";
import { job_getTwoForHomeView } from "@/app_modules/job/fun/get/get_two_for_home_view";
import notifikasi_countUserNotifikasi from "@/app_modules/notifikasi/fun/count/fun_count_by_id";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
export default async function PageHome() {
@@ -20,8 +18,8 @@ export default async function PageHome() {
// if (dataUser?.active === false) {
// return redirect(RouterHome.home_user_non_active);
// }
if (dataUser?.masterUserRoleId === "2" || dataUser?.masterUserRoleId === "3")
return redirect(RouterAdminDashboard.main_admin);
// if (dataUser?.masterUserRoleId === "2" || dataUser?.masterUserRoleId === "3")
// return redirect(RouterAdminDashboard.main_admin);
return (
<>

View File

@@ -51,7 +51,7 @@ export function ComponentGlobal_AvatarAndUsername({
</Avatar>
) : (
<ComponentGlobal_LoaderAvatar
fileId={profile.imageId as any}
fileId={profile?.imageId as any}
sizeAvatar={sizeAvatar}
/>
)}

View File

@@ -24,6 +24,7 @@ import { useState } from "react";
import ComponentAdminGlobal_HeaderTamplate from "../../_admin_global/header_tamplate";
import { adminEvent_funGetListPublish } from "../fun";
import QRCode from "react-qr-code";
import { useShallowEffect } from "@mantine/hooks";
export default function AdminEvent_TablePublish({
listPublish,
@@ -49,6 +50,21 @@ function TableStatus({ listPublish }: { listPublish: any }) {
const [eventId, setEventId] = useState("");
const [loading, setLoading] = useState(false);
const [origin, setOrigin] = useState("");
useShallowEffect(() => {
onLoadOrigin(setOrigin);
// if (typeof window !== "undefined") {
// setOrigin(window.location.origin);
// }
}, [setOrigin]);
async function onLoadOrigin(setOrigin: any) {
const res = await fetch("/api/origin-url");
const result = await res.json();
setOrigin(result.origin);
}
async function onSearch(s: string) {
setSearch(s);
const loadData = await adminEvent_funGetListPublish({
@@ -80,9 +96,12 @@ function TableStatus({ listPublish }: { listPublish: any }) {
<tr key={i}>
<td>
<Center w={200}>
<QRCode style={{ height: 50, width: 50 }} value={e.id} />
<QRCode
style={{ height: 70, width: 70 }}
value={`${origin}/dev/event/konfirmasi/${e.id}`}
/>
</Center>
</td>
</td>
<td>
<Center w={200}>
<Text>{e?.Author?.username}</Text>

View File

@@ -0,0 +1,136 @@
"use client";
import {
UIGlobal_LayoutDefault,
UIGlobal_LayoutTamplate,
} from "@/app_modules/_global/ui";
import { Button, Paper, Skeleton, Stack, Text, Title } from "@mantine/core";
import { MODEL_EVENT } from "../model/interface";
import { useShallowEffect } from "@mantine/hooks";
import { AccentColor, MainColor } from "@/app_modules/_global/color";
import { event_funCheckKehadiran, event_funUpdateKehadiran } from "../fun";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
} from "@/app_modules/_global/notif_global";
import { useRouter } from "next/navigation";
import { RouterEvent } from "@/app/lib/router_hipmi/router_event";
import { useState } from "react";
export default function Ui_Konfirmasi({
dataEvent,
userLoginId,
}: {
dataEvent: MODEL_EVENT;
userLoginId: string;
}) {
// console.log(dataEvent);
const router = useRouter();
const [isLoading, setLoading] = useState(false);
const [isPresent, setIsPresent] = useState<boolean | null>(null);
// useShallowEffect(() => {
// onLoadData({
// onPublish(val) {
// setData(val);
// },
// });
// }, [setData]);
useShallowEffect(() => {
onLoadKehadiran({
onChange(val) {
setIsPresent(val);
},
});
}, [setIsPresent]);
async function onLoadKehadiran({
onChange,
}: {
onChange: (val: boolean) => void;
}) {
const checkKehadiran = await event_funCheckKehadiran({
eventId: dataEvent.id,
userId: userLoginId as string,
});
onChange(checkKehadiran);
}
async function onUpdateKonfirmasi() {
setLoading(true);
const res = await event_funUpdateKehadiran({
eventId: dataEvent.id,
userId: userLoginId,
});
if (res.status === 200) {
ComponentGlobal_NotifikasiBerhasil(res.message, 2000);
router.push(RouterEvent.detail_main + dataEvent.id);
} else {
setLoading(false);
ComponentGlobal_NotifikasiGagal(res.message);
}
}
if (isPresent === null) {
return <></>;
}
return (
<>
<UIGlobal_LayoutDefault>
<Stack h={"100vh"} align="center" justify="center">
{isPresent == null ? (
<Skeleton h={200} w={300} radius={"sm"} />
) : isPresent ? (
<Paper p={"md"} withBorder bg={AccentColor.softblue}>
<Stack align="center" justify="center">
<Text fw={"bold"} align="center">
Anda telah terkonfirmasi silahkan kembali ke beranda !
</Text>
<Title order={3}>{dataEvent.title}</Title>
<Button
loading={isLoading}
loaderPosition="center"
radius={"md"}
color="green"
c={"black"}
onClick={() => {
router.push(RouterEvent.beranda, { scroll: false });
}}
>
Beranda
</Button>
</Stack>
</Paper>
) : (
<Paper p={"md"} withBorder bg={AccentColor.softblue}>
<Stack align="center" justify="center">
<Text fw={"bold"} align="center">
Anda mengkonfirmasi bahwa anda telah datang & ikut menghadir
di event
</Text>
<Title order={3}>{dataEvent.title}</Title>
<Button
loading={isLoading}
loaderPosition="center"
radius={"xs"}
bg={MainColor.yellow}
color="yellow"
c={"black"}
onClick={() => {
onUpdateKonfirmasi();
}}
>
YA
</Button>
</Stack>
</Paper>
)}
</Stack>
</UIGlobal_LayoutDefault>
</>
);
}

View File

@@ -1,19 +1,31 @@
"use client";
import {
ActionIcon,
Avatar,
Center,
Grid,
Group,
Stack,
Text,
Title
Title,
} from "@mantine/core";
import _ from "lodash";
import {
ComponentGlobal_AvatarAndUsername,
ComponentGlobal_CardStyles,
ComponentGlobal_LoaderAvatar,
} from "@/app_modules/_global/component";
import { useRouter } from "next/navigation";
import { MODEL_EVENT_PESERTA } from "../../model/interface";
import { Prisma } from "@prisma/client";
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { funGlobal_CheckProfile } from "@/app_modules/_global/fun/get";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
import { useState } from "react";
import moment from "moment";
export default function ComponentEvent_ListPeserta({
listPeserta,
@@ -41,11 +53,21 @@ export default function ComponentEvent_ListPeserta({
<Stack>
{listPeserta.map((e, i) => (
<Stack key={i} spacing={"sm"}>
<ComponentGlobal_AvatarAndUsername
profile={e.User.Profile as any}
{/* <ComponentGlobal_AvatarAndUsername
profile={e?.User?.Profile as any}
sizeAvatar={30}
fontSize={"sm"}
/> */}
<ComponentEvent_AvatarAndUsername
profile={e?.User?.Profile as any}
sizeAvatar={30}
fontSize={"sm"}
tanggalMulai={e?.Event?.tanggal}
tanggalSelesai={e?.Event?.tanggalSelesai}
isPresent={e?.isPresent}
/>
{/* <Divider /> */}
</Stack>
))}
@@ -56,3 +78,101 @@ export default function ComponentEvent_ListPeserta({
</>
);
}
type IFontSize = "xs" | "sm" | "md" | "lg" | "xl";
function ComponentEvent_AvatarAndUsername({
profile,
component,
sizeAvatar,
fontSize,
tanggalMulai,
tanggalSelesai,
isPresent,
}: {
profile: Prisma.ProfileSelect;
component?: React.ReactNode;
sizeAvatar?: number;
fontSize?: IFontSize | {};
tanggalMulai?: Date;
tanggalSelesai?: Date;
isPresent?: boolean;
}) {
const router = useRouter();
const [visible, setVisible] = useState(false);
async function onCheckProfile() {
const res = await funGlobal_CheckProfile({ profileId: profile.id as any });
if (res !== null) {
setVisible(true);
router.push(RouterProfile.katalog({ id: profile.id as any }));
} else {
ComponentGlobal_NotifikasiPeringatan("Id tidak ditemukan");
}
}
const tglMulai = moment(tanggalMulai).diff(moment(), "minutes");
const tglSelesai = moment(tanggalSelesai).diff(moment(), "minutes");
// console.log("mulai:", tglMulai, "selesai:", tglSelesai);
return (
<>
<Grid align="flex-start" justify="space-around">
<Grid.Col span={2} style={{ minHeight: 50 }}>
<ActionIcon
radius={"xl"}
variant="transparent"
onClick={() => onCheckProfile()}
>
{visible ? (
<Avatar radius={"xl"} size={40}>
<ComponentGlobal_Loader />
</Avatar>
) : (
<ComponentGlobal_LoaderAvatar
fileId={profile?.imageId as any}
sizeAvatar={sizeAvatar}
/>
)}
</ActionIcon>
</Grid.Col>
<Grid.Col span={"auto"} style={{ minHeight: 50 }}>
<Stack justify="center" h={30}>
<Text
fw={"bold"}
fz={fontSize ? fontSize : "sm"}
lineClamp={1}
onClick={() => onCheckProfile()}
>
{profile?.name}
</Text>
</Stack>
</Grid.Col>
{/* {component && (
<Grid.Col span={"auto"} style={{ minHeight: 50 }}>
<Stack justify="center" h={30}>
{component}
</Stack>
</Grid.Col>
)} */}
{tglMulai < 0 && (
<Grid.Col span={3} style={{ minHeight: 50 }}>
<Group position="right">
<Stack justify="center" h={30}>
<Text fw={"bold"} fz={fontSize ? fontSize : "sm"}>
{isPresent ? "Hadir" : "-"}
</Text>
</Stack>
</Group>
</Grid.Col>
)}
</Grid>
</>
);
}

View File

@@ -0,0 +1,24 @@
"use server";
import { prisma } from "@/app/lib";
export async function event_funUpdateKehadiran({
userId,
eventId,
}: {
userId: string;
eventId: string;
}) {
const updt = await prisma.event_Peserta.updateMany({
where: {
userId: userId,
eventId: eventId,
},
data: {
isPresent: true,
},
});
if(!updt) return { status: 400, message: "Gagal Update" };
return { status: 200, message: "Anda telah terkonfirmasi" };
}

View File

@@ -0,0 +1,27 @@
"use server";
import { prisma } from "@/app/lib";
export async function event_funCheckKehadiran({
userId,
eventId,
}: {
userId: string;
eventId: string;
}) {
const checkKehadiran = await prisma.event_Peserta.findFirst({
where: {
userId: userId,
eventId: eventId,
},
select: {
isPresent: true,
},
});
if (checkKehadiran?.isPresent) {
return true;
} else {
return false;
}
}

View File

@@ -0,0 +1,24 @@
"use server";
import { prisma } from "@/app/lib";
export async function event_funCheckPesertaByUserId({
userId,
eventId,
}: {
userId: string;
eventId: string;
}) {
const check = await prisma.event_Peserta.findFirst({
where: {
userId: userId,
eventId: eventId,
},
});
if (check != null) {
return true;
} else {
return false;
}
}

View File

@@ -13,12 +13,14 @@ export async function Event_getListPesertaById(eventId: string) {
createdAt: true,
updatedAt: true,
userId: true,
isPresent: true,
User: {
select: {
Profile: true,
},
},
// Event: true,
Event: true,
eventId: true,
},
});

View File

@@ -1,5 +1,11 @@
import { event_funUpdateKehadiran } from "./edit/fun_update_konfirmasi_by_user_id";
import { event_funCheckKehadiran } from "./get/fun_check_kehadiran";
import { event_funCheckPesertaByUserId } from "./get/fun_check_peserta_by_user_id";
import { event_getAllByStatusId } from "./get/status/get_all_by_status_id";
import { event_getMasterStatus } from "./master/get_status_event";
export { event_getAllByStatusId };
export { event_getMasterStatus };
export { event_funCheckPesertaByUserId };
export { event_funUpdateKehadiran };
export { event_funCheckKehadiran };

View File

@@ -30,5 +30,6 @@ export interface MODEL_EVENT_PESERTA {
userId: string;
User: MODEL_USER;
eventId: string;
isPresent: boolean
Event: MODEL_EVENT;
}

View File

@@ -15,6 +15,7 @@ import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state";
import { useAtom } from "jotai";
import notifikasi_countUserNotifikasi from "../notifikasi/fun/count/fun_count_by_id";
import { Center, Text, Title } from "@mantine/core";
import { useRouter } from "next/navigation";
export default function HomeView({
dataUser,
@@ -25,9 +26,19 @@ export default function HomeView({
dataJob: MODEL_JOB[];
countNotifikasi: number;
}) {
const router = useRouter();
const [countNtf, setCountNtf] = useState(countNotifikasi);
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
const [countLoadNtf, setCountLoadNtf] = useAtom(gs_count_ntf);
const userRoleId = dataUser.masterUserRoleId;
useShallowEffect(() => {
if (userRoleId === "2" || userRoleId === "3") {
setTimeout(() => {
router.push("/waiting-room", { scroll: false });
}, 1000);
}
}, [userRoleId]);
useShallowEffect(() => {
onLoadNotifikasi({

View File

@@ -28,11 +28,13 @@ function ButtonAction({ jobId }: { jobId: string }) {
// if (typeof window !== "undefined") {
// setOrigin(window.location.origin);
// }
}, [setOrigin]);
async function onLoadOrigin(setOrigin: any) {
const res = await fetch("/api/zz-makuro");
const res = await fetch("/api/origin-url");
const result = await res.json();
console.log(result);
setOrigin(result.origin);
}

View File

@@ -20,6 +20,7 @@ const middlewareConfig: MiddlewareConfig = {
publicRoutes: [
"/",
"/api/auth/*",
"/api/origin-url",
"/login",
"/register",
"/validasi",