Merge pull request #165 from bipproduction/amalia/06-des-24
upd: portofolio detail
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 { 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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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_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 }
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
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