Merge pull request #167 from bipproduction/join

Fix home & event
This commit is contained in:
Bagasbanuna02
2024-12-08 17:17:39 +08:00
committed by GitHub
30 changed files with 1005 additions and 190 deletions

View File

@@ -1,10 +1,12 @@
import { prisma } from "@/app/lib";
import { data } from "autoprefixer";
import { NextResponse } from "next/server";
import { NextRequest, NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get("id");
export async function GET(request: NextRequest) {
const id = request.nextUrl.searchParams.get("id");
// const { searchParams } = new URL(request.url);
// const id = searchParams.get("id");
try {
const data = await prisma.kodeOtp.findFirst({
@@ -12,10 +14,10 @@ export async function GET(request: Request) {
id: id as string,
},
});
return new Response(JSON.stringify({ data }), { status: 200 });
return NextResponse.json(data, { status: 200 });
} catch (error) {
console.log(error);
}
return new Response(JSON.stringify({ data: null }), { status: 404 });
return NextResponse.json(null, { status: 500 });
}

View File

@@ -18,14 +18,11 @@ export async function POST(req: Request) {
const sendWa = await res.json();
if (sendWa.status !== "success")
return new Response(
JSON.stringify({
success: false,
message: "Nomor Whatsapp Tidak Aktif",
}),
return NextResponse.json(
{ success: false, message: "Nomor Whatsapp Tidak Aktif" },
{ status: 400 }
);
const createOtpId = await prisma.kodeOtp.create({
data: {
nomor: nomor,
@@ -34,32 +31,30 @@ export async function POST(req: Request) {
});
if (!createOtpId)
return new Response(
JSON.stringify({
success: false,
message: "Gagal Membuat Kode OTP",
}),
return NextResponse.json(
{ success: false, message: "Gagal Membuat Kode OTP" },
{ status: 400 }
);
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: true,
message: "Kode Verifikasi Dikirim",
kodeId: createOtpId.id,
}),
},
{ status: 200 }
);
} catch (error) {
console.log(error);
return new Response(
JSON.stringify({
success: false,
message: "Server Whatsapp Error !!",
}),
return NextResponse.json(
{ success: false, message: "Server Whatsapp Error !! " },
{ status: 500 }
);
}
}
return NextResponse.json({ success: false });
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }
);
}

View File

@@ -1,28 +1,21 @@
import { prisma } from "@/app/lib";
import { cookies } from "next/headers";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get("id");
import { NextRequest, NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(request: NextRequest) {
const id = request.nextUrl.searchParams.get("id");
// 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 new Response(JSON.stringify({ success: true, message: "Logout Berhasil" }), {status: 200});
}
// import { cookies } from "next/headers";
// import { NextResponse } from "next/server";
// export async function GET() {
// cookies().set({
// name: "mySession",
// value: "",
// maxAge: 0,
// });
// return NextResponse.json({ status: 200, message: "Logout" });
// }
return NextResponse.json(
{ success: true, message: "Logout Berhasil" },
{ status: 200 }
);
}

View File

@@ -1,5 +1,6 @@
import { sessionCreate } from "@/app/auth/_lib/session_create";
import prisma from "@/app/lib/prisma";
import { NextResponse } from "next/server";
export async function POST(req: Request) {
if (req.method === "POST") {
@@ -12,11 +13,8 @@ export async function POST(req: Request) {
});
if (cekUsername)
return new Response(
JSON.stringify({
success: false,
message: "Username sudah digunakan",
}),
return NextResponse.json(
{ success: false, message: "Username sudah digunakan" },
{ status: 400 }
);
@@ -43,28 +41,22 @@ export async function POST(req: Request) {
});
if (!createUserSession)
return new Response(
JSON.stringify({
success: false,
message: "Gagal Membuat Session",
}),
return NextResponse.json(
{ success: false, message: "Gagal Membuat Session" },
{ status: 400 }
);
} catch (error) {
console.log(error);
}
return new Response(
JSON.stringify({
success: true,
message: "Berhasil Login",
}),
return NextResponse.json(
{ success: true, message: "Berhasil Login", data: createUser },
{ status: 200 }
);
}
return new Response(
JSON.stringify({ success: false, message: "Method Not Allowed" }),
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }
);
}

View File

