upd: portofolio detail
Deskripsi: - update api detail portofolio - delete api portofolio No Issues
This commit is contained in:
172
src/app/api/new/portofolio/[id]/route.ts
Normal file
172
src/app/api/new/portofolio/[id]/route.ts
Normal 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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,27 +1,20 @@
|
|||||||
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
|
import { PortofolioLayoutNew } from "@/app_modules/katalog/portofolio";
|
||||||
import { PortofolioLayout } from "@/app_modules/katalog/portofolio";
|
|
||||||
import { portofolio_getOneById } from "@/app_modules/katalog/portofolio/fun/get/get_one_portofolio";
|
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({ children, params, }: { children: any; params: { id: string }; }) {
|
||||||
children,
|
// let portoId = params.id;
|
||||||
params,
|
// const getPorto = await portofolio_getOneById(portoId);
|
||||||
}: {
|
// const userLoginId = await funGetUserIdByToken();
|
||||||
children: any;
|
|
||||||
params: { id: string };
|
|
||||||
}) {
|
|
||||||
let portoId = params.id;
|
|
||||||
const getPorto = await portofolio_getOneById(portoId);
|
|
||||||
const userLoginId = await funGetUserIdByToken();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PortofolioLayout
|
{/* <PortofolioLayout
|
||||||
portoId={portoId}
|
portoId={portoId}
|
||||||
userLoginId={userLoginId as string}
|
userLoginId={userLoginId as string}
|
||||||
authorId={getPorto?.Profile?.User?.id as any}
|
authorId={getPorto?.Profile?.User?.id as any}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</PortofolioLayout>
|
</PortofolioLayout> */}
|
||||||
|
<PortofolioLayoutNew>{children}</PortofolioLayoutNew>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
|
import { Portofolio_UiDetailNew } from "@/app_modules/katalog/portofolio";
|
||||||
import { ViewPortofolio } from "@/app_modules/katalog/portofolio";
|
|
||||||
import { portofolio_getOneById } from "@/app_modules/katalog/portofolio/fun/get/get_one_portofolio";
|
|
||||||
|
|
||||||
const mapboxToken = process.env.MAPBOX_TOKEN!;
|
const mapboxToken = process.env.MAPBOX_TOKEN!;
|
||||||
export default async function Page({ params }: { params: { id: string } }) {
|
export default async function Page({ params }: { params: { id: string } }) {
|
||||||
const portofolioId = params.id;
|
// const portofolioId = params.id;
|
||||||
const dataPortofolio = await portofolio_getOneById(portofolioId);
|
// const dataPortofolio = await portofolio_getOneById(portofolioId);
|
||||||
const userLoginId = await funGetUserIdByToken();
|
// const userLoginId = await funGetUserIdByToken();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewPortofolio
|
{/* <ViewPortofolio
|
||||||
dataPorto={dataPortofolio as any}
|
dataPorto={dataPortofolio as any}
|
||||||
userLoginId={userLoginId as any}
|
userLoginId={userLoginId as any}
|
||||||
mapboxToken={mapboxToken}
|
mapboxToken={mapboxToken}
|
||||||
/>
|
/> */}
|
||||||
|
<Portofolio_UiDetailNew mapboxToken={mapboxToken} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@ import LayoutPortofolio_EditDataBisnis from "./edit/data/layout";
|
|||||||
import LayoutPortofolio_EditLogoBisnis from "./edit/logo/layout";
|
import LayoutPortofolio_EditLogoBisnis from "./edit/logo/layout";
|
||||||
import LayoutPortofolio_EditMedsosBisnis from "./edit/medsos/layout";
|
import LayoutPortofolio_EditMedsosBisnis from "./edit/medsos/layout";
|
||||||
import ListDetailPortofolioNew from './view/list_detail_portofolio_new';
|
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 {
|
export {
|
||||||
CreatePortofolio,
|
CreatePortofolio,
|
||||||
@@ -28,4 +30,6 @@ export {
|
|||||||
export type { IListPortofolio };
|
export type { IListPortofolio };
|
||||||
export { Portofolio_ViewListDetail } from "./view/view_list_detail_portofolio";
|
export { Portofolio_ViewListDetail } from "./view/view_list_detail_portofolio";
|
||||||
export { ListDetailPortofolioNew }
|
export { ListDetailPortofolioNew }
|
||||||
|
export { Portofolio_UiDetailNew }
|
||||||
|
export { PortofolioLayoutNew }
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,19 @@
|
|||||||
export const apiGetPortofolioByProfile = async (path?: string) => {
|
export const apiGetPortofolioByProfile = async (path?: string) => {
|
||||||
const response = await fetch(`/api/new/portofolio${(path) ? path : ''}`)
|
const response = await fetch(`/api/new/portofolio${(path) ? path : ''}`)
|
||||||
return await response.json().catch(() => null)
|
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);
|
||||||
}
|
}
|
||||||
@@ -3,4 +3,33 @@ export interface IListPortofolio {
|
|||||||
id_Portofolio: string
|
id_Portofolio: string
|
||||||
profileId: string
|
profileId: string
|
||||||
namaBisnis: 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
|
||||||
}
|
}
|
||||||
131
src/app_modules/katalog/portofolio/ui/ui_detail_data_new.tsx
Normal file
131
src/app_modules/katalog/portofolio/ui/ui_detail_data_new.tsx
Normal 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>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
129
src/app_modules/katalog/portofolio/ui/ui_detail_map_new.tsx
Normal file
129
src/app_modules/katalog/portofolio/ui/ui_detail_map_new.tsx
Normal 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>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
131
src/app_modules/katalog/portofolio/ui/ui_detail_media_new.tsx
Normal file
131
src/app_modules/katalog/portofolio/ui/ui_detail_media_new.tsx
Normal 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>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
20
src/app_modules/katalog/portofolio/ui/ui_layout_new.tsx
Normal file
20
src/app_modules/katalog/portofolio/ui/ui_layout_new.tsx
Normal 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>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
</>;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user