Merge pull request #171 from bipproduction/join

This commit is contained in:
Bagasbanuna02
2024-12-09 14:29:05 +08:00
committed by GitHub
26 changed files with 765 additions and 168 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.20](https://github.com/bipproduction/hipmi/compare/v1.2.19...v1.2.20) (2024-12-09)
## [1.2.19](https://github.com/bipproduction/hipmi/compare/v1.2.18...v1.2.19) (2024-12-06)
## [1.2.18](https://github.com/bipproduction/hipmi/compare/v1.2.17...v1.2.18) (2024-12-04)

View File

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

View File

@@ -14,6 +14,7 @@ export async function GET(request: NextRequest) {
id: id as string,
},
});
return NextResponse.json(data, { status: 200 });
} catch (error) {
console.log(error);

View File

@@ -1,4 +1,3 @@
import { prisma } from "@/app/lib";
import { cookies } from "next/headers";
import { NextRequest, NextResponse } from "next/server";
export const dynamic = "force-dynamic";
@@ -7,15 +6,15 @@ export async function GET(request: NextRequest) {
// const { searchParams } = new URL(request.url);
// const id = searchParams.get("id");
const delToken = await prisma.userSession.delete({
where: {
userId: id as string,
},
});
// const delToken = await prisma.userSession.delete({
// where: {
// userId: id as string,
// },
// });
const del = cookies().delete(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!);
return NextResponse.json(
{ success: true, message: "Logout Berhasil" },
{ status: 200 }
);
}
}

View File

@@ -32,22 +32,22 @@ export async function POST(req: Request) {
user: createUser as any,
});
try {
const createUserSession = await prisma.userSession.create({
data: {
token: token as string,
userId: createUser.id,
},
});
// try {
// const createUserSession = await prisma.userSession.create({
// data: {
// token: token as string,
// userId: createUser.id,
// },
// });
if (!createUserSession)
return NextResponse.json(
{ success: false, message: "Gagal Membuat Session" },
{ status: 400 }
);
} catch (error) {
console.log(error);
}
// if (!createUserSession)
// return NextResponse.json(
// { success: false, message: "Gagal Membuat Session" },
// { status: 400 }
// );
// } catch (error) {
// console.log(error);
// }
return NextResponse.json(
{ success: true, message: "Berhasil Login", data: createUser },

View File

@@ -6,73 +6,76 @@ export async function POST(req: Request) {
if (req.method === "POST") {
const { nomor } = await req.json();
const dataUser = await prisma.user.findUnique({
where: {
nomor: nomor,
},
select: {
id: true,
nomor: true,
username: true,
active: true,
masterUserRoleId: true,
},
});
if (dataUser === null)
return NextResponse.json(
{ success: false, message: "Nomor Belum Terdaftar" },
{ status: 404 }
);
const token = await sessionCreate({
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
user: dataUser as any,
});
const cekSessionUser = await prisma.userSession.findFirst({
where: {
userId: dataUser.id,
},
});
if (cekSessionUser !== null) {
await prisma.userSession.delete({
where: {
userId: dataUser.id,
},
});
}
try {
const createUserSession = await prisma.userSession.create({
data: {
token: token as string,
userId: dataUser.id,
const dataUser = await prisma.user.findUnique({
where: {
nomor: nomor,
},
select: {
id: true,
nomor: true,
username: true,
active: true,
masterUserRoleId: true,
},
});
if (!createUserSession)
if (dataUser === null)
return NextResponse.json(
{ success: false, message: "Gagal Membuat Session" },
{ status: 400 }
{ success: false, message: "Nomor Belum Terdaftar" },
{ status: 404 }
);
const token = await sessionCreate({
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
user: dataUser as any,
});
// const cekSessionUser = await prisma.userSession.findFirst({
// where: {
// userId: dataUser.id,
// },
// });
// if (cekSessionUser !== null) {
// await prisma.userSession.delete({
// where: {
// userId: dataUser.id,
// },
// });
// }
// try {
// const createUserSession = await prisma.userSession.create({
// data: {
// token: token as string,
// userId: dataUser.id,
// },
// });
// if (!createUserSession)
// return NextResponse.json(
// { success: false, message: "Gagal Membuat Session" },
// { status: 400 }
// );
// } catch (error) {
// console.log(error);
// }
return NextResponse.json(
{
success: true,
message: "Berhasil Login",
roleId: dataUser.masterUserRoleId,
active: dataUser.active,
},
{ status: 200 }
);
} catch (error) {
console.log(error);
}
return NextResponse.json(
{
success: true,
message: "Berhasil Login",
roleId: dataUser.masterUserRoleId,
active: dataUser.active,
},
{ status: 200 }
);
}
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }

View File

@@ -1,6 +1,7 @@
import { prisma } from "@/app/lib";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// GET DATA HOME

View File

@@ -0,0 +1,76 @@
import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const data = await prisma.businessMaps.findUnique({
where: {
id: id,
},
select: {
namePin: true,
latitude: true,
longitude: true,
pinId: true,
imageId: true,
Author: {
select: {
Profile: {
select: {
id: true,
name: true,
imageId: true,
}
}
}
},
Portofolio: {
select: {
id: true,
alamatKantor: true,
tlpn: true,
deskripsi: true,
namaBisnis: true,
MasterBidangBisnis: {
select: {
name: true,
},
},
},
},
}
});
const dataLokasi = {
namePin: data?.namePin,
latitude: data?.latitude,
longitude: data?.longitude,
pinId: data?.pinId,
imageId: data?.imageId,
}
const dataAuthor = {
id: data?.Author?.Profile?.id,
name: data?.Author?.Profile?.name,
imageId: data?.Author?.Profile?.imageId,
}
const dataBisnis = {
id: data?.Portofolio?.id,
alamatKantor: data?.Portofolio?.alamatKantor,
tlpn: data?.Portofolio?.tlpn,
deskripsi: data?.Portofolio?.deskripsi,
namaBisnis: data?.Portofolio?.namaBisnis,
bidangBisnis: data?.Portofolio?.MasterBidangBisnis?.name,
}
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", dataLokasi, dataAuthor, dataBisnis }, { status: 200 });
}
catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -0,0 +1,40 @@
import { prisma } from "@/app/lib";
import _ from "lodash";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// GET ALL DATA MAP
export async function GET(request: Request) {
try {
const data = await prisma.businessMaps.findMany({
where: {
isActive: true,
},
select: {
id: true,
namePin: true,
latitude: true,
longitude: true,
pinId: true,
Portofolio: {
select: {
logoId: true,
}
}
}
});
const dataFix = data.map((v: any) => ({
..._.omit(v, ["Portofolio"]),
logoId: v.Portofolio.logoId
}))
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data: dataFix }, { status: 200 });
}
catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -1,6 +1,7 @@
import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
import fs from "fs";
export const dynamic = "force-dynamic";

View File

@@ -1,5 +1,6 @@
import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// GET ALL DATA PORTOFOLIO BY PROFILE ID

View File

@@ -1,5 +1,6 @@
import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// GET ONE DATA USER PROFILE BY PROFILE ID

View File

@@ -1,13 +1,13 @@
import { map_funGetAllMap } from "@/app_modules/map/fun/get/fun_get_all_map";
import { Map_View } from "@/app_modules/map/view";
import { Map_ViewNew } from "@/app_modules/map/view/main_view_new";
const mapboxToken = process.env.MAPBOX_TOKEN!;
export default async function Page() {
const dataMap = await map_funGetAllMap();
// const dataMap = await map_funGetAllMap();
return (
<>
<Map_View mapboxToken={mapboxToken} dataMap={dataMap} />
{/* <Map_View mapboxToken={mapboxToken} dataMap={dataMap} /> */}
<Map_ViewNew mapboxToken={mapboxToken} />
</>
);
}

View File

@@ -2,6 +2,7 @@
import { MODEL_EVENT_PESERTA } from "@/app_modules/event/model/interface";
import {
Badge,
Button,
Center,
Pagination,
@@ -26,6 +27,7 @@ export function AdminEvent_ViewDetailPeserta({
const [isNPage, setNPage] = useState(dataPeserta.nPage);
const [isActivePage, setActivePage] = useState(1);
async function onPageClick(p: any) {
setActivePage(p);
const loadData = await adminEvent_getListPesertaById({
@@ -52,6 +54,15 @@ export function AdminEvent_ViewDetailPeserta({
<td>
<Center>{e?.User?.Profile?.email}</Center>
</td>
<td>
<Center>
{e.isPresent ? (
<Badge color="green">Hadir</Badge>
) : (
<Badge color="red">Tidak Hadir</Badge>
)}
</Center>
</td>
</tr>
));
@@ -81,6 +92,9 @@ export function AdminEvent_ViewDetailPeserta({
<th>
<Center>Email</Center>
</th>
<th>
<Center>Konfirmasi Kehadiran</Center>
</th>
</tr>
</thead>
<tbody>{tableRow}</tbody>

View File

@@ -22,6 +22,7 @@ export async function adminEvent_getListPesertaById({
eventId: eventId,
},
select: {
isPresent: true,
User: {
include: {
Profile: true,

View File

@@ -41,7 +41,7 @@ export default function Register() {
const res = await fetch(`/api/auth/check?id=${kodeId}`);
const result = await res.json();
onSetData(result.data.nomor);
onSetData(result.nomor);
}
async function onRegistarsi() {

View File

@@ -43,7 +43,7 @@ export default function Validasi() {
useShallowEffect(() => {
const kodeId = localStorage.getItem("hipmi_auth_code_id");
if (kodeId != null) {
onCheckAuthCode({ kodeId: kodeId as string, onSetData: setData });
onCheckAuthCode({ kodeId: kodeId as string });
} else {
console.log("code id not found");
}
@@ -51,27 +51,25 @@ export default function Validasi() {
if (triggerOtp) {
const kodeId = localStorage.getItem("hipmi_auth_code_id");
if (kodeId != null) {
onCheckAuthCode({ kodeId: kodeId as string, onSetData: setData });
onCheckAuthCode({ kodeId: kodeId as string });
} else {
console.log("code id not found");
}
setTriggerOtp(false);
}
}, [triggerOtp, setData, setTriggerOtp]);
}, [triggerOtp]);
async function onCheckAuthCode({
kodeId,
onSetData,
}: {
kodeId: string;
onSetData: any;
}) {
const res = await fetch(`/api/auth/check?id=${kodeId}`);
const result = await res.json();
onSetData({
nomor: result.data.nomor,
code: result.data.otp,
setData({
nomor: result.nomor,
code: result.otp,
});
}

View File

@@ -8,17 +8,8 @@ import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
} from "@/app_modules/_global/notif_global";
import {
UIGlobal_LayoutDefault
} from "@/app_modules/_global/ui";
import {
Button,
Center,
Group,
Skeleton,
Stack,
Text
} from "@mantine/core";
import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui";
import { Button, Center, Group, Skeleton, Stack, Text } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useAtom } from "jotai";
import moment from "moment";
@@ -28,6 +19,7 @@ import { event_funUpdateKehadiran } from "../fun";
import { Event_funJoinAndConfirmEvent } from "../fun/create/fun_join_and_confirm";
import { gs_event_hotMenu } from "../global_state";
import { MODEL_EVENT } from "../model/interface";
import { Event_funJoinEvent } from "../fun/create/fun_join_event";
export default function Ui_Konfirmasi({
userLoginId,
@@ -68,7 +60,7 @@ export default function Ui_Konfirmasi({
setIsJoin(data);
}
// CEK KEHADIRAN
// =========== CEK KEHADIRAN ===========//
useShallowEffect(() => {
onLoadKehadiran();
}, []);
@@ -80,11 +72,14 @@ export default function Ui_Konfirmasi({
const data = await res.json();
setIsPresent(data);
}
// =========== CEK KEHADIRAN ===========//
// Jika data kosong
if (data == null && isPresent == null) {
return <SkeletonIsDataNull />;
}
// Jika data tidak ada
if (data == null) {
return (
<>
@@ -93,6 +88,7 @@ export default function Ui_Konfirmasi({
);
}
// Jika tanggal acara lewat
if (moment(data?.tanggalSelesai).diff(moment(), "minute") < 0) {
return (
<>
@@ -101,10 +97,26 @@ export default function Ui_Konfirmasi({
);
}
if (isJoin == false) {
// Jika belum join dan tanggal mulai acara belum lewat
if (isJoin == false && moment(data?.tanggal).diff(moment(), "minute") > 0) {
return (
<>
<UserNotJoin
<UserAllowToJoin
title={data?.title}
tanggal={data?.tanggal}
lokasi={data.lokasi}
eventId={eventId}
userLoginId={userLoginId}
/>
</>
);
}
// Jika belum join dan tanggal mulai acara sudah lewat
if (isJoin == false && moment(data?.tanggal).diff(moment(), "minute") < 0) {
return (
<>
<UserNotJoinAndEventReady
title={data?.title}
eventId={eventId}
userLoginId={userLoginId}
@@ -113,7 +125,8 @@ export default function Ui_Konfirmasi({
);
}
if (isPresent && data) {
// Jika sudah join, belum konfirm dan acara sudah mulai
if (isPresent && moment(data?.tanggal).diff(moment(), "minute") < 0) {
return <UserAlreadyConfirm title={data.title} />;
}
@@ -126,16 +139,6 @@ export default function Ui_Konfirmasi({
/>
);
}
// const tgl = moment(data?.tanggal).diff(moment(), "minute") < 0;
// return (
// <>
// <UIGlobal_LayoutDefault>
// <Stack h={"100vh"} justify="center" c={"white"}>
// {JSON.stringify(tgl)}
// </Stack>
// </UIGlobal_LayoutDefault>
// </>
// );
}
function DataNotFound() {
@@ -196,7 +199,91 @@ function SkeletonIsDataNull() {
);
}
function UserNotJoin({
function UserAllowToJoin({
title,
tanggal,
lokasi,
eventId,
userLoginId,
}: {
title: string;
tanggal: Date;
lokasi: string;
eventId: string;
userLoginId: string;
}) {
const router = useRouter();
const [isLoading, setLoading] = useState(false);
async function onJoinEvent() {
setLoading(true);
const data = {
userId: userLoginId,
eventId: eventId,
};
const res = await Event_funJoinEvent(data as any);
if (res.status === 200) {
ComponentGlobal_NotifikasiBerhasil(res.message, 2000);
router.push(RouterEvent.detail_main + eventId);
} else {
setLoading(false);
ComponentGlobal_NotifikasiGagal(res.message);
}
}
return (
<>
<UIGlobal_LayoutDefault>
<Stack h={"100vh"} justify="center">
<ComponentGlobal_CardStyles>
<Stack align="center" justify="center">
<Text align="center">
Halo, Bapak/Ibu. Kami dengan senang hati mengundang Anda untuk
bergabung dalam acara
<Text inherit span fw={"bold"}>
{title}
</Text>{" "}
yang akan diselenggarakan pada{" "}
<Text inherit span fw={"bold"}>
{moment(tanggal).format("LL")}
</Text>{" "}
pukul
<Text inherit span fw={"bold"}>
{moment(tanggal).format("LT")}
</Text>{" "}
di
<Text inherit span fw={"bold"}>
{lokasi}
</Text>{" "}
. Pastikan Anda sudah melakukan registrasi melalui aplikasi
[Nama Aplikasi] agar dapat berpartisipasi. Kami sangat
menantikan kehadiran Anda. Sampai jumpa di acara ini.
</Text>
<Button
loading={isLoading}
loaderPosition="center"
radius={"xs"}
bg={MainColor.yellow}
color="yellow"
c={"black"}
onClick={() => {
onJoinEvent();
}}
>
Join Event
</Button>
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</UIGlobal_LayoutDefault>
</>
);
}
function UserNotJoinAndEventReady({
title,
eventId,
userLoginId,
@@ -373,8 +460,12 @@ function UserNotConfirm({
{title}
</Text>{" "}
pada hari ini. Mohon untuk mengonfirmasi kehadiran Anda dengan
menekan tombol {"Hadir"} atau fitur konfirmasi yang tersedia di
bawah. Terima kasih dan selamat menikmati acara.
menekan tombol{" "}
<Text inherit span fw={"bold"}>
Konfirmasi Kehadiran
</Text>{" "}
atau fitur konfirmasi yang tersedia di bawah. Terima kasih dan
selamat menikmati acara.
</Text>
<Button
@@ -388,7 +479,7 @@ function UserNotConfirm({
onUpdateKonfirmasi();
}}
>
HADIR
Konfirmasi Kehadiran
</Button>
</Stack>
</ComponentGlobal_CardStyles>

View File

@@ -3,6 +3,7 @@
import {
ActionIcon,
Avatar,
Badge,
Center,
Grid,
Group,
@@ -136,11 +137,8 @@ function ComponentEvent_AvatarAndUsername({
}
}
const tglMulai = moment(tanggalMulai).diff(moment(), "minutes");
const tglMulai = moment(tanggalMulai).diff(moment(), "minutes") < 0;
const tglSelesai = moment(tanggalSelesai).diff(moment(), "minutes");
// console.log("mulai:", tglMulai, "selesai:", tglSelesai);
return (
<>
@@ -177,20 +175,12 @@ function ComponentEvent_AvatarAndUsername({
</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 }}>
{tglMulai && (
<Grid.Col span={4} style={{ minHeight: 50 }}>
<Group position="right">
<Stack justify="center" h={30}>
<Text fw={"bold"} fz={fontSize ? fontSize : "sm"}>
{isPresent ? "Hadir" : "-"}
{isPresent ? <Badge color="green" >Hadir</Badge> : <Badge>-</Badge>}
</Text>
</Stack>
</Group>

View File

@@ -47,40 +47,46 @@ export function Profile_ComponentCreateNewProfile({
"Lengkapi background profile"
);
setLoading(true);
try {
setLoading(true);
const uploadPhoto = await funGlobal_UploadToStorage({
file: filePP,
dirId: DIRECTORY_ID.profile_foto,
});
if (!uploadPhoto.success) {
setLoading(false);
return ComponentGlobal_NotifikasiPeringatan("Gagal upload foto profile");
}
const uploadPhoto = await funGlobal_UploadToStorage({
file: filePP,
dirId: DIRECTORY_ID.profile_foto,
});
if (!uploadPhoto.success) {
setLoading(false);
return ComponentGlobal_NotifikasiPeringatan(
"Gagal upload foto profile"
);
}
const uploadBackground = await funGlobal_UploadToStorage({
file: fileBG,
dirId: DIRECTORY_ID.profile_background,
});
if (!uploadBackground.success) {
setLoading(false);
return ComponentGlobal_NotifikasiPeringatan(
"Gagal upload background profile"
);
}
const uploadBackground = await funGlobal_UploadToStorage({
file: fileBG,
dirId: DIRECTORY_ID.profile_background,
});
if (!uploadBackground.success) {
setLoading(false);
return ComponentGlobal_NotifikasiPeringatan(
"Gagal upload background profile"
);
}
const create = await funCreateNewProfile({
data: newData as any,
imageId: uploadPhoto.data.id,
imageBackgroundId: uploadBackground.data.id,
});
const create = await funCreateNewProfile({
data: newData as any,
imageId: uploadPhoto.data.id,
imageBackgroundId: uploadBackground.data.id,
});
if (create.status === 201) {
ComponentGlobal_NotifikasiBerhasil("Berhasil membuat profile", 3000);
router.push(RouterHome.main_home, { scroll: false });
} else {
ComponentGlobal_NotifikasiGagal(create.message);
setLoading(false);
if (create.status === 201) {
ComponentGlobal_NotifikasiBerhasil("Berhasil membuat profile", 3000);
router.push(RouterHome.main_home, { scroll: false });
} else {
ComponentGlobal_NotifikasiGagal(create.message);
setLoading(false);
}
} catch (error) {
console.log(error);
}
}

View File

@@ -74,7 +74,7 @@ export function ComponentMap_DetailData({
<IconPhoneCall />
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>+{data?.Portofolio.tlpn}</Text>
<Text>{data?.Portofolio.tlpn}</Text>
</Grid.Col>
</Grid>
<Grid>

View File

@@ -0,0 +1,206 @@
import { RouterPortofolio } from "@/app/lib/router_hipmi/router_katalog";
import { AccentColor, MainColor } from "@/app_modules/_global/color";
import { ComponentGlobal_LoaderAvatar } from "@/app_modules/_global/component";
import { ActionIcon, Box, Button, Drawer, Grid, Group, Skeleton, Stack, Text, Title } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconBuildingSkyscraper, IconListDetails, IconMapPin, IconPhoneCall, IconX } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { apiGetOneMapById } from "../lib/api_map";
import { IDataMap, IDataMapDetailAuthor, IDataMapDetailBisnis } from "../lib/type_map";
import { ComponentMap_LoadImageMap } from "./comp_load_image_map";
import { ComponentMap_SkeletonDrawerDetailData } from "./skeleton_detail_data";
// SALAHHHHHHHH ---- HARUS ULANGG
export function ComponentMap_DrawerDetailDataNew({ opened, close, mapId, }: { opened: boolean; close: () => void; mapId: string }) {
const router = useRouter();
const [dataLokasi, setDataLokasi] = useState<IDataMap>()
const [dataAuthor, setDataAuthor] = useState<IDataMapDetailAuthor>()
const [dataBisnis, setDataBisnis] = useState<IDataMapDetailBisnis>()
const [loading, setLoading] = useState(false)
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
setLoading(true)
const response = await apiGetOneMapById(mapId)
if (response.success) {
setDataLokasi(response.dataLokasi)
setDataAuthor(response.dataAuthor)
setDataBisnis(response.dataBisnis)
}
} catch (error) {
console.error(error)
} finally {
setLoading(false)
}
}
return (
<>
<Drawer
opened={opened}
onClose={() => close()}
position={"bottom"}
size={"auto"}
withCloseButton={false}
styles={{
content: {
padding: 0,
position: "absolute",
margin: "auto",
backgroundColor: "transparent",
left: 0,
right: 0,
width: 500,
},
body: {
backgroundColor: AccentColor.darkblue,
borderTop: `2px solid ${AccentColor.blue}`,
borderRight: `1px solid ${AccentColor.blue}`,
borderLeft: `1px solid ${AccentColor.blue}`,
borderRadius: "20px 20px 0px 0px",
color: "white",
paddingBottom: "5%",
},
}}
>
<Stack spacing={"xs"}>
<Group position="apart">
<Title order={5}>
{dataLokasi?.namePin ? (
dataLokasi?.namePin
) : (
<Skeleton radius={"xl"} w={100} />
)}
</Title>
<ActionIcon onClick={close} variant="transparent">
<IconX color="white" />
</ActionIcon>
</Group>
{
loading ?
<ComponentMap_SkeletonDrawerDetailData /> :
<Stack mt={"lg"} spacing={"xl"} px={"md"}>
<Grid align="flex-start" justify="space-around">
<Grid.Col span={"content"} style={{ minHeight: 50 }}>
<ActionIcon
radius={"xl"}
variant="transparent"
// onClick={() => onCheckProfile()}
>
<ComponentGlobal_LoaderAvatar
fileId={dataAuthor?.imageId as any}
/>
</ActionIcon>
</Grid.Col>
<Grid.Col span={"auto"} style={{ minHeight: 50 }}>
<Stack justify="center" h={30}>
<Text
fw={"bold"}
fz={"sm"}
lineClamp={1}
// onClick={() => onCheckProfile()}
>
{dataAuthor?.name}
</Text>
</Stack>
</Grid.Col>
</Grid>
<ComponentMap_LoadImageMap fileId={String(dataLokasi?.imageId)} />
<Box>
<Grid>
<Grid.Col span={2}>
<IconBuildingSkyscraper />
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>{dataBisnis?.namaBisnis}</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<IconListDetails />
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>{dataBisnis?.bidangBisnis}</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<IconPhoneCall />
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>+{dataBisnis?.tlpn}</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<IconMapPin />
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>{dataBisnis?.alamatKantor}</Text>
</Grid.Col>
</Grid>
</Box>
<Group grow position={"apart"}>
<Button
onClick={() => {
router.push(
RouterPortofolio.main_detail + dataBisnis?.id, { scroll: false, }
);
}}
loaderPosition="center"
radius={"xl"}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Detail
</Button>
<Button
radius={"xl"}
bg={MainColor.yellow}
color="yellow"
c={"black"}
onClick={() => {
window.open(
`https://maps.google.com?q=${dataLokasi?.latitude},${dataLokasi?.longitude}`,
"_blank",
"width=800,height=600,noopener,noreferrer"
);
}}
>
Buka Maps
</Button>
</Group>
</Stack>
}
</Stack>
</Drawer>
</>
);
}

View File

@@ -0,0 +1,9 @@
export const apiGetAllMap = async (path?: string) => {
const response = await fetch(`/api/new/map${(path) ? path : ''}`)
return await response.json().catch(() => null)
}
export const apiGetOneMapById = async (path: string) => {
const response = await fetch(`/api/new/map/${path}`);
return await response.json().catch(() => null);
}

View File

@@ -0,0 +1,24 @@
export interface IDataMap {
id: string
namePin: string
latitude: string
longitude: string
pinId: string
logoId: string
imageId: string
}
export interface IDataMapDetailAuthor {
id: string
name: string
imageId: string
}
export interface IDataMapDetailBisnis {
id: string
alamatKantor: string
tlpn: string
deskripsi: string
namaBisnis: string
bidangBisnis: string
}

View File

@@ -0,0 +1,120 @@
"use client";
import { APIs } from "@/app/lib";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { Avatar, Stack } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import "mapbox-gl/dist/mapbox-gl.css";
import { useState } from "react";
import Map, { AttributionControl, Marker, NavigationControl, ScaleControl, } from "react-map-gl";
import { ComponentMap_DetailData, ComponentMap_DrawerDetailData } from "../_component";
import { apiGetAllMap } from "../lib/api_map";
import { defaultLatLong, defaultMapZoom } from "../lib/default_lat_long";
import { IDataMap } from "../lib/type_map";
export function UiMap_MapBoxViewNew({ mapboxToken, }: { mapboxToken: string }) {
const [mapId, setMapId] = useState("");
const [openDrawer, setOpenDrawer] = useState(false);
const [data, setData] = useState<IDataMap[]>([]);
const [loading, setLoading] = useState(false);
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
setLoading(true)
const response = await apiGetAllMap()
if (response.success) {
setData(response.data)
}
} catch (error) {
console.error(error)
} finally {
setLoading(false)
}
}
if (!mapboxToken)
return <ComponentGlobal_IsEmptyData text="Mapbox token not found" />;
return (
<>
<Stack style={{ borderRadius: "10px" }}>
{
loading ?
<></> :
<Map
mapboxAccessToken={mapboxToken}
mapStyle={"mapbox://styles/mapbox/streets-v11"}
initialViewState={{
latitude: defaultLatLong[0],
longitude: defaultLatLong[1],
zoom: defaultMapZoom,
}}
style={{
cursor: "pointer",
width: "auto",
height: "90vh",
borderRadius: "5px",
}}
attributionControl={false}
>
{data.map((e, i) => (
<Stack key={i}>
<Marker
style={{
width: 40,
cursor: "pointer",
}}
latitude={Number(e.latitude)}
longitude={Number(e.longitude)}
anchor="bottom"
offset={[0, 0]}
scale={1}
>
<Stack
spacing={0}
align="center"
onClick={() => {
setMapId(e.id);
setOpenDrawer(true);
}}
>
<Avatar
alt="Logo"
style={{
border: `2px solid ${AccentColor.softblue}`,
borderRadius: "100%",
backgroundColor: "white",
}}
src={
e.pinId === null
? APIs.GET({ fileId: e.logoId })
: APIs.GET({ fileId: e.pinId })
}
/>
</Stack>
</Marker>
</Stack>
))}
<NavigationControl />
<ScaleControl position="top-left" />
<AttributionControl customAttribution="Map design by PT. Bali Interaktif Perkasa" />
</Map>
}
</Stack>
<ComponentMap_DrawerDetailData
opened={openDrawer}
close={() => setOpenDrawer(false)}
mapId={mapId}
component={<ComponentMap_DetailData mapId={mapId} />}
/>
{/* <ComponentMap_DrawerDetailDataNew opened={openDrawer} close={() => setOpenDrawer(false)} mapId={mapId}/> */}
</>
);
}

View File

@@ -0,0 +1,13 @@
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate";
import { ComponentMap_Header } from "../_component";
import { UiMap_MapBoxViewNew } from "../ui/ui_map_new";
export async function Map_ViewNew({ mapboxToken }: { mapboxToken: string }) {
return (
<>
<UIGlobal_LayoutTamplate header={<ComponentMap_Header />}>
<UiMap_MapBoxViewNew mapboxToken={mapboxToken} />
</UIGlobal_LayoutTamplate>
</>
);
}