@@ -18,11 +18,11 @@ export async function POST(req: Request) {
const sendWa = await res.json();
if (sendWa.status !== "success")
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: false,
message: "Nomor Whatsapp Tidak Aktif",
}),
},
{ status: 400 }
);
@@ -34,32 +34,36 @@ export async function POST(req: Request) {
});
if (!createOtpId)
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: false,
message: "Gagal Membuat Kode OTP",
}),
},
{ status: 400 }
);
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: true,
message: "Kode Verifikasi Dikirim",
kodeId: createOtpId.id,
}),
},
{ status: 200 }
);
} catch (error) {
console.log(error);
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: false,
message: "Server Whatsapp Error !!",
}),
},
{ status: 500 }
);
}
}
return NextResponse.json({ success: false });
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }
);
}

View File

@@ -1,9 +1,5 @@
import { sessionCreate } from "@/app/auth/_lib/session_create";
import prisma from "@/app/lib/prisma";
import { ServerEnv } from "@/app/lib/server_env";
import { sealData } from "iron-session";
import { revalidatePath } from "next/cache";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
export async function POST(req: Request) {
@@ -23,10 +19,9 @@ export async function POST(req: Request) {
},
});
if (dataUser === null)
return new Response(
JSON.stringify({ success: false, message: "Nomor Belum Terdaftar" }),
return NextResponse.json(
{ success: false, message: "Nomor Belum Terdaftar" },
{ status: 404 }
);
@@ -59,49 +54,27 @@ export async function POST(req: Request) {
});
if (!createUserSession)
return new Response(
JSON.stringify({ success: false, message: "Gagal Membuat Session" }),
return NextResponse.json(
{ success: false, message: "Gagal Membuat Session" },
{ status: 400 }
);
} catch (error) {
console.log(error);
}
// if (data) {
// const res = await sealData(
// JSON.stringify({
// id: data.id,
// username: data.username,
// }),
// {
// password: ServerEnv.value?.WIBU_PWD as string,
// }
// );
// cookies().set({
// name: "mySession",
// value: res,
// maxAge: 60 * 60 * 24 * 7,
// });
// revalidatePath("/dev/home");
// return NextResponse.json({ status: 200, data });
// }
// return NextResponse.json({ success: true });
return new Response(
JSON.stringify({
return NextResponse.json(
{
success: true,
message: "Berhasil Login",
roleId: dataUser.masterUserRoleId,
active: dataUser.active,
}),
},
{ status: 200 }
);
}
return new Response(
JSON.stringify({ success: false, message: "Method Not Allowed" }),
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }
);
}

View File

@@ -8,7 +8,7 @@ export async function GET(req: Request) {
if (!c || !c?.value || _.isEmpty(c?.value) || _.isUndefined(c?.value)) {
return NextResponse.json({ success: false });
// return new Response(JSON.stringify({ success: false }));
}
return NextResponse.json({ success: true });
}

View File

@@ -1,4 +1,5 @@
import { event_newGetListPesertaById } from "@/app_modules/event/fun";
import { Event_getListPesertaById } from "@/app_modules/event/fun/get/get_list_peserta_by_id";
import { toNumber } from "lodash";
import { NextResponse } from "next/server";

View File

@@ -0,0 +1,172 @@
import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
import fs from "fs";
// GET ONE DATA PORTOFOLIO BY ID PORTOFOLIO
export async function GET(request: Request, context: { params: { id: string } }) {
try {
let dataFix
const { id } = context.params;
const { searchParams } = new URL(request.url);
const kategori = searchParams.get('cat');
if (kategori == "bisnis") {
const data = await prisma.portofolio.findUnique({
where: {
id: id,
},
select: {
id_Portofolio: true,
namaBisnis: true,
alamatKantor: true,
tlpn: true,
deskripsi: true,
logoId: true,
MasterBidangBisnis: {
select: {
name: true
}
},
Profile: {
select: {
userId: true
}
}
}
});
dataFix = {
id_Portofolio: data?.id_Portofolio,
namaBisnis: data?.namaBisnis,
alamatKantor: data?.alamatKantor,
tlpn: data?.tlpn,
deskripsi: data?.deskripsi,
logoId: data?.logoId,
bidangBisnis: data?.MasterBidangBisnis?.name,
authorId: data?.Profile?.userId
}
} else if (kategori == "lokasi") {
const data = await prisma.portofolio.findUnique({
where: {
id: id,
},
select: {
logoId: true,
BusinessMaps: {
select: {
id: true,
namePin: true,
latitude: true,
longitude: true,
imageId: true,
pinId: true
}
}
}
});
dataFix = {
mapId: data?.BusinessMaps?.id,
logoId: data?.logoId,
namePin: data?.BusinessMaps?.namePin,
latitude: data?.BusinessMaps?.latitude,
longitude: data?.BusinessMaps?.longitude,
imageId: data?.BusinessMaps?.imageId,
pinId: data?.BusinessMaps?.pinId
}
} else if (kategori == "sosmed") {
const data = await prisma.portofolio.findUnique({
where: {
id: id,
},
select: {
Portofolio_MediaSosial: {
select: {
facebook: true,
twitter: true,
instagram: true,
tiktok: true,
youtube: true
}
}
}
});
dataFix = {
facebook: data?.Portofolio_MediaSosial?.facebook,
twitter: data?.Portofolio_MediaSosial?.twitter,
instagram: data?.Portofolio_MediaSosial?.instagram,
tiktok: data?.Portofolio_MediaSosial?.tiktok,
youtube: data?.Portofolio_MediaSosial?.youtube
}
}
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 (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}
// DELETE ONE DATA PORTOFOLIO
export async function DELETE(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const data = await prisma.portofolio.findUnique({
where: {
id: id
}
})
const findLogo = await prisma.images.findFirst({
where: {
id: String(data?.logoId),
},
select: {
id: true,
url: true,
},
});
if (findLogo) {
fs.unlinkSync(`./public/portofolio/logo/${findLogo.url}`)
const deleteLogo = await prisma.images.delete({
where: {
id: String(findLogo?.id),
},
});
}
const deletePortoMedsos = await prisma.portofolio_MediaSosial.delete({
where: {
portofolioId: id,
},
});
const deleteMap = await prisma.businessMaps.delete({
where: {
portofolioId: id
}
})
const deletePortofolio = await prisma.portofolio.delete({
where: {
id: id,
},
});
return NextResponse.json({ success: true, message: "Berhasil menghapus data" }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menghapus data, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });
}
}

View File

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

View File

@@ -1,8 +1,11 @@
import prisma from "@/app/lib/prisma";
import { NextResponse } from "next/server";
export async function GET(req: Request) {
const page = new URL(req.url).searchParams.get("page");
if (!page) return new Response("page require", { status: 400 });
if (!page)
return NextResponse.json({ message: "Page not found" }, { status: 400 });
const res = await prisma.projectCollaboration_Message.findMany({
take: 5,
skip: +page * 5 - 5,

View File

@@ -1,7 +1,9 @@
import { NextResponse } from "next/server";
export async function GET(req: Request) {
const auth = req.headers.get("Authorization");
const token = auth?.split(" ")[1];
if (!token)
return new Response(JSON.stringify({ success: false }), { status: 401 });
return new Response(JSON.stringify({ success: true }));
if (!token) return NextResponse.json({ success: false }, { status: 401 });
return NextResponse.json({ success: true });
}

View File

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

View File

@@ -1,5 +1,6 @@
import { prisma } from "@/app/lib";
import { sessionCreate } from "../../_lib/session_create";
import { NextResponse } from "next/server";
export async function POST(req: Request) {
const user = await prisma.user.findUnique({
@@ -12,10 +13,7 @@ export async function POST(req: Request) {
},
});
if (!user)
return new Response(
JSON.stringify({ success: false, message: "User not found" }), {status: 404}
);
if (!user) return NextResponse.json({ success: false }, { status: 404 });
const token = await sessionCreate({
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
@@ -23,5 +21,5 @@ export async function POST(req: Request) {
user: user as any,
});
return new Response(JSON.stringify({ success: true, token }));
return NextResponse.json({ success: true, token });
}

View File

@@ -1,5 +1,8 @@
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
export async function GET() {
const del = cookies().delete(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!);
return new Response(JSON.stringify({ success: true }));
return NextResponse.json({ success: true, message: "Logout Berhasil" });
}

View File

@@ -1,10 +1,5 @@
import { newFunGetUserId } from "@/app/lib/new_fun_user_id";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import Ui_Konfirmasi from "@/app_modules/event/_ui/konfirmasi";
import { event_funCheckPesertaByUserId } from "@/app_modules/event/fun";
import { event_getOneById } from "@/app_modules/event/fun/get/get_one_by_id";
import moment from "moment";
import { redirect } from "next/navigation";
export default async function Page({
params,

View File

@@ -1,27 +1,20 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { PortofolioLayout } from "@/app_modules/katalog/portofolio";
import { portofolio_getOneById } from "@/app_modules/katalog/portofolio/fun/get/get_one_portofolio";
import { PortofolioLayoutNew } from "@/app_modules/katalog/portofolio";
export default async function Layout({
children,
params,
}: {
children: any;
params: { id: string };
}) {
let portoId = params.id;
const getPorto = await portofolio_getOneById(portoId);
const userLoginId = await funGetUserIdByToken();
export default async function Layout({ children, params, }: { children: any; params: { id: string }; }) {
// let portoId = params.id;
// const getPorto = await portofolio_getOneById(portoId);
// const userLoginId = await funGetUserIdByToken();
return (
<>
<PortofolioLayout
{/* <PortofolioLayout
portoId={portoId}
userLoginId={userLoginId as string}
authorId={getPorto?.Profile?.User?.id as any}
>
{children}
</PortofolioLayout>
</PortofolioLayout> */}
<PortofolioLayoutNew>{children}</PortofolioLayoutNew>
</>
);
}

View File

@@ -1,20 +1,19 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { ViewPortofolio } from "@/app_modules/katalog/portofolio";
import { portofolio_getOneById } from "@/app_modules/katalog/portofolio/fun/get/get_one_portofolio";
import { Portofolio_UiDetailNew } from "@/app_modules/katalog/portofolio";
const mapboxToken = process.env.MAPBOX_TOKEN!;
export default async function Page({ params }: { params: { id: string } }) {
const portofolioId = params.id;
const dataPortofolio = await portofolio_getOneById(portofolioId);
const userLoginId = await funGetUserIdByToken();
// const portofolioId = params.id;
// const dataPortofolio = await portofolio_getOneById(portofolioId);
// const userLoginId = await funGetUserIdByToken();
return (
<>
<ViewPortofolio
{/* <ViewPortofolio
dataPorto={dataPortofolio as any}
userLoginId={userLoginId as any}
mapboxToken={mapboxToken}
/>
/> */}
<Portofolio_UiDetailNew mapboxToken={mapboxToken} />
</>
);
}

View File

@@ -1,38 +1,33 @@
"use client";
import {
UIGlobal_LayoutDefault,
UIGlobal_LayoutTamplate,
} from "@/app_modules/_global/ui";
import {
Button,
Card,
Center,
Group,
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 { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event";
import { RouterEvent } from "@/app/lib/router_hipmi/router_event";
import { MainColor } from "@/app_modules/_global/color";
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
} from "@/app_modules/_global/notif_global";
import { redirect, useRouter } from "next/navigation";
import { RouterEvent } from "@/app/lib/router_hipmi/router_event";
import { useState } from "react";
import { API_RouteEvent } from "@/app/lib/api_user_router/route_api_event";
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import moment from "moment";
import { gs_event_hotMenu } from "../global_state";
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 { Event_funJoinEvent } from "../fun/create/fun_join_event";
import moment from "moment";
import { useRouter } from "next/navigation";
import { useState } from "react";
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";
export default function Ui_Konfirmasi({
userLoginId,
@@ -70,7 +65,6 @@ export default function Ui_Konfirmasi({
API_RouteEvent.check_peserta({ eventId: eventId, userId: userLoginId })
);
const data = await res.json();
console.log("cek peserta", data);
setIsJoin(data);
}
@@ -87,9 +81,6 @@ export default function Ui_Konfirmasi({
setIsPresent(data);
}
// console.log("kehadiran:", isPresent);
// console.log("data:", data);
if (data == null && isPresent == null) {
return <SkeletonIsDataNull />;
}
@@ -102,7 +93,7 @@ export default function Ui_Konfirmasi({
);
}
if (moment(data?.tanggal).diff(moment(), "minute") < 0) {
if (moment(data?.tanggalSelesai).diff(moment(), "minute") < 0) {
return (
<>
<EventAlreadyDone title={data?.title} eventId={eventId} />

View File

@@ -0,0 +1,97 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { ComponentGlobal_NotifikasiBerhasil, ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global";
import { UIGlobal_Modal } from "@/app_modules/_global/ui";
import { Button } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconTrash } from "@tabler/icons-react";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { apiDeletePortofolio, apiGetOnePortofolioById } from "../lib/api_portofolio";
import { IDetailPortofolioBisnis } from "../lib/type_portofolio";
export default function ComponentPortofolio_ButtonDeleteNew() {
const param = useParams<{ id: string }>()
const [openModal, setModal] = useState(false)
const [loadingDel, setLoadingDel] = useState(false)
const [userLoginId, setUserLoginId] = useState("")
const [dataPorto, setDataPorto] = useState<IDetailPortofolioBisnis>()
const router = useRouter()
async function onDelete() {
try {
setLoadingDel(true)
const response = await apiDeletePortofolio(param.id)
if (response.success) {
ComponentGlobal_NotifikasiBerhasil(response.message)
router.back()
} else {
ComponentGlobal_NotifikasiGagal(response.message);
}
} catch (error) {
console.error(error)
ComponentGlobal_NotifikasiGagal("Gagal menghapus portofolio");
} finally {
setLoadingDel(false)
}
}
async function funGetPortofolio() {
try {
const response = await apiGetOnePortofolioById(param.id, "bisnis")
const response2 = await funGetUserIdByToken()
if (response.success) {
setDataPorto(response.data)
setUserLoginId(response2)
}
} catch (error) {
console.error(error);
}
}
useShallowEffect(() => {
funGetPortofolio()
}, []);
return (
<>
{userLoginId === dataPorto?.authorId ? (
<Button
radius={"xl"}
bg={"red"}
color="red"
onClick={() => {
setModal(true)
}}
>
<IconTrash />
</Button>
) : (
""
)}
<UIGlobal_Modal
title={"Anda yakin menghapus portofolio ini ?"}
opened={openModal}
close={() => setModal(false)}
buttonKiri={
<Button radius={"xl"} onClick={() => setModal(false)}>
Batal
</Button>
}
buttonKanan={
<Button
radius={"xl"}
color="red"
loaderPosition="center"
loading={loadingDel}
onClick={() => onDelete()}
>
Hapus
</Button>
}
/>
</>
)
}

View File

@@ -0,0 +1,87 @@
import { RouterPortofolio } from "@/app/lib/router_hipmi/router_katalog";
import { RouterMap } from "@/app/lib/router_hipmi/router_map";
import { UIGlobal_Drawer } from "@/app_modules/_global/ui";
import { ActionIcon } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconEdit, IconPhotoEdit, IconId, IconMapPin2, IconMapPin, IconDotsVertical } from "@tabler/icons-react";
import { useParams } from "next/navigation";
import { useState } from "react";
import { apiGetOnePortofolioById } from "../lib/api_portofolio";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
export default function ComponentPortofolio_ButtonMoreNew() {
const param = useParams<{ id: string }>()
const [userLoginId, setUserLoginId] = useState("")
const [authorId, setAuthorId] = useState("")
const [openDrawer, setOpenDrawer] = useState(false)
const listPage = [
{
id: "1",
name: "Edit detail ",
icon: <IconEdit />,
path: RouterPortofolio.edit_data_bisnis + `${param.id}`,
},
{
id: "2",
name: "Edit logo ",
icon: <IconPhotoEdit />,
path: RouterPortofolio.edit_logo_bisnis + `${param.id}`,
},
{
id: "3",
name: "Edit sosial media",
icon: <IconId />,
path: RouterPortofolio.edit_medsos_bisnis + `${param.id}`,
},
{
id: "4",
name: "Edit data map",
icon: <IconMapPin2 />,
path: RouterMap.edit + `${param.id}`,
},
{
id: "5",
name: "Custom pin map",
icon: <IconMapPin />,
path: RouterMap.custom_pin + `${param.id}`,
},
];
async function funGetPortofolio() {
try {
const response = await apiGetOnePortofolioById(param.id, "bisnis")
const response2 = await funGetUserIdByToken()
if (response.success) {
setAuthorId(response.data.authorId)
setUserLoginId(response2)
}
} catch (error) {
console.error(error);
}
}
useShallowEffect(() => {
funGetPortofolio()
}, []);
return (
<>
{userLoginId === authorId ? (
<ActionIcon variant="transparent" onClick={() => setOpenDrawer(true)}>
<IconDotsVertical color="white" />
</ActionIcon>
) : (
<ActionIcon disabled variant="transparent"></ActionIcon>
)}
<UIGlobal_Drawer
opened={openDrawer}
close={() => setOpenDrawer(false)}
component={listPage}
/>
</>
)
}

View File

@@ -11,6 +11,8 @@ import LayoutPortofolio_EditDataBisnis from "./edit/data/layout";
import LayoutPortofolio_EditLogoBisnis from "./edit/logo/layout";
import LayoutPortofolio_EditMedsosBisnis from "./edit/medsos/layout";
import ListDetailPortofolioNew from './view/list_detail_portofolio_new';
import Portofolio_UiDetailNew from './ui/ui_detail_portofolio_new';
import PortofolioLayoutNew from './ui/ui_layout_new';
export {
CreatePortofolio,
@@ -28,4 +30,6 @@ export {
export type { IListPortofolio };
export { Portofolio_ViewListDetail } from "./view/view_list_detail_portofolio";
export { ListDetailPortofolioNew }
export { Portofolio_UiDetailNew }
export { PortofolioLayoutNew }

View File

@@ -1,4 +1,19 @@
export const apiGetPortofolioByProfile = async (path?: string) => {
const response = await fetch(`/api/new/portofolio${(path) ? path : ''}`)
return await response.json().catch(() => null)
}
export const apiGetOnePortofolioById = async (path: string, cat:string) => {
const response = await fetch(`/api/new/portofolio/${path}?cat=${cat}`);
return await response.json().catch(() => null);
}
export const apiDeletePortofolio = async (path: string) => {
const response = await fetch(`/api/new/portofolio/${path}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
});
return await response.json().catch(() => null);
}

View File

@@ -3,4 +3,33 @@ export interface IListPortofolio {
id_Portofolio: string
profileId: string
namaBisnis: string
}
export interface IDetailPortofolioBisnis {
id_Portofolio: string
namaBisnis: string
alamatKantor: string
tlpn: string
deskripsi: string
logoId: string
bidangBisnis: string
authorId: string
}
export interface IDetailPortofolioLokasi {
mapId: string
logoId: string
namePin: string
latitude: string
longitude: string
imageId: string
pinId: string
}
export interface IDetailPortofolioSosmed {
facebook: string
twitter: string
instagram: string
tiktok: string
youtube: string
}

View File

@@ -0,0 +1,131 @@
import { AccentColor, MainColor } from "@/app_modules/_global/color";
import { ComponentGlobal_LoadImage } from "@/app_modules/_global/component";
import { Paper, Stack, Group, Title, SimpleGrid, Box, Grid, Divider, Text } from "@mantine/core";
import { IconBuildingSkyscraper, IconListDetails, IconPhoneCall, IconMapPin, IconPinned } from "@tabler/icons-react";
import { useState } from "react";
import { IDetailPortofolioBisnis } from "../lib/type_portofolio";
import { useParams } from "next/navigation";
import { apiGetOnePortofolioById } from "../lib/api_portofolio";
import { useShallowEffect } from "@mantine/hooks";
import SkeletonDetailBisnis from "./ui_skeleton_detail_bisnis";
export default function Portofolio_UiDetailDataNew() {
const [loading, setLoading] = useState(true)
const param = useParams<{ id: string }>()
const [dataPorto, setDataPorto] = useState<IDetailPortofolioBisnis>();
async function funGetPortofolio() {
try {
setLoading(true)
const response = await apiGetOnePortofolioById(param.id, "bisnis");
if (response.success) {
setDataPorto(response.data);
}
} catch (error) {
console.error(error);
} finally {
setLoading(false)
}
}
useShallowEffect(() => {
funGetPortofolio()
}, []);
return (
<>
<Paper
p={"sm"}
style={{
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px ",
padding: "15px",
color: "white",
}}
>
{
loading ?
<SkeletonDetailBisnis />
:
<Stack>
<Group position="apart">
<Title order={6}>Data Bisnis</Title>
<Text color={MainColor.yellow} fw={"bold"}>
id: {" "}
<Text span inherit>
#{dataPorto?.id_Portofolio}
</Text>
</Text>
</Group>
<Stack>
<SimpleGrid
cols={2}
spacing={"md"}
breakpoints={[
{ maxWidth: "62rem", cols: 2, spacing: "md" },
{ maxWidth: "48rem", cols: 1, spacing: "sm" },
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
]}
>
<Box>
<Paper>
<ComponentGlobal_LoadImage fileId={String(dataPorto?.logoId)} />
</Paper>
</Box>
<Box>
<Grid>
<Grid.Col span={2}>
<IconBuildingSkyscraper />
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>{dataPorto?.namaBisnis}</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<IconListDetails />
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>{dataPorto?.bidangBisnis}</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<IconPhoneCall />
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>{dataPorto?.tlpn}</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<IconMapPin />
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>{dataPorto?.alamatKantor}</Text>
</Grid.Col>
</Grid>
</Box>
</SimpleGrid>
</Stack>
<Divider color={AccentColor.softblue} />
<Stack spacing={5}>
<Group spacing={"xs"}>
<IconPinned />
<Text fz={"sm"} fw={"bold"}>
Tentang Kami
</Text>
</Group>
<Text px={"sm"}>{dataPorto?.deskripsi}</Text>
</Stack>
</Stack>
}
</Paper>
</>
)
}

View File

@@ -0,0 +1,129 @@
import { APIs } from "@/app/lib";
import { AccentColor } from "@/app_modules/_global/color";
import { defaultMapZoom } from "@/app_modules/map/lib/default_lat_long";
import { Paper, Stack, Title, Avatar, Skeleton } from "@mantine/core";
import "mapbox-gl/dist/mapbox-gl.css";
import { useParams } from "next/navigation";
import { useState } from "react";
import { AttributionControl, Map, Marker, NavigationControl, ScaleControl, } from "react-map-gl";
import { IDetailPortofolioLokasi } from "../lib/type_portofolio";
import { apiGetOnePortofolioById } from "../lib/api_portofolio";
import { useShallowEffect } from "@mantine/hooks";
import { ComponentMap_DetailData, ComponentMap_DrawerDetailData } from "@/app_modules/map/_component";
export default function Portofolio_UiMapNew({ mapboxToken }: { mapboxToken: string }) {
const [loading, setLoading] = useState(true)
const param = useParams<{ id: string }>()
const [dataPorto, setDataPorto] = useState<IDetailPortofolioLokasi>()
const [openDrawer, setOpenDrawer] = useState(false)
async function funGetPortofolio() {
try {
setLoading(true)
const response = await apiGetOnePortofolioById(param.id, "lokasi");
if (response.success) {
setDataPorto(response.data);
}
} catch (error) {
console.error(error);
} finally {
setLoading(false)
}
}
useShallowEffect(() => {
funGetPortofolio()
}, []);
return (
<>
<Paper
p={"sm"}
style={{
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px ",
padding: "15px",
color: "white",
}}
>
<Stack spacing={0}>
<Title mb={"lg"} order={6}>
Lokasi Bisnis
</Title>
{
loading ?
<Skeleton radius={"md"} w={"100%"} h={100} />
:
<Map
mapboxAccessToken={mapboxToken}
mapStyle={"mapbox://styles/mapbox/streets-v11"}
initialViewState={{
latitude: Number(dataPorto?.latitude),
longitude: Number(dataPorto?.longitude),
zoom: defaultMapZoom,
}}
style={{
cursor: "pointer",
width: "100%",
height: "50vh",
borderRadius: "10px",
}}
attributionControl={false}
>
<Marker
style={{
color: "red",
width: 40,
cursor: "pointer",
}}
latitude={Number(dataPorto?.latitude)}
longitude={Number(dataPorto?.longitude)}
anchor="bottom"
offset={[0, 0]}
scale={1}
onClick={() => {
setOpenDrawer(true);
}}
pitchAlignment="auto"
>
<Stack spacing={0} align="center">
<Avatar
src={
dataPorto?.pinId === null
? APIs.GET({ fileId: String(dataPorto?.logoId) })
: APIs.GET({ fileId: String(dataPorto?.pinId) })
}
alt="Logo"
style={{
border: `2px solid ${AccentColor.softblue}`,
backgroundColor: "white",
borderRadius: "100%",
}}
/>
</Stack>
</Marker>
<NavigationControl />
<ScaleControl position="top-left" />
<AttributionControl
style={{ color: "black" }}
customAttribution="Map design by PT. Bali Interaktif Perkasa"
/>
</Map>
}
</Stack>
<ComponentMap_DrawerDetailData
opened={openDrawer}
close={() => setOpenDrawer(false)}
mapId={String(dataPorto?.mapId)}
component={<ComponentMap_DetailData mapId={String(dataPorto?.mapId)} isDetail />}
/>
</Paper>
</>
)
}

View File

@@ -0,0 +1,131 @@
import { AccentColor } from "@/app_modules/_global/color";
import { Paper, Title, Stack, Grid, Text, Skeleton, Box } from "@mantine/core";
import { IconBrandFacebook, IconBrandInstagram, IconBrandTiktok, IconBrandTwitter, IconBrandYoutube } from "@tabler/icons-react";
import { useParams } from "next/navigation";
import { useState } from "react";
import { IDetailPortofolioSosmed } from "../lib/type_portofolio";
import { apiGetOnePortofolioById } from "../lib/api_portofolio";
import { useShallowEffect } from "@mantine/hooks";
export default function Portofolio_UiSosialMediaNew() {
const [loading, setLoading] = useState(true)
const param = useParams<{ id: string }>()
const [dataPorto, setDataPorto] = useState<IDetailPortofolioSosmed>();
async function funGetPortofolio() {
try {
setLoading(true)
const response = await apiGetOnePortofolioById(param.id, "sosmed");
if (response.success) {
setDataPorto(response.data);
}
} catch (error) {
console.error(error);
} finally {
setLoading(false)
}
}
useShallowEffect(() => {
funGetPortofolio()
}, []);
return (
<>
<Paper
p={"sm"}
style={{
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px ",
padding: "15px",
color: "white",
}}
>
<Title order={6}>Media Sosial Bisnis</Title>
{
loading ?
<Box>
{[...Array(4)].map((_, index) => (
<Box key={index} py={5}>
<Grid align="center">
<Grid.Col span={1}>
<Skeleton w={25} h={25} />
</Grid.Col>
<Grid.Col span={11}>
<Skeleton w={"100%"} h={15} />
</Grid.Col>
</Grid>
</Box>
))}
</Box>
:
<Stack p={"sm"}>
<Grid>
<Grid.Col span={2}>
<IconBrandFacebook />
</Grid.Col>
<Grid.Col span={"auto"}>
{dataPorto?.facebook ? (
<Text>{dataPorto?.facebook}</Text>
) : (
"-"
)}
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<IconBrandInstagram />
</Grid.Col>
<Grid.Col span={"auto"}>
{dataPorto?.instagram ? (
<Text>{dataPorto?.instagram}</Text>
) : (
"-"
)}
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<IconBrandTiktok />
</Grid.Col>
<Grid.Col span={"auto"}>
{dataPorto?.tiktok ? (
<Text>{dataPorto?.tiktok}</Text>
) : (
"-"
)}
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<IconBrandTwitter />
</Grid.Col>
<Grid.Col span={"auto"}>
{dataPorto?.twitter ? (
<Text>{dataPorto?.twitter}</Text>
) : (
"-"
)}
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<IconBrandYoutube />
</Grid.Col>
<Grid.Col span={"auto"}>
{dataPorto?.youtube ? (
<Text>{dataPorto?.youtube}</Text>
) : (
"-"
)}
</Grid.Col>
</Grid>
</Stack>
}
</Paper>
</>
)
}

View File

@@ -0,0 +1,19 @@
'use client'
import { Stack } from "@mantine/core";
import Portofolio_UiDetailDataNew from "./ui_detail_data_new";
import Portofolio_UiMapNew from "./ui_detail_map_new";
import Portofolio_UiSosialMediaNew from "./ui_detail_media_new";
import ComponentPortofolio_ButtonDeleteNew from "../component/button_delete_new";
export default function Portofolio_UiDetailNew({ mapboxToken }: { mapboxToken: string }) {
return (
<>
<Stack mb={"lg"}>
<Portofolio_UiDetailDataNew />
<Portofolio_UiMapNew mapboxToken={mapboxToken} />
<Portofolio_UiSosialMediaNew />
<ComponentPortofolio_ButtonDeleteNew/>
</Stack>
</>
)
}

View File

@@ -0,0 +1,20 @@
'use client'
import { UIGlobal_LayoutHeaderTamplate, UIGlobal_LayoutTamplate } from "@/app_modules/_global/ui";
import ComponentPortofolio_ButtonMoreNew from "../component/button_more_new";
export default function PortofolioLayoutNew({ children }: { children: any }) {
return (
<>
<UIGlobal_LayoutTamplate
header={
<UIGlobal_LayoutHeaderTamplate
title="Detail Portofolio"
customButtonRight={<ComponentPortofolio_ButtonMoreNew />}
/>
}
>
{children}
</UIGlobal_LayoutTamplate>
</>
)
}

View File

@@ -0,0 +1,35 @@
import { Box, Grid, Group, Skeleton, Stack } from "@mantine/core";
export default function SkeletonDetailBisnis() {
return <>
<Box>
<Grid>
<Grid.Col span={6}>
<Skeleton w={"100%"} height={200} radius="md" />
</Grid.Col>
<Grid.Col span={6}>
<Box>
{[...Array(4)].map((_, index) => (
<Box key={index} py={5}>
<Grid align="center">
<Grid.Col span={2}>
<Skeleton w={25} h={25} />
</Grid.Col>
<Grid.Col span={10}>
<Skeleton w={"100%"} h={15} />
</Grid.Col>
</Grid>
</Box>
))}
</Box>
</Grid.Col>
</Grid>
<Box mt={"md"}>
<Skeleton w={"30%"} h={15} my={10} />
<Skeleton w={"95%"} h={15} my={10} />
<Skeleton w={"95%"} h={15} my={10} />
<Skeleton w={"95%"} h={15} my={10} />
</Box>
</Box>
</>;
}