Portofolio
#feat - Create porto - Edit Porto - Upload gambar background profile - List user - Search user ## No issuue
This commit is contained in:
71
src/app_modules/katalog/component/header_tamplate.tsx
Normal file
71
src/app_modules/katalog/component/header_tamplate.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
"use client";
|
||||
|
||||
import { Header, Group, ActionIcon, Text, Title } from "@mantine/core";
|
||||
import { IconArrowLeft, IconChevronLeft } from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function ComponentKatalog_HeaderTamplate({
|
||||
hideBack,
|
||||
changeIconBack,
|
||||
route,
|
||||
route2,
|
||||
title,
|
||||
icon,
|
||||
bg,
|
||||
titleColor,
|
||||
}: {
|
||||
hideBack?: boolean;
|
||||
changeIconBack?: any;
|
||||
route?: any;
|
||||
route2?: any;
|
||||
title: string;
|
||||
icon?: any;
|
||||
bg?: any;
|
||||
titleColor?: string
|
||||
}) {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
<Header
|
||||
height={50}
|
||||
sx={{ borderStyle: "none" }}
|
||||
bg={bg === null ? "" : bg}
|
||||
>
|
||||
<Group h={50} position="apart" px={"md"}>
|
||||
{hideBack ? (
|
||||
<ActionIcon variant="transparent" disabled></ActionIcon>
|
||||
) : (
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
onClick={() => {
|
||||
if (route === null || route === undefined) {
|
||||
return router.back();
|
||||
} else {
|
||||
return router.push(route);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{changeIconBack ? changeIconBack : <IconChevronLeft />}
|
||||
</ActionIcon>
|
||||
)}
|
||||
<Title order={5} c={titleColor ? titleColor : "black"} >{title}</Title>
|
||||
{(() => {
|
||||
if (route2 === null || route2 === undefined) {
|
||||
return <ActionIcon disabled variant="transparent"></ActionIcon>;
|
||||
} else {
|
||||
return (
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
onClick={() => router.push(route2)}
|
||||
>
|
||||
{icon}
|
||||
</ActionIcon>
|
||||
);
|
||||
}
|
||||
})()}
|
||||
</Group>
|
||||
</Header>
|
||||
</>
|
||||
);
|
||||
}
|
||||
22
src/app_modules/katalog/component/noted_box.tsx
Normal file
22
src/app_modules/katalog/component/noted_box.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Center, Grid, Group, Paper, Text, Title } from "@mantine/core";
|
||||
|
||||
export default function ComponentKatalog_NotedBox({
|
||||
informasi,
|
||||
}: {
|
||||
informasi: string;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<Paper bg={"blue.3"} p={10}>
|
||||
<Group>
|
||||
<Text fz={10} fs={"italic"}>
|
||||
<Text span inherit c={"red"}>
|
||||
*{" "}
|
||||
</Text>
|
||||
{informasi}
|
||||
</Text>
|
||||
</Group>
|
||||
</Paper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -2,36 +2,37 @@
|
||||
|
||||
import { Logout } from "@/app_modules/auth";
|
||||
import { ActionIcon, AppShell, Group, Header, Text } from "@mantine/core";
|
||||
import { IconUserSearch, IconAward, IconQrcode, IconArrowLeft, IconPencilPlus } from "@tabler/icons-react";
|
||||
import {
|
||||
IconUserSearch,
|
||||
IconAward,
|
||||
IconQrcode,
|
||||
IconArrowLeft,
|
||||
IconPencilPlus,
|
||||
IconChevronLeft,
|
||||
} from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import ComponentKatalog_HeaderTamplate from "../component/header_tamplate";
|
||||
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||
import { RouterHome } from "@/app/lib/router_hipmi/router_home";
|
||||
|
||||
export default function KatalogLayout({ children, profileId }: { children: any, profileId: any }) {
|
||||
const router = useRouter()
|
||||
export default function KatalogLayout({
|
||||
children,
|
||||
profileId,
|
||||
}: {
|
||||
children: any;
|
||||
profileId: any;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
<AppShell
|
||||
header={
|
||||
<Header height={50} bg={"dark"}>
|
||||
<Group position="apart" align="center" h={50} p={"sm"}>
|
||||
<Group spacing={"sm"}>
|
||||
<ActionIcon variant="transparent" onClick={() => router.push("/dev/home")}>
|
||||
<IconArrowLeft/>
|
||||
</ActionIcon>
|
||||
{/* <ActionIcon>
|
||||
<IconAward />
|
||||
</ActionIcon> */}
|
||||
</Group>
|
||||
<Text color="white" fw={"bold"}>
|
||||
Katalog
|
||||
</Text>
|
||||
<Group spacing={"sm"}>
|
||||
<ActionIcon variant="transparent" onClick={() => router.push(`/dev/portofolio/create/${profileId}`)}>
|
||||
<IconPencilPlus />
|
||||
</ActionIcon>
|
||||
{/* <Logout /> */}
|
||||
</Group>
|
||||
</Group>
|
||||
</Header>
|
||||
<ComponentKatalog_HeaderTamplate
|
||||
title="Katalog"
|
||||
bg={"black"}
|
||||
titleColor="white"
|
||||
// route={RouterHome.main_home}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -11,37 +11,38 @@ import {
|
||||
Group,
|
||||
Image,
|
||||
Paper,
|
||||
Stack,
|
||||
Text,
|
||||
} from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import {
|
||||
IconAddressBook,
|
||||
IconCamera,
|
||||
IconEditCircle,
|
||||
IconGenderFemale,
|
||||
IconGenderMale,
|
||||
IconHome,
|
||||
IconMail,
|
||||
} from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { ProfileView, getProfile } from "../profile";
|
||||
import { gs_profile } from "../profile/state/global_state";
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
import { useAtom } from "jotai";
|
||||
import { loadDataProfile } from "../profile/fun/fun_get_profile";
|
||||
import { getFotoProfile } from "../profile/api/get-foto-profile";
|
||||
import { ApiHipmi } from "@/app/lib/api";
|
||||
import { ProfileView } from "../profile";
|
||||
import { ListPortofolioView } from "../portofolio";
|
||||
import { User } from "@prisma/client";
|
||||
import { MODEL_User_profile } from "@/app_modules/home/models/user_profile";
|
||||
import { MODEL_PROFILE_OLD } from "@/app_modules/home/model/user_profile";
|
||||
import { LIST_PORTOFOLIO } from "@/app_modules/models/portofolio";
|
||||
import User_Logout from "@/app_modules/auth/logout/view";
|
||||
import { MODEL_PORTOFOLIO } from "../portofolio/model/interface";
|
||||
import { MODEL_PROFILE } from "../profile/model/interface";
|
||||
|
||||
export default function KatalogView({
|
||||
profile,
|
||||
listPorto,
|
||||
userLoginId,
|
||||
}: {
|
||||
profile: MODEL_PROFILE;
|
||||
listPorto: LIST_PORTOFOLIO;
|
||||
userLoginId: string;
|
||||
}) {
|
||||
|
||||
export default function KatalogView({ user, listPorto }: { user: MODEL_User_profile, listPorto: LIST_PORTOFOLIO }) {
|
||||
return (
|
||||
<>
|
||||
<ProfileView user={user} />
|
||||
<ListPortofolioView listPorto={listPorto} />
|
||||
<Stack>
|
||||
<ProfileView profile={profile as any} userLoginId={userLoginId} />
|
||||
<ListPortofolioView
|
||||
listPorto={listPorto as any}
|
||||
profile={profile}
|
||||
userLoginId={userLoginId}
|
||||
/>
|
||||
{profile.User.id === userLoginId ? <User_Logout /> : ""}
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { ActionIcon, AppShell, Group, Header, Text } from "@mantine/core";
|
||||
import { IconArrowLeft } from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import ComponentKatalog_HeaderTamplate from "../../component/header_tamplate";
|
||||
|
||||
export default function CreatePortofolioLayout({ children, profileId }: { children: any, profileId: any }) {
|
||||
const router = useRouter();
|
||||
@@ -10,18 +11,7 @@ export default function CreatePortofolioLayout({ children, profileId }: { childr
|
||||
<>
|
||||
<AppShell
|
||||
header={
|
||||
<Header height={50} px={"sm"}>
|
||||
<Group position="apart" h={50}>
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
onClick={() => router.push(`/dev/katalog/${profileId}`)}
|
||||
>
|
||||
<IconArrowLeft />
|
||||
</ActionIcon>
|
||||
<Text>Buat Portofolio</Text>
|
||||
<ActionIcon variant="transparent"></ActionIcon>
|
||||
</Group>
|
||||
</Header>
|
||||
<ComponentKatalog_HeaderTamplate title="Buat Portofolio"/>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -3,107 +3,227 @@
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
import { ApiHipmi } from "@/app/lib/api";
|
||||
import { Warna } from "@/app/lib/warna";
|
||||
import { BIDANG_BISNIS } from "@/app_modules/models/portofolio";
|
||||
import { Button, Select, Stack, TextInput, Title } from "@mantine/core";
|
||||
import {
|
||||
BIDANG_BISNIS_OLD,
|
||||
MODEL_PORTOFOLIO_OLD,
|
||||
} from "@/app_modules/models/portofolio";
|
||||
import {
|
||||
AspectRatio,
|
||||
Button,
|
||||
Center,
|
||||
FileButton,
|
||||
Image,
|
||||
Paper,
|
||||
Select,
|
||||
Stack,
|
||||
TextInput,
|
||||
Textarea,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import _ from "lodash";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import toast from "react-simple-toasts";
|
||||
import funCreatePortofolio from "../fun/fun_create_portofolio";
|
||||
import { IconCamera } from "@tabler/icons-react";
|
||||
import ComponentKatalog_NotedBox from "../../component/noted_box";
|
||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import { NotifPeringatan } from "@/app_modules/donasi/component/notifikasi/notif_peringatan";
|
||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
||||
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
|
||||
|
||||
export default function CreatePortofolio({
|
||||
bidangBisnis,
|
||||
profileId,
|
||||
}: {
|
||||
bidangBisnis: BIDANG_BISNIS;
|
||||
bidangBisnis: BIDANG_BISNIS_OLD;
|
||||
profileId: any;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [value, setValue] = useState({
|
||||
namaBisnis: "",
|
||||
bidangBisnisId: "",
|
||||
masterBidangBisnisId: "",
|
||||
alamatKantor: "",
|
||||
tlpn: "",
|
||||
deskripsi: "",
|
||||
});
|
||||
|
||||
async function onSubmit() {
|
||||
const body = {
|
||||
profileId: profileId,
|
||||
namaBisnis: value.namaBisnis,
|
||||
masterBidangBisnisId: value.bidangBisnisId,
|
||||
alamatKantor: value.alamatKantor,
|
||||
tlpn: value.tlpn,
|
||||
deskripsi: value.deskripsi,
|
||||
};
|
||||
const [medsos, setMedsos] = useState({
|
||||
facebook: "",
|
||||
twitter: "",
|
||||
instagram: "",
|
||||
youtube: "",
|
||||
tiktok: "",
|
||||
});
|
||||
|
||||
if (_.values(body).includes("")) return toast("Lengkapi Data");
|
||||
|
||||
await funCreatePortofolio(body as any).then((res) => {
|
||||
if (res.status === 201) {
|
||||
toast("Berhasil disimpan");
|
||||
return setTimeout(() => router.push(`/dev/katalog/${profileId}`), 1000)
|
||||
} else {
|
||||
return toast("Gagal disimpan");
|
||||
}
|
||||
});
|
||||
}
|
||||
const [file, setFile] = useState<File | any>(null);
|
||||
const [img, setImg] = useState<any | null>(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* {JSON.stringify(profileId)} */}
|
||||
|
||||
<Stack px={"sm"}>
|
||||
<TextInput
|
||||
label="Nama Bisnis"
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
namaBisnis: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Select
|
||||
label="Bidang Bisnis"
|
||||
data={_.map(bidangBisnis as any).map((e: any) => ({
|
||||
value: e.id,
|
||||
label: e.name,
|
||||
}))}
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
bidangBisnisId: val as any,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Alamat Kantor"
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
alamatKantor: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Nomor Telepon"
|
||||
type="number"
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
tlpn: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Deskripsi"
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
deskripsi: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Stack px={"sm"} spacing={50}>
|
||||
<Stack spacing={"sm"}>
|
||||
<ComponentKatalog_NotedBox informasi="Lengkapi Data Bisnis" />
|
||||
<TextInput
|
||||
withAsterisk
|
||||
label="Nama Bisnis"
|
||||
placeholder="Nama bisnis"
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
namaBisnis: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Select
|
||||
withAsterisk
|
||||
label="Bidang Bisnis"
|
||||
placeholder="Pilih salah satu bidang bisnis"
|
||||
data={_.map(bidangBisnis as any).map((e: any) => ({
|
||||
value: e.id,
|
||||
label: e.name,
|
||||
}))}
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
masterBidangBisnisId: val as any,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
withAsterisk
|
||||
label="Alamat Kantor"
|
||||
placeholder="Alamat kantor"
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
alamatKantor: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
withAsterisk
|
||||
label="Nomor Telepon Kantor"
|
||||
placeholder="62 xxx xxx xxx"
|
||||
type="number"
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
tlpn: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Textarea
|
||||
autosize
|
||||
minRows={2}
|
||||
maxRows={5}
|
||||
withAsterisk
|
||||
label="Deskripsi"
|
||||
placeholder="Deskripsi singkat mengenai usaha"
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
deskripsi: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<Stack>
|
||||
<ComponentKatalog_NotedBox informasi="Upload Logo Bisnis Anda!" />
|
||||
<AspectRatio ratio={16 / 9}>
|
||||
<Paper radius={"md"} withBorder>
|
||||
<Image alt="Foto" src={img ? img : "/aset/no-img.png"} />
|
||||
</Paper>
|
||||
</AspectRatio>
|
||||
<Center>
|
||||
<FileButton
|
||||
onChange={async (files: any | null) => {
|
||||
try {
|
||||
const buffer = URL.createObjectURL(
|
||||
new Blob([new Uint8Array(await files.arrayBuffer())])
|
||||
);
|
||||
// console.log(buffer, "ini buffer");
|
||||
// console.log(files, " ini file");
|
||||
setImg(buffer);
|
||||
setFile(files);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}}
|
||||
accept="image/png,image/jpeg"
|
||||
>
|
||||
{(props) => (
|
||||
<Button
|
||||
{...props}
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
w={150}
|
||||
leftIcon={<IconCamera />}
|
||||
compact
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
)}
|
||||
</FileButton>
|
||||
</Center>
|
||||
</Stack>
|
||||
|
||||
<Stack>
|
||||
<ComponentKatalog_NotedBox informasi="Isi hanya pada sosial media yang anda miliki" />
|
||||
<TextInput
|
||||
label="Facebook"
|
||||
placeholder="Facebook"
|
||||
onChange={(val) => {
|
||||
setMedsos({
|
||||
...medsos,
|
||||
facebook: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Instagram"
|
||||
placeholder="Instagram"
|
||||
onChange={(val) => {
|
||||
setMedsos({
|
||||
...medsos,
|
||||
instagram: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Tiktok"
|
||||
placeholder="Tiktok"
|
||||
onChange={(val) => {
|
||||
setMedsos({
|
||||
...medsos,
|
||||
tiktok: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Twitter"
|
||||
placeholder="Twitter"
|
||||
onChange={(val) => {
|
||||
setMedsos({
|
||||
...medsos,
|
||||
twitter: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Youtube"
|
||||
placeholder="Youtube"
|
||||
onChange={(val) => {
|
||||
setMedsos({
|
||||
...medsos,
|
||||
youtube: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<Button
|
||||
mt={"md"}
|
||||
@@ -111,14 +231,46 @@ export default function CreatePortofolio({
|
||||
bg={Warna.hijau_muda}
|
||||
color="green"
|
||||
onClick={() => {
|
||||
onSubmit();
|
||||
onSubmit(router, profileId, value as any, file, medsos);
|
||||
}}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</Stack>
|
||||
|
||||
{/* <pre> {JSON.stringify(data, null, 2)}</pre> */}
|
||||
{/* <pre> {JSON.stringify(bidangBisnis, null, 2)}</pre> */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function onSubmit(
|
||||
router: AppRouterInstance,
|
||||
profileId: string,
|
||||
dataPorto: MODEL_PORTOFOLIO_OLD,
|
||||
file: FormData,
|
||||
dataMedsos: any
|
||||
) {
|
||||
const porto = {
|
||||
namaBisnis: dataPorto.namaBisnis,
|
||||
masterBidangBisnisId: dataPorto.masterBidangBisnisId,
|
||||
alamatKantor: dataPorto.alamatKantor,
|
||||
tlpn: dataPorto.tlpn,
|
||||
deskripsi: dataPorto.deskripsi,
|
||||
};
|
||||
if (_.values(porto).includes("")) return toast("Lengkapi Data");
|
||||
if (!file) return NotifPeringatan("Lengkapi logo binnis");
|
||||
|
||||
const gambar = new FormData
|
||||
gambar.append("file",file as any)
|
||||
|
||||
await funCreatePortofolio(profileId, porto as any, gambar, dataMedsos).then(
|
||||
(res) => {
|
||||
if (res.status === 201) {
|
||||
ComponentGlobal_NotifikasiBerhasil("Berhasil disimpan");
|
||||
router.back();
|
||||
} else {
|
||||
ComponentGlobal_NotifikasiGagal("Gagal disimpan");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
130
src/app_modules/katalog/portofolio/edit/data/index.tsx
Normal file
130
src/app_modules/katalog/portofolio/edit/data/index.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
"use client";
|
||||
|
||||
import { Box, Button, Select, Stack, TextInput, Textarea } from "@mantine/core";
|
||||
import {
|
||||
MODEL_PORTOFOLIO,
|
||||
MODEL_PORTOFOLIO_BIDANG_BISNIS,
|
||||
} from "../../model/interface";
|
||||
import { useState } from "react";
|
||||
import _ from "lodash";
|
||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Portofolio_funEditDataBisnis } from "../../fun/edit/fun_edit_data_bisnis_by_id";
|
||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
||||
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
|
||||
|
||||
export default function Portofolio_EditDataBisnis({
|
||||
dataPorto,
|
||||
listBidang,
|
||||
}: {
|
||||
dataPorto: MODEL_PORTOFOLIO;
|
||||
listBidang: MODEL_PORTOFOLIO_BIDANG_BISNIS[];
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [porto, setPorto] = useState(dataPorto);
|
||||
// const [value, setPorto] = useState({
|
||||
// namaBisnis: "",
|
||||
// masterBidangBisnisId: "",
|
||||
// alamatKantor: "",
|
||||
// tlpn: "",
|
||||
// deskripsi: "",
|
||||
// });
|
||||
return (
|
||||
<>
|
||||
{/* <pre>{JSON.stringify(porto, null, 2)}</pre> */}
|
||||
<Stack spacing={50} p={"md"}>
|
||||
<Stack>
|
||||
<TextInput
|
||||
withAsterisk
|
||||
value={porto.namaBisnis}
|
||||
label="Nama Bisnis"
|
||||
placeholder="Nama bisnis"
|
||||
onChange={(val) => {
|
||||
setPorto({
|
||||
...porto,
|
||||
namaBisnis: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Select
|
||||
withAsterisk
|
||||
value={porto.MasterBidangBisnis.id}
|
||||
label="Bidang Bisnis"
|
||||
placeholder="Pilih salah satu bidang bisnis"
|
||||
data={listBidang.map((e) => ({
|
||||
value: e.id,
|
||||
label: e.name,
|
||||
}))}
|
||||
onChange={(val) => {
|
||||
setPorto({
|
||||
...(porto as any),
|
||||
MasterBidangBisnis: {
|
||||
id: val,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
withAsterisk
|
||||
value={porto.alamatKantor}
|
||||
label="Alamat Kantor"
|
||||
placeholder="Alamat kantor"
|
||||
onChange={(val) => {
|
||||
setPorto({
|
||||
...porto,
|
||||
alamatKantor: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
withAsterisk
|
||||
value={porto.tlpn}
|
||||
label="Nomor Telepon Kantor"
|
||||
placeholder="62 xxx xxx xxx"
|
||||
type="number"
|
||||
onChange={(val) => {
|
||||
setPorto({
|
||||
...porto,
|
||||
tlpn: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Textarea
|
||||
autosize
|
||||
minRows={2}
|
||||
maxRows={5}
|
||||
withAsterisk
|
||||
value={porto.deskripsi}
|
||||
label="Deskripsi"
|
||||
placeholder="Deskripsi singkat mengenai usaha"
|
||||
onChange={(val) => {
|
||||
setPorto({
|
||||
...porto,
|
||||
deskripsi: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
<Button
|
||||
radius={"xl"}
|
||||
onClick={() => {
|
||||
onUpdate(router, porto as any);
|
||||
}}
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function onUpdate(router: AppRouterInstance, data: MODEL_PORTOFOLIO) {
|
||||
await Portofolio_funEditDataBisnis(data).then((res) => {
|
||||
if (res.status === 200) {
|
||||
ComponentGlobal_NotifikasiBerhasil(res.message);
|
||||
router.back();
|
||||
} else {
|
||||
ComponentGlobal_NotifikasiGagal(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
22
src/app_modules/katalog/portofolio/edit/data/layout.tsx
Normal file
22
src/app_modules/katalog/portofolio/edit/data/layout.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
"use client";
|
||||
|
||||
import ComponentKatalog_HeaderTamplate from "@/app_modules/katalog/component/header_tamplate";
|
||||
import { AppShell } from "@mantine/core";
|
||||
import React from "react";
|
||||
|
||||
|
||||
export default function LayoutPortofolio_EditDataBisnis({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<AppShell
|
||||
header={<ComponentKatalog_HeaderTamplate title="Edit Data Bisnis" />}
|
||||
>
|
||||
{children}
|
||||
</AppShell>
|
||||
</>
|
||||
);
|
||||
}
|
||||
21
src/app_modules/katalog/portofolio/edit/layout.tsx
Normal file
21
src/app_modules/katalog/portofolio/edit/layout.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import { AppShell } from "@mantine/core";
|
||||
import React from "react";
|
||||
import ComponentKatalog_HeaderTamplate from "../../component/header_tamplate";
|
||||
|
||||
export default function LayoutPortofolio_EditBisnis({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<AppShell
|
||||
header={<ComponentKatalog_HeaderTamplate title="Edit Portofolio" />}
|
||||
>
|
||||
{children}
|
||||
</AppShell>
|
||||
</>
|
||||
);
|
||||
}
|
||||
113
src/app_modules/katalog/portofolio/edit/logo/index.tsx
Normal file
113
src/app_modules/katalog/portofolio/edit/logo/index.tsx
Normal file
@@ -0,0 +1,113 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
RouterPortofolio,
|
||||
RouterProfile,
|
||||
} from "@/app/lib/router_hipmi/router_katalog";
|
||||
import {
|
||||
AspectRatio,
|
||||
Box,
|
||||
Button,
|
||||
Center,
|
||||
FileButton,
|
||||
Image,
|
||||
Paper,
|
||||
Stack,
|
||||
} from "@mantine/core";
|
||||
import { IconCamera } from "@tabler/icons-react";
|
||||
import { profile } from "console";
|
||||
import image from "next/image";
|
||||
import { useRouter } from "next/navigation";
|
||||
import router from "next/router";
|
||||
import { useState } from "react";
|
||||
import { MODEL_PORTOFOLIO } from "../../model/interface";
|
||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import { Portofolio_funEditLogoBisnisById } from "../../fun/edit/fun_edit_logo_bisnis_by_id";
|
||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
||||
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
|
||||
|
||||
export default function Portofolio_EditLogoBisnis({
|
||||
dataPorto,
|
||||
}: {
|
||||
dataPorto: MODEL_PORTOFOLIO;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [image, setImage] = useState<any | null>(null);
|
||||
return (
|
||||
<>
|
||||
<Stack spacing={"xl"} px={"sm"}>
|
||||
<Paper p={"sm"} withBorder radius={"sm"} shadow="lg">
|
||||
<Stack>
|
||||
<AspectRatio ratio={1 / 1}>
|
||||
<Image
|
||||
alt="Foto"
|
||||
src={
|
||||
image
|
||||
? image
|
||||
: RouterPortofolio.api_logo_porto + `${dataPorto.logoId}`
|
||||
}
|
||||
/>
|
||||
</AspectRatio>
|
||||
<Center>
|
||||
<FileButton
|
||||
onChange={async (files: any | null) => {
|
||||
try {
|
||||
const buffer = URL.createObjectURL(
|
||||
new Blob([new Uint8Array(await files.arrayBuffer())])
|
||||
);
|
||||
// console.log(buffer, "ini buffer");
|
||||
// console.log(files, " ini file");
|
||||
setImage(buffer);
|
||||
setFile(files);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}}
|
||||
accept="image/png,image/jpeg"
|
||||
>
|
||||
{(props) => (
|
||||
<Button
|
||||
{...props}
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
w={150}
|
||||
leftIcon={<IconCamera />}
|
||||
compact
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
)}
|
||||
</FileButton>
|
||||
</Center>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
<Button
|
||||
radius={"xl"}
|
||||
onClick={() => onUpdate(router, dataPorto.id, file as any)}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function onUpdate(
|
||||
router: AppRouterInstance,
|
||||
portoId: string,
|
||||
file: FormData
|
||||
) {
|
||||
const gambar = new FormData();
|
||||
gambar.append("file", file as any);
|
||||
|
||||
await Portofolio_funEditLogoBisnisById(portoId, gambar).then((res) => {
|
||||
if (res.status === 200) {
|
||||
ComponentGlobal_NotifikasiBerhasil(res.message);
|
||||
router.back();
|
||||
} else {
|
||||
ComponentGlobal_NotifikasiGagal(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
21
src/app_modules/katalog/portofolio/edit/logo/layout.tsx
Normal file
21
src/app_modules/katalog/portofolio/edit/logo/layout.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import ComponentKatalog_HeaderTamplate from "@/app_modules/katalog/component/header_tamplate";
|
||||
import { AppShell } from "@mantine/core";
|
||||
import React from "react";
|
||||
|
||||
export default function LayoutPortofolio_EditLogoBisnis({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<AppShell
|
||||
header={<ComponentKatalog_HeaderTamplate title="Edit Logo Bisnis" />}
|
||||
>
|
||||
{children}
|
||||
</AppShell>
|
||||
</>
|
||||
);
|
||||
}
|
||||
107
src/app_modules/katalog/portofolio/edit/medsos/index.tsx
Normal file
107
src/app_modules/katalog/portofolio/edit/medsos/index.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
"use client";
|
||||
|
||||
import ComponentKatalog_NotedBox from "@/app_modules/katalog/component/noted_box";
|
||||
import { Box, Button, Paper, Stack, TextInput } from "@mantine/core";
|
||||
import { useState } from "react";
|
||||
import { MODEL_PORTOFOLIO_MEDSOS } from "../../model/interface";
|
||||
import { Portofolio_funEditMedsosById } from "../../fun/edit/fun_edit_medsos_bisnis_by_id";
|
||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/component_global/notif_global/notifikasi_peringatan";
|
||||
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
|
||||
|
||||
export default function Portofolio_EditMedsosBisnis({
|
||||
dataMedsos,
|
||||
}: {
|
||||
dataMedsos: MODEL_PORTOFOLIO_MEDSOS;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [medsos, setMedsos] = useState(dataMedsos);
|
||||
return (
|
||||
<>
|
||||
<pre>{JSON.stringify(dataMedsos, null, 2)}</pre>
|
||||
<Paper shadow="lg" p={"sm"}>
|
||||
<Stack px={"sm"}>
|
||||
<TextInput
|
||||
label="Facebook"
|
||||
value={medsos.facebook}
|
||||
placeholder="Facebook"
|
||||
onChange={(val) => {
|
||||
setMedsos({
|
||||
...medsos,
|
||||
facebook: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Instagram"
|
||||
value={medsos.instagram}
|
||||
placeholder="Instagram"
|
||||
onChange={(val) => {
|
||||
setMedsos({
|
||||
...medsos,
|
||||
instagram: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Tiktok"
|
||||
value={medsos.tiktok}
|
||||
placeholder="Tiktok"
|
||||
onChange={(val) => {
|
||||
setMedsos({
|
||||
...medsos,
|
||||
tiktok: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Twitter"
|
||||
value={medsos.twitter}
|
||||
placeholder="Twitter"
|
||||
onChange={(val) => {
|
||||
setMedsos({
|
||||
...medsos,
|
||||
twitter: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Youtube"
|
||||
value={medsos.youtube}
|
||||
placeholder="Youtube"
|
||||
onChange={(val) => {
|
||||
setMedsos({
|
||||
...medsos,
|
||||
youtube: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
mt={"xl"}
|
||||
radius={"xl"}
|
||||
onClick={() => onUpdate(router, medsos)}
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function onUpdate(
|
||||
router: AppRouterInstance,
|
||||
medsos: MODEL_PORTOFOLIO_MEDSOS
|
||||
) {
|
||||
await Portofolio_funEditMedsosById(medsos).then((res) => {
|
||||
if (res.status === 200) {
|
||||
ComponentGlobal_NotifikasiBerhasil(res.message);
|
||||
router.back();
|
||||
} else {
|
||||
ComponentGlobal_NotifikasiGagal(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
21
src/app_modules/katalog/portofolio/edit/medsos/layout.tsx
Normal file
21
src/app_modules/katalog/portofolio/edit/medsos/layout.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import ComponentKatalog_HeaderTamplate from "@/app_modules/katalog/component/header_tamplate";
|
||||
import { AppShell } from "@mantine/core";
|
||||
import React from "react";
|
||||
|
||||
export default function LayoutPortofolio_EditMedsosBisnis({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<AppShell
|
||||
header={<ComponentKatalog_HeaderTamplate title="Edit Media Sosial" />}
|
||||
>
|
||||
{children}
|
||||
</AppShell>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { MODEL_PORTOFOLIO } from "../../model/interface";
|
||||
import fs from "fs";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export async function Portofolio_funDeletePortofolioById(
|
||||
data: MODEL_PORTOFOLIO
|
||||
) {
|
||||
const findLogo = await prisma.images.findFirst({
|
||||
where: {
|
||||
id: data.logoId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (findLogo) fs.unlinkSync(`./public/portofolio/logo/${findLogo.url}`);
|
||||
|
||||
const deleteLogo = await prisma.images.delete({
|
||||
where: {
|
||||
id: data.logoId,
|
||||
},
|
||||
});
|
||||
if (!deleteLogo) return { status: 400, message: "Gagal hapus data logo" };
|
||||
|
||||
const deletePortoMedsos = await prisma.portofolio_MediaSosial.delete({
|
||||
where: {
|
||||
portofolioId: data.id,
|
||||
},
|
||||
});
|
||||
if (!deletePortoMedsos)
|
||||
return { status: 400, message: "Gagal hapus data medsos" };
|
||||
|
||||
const deletePortofolio = await prisma.portofolio.delete({
|
||||
where: {
|
||||
id: data.id,
|
||||
},
|
||||
});
|
||||
if (!deletePortofolio)
|
||||
return { status: 400, message: "Gagal hapus portofolio" };
|
||||
revalidatePath("/dev/katalog");
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
message: "Berhasil hapus portofolio",
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { MODEL_PORTOFOLIO } from "../../model/interface";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export async function Portofolio_funEditDataBisnis(data: MODEL_PORTOFOLIO) {
|
||||
const res = await prisma.portofolio.update({
|
||||
where: {
|
||||
id: data.id,
|
||||
},
|
||||
data: {
|
||||
namaBisnis: data.namaBisnis,
|
||||
alamatKantor: data.alamatKantor,
|
||||
tlpn: data.tlpn,
|
||||
deskripsi: data.deskripsi,
|
||||
masterBidangBisnisId: data.MasterBidangBisnis.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!res) return { status: 400, message: "Gagal update" };
|
||||
revalidatePath("/dev/portofolio/main/")
|
||||
return {
|
||||
status: 200,
|
||||
message: "Update berhasil",
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import _ from "lodash";
|
||||
import { v4 } from "uuid";
|
||||
import fs from "fs";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export async function Portofolio_funEditLogoBisnisById(
|
||||
portoId: string,
|
||||
file: FormData
|
||||
) {
|
||||
const gambar: any = file.get("file");
|
||||
const fileName = gambar.name;
|
||||
const fileExtension = _.lowerCase(gambar.name.split(".").pop());
|
||||
const randomNameFile = v4(fileName) + "." + fileExtension;
|
||||
|
||||
const upload = await prisma.images.create({
|
||||
data: {
|
||||
url: randomNameFile,
|
||||
label: "PORTOFOLIO_LOGO",
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!upload) return { status: 400, message: "Gagal upload gambar" };
|
||||
const upload_toFolder = Buffer.from(await gambar.arrayBuffer());
|
||||
fs.writeFileSync(`./public/portofolio/logo/${upload.url}`, upload_toFolder);
|
||||
|
||||
const updatePorto = await prisma.portofolio.update({
|
||||
where: {
|
||||
id: portoId,
|
||||
},
|
||||
data: {
|
||||
logoId: upload.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!updatePorto) return { status: 200, message: "Update gagal" };
|
||||
revalidatePath("/dev/portofolio/edit/logo");
|
||||
revalidatePath("/dev/portofolio/main");
|
||||
return {
|
||||
status: 200,
|
||||
message: "Berhasil mengubah Logo Bisnis!",
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { MODEL_PORTOFOLIO_MEDSOS } from "../../model/interface";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export async function Portofolio_funEditMedsosById(
|
||||
data: MODEL_PORTOFOLIO_MEDSOS
|
||||
) {
|
||||
const res = await prisma.portofolio_MediaSosial.update({
|
||||
where: {
|
||||
id: data.id,
|
||||
},
|
||||
data: {
|
||||
facebook: data.facebook,
|
||||
instagram: data.instagram,
|
||||
tiktok: data.tiktok,
|
||||
twitter: data.twitter,
|
||||
youtube: data.youtube,
|
||||
},
|
||||
});
|
||||
|
||||
if (!res) return { status: 400, message: "Gagal update" };
|
||||
revalidatePath("/dev/portofolio/main");
|
||||
return {
|
||||
status: 200,
|
||||
message: "Berhasil update",
|
||||
};
|
||||
}
|
||||
@@ -1,32 +1,70 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { MODEL_PORTOFOLIO } from "@/app_modules/models/portofolio";
|
||||
import { MODEL_PORTOFOLIO_OLD } from "@/app_modules/models/portofolio";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { MODEL_PORTOFOLIO, MODEL_PORTOFOLIO_MEDSOS } from "../model/interface";
|
||||
import _ from "lodash";
|
||||
import { v4 } from "uuid";
|
||||
import fs from "fs";
|
||||
|
||||
export default async function funCreatePortofolio(data: MODEL_PORTOFOLIO) {
|
||||
console.log(data);
|
||||
export default async function funCreatePortofolio(
|
||||
profileId: string,
|
||||
data: MODEL_PORTOFOLIO,
|
||||
file: FormData,
|
||||
medsos: MODEL_PORTOFOLIO_MEDSOS
|
||||
) {
|
||||
const gambar: any = file.get("file");
|
||||
const fileName = gambar.name;
|
||||
const fileExtension = _.lowerCase(gambar.name.split(".").pop());
|
||||
const fRandomName = v4(fileName) + "." + fileExtension;
|
||||
|
||||
const res = await prisma.katalog.create({
|
||||
const upload = await prisma.images.create({
|
||||
data: {
|
||||
profileId: data.profileId,
|
||||
url: fRandomName,
|
||||
label: "PORTOFOLIO_LOGO",
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!upload) return { status: 400, message: "Gagal upload logo portofolio" };
|
||||
const upload_Folder = Buffer.from(await gambar.arrayBuffer());
|
||||
fs.writeFileSync(`./public/portofolio/logo/${upload.url}`, upload_Folder);
|
||||
|
||||
const createProto = await prisma.portofolio.create({
|
||||
data: {
|
||||
profileId: profileId,
|
||||
namaBisnis: data.namaBisnis,
|
||||
deskripsi: data.deskripsi,
|
||||
tlpn: data.tlpn,
|
||||
alamatKantor: data.alamatKantor,
|
||||
masterBidangBisnisId: data.masterBidangBisnisId,
|
||||
logoId: upload.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!res)
|
||||
return {
|
||||
status: 401,
|
||||
success: false,
|
||||
};
|
||||
if (!createProto) return { status: 400, message: "Gagal membuat portofolio" };
|
||||
|
||||
revalidatePath(`/dev/katalog/${data.profileId}`);
|
||||
const createMedsos = await prisma.portofolio_MediaSosial.create({
|
||||
data: {
|
||||
portofolioId: createProto.id,
|
||||
facebook: medsos.facebook,
|
||||
instagram: medsos.instagram,
|
||||
tiktok: medsos.tiktok,
|
||||
twitter: medsos.twitter,
|
||||
youtube: medsos.youtube,
|
||||
},
|
||||
});
|
||||
|
||||
if (!createMedsos)
|
||||
return { status: 400, message: "Gagal menambahkan medsos" };
|
||||
|
||||
revalidatePath(`/dev/katalog`);
|
||||
return {
|
||||
status: 201,
|
||||
success: true,
|
||||
message: "Berhasil menambahakan portofolio",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import toast from "react-simple-toasts";
|
||||
import { funGetListPortofolio } from "./get_list_portofolio";
|
||||
import { funGetListPortofolio } from "./get/get_list_portofolio";
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -3,18 +3,13 @@
|
||||
import prisma from "@/app/lib/prisma";
|
||||
|
||||
export async function funGetListPortofolio(profileId: any) {
|
||||
const data = await prisma.katalog.findMany({
|
||||
const data = await prisma.portofolio.findMany({
|
||||
where: {
|
||||
profileId: profileId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
namaBisnis: true,
|
||||
alamatKantor: true,
|
||||
tlpn: true,
|
||||
deskripsi: true,
|
||||
masterBidangBisnisId: true,
|
||||
active: true,
|
||||
profileId: true
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
|
||||
export async function Portofolio_geOnetMedsosById(portoId: string) {
|
||||
const data = await prisma.portofolio_MediaSosial.findFirst({
|
||||
where: {
|
||||
portofolioId: portoId,
|
||||
},
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
|
||||
export async function getOnePortofolio(id: string) {
|
||||
export async function Portofolio_getOneById(portoId: string) {
|
||||
// console.log(id)
|
||||
const data = await prisma.katalog.findUnique({
|
||||
const data = await prisma.portofolio.findUnique({
|
||||
where: {
|
||||
id: id,
|
||||
id: portoId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
@@ -15,6 +15,10 @@ export async function getOnePortofolio(id: string) {
|
||||
deskripsi: true,
|
||||
tlpn: true,
|
||||
active: true,
|
||||
profileId: true,
|
||||
Logo: true,
|
||||
logoId: true,
|
||||
masterBidangBisnisId: true,
|
||||
MasterBidangBisnis: {
|
||||
select: {
|
||||
id: true,
|
||||
@@ -22,7 +26,11 @@ export async function getOnePortofolio(id: string) {
|
||||
active: true,
|
||||
},
|
||||
},
|
||||
profileId: true,
|
||||
Portofolio_MediaSosial: true,
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
"use server"
|
||||
|
||||
import { myConsole } from "@/app/fun/my_console"
|
||||
import prisma from "@/app/lib/prisma"
|
||||
|
||||
export async function getBidangBisnis() {
|
||||
const data = await prisma.masterBidangBisnis.findMany()
|
||||
return data
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
"use server";
|
||||
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
import prisma from "@/app/lib/prisma";
|
||||
|
||||
export async function Portofolio_getMasterBidangBisnis() {
|
||||
const data = await prisma.masterBidangBisnis.findMany();
|
||||
return data;
|
||||
}
|
||||
@@ -3,5 +3,25 @@ import CreatePortofolioLayout from "./create/layout";
|
||||
import ListPortofolioView from "./list_view/view";
|
||||
import PortofolioLayout from "./main/layout";
|
||||
import ViewPortofolio from "./main/view";
|
||||
import Portofolio_EditDataBisnis from "./edit/data";
|
||||
import Portofolio_EditLogoBisnis from "./edit/logo";
|
||||
import Portofolio_EditMedsosBisnis from "./edit/medsos";
|
||||
import LayoutPortofolio_EditBisnis from "./edit/layout";
|
||||
import LayoutPortofolio_EditDataBisnis from "./edit/data/layout";
|
||||
import LayoutPortofolio_EditLogoBisnis from "./edit/logo/layout";
|
||||
import LayoutPortofolio_EditMedsosBisnis from "./edit/medsos/layout";
|
||||
|
||||
export {CreatePortofolio, CreatePortofolioLayout, ListPortofolioView, PortofolioLayout, ViewPortofolio}
|
||||
export {
|
||||
CreatePortofolio,
|
||||
CreatePortofolioLayout,
|
||||
ListPortofolioView,
|
||||
PortofolioLayout,
|
||||
ViewPortofolio,
|
||||
Portofolio_EditDataBisnis,
|
||||
Portofolio_EditLogoBisnis,
|
||||
Portofolio_EditMedsosBisnis,
|
||||
LayoutPortofolio_EditBisnis,
|
||||
LayoutPortofolio_EditDataBisnis,
|
||||
LayoutPortofolio_EditLogoBisnis,
|
||||
LayoutPortofolio_EditMedsosBisnis,
|
||||
};
|
||||
|
||||
@@ -1,44 +1,78 @@
|
||||
"use client";
|
||||
import { Box, Center, Grid, Paper, Text, Title } from "@mantine/core";
|
||||
import {
|
||||
ActionIcon,
|
||||
Box,
|
||||
Center,
|
||||
Grid,
|
||||
Group,
|
||||
Paper,
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { useState } from "react";
|
||||
import _ from "lodash";
|
||||
import { IconCaretRightFilled } from "@tabler/icons-react";
|
||||
import { loadDataProfile } from "../../profile/fun/fun_get_profile";
|
||||
import { useAtom } from "jotai";
|
||||
import { gs_profile } from "../../profile/state/global_state";
|
||||
import { gs_ListPortofolio } from "../state/global_state";
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
import { getProfile } from "../../profile";
|
||||
import {
|
||||
IconCaretRightFilled,
|
||||
IconCirclePlus,
|
||||
IconPencilPlus,
|
||||
} from "@tabler/icons-react";
|
||||
|
||||
import { LIST_PORTOFOLIO } from "@/app_modules/models/portofolio";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { RouterPortofolio } from "@/app/lib/router_hipmi/router_katalog";
|
||||
import { Warna } from "@/app/lib/warna";
|
||||
import { MODEL_PROFILE } from "../../profile/model/interface";
|
||||
|
||||
export default function ListPortofolioView({
|
||||
listPorto,
|
||||
profile,
|
||||
userLoginId,
|
||||
}: {
|
||||
listPorto: LIST_PORTOFOLIO;
|
||||
listPorto: LIST_PORTOFOLIO[];
|
||||
profile: MODEL_PROFILE;
|
||||
userLoginId: string;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [porto, setPorto] = useState(listPorto);
|
||||
return (
|
||||
<>
|
||||
{/* <pre>{JSON.stringify(porto, null, 2)}</pre> */}
|
||||
<Center>
|
||||
<Title order={4}>Portofolio</Title>
|
||||
</Center>
|
||||
<Box mt={"md"}>
|
||||
{(() => {
|
||||
if (porto) {
|
||||
return (
|
||||
<>
|
||||
{" "}
|
||||
{_.map(porto as any).map((e: any) => (
|
||||
<Paper p={"sm"} shadow="lg" withBorder bg={"gray.1"}>
|
||||
<Stack spacing={"md"}>
|
||||
<Group position="apart">
|
||||
<ActionIcon variant="transparent" disabled></ActionIcon>
|
||||
<Title order={4}>Portofolio</Title>
|
||||
{profile.User.id === userLoginId ? (
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
onClick={() =>
|
||||
router.push(RouterPortofolio.create + `${profile.id}`)
|
||||
}
|
||||
>
|
||||
<IconPencilPlus color={Warna.biru} />
|
||||
</ActionIcon>
|
||||
) : (
|
||||
<ActionIcon variant="transparent" disabled></ActionIcon>
|
||||
)}
|
||||
</Group>
|
||||
<Box>
|
||||
{_.isEmpty(porto) ? (
|
||||
<Center>
|
||||
<Text fs={"italic"} fz={"xs"}>
|
||||
- Belum Ada Portofolio -
|
||||
</Text>
|
||||
</Center>
|
||||
) : (
|
||||
<Box>
|
||||
{porto.map((e: any) => (
|
||||
<Paper
|
||||
key={e.id}
|
||||
h={50}
|
||||
bg={"gray"}
|
||||
my={"md"}
|
||||
radius={50}
|
||||
mb={"lg"}
|
||||
radius={"md"}
|
||||
onClick={() => router.push(`/dev/portofolio/main/${e.id}/`)}
|
||||
>
|
||||
<Grid h={50} align="center" px={"md"}>
|
||||
@@ -51,13 +85,11 @@ export default function ListPortofolioView({
|
||||
</Grid>
|
||||
</Paper>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return <></>;
|
||||
}
|
||||
})()}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,31 +1,89 @@
|
||||
"use client";
|
||||
|
||||
import { ActionIcon, AppShell } from "@mantine/core";
|
||||
import {
|
||||
ActionIcon,
|
||||
AppShell,
|
||||
Button,
|
||||
Group,
|
||||
Header,
|
||||
Modal,
|
||||
Stack,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import HeaderTransparent from "../../component/header_transparent";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
import { IconArrowLeft, IconEdit } from "@tabler/icons-react";
|
||||
import { IconArrowLeft, IconChevronLeft, IconEdit } from "@tabler/icons-react";
|
||||
import ComponentKatalog_HeaderTamplate from "../../component/header_tamplate";
|
||||
import { title } from "process";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import { RouterPortofolio } from "@/app/lib/router_hipmi/router_katalog";
|
||||
|
||||
export default function PortofolioLayout({ children, profileId }: { children: any, profileId: any }) {
|
||||
export default function PortofolioLayout({
|
||||
children,
|
||||
portoId,
|
||||
}: {
|
||||
children: any;
|
||||
portoId: any;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
return (
|
||||
<>
|
||||
<AppShell
|
||||
header={
|
||||
<HeaderTransparent
|
||||
route={`/dev/katalog/${profileId}`}
|
||||
title="Portofolio"
|
||||
icon2={
|
||||
<Header height={50} sx={{ borderStyle: "none" }}>
|
||||
<Group h={50} position="apart" px={"md"}>
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
onClick={() => router.push("/dev/portofolio/edit")}
|
||||
onClick={() => {
|
||||
router.back();
|
||||
}}
|
||||
>
|
||||
<IconChevronLeft />
|
||||
</ActionIcon>
|
||||
<Title order={5}>Detail Portofolio</Title>
|
||||
<ActionIcon variant="transparent" onClick={() => open()}>
|
||||
<IconEdit />
|
||||
</ActionIcon>
|
||||
}
|
||||
/>
|
||||
</Group>
|
||||
</Header>
|
||||
}
|
||||
>
|
||||
<Modal opened={opened} onClose={close} centered withCloseButton={false}>
|
||||
<Stack>
|
||||
<Title order={6}>Anda ingin mengupdate Detail Bisnis ?</Title>
|
||||
<Button
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
router.push(RouterPortofolio.edit_data_bisnis + `${portoId}`);
|
||||
}}
|
||||
>
|
||||
Data Bisnis
|
||||
</Button>
|
||||
<Button
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
color="green"
|
||||
onClick={() => {
|
||||
router.push(RouterPortofolio.edit_logo_bisnis + `${portoId}`);
|
||||
}}
|
||||
>
|
||||
Logo Bisnis
|
||||
</Button>
|
||||
<Button
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
color="orange"
|
||||
onClick={() => {
|
||||
router.push(RouterPortofolio.edit_medsos_bisnis + `${portoId}`);
|
||||
}}
|
||||
>
|
||||
Media Sosial
|
||||
</Button>
|
||||
</Stack>
|
||||
</Modal>
|
||||
{children}
|
||||
</AppShell>
|
||||
</>
|
||||
|
||||
@@ -1,11 +1,50 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
RouterPortofolio,
|
||||
RouterProfile,
|
||||
} from "@/app/lib/router_hipmi/router_katalog";
|
||||
import { Warna } from "@/app/lib/warna";
|
||||
import { MODEL_PORTOFOLIO } from "@/app_modules/models/portofolio";
|
||||
import { Box, Button, Center, Text, Title } from "@mantine/core";
|
||||
import { IconTrash } from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { MODEL_PORTOFOLIO_OLD } from "@/app_modules/models/portofolio";
|
||||
import {
|
||||
AspectRatio,
|
||||
Box,
|
||||
Button,
|
||||
Center,
|
||||
Grid,
|
||||
Group,
|
||||
Image,
|
||||
Modal,
|
||||
Paper,
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import {
|
||||
IconBrandFacebook,
|
||||
IconBrandInstagram,
|
||||
IconBrandTiktok,
|
||||
IconBrandTwitter,
|
||||
IconBrandYoutube,
|
||||
IconBuilding,
|
||||
IconBuildingSkyscraper,
|
||||
IconListDetails,
|
||||
IconMapPin,
|
||||
IconNotes,
|
||||
IconPhoneCall,
|
||||
IconPinned,
|
||||
IconTrash,
|
||||
} from "@tabler/icons-react";
|
||||
import { redirect, useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { MODEL_PORTOFOLIO } from "../model/interface";
|
||||
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
|
||||
import { Portofolio_getOneById } from "../fun/get/get_one_portofolio";
|
||||
import _ from "lodash";
|
||||
import { Portofolio_funDeletePortofolioById } from "../fun/delete/fun_delete_by_id";
|
||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
|
||||
|
||||
export default function ViewPortofolio({
|
||||
dataPorto,
|
||||
@@ -14,21 +53,178 @@ export default function ViewPortofolio({
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [porto, setPorto] = useState(dataPorto);
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box>
|
||||
<Text>{porto.namaBisnis}</Text>
|
||||
<Text>{porto.alamatKantor}</Text>
|
||||
<Text>+{porto.tlpn}</Text>
|
||||
<Text>{porto.deskripsi}</Text>
|
||||
<Text>{porto.MasterBidangBisnis.name}</Text>
|
||||
</Box>
|
||||
<Center mt={"md"}>
|
||||
<Button bg={"red"} color="red" w={300} onClick={() => {}}>
|
||||
{/* <pre>{JSON.stringify(porto, null, 2)}</pre> */}
|
||||
<Stack>
|
||||
<Paper p={"sm"} withBorder shadow="lg">
|
||||
<Title order={6}>Data Bisnis</Title>
|
||||
<Stack p={"sm"}>
|
||||
<Grid>
|
||||
<Grid.Col span={2}>
|
||||
<IconBuildingSkyscraper />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text truncate>{dataPorto.namaBisnis}</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>
|
||||
<Grid>
|
||||
<Grid.Col span={2}>
|
||||
<IconListDetails />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text>{dataPorto.MasterBidangBisnis.name}</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Grid.Col span={2}>
|
||||
<IconPinned />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text>{dataPorto.deskripsi}</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Stack>
|
||||
</Paper>
|
||||
<Paper p={"sm"} withBorder shadow="lg">
|
||||
<Title order={6}>Logo Bisnis</Title>
|
||||
|
||||
<AspectRatio ratio={1 / 1}>
|
||||
<Paper>
|
||||
<Image
|
||||
alt="Foto"
|
||||
src={RouterPortofolio.api_logo_porto + `${dataPorto.logoId}`}
|
||||
/>
|
||||
</Paper>
|
||||
</AspectRatio>
|
||||
</Paper>
|
||||
<Paper p={"sm"} withBorder shadow="lg">
|
||||
<Title order={6}>Media Sosial Bisnis</Title>
|
||||
|
||||
<Stack p={"sm"}>
|
||||
<Grid>
|
||||
<Grid.Col span={2}>
|
||||
<IconBrandFacebook />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
{dataPorto.Portofolio_MediaSosial.facebook ? (
|
||||
<Text>{dataPorto.Portofolio_MediaSosial.facebook}</Text>
|
||||
) : (
|
||||
"-"
|
||||
)}
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Grid.Col span={2}>
|
||||
<IconBrandInstagram />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
{dataPorto.Portofolio_MediaSosial.instagram ? (
|
||||
<Text>{dataPorto.Portofolio_MediaSosial.instagram}</Text>
|
||||
) : (
|
||||
"-"
|
||||
)}
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Grid.Col span={2}>
|
||||
<IconBrandTiktok />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
{dataPorto.Portofolio_MediaSosial.tiktok ? (
|
||||
<Text>{dataPorto.Portofolio_MediaSosial.tiktok}</Text>
|
||||
) : (
|
||||
"-"
|
||||
)}
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Grid.Col span={2}>
|
||||
<IconBrandTwitter />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
{dataPorto.Portofolio_MediaSosial.twitter ? (
|
||||
<Text>{dataPorto.Portofolio_MediaSosial.twitter}</Text>
|
||||
) : (
|
||||
"-"
|
||||
)}
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Grid.Col span={2}>
|
||||
<IconBrandYoutube />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
{dataPorto.Portofolio_MediaSosial.youtube ? (
|
||||
<Text>{dataPorto.Portofolio_MediaSosial.youtube}</Text>
|
||||
) : (
|
||||
"-"
|
||||
)}
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Stack>
|
||||
</Paper>
|
||||
<Button
|
||||
radius={"xl"}
|
||||
bg={"red"}
|
||||
color="red"
|
||||
onClick={() => {
|
||||
open();
|
||||
}}
|
||||
>
|
||||
<IconTrash />
|
||||
</Button>{" "}
|
||||
</Center>
|
||||
</Button>
|
||||
</Stack>
|
||||
|
||||
<Modal opened={opened} onClose={close} centered withCloseButton={false}>
|
||||
<Stack>
|
||||
<Title order={6}>Anda yakin menghapus portofolio ini ?</Title>
|
||||
<Group position="center">
|
||||
<Button radius={"xl"} onClick={() => close()}>
|
||||
Batal
|
||||
</Button>
|
||||
<Button
|
||||
radius={"xl"}
|
||||
color="red"
|
||||
onClick={() => onDelete(router, dataPorto as any)}
|
||||
>
|
||||
Hapus
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function onDelete(
|
||||
router: AppRouterInstance,
|
||||
dataPorto: MODEL_PORTOFOLIO
|
||||
) {
|
||||
await Portofolio_funDeletePortofolioById(dataPorto).then((res) => {
|
||||
if (res.status === 200) {
|
||||
ComponentGlobal_NotifikasiBerhasil(res.message);
|
||||
router.push(RouterProfile.katalog + `${dataPorto.profileId}`);
|
||||
} else {
|
||||
ComponentGlobal_NotifikasiGagal(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
35
src/app_modules/katalog/portofolio/model/interface.ts
Normal file
35
src/app_modules/katalog/portofolio/model/interface.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { MODEL_IMAGES } from "@/app_modules/models/interface";
|
||||
|
||||
export interface MODEL_PORTOFOLIO {
|
||||
id: string;
|
||||
namaBisnis: string;
|
||||
alamatKantor: string;
|
||||
deskripsi: string;
|
||||
tlpn: string;
|
||||
active: boolean;
|
||||
MasterBidangBisnis: MODEL_PORTOFOLIO_BIDANG_BISNIS;
|
||||
masterBidangBisnisId: string;
|
||||
profileId: string;
|
||||
Logo: MODEL_IMAGES;
|
||||
logoId: string;
|
||||
Portofolio_MediaSosial: MODEL_PORTOFOLIO_MEDSOS
|
||||
}
|
||||
|
||||
export interface MODEL_PORTOFOLIO_BIDANG_BISNIS {
|
||||
id: string;
|
||||
name: string;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
export interface MODEL_PORTOFOLIO_MEDSOS {
|
||||
id: string
|
||||
facebook: string
|
||||
twitter: string
|
||||
instagram: string
|
||||
tiktok: string;
|
||||
youtube:string
|
||||
active: boolean
|
||||
createdAt: Date
|
||||
updatedAt:Date
|
||||
portofolioId: string
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
"use server";
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
import prisma from "@/app/lib/prisma";
|
||||
|
||||
export async function getFotoProfile(id: any) {
|
||||
const imgUrl = await prisma.images.findUnique({
|
||||
where: {
|
||||
id: id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
return imgUrl;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
"use server";
|
||||
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { getToken } from "@/app_modules/home";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
|
||||
/**
|
||||
* @function api get data profile by user id
|
||||
* @returns data profile
|
||||
*/
|
||||
export async function getProfile() {
|
||||
const token = await getToken();
|
||||
|
||||
const dataProfile = await prisma.profile.findUnique({
|
||||
where: {
|
||||
userId: token.id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
alamat: true,
|
||||
jenisKelamin: true,
|
||||
active: true,
|
||||
imagesId: true,
|
||||
User: {
|
||||
select : {
|
||||
username: true,
|
||||
nomor: true
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return dataProfile;
|
||||
}
|
||||
@@ -18,7 +18,7 @@ export default function ProfileLayout({ children }: { children: any }) {
|
||||
<AppShell
|
||||
|
||||
header={
|
||||
<Header height={50} px={"sm"}>
|
||||
<Header height={50} px={"sm"} sx={{borderBlockStyle: "none"}}>
|
||||
<Group position="apart" h={50}>
|
||||
<ActionIcon variant="transparent" onClick={() => router.push("/dev/home")}>
|
||||
<IconArrowLeft />
|
||||
|
||||
@@ -3,17 +3,40 @@
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
import { ApiHipmi } from "@/app/lib/api";
|
||||
import { Warna } from "@/app/lib/warna";
|
||||
import { gs_token } from "@/app_modules/home/state/global_state";
|
||||
import { Button, Select, Stack, TextInput } from "@mantine/core";
|
||||
import {
|
||||
AspectRatio,
|
||||
Avatar,
|
||||
Box,
|
||||
Button,
|
||||
Center,
|
||||
FileButton,
|
||||
Image,
|
||||
Paper,
|
||||
Select,
|
||||
Stack,
|
||||
TextInput,
|
||||
} from "@mantine/core";
|
||||
import { useAtom } from "jotai";
|
||||
import _ from "lodash";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import toast from "react-simple-toasts";
|
||||
import funCreateNewProfile from "../fun/fun_create_profile";
|
||||
import { IconCamera } from "@tabler/icons-react";
|
||||
import ComponentKatalog_NotedBox from "../../component/noted_box";
|
||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import { MODEL_PROFILE } from "../model/interface";
|
||||
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/component_global/notif_global/notifikasi_peringatan";
|
||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
||||
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
|
||||
|
||||
export default function CreateProfile({ userId }: { userId: any }) {
|
||||
const router = useRouter();
|
||||
const [filePP, setFilePP] = useState<File | null>(null);
|
||||
const [imgPP, setImgPP] = useState<any | null>();
|
||||
const [fileBG, setFileBG] = useState<File | null>(null);
|
||||
const [imgBG, setImgBG] = useState<any | null>();
|
||||
|
||||
const [value, setValue] = useState({
|
||||
name: "",
|
||||
@@ -22,33 +45,108 @@ export default function CreateProfile({ userId }: { userId: any }) {
|
||||
jenisKelamin: "",
|
||||
});
|
||||
|
||||
async function onSubmit() {
|
||||
const body = {
|
||||
userId: userId,
|
||||
name: value.name,
|
||||
email: value.email,
|
||||
alamat: value.alamat,
|
||||
jenisKelamin: value.jenisKelamin,
|
||||
};
|
||||
|
||||
myConsole(body);
|
||||
|
||||
if (_.values(value).includes("")) return toast("Lengkapi data");
|
||||
// if(_.values(value.email).includes(`${/^\S+@\S+$/.test(value.email) ? null : "Invalid email"}`)){}
|
||||
|
||||
await funCreateNewProfile(body).then((res) => {
|
||||
if (res.status === 201) {
|
||||
toast("Data tersimpan");
|
||||
return router.push(`/dev/katalog/${userId}`);
|
||||
} else {
|
||||
toast("Gagal")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack px={"sm"}>
|
||||
<Stack px={"sm"} spacing={"xl"}>
|
||||
<Box>
|
||||
<Stack>
|
||||
<ComponentKatalog_NotedBox informasi="Upload foto profile anda." />
|
||||
<Center>
|
||||
<Avatar
|
||||
sx={{
|
||||
borderStyle: "solid",
|
||||
borderColor: "black",
|
||||
borderWidth: "1px",
|
||||
}}
|
||||
src={imgPP ? imgPP : "/aset/global/avatar.png"}
|
||||
size={150}
|
||||
radius={"100%"}
|
||||
/>
|
||||
</Center>
|
||||
<Center>
|
||||
<FileButton
|
||||
onChange={async (files: any | null) => {
|
||||
try {
|
||||
const buffer = URL.createObjectURL(
|
||||
new Blob([new Uint8Array(await files.arrayBuffer())])
|
||||
);
|
||||
// console.log(buffer, "ini buffer");
|
||||
// console.log(files, " ini file");
|
||||
setImgPP(buffer);
|
||||
setFilePP(files);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}}
|
||||
accept="image/png,image/jpeg"
|
||||
>
|
||||
{(props) => (
|
||||
<Button
|
||||
{...props}
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
w={150}
|
||||
leftIcon={<IconCamera />}
|
||||
compact
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
)}
|
||||
</FileButton>
|
||||
</Center>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Stack>
|
||||
<ComponentKatalog_NotedBox informasi="Upload foto latar belakang profile anda." />
|
||||
<AspectRatio ratio={16 / 9}>
|
||||
<Paper
|
||||
radius={"md"}
|
||||
sx={{
|
||||
borderStyle: "solid",
|
||||
borderColor: "black",
|
||||
borderWidth: "1px",
|
||||
}}
|
||||
>
|
||||
<Image alt="Foto" src={imgBG ? imgBG : "/aset/no-img.png"} />
|
||||
</Paper>
|
||||
</AspectRatio>
|
||||
|
||||
<Center>
|
||||
<FileButton
|
||||
onChange={async (files: any | null) => {
|
||||
try {
|
||||
const buffer = URL.createObjectURL(
|
||||
new Blob([new Uint8Array(await files.arrayBuffer())])
|
||||
);
|
||||
// console.log(buffer, "ini buffer");
|
||||
// console.log(files, " ini file");
|
||||
setImgBG(buffer);
|
||||
setFileBG(files);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}}
|
||||
accept="image/png,image/jpeg"
|
||||
>
|
||||
{(props) => (
|
||||
<Button
|
||||
{...props}
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
w={150}
|
||||
leftIcon={<IconCamera />}
|
||||
compact
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
)}
|
||||
</FileButton>
|
||||
</Center>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
<TextInput
|
||||
label="Nama"
|
||||
onChange={(val) => {
|
||||
@@ -94,7 +192,9 @@ export default function CreateProfile({ userId }: { userId: any }) {
|
||||
radius={50}
|
||||
bg={Warna.hijau_muda}
|
||||
color="green"
|
||||
onClick={() => onSubmit()}
|
||||
onClick={() =>
|
||||
onSubmit(router, value as any, userId, filePP as any, fileBG as any)
|
||||
}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
@@ -102,3 +202,41 @@ export default function CreateProfile({ userId }: { userId: any }) {
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function onSubmit(
|
||||
router: AppRouterInstance,
|
||||
value: MODEL_PROFILE,
|
||||
userId: string,
|
||||
filePP: FormData,
|
||||
fileBg: FormData
|
||||
) {
|
||||
const body = {
|
||||
userId: userId,
|
||||
name: value.name,
|
||||
email: value.email,
|
||||
alamat: value.alamat,
|
||||
jenisKelamin: value.jenisKelamin,
|
||||
};
|
||||
if(_.values(body).includes("")) return ComponentGlobal_NotifikasiPeringatan("Lengkapi Data")
|
||||
|
||||
const gambarPP = new FormData();
|
||||
gambarPP.append("filePP", filePP as any);
|
||||
|
||||
const gambarBG = new FormData();
|
||||
gambarBG.append("fileBG", fileBg as any);
|
||||
|
||||
|
||||
if(!gambarPP) return ComponentGlobal_NotifikasiPeringatan("Lengkapi foto profile")
|
||||
if(!gambarBG) return ComponentGlobal_NotifikasiPeringatan("Lengkapi background profile")
|
||||
|
||||
|
||||
await funCreateNewProfile(body as any, gambarPP, gambarBG).then((res) => {
|
||||
if (res.status === 201) {
|
||||
ComponentGlobal_NotifikasiBerhasil("Berhasil Membuat Profile")
|
||||
router.push(RouterProfile.katalog + `${userId}`);
|
||||
} else {
|
||||
ComponentGlobal_NotifikasiGagal(res.message);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -10,24 +10,20 @@ import {
|
||||
} from "@mantine/core";
|
||||
import { IconArrowLeft } from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import ComponentKatalog_HeaderTamplate from "../../component/header_tamplate";
|
||||
|
||||
export default function EditProfileLayout({ children, profileId }: { children: any, profileId: any }) {
|
||||
const router = useRouter()
|
||||
export default function EditProfileLayout({
|
||||
children,
|
||||
profileId,
|
||||
}: {
|
||||
children: any;
|
||||
profileId: any;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
<AppShell
|
||||
|
||||
header={
|
||||
<Header height={50} px={"sm"}>
|
||||
<Group position="apart" h={50}>
|
||||
<ActionIcon variant="transparent" onClick={() => router.push(`/dev/katalog/${profileId}`)}>
|
||||
<IconArrowLeft />
|
||||
</ActionIcon>
|
||||
<Text>Edit Profile</Text>
|
||||
<ActionIcon variant="transparent"></ActionIcon>
|
||||
</Group>
|
||||
</Header>
|
||||
}
|
||||
header={<ComponentKatalog_HeaderTamplate title="Edit Profile" />}
|
||||
>
|
||||
{children}
|
||||
</AppShell>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
import { ApiHipmi } from "@/app/lib/api";
|
||||
import { Warna } from "@/app/lib/warna";
|
||||
import { gs_token } from "@/app_modules/home/state/global_state";
|
||||
import { Button, Loader, Select, Stack, TextInput } from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { useAtom } from "jotai";
|
||||
@@ -11,12 +10,15 @@ import _ from "lodash";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import toast from "react-simple-toasts";
|
||||
import { gs_profile } from "../state/global_state";
|
||||
import { loadDataProfile } from "../fun/fun_get_profile";
|
||||
import { MODEL_User_profile } from "@/app_modules/home/models/user_profile";
|
||||
import funEditProfile from "../fun/fun_edit_profile";
|
||||
|
||||
export default function EditProfile({ data }: { data: MODEL_User_profile }) {
|
||||
import funEditProfile from "../fun/fun_edit_profile";
|
||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
||||
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
|
||||
import { MODEL_PROFILE } from "../model/interface";
|
||||
import { Profile_funEditById } from "../fun/update/fun_edit_profile_by_id";
|
||||
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||
|
||||
export default function EditProfile({ data }: { data: MODEL_PROFILE }) {
|
||||
const router = useRouter();
|
||||
|
||||
//Get data profile
|
||||
@@ -26,12 +28,12 @@ export default function EditProfile({ data }: { data: MODEL_User_profile }) {
|
||||
const body = dataProfile;
|
||||
if (_.values(body).includes("")) return toast("Lengkapi data");
|
||||
|
||||
await funEditProfile(body).then((res) => {
|
||||
await Profile_funEditById(body).then((res) => {
|
||||
if (res.status === 200) {
|
||||
toast("Update berhasil");
|
||||
setTimeout(() => router.push(`/dev/katalog/${data.Profile?.id}`), 1000);
|
||||
ComponentGlobal_NotifikasiBerhasil(res.message);
|
||||
setTimeout(() => router.back(), 1000)
|
||||
} else {
|
||||
toast("Gagal update");
|
||||
ComponentGlobal_NotifikasiGagal(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -46,20 +48,21 @@ export default function EditProfile({ data }: { data: MODEL_User_profile }) {
|
||||
return (
|
||||
<>
|
||||
<Stack px={"sm"}>
|
||||
<TextInput label="Username" disabled value={dataProfile.username} />
|
||||
<TextInput label="Nomor" disabled value={dataProfile.nomor} />
|
||||
<TextInput
|
||||
label="Username"
|
||||
disabled
|
||||
value={dataProfile.User.username}
|
||||
/>
|
||||
<TextInput label="Nomor" disabled value={dataProfile.User.nomor} />
|
||||
|
||||
<TextInput
|
||||
label="Nama"
|
||||
placeholder="username"
|
||||
value={dataProfile.Profile?.name}
|
||||
placeholder="Nama"
|
||||
value={dataProfile.name}
|
||||
onChange={(val) => {
|
||||
setDataProfile({
|
||||
...(dataProfile as any),
|
||||
Profile: {
|
||||
...dataProfile.Profile,
|
||||
name: val.target.value,
|
||||
},
|
||||
...dataProfile,
|
||||
name: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
@@ -67,14 +70,11 @@ export default function EditProfile({ data }: { data: MODEL_User_profile }) {
|
||||
<TextInput
|
||||
label="Email"
|
||||
placeholder="email"
|
||||
value={dataProfile.Profile?.email}
|
||||
value={dataProfile.email}
|
||||
onChange={(val) => {
|
||||
setDataProfile({
|
||||
...(dataProfile as any),
|
||||
Profile: {
|
||||
...dataProfile.Profile,
|
||||
email: val.target.value,
|
||||
},
|
||||
...dataProfile,
|
||||
email: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
@@ -82,32 +82,26 @@ export default function EditProfile({ data }: { data: MODEL_User_profile }) {
|
||||
<TextInput
|
||||
label="Alamat"
|
||||
placeholder="alamat"
|
||||
value={dataProfile.Profile?.alamat}
|
||||
value={dataProfile.alamat}
|
||||
onChange={(val) => {
|
||||
setDataProfile({
|
||||
...(dataProfile as any),
|
||||
Profile: {
|
||||
...dataProfile.Profile,
|
||||
alamat: val.target.value,
|
||||
},
|
||||
...dataProfile,
|
||||
alamat: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
<Select
|
||||
label="Jenis Kelamin"
|
||||
value={dataProfile.Profile?.jenisKelamin}
|
||||
value={dataProfile.jenisKelamin}
|
||||
data={[
|
||||
{ value: "Laki-laki", label: "Laki-laki" },
|
||||
{ value: "Perempuan", label: "Perempuan" },
|
||||
]}
|
||||
onChange={(val) => {
|
||||
onChange={(val: any) => {
|
||||
setDataProfile({
|
||||
...(dataProfile as any),
|
||||
Profile: {
|
||||
...dataProfile.Profile,
|
||||
jenisKelamin: val,
|
||||
},
|
||||
...dataProfile,
|
||||
jenisKelamin: val
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -1,25 +1,88 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { MODEL_PROFILE } from "../model/interface";
|
||||
import _ from "lodash";
|
||||
import { v4 } from "uuid";
|
||||
import fs from "fs";
|
||||
|
||||
export default async function funCreateNewProfile(data: any) {
|
||||
// console.log(data);
|
||||
const body = data;
|
||||
export default async function funCreateNewProfile(
|
||||
req: MODEL_PROFILE,
|
||||
gambarPP: FormData,
|
||||
gambarBG: FormData
|
||||
) {
|
||||
const body = req;
|
||||
|
||||
const res = await prisma.profile.create({
|
||||
const findEmail = await prisma.profile.findUnique({
|
||||
where: {
|
||||
email: body.email,
|
||||
},
|
||||
});
|
||||
|
||||
if (findEmail) return { status: 400, message: "Email telah digunakan" };
|
||||
|
||||
const gambarProfile: any = gambarPP.get("filePP");
|
||||
const fileName = gambarProfile.name;
|
||||
const fileExtension = _.lowerCase(gambarProfile.name.split(".").pop());
|
||||
const fRandomName = v4(fileName) + "." + fileExtension;
|
||||
|
||||
const uploadPP = await prisma.images.create({
|
||||
data: {
|
||||
url: fRandomName,
|
||||
label: "PROFILE_FOTO",
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!uploadPP) return { status: 400, message: "Gagal upload foto profile" };
|
||||
const uploadPP_Folder = Buffer.from(await gambarProfile.arrayBuffer());
|
||||
fs.writeFileSync(`./public/profile/foto/${uploadPP.url}`, uploadPP_Folder);
|
||||
|
||||
const gambarBackground: any = gambarBG.get("fileBG");
|
||||
const fileNameBG = gambarBackground.name;
|
||||
const fileExtensionBG = _.lowerCase(gambarBackground.name.split(".").pop());
|
||||
const fRandomNameBG = v4(fileNameBG) + "." + fileExtensionBG;
|
||||
|
||||
const uploadBG = await prisma.imagesBackground.create({
|
||||
data: {
|
||||
url: fRandomNameBG,
|
||||
label: "PROFILE_BACKGROUND",
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!uploadBG)
|
||||
return { status: 400, message: "Gagal upload background profile" };
|
||||
const uploadBG_Folder = Buffer.from(await gambarBackground.arrayBuffer());
|
||||
fs.writeFileSync(
|
||||
`./public/profile/background/${uploadBG.url}`,
|
||||
uploadBG_Folder
|
||||
);
|
||||
|
||||
|
||||
|
||||
const createProfile = await prisma.profile.create({
|
||||
data: {
|
||||
userId: body.userId,
|
||||
name: body.name,
|
||||
email: body.email,
|
||||
alamat: body.alamat,
|
||||
jenisKelamin: body.jenisKelamin,
|
||||
imagesId: uploadPP.id,
|
||||
imagesBackgroundId: uploadBG.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!res) return { status: 400 };
|
||||
if (!createProfile) return { status: 400, message: "Gagal membuat profile" };
|
||||
|
||||
return {
|
||||
status: 201,
|
||||
success: true,
|
||||
message: "Berhasil",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { MODEL_User_profile } from "@/app_modules/home/models/user_profile";
|
||||
import { MODEL_PROFILE_OLD } from "@/app_modules/home/model/user_profile";
|
||||
|
||||
export default async function funEditProfile(data: MODEL_PROFILE_OLD) {
|
||||
// const cekEmail = await prisma.profile.findMany({
|
||||
// where: {
|
||||
// email: data.Profile.email
|
||||
// }
|
||||
// })
|
||||
|
||||
// if(cekEmail) return {status: 400, message: "Email sudah di gunakan"}
|
||||
|
||||
export default async function funEditProfile(data: MODEL_User_profile) {
|
||||
const res = await prisma.profile.update({
|
||||
where: {
|
||||
id: data.Profile?.id,
|
||||
@@ -16,10 +24,10 @@ export default async function funEditProfile(data: MODEL_User_profile) {
|
||||
},
|
||||
});
|
||||
|
||||
if (!res) return { status: 400 };
|
||||
if (!res) return { status: 400, message: "Gagal update" };
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
success: true,
|
||||
message: "Berhasil update",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
import { getProfile } from "..";
|
||||
|
||||
/**
|
||||
* @function get data profile
|
||||
* @param setProfile
|
||||
* @returns data profile
|
||||
*/
|
||||
export async function loadDataProfile(setProfile: any) {
|
||||
await getProfile()
|
||||
.then((res) => res)
|
||||
.then((val) => {
|
||||
setProfile(val);
|
||||
});
|
||||
}
|
||||
14
src/app_modules/katalog/profile/fun/get/get_one_profile.ts
Normal file
14
src/app_modules/katalog/profile/fun/get/get_one_profile.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
|
||||
export async function Profile_getOneById(profileId: string) {
|
||||
const data = await prisma.profile.findFirst({
|
||||
where: {
|
||||
id: profileId,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
|
||||
export async function Profile_getOneProfileAndUserById(profileId: string) {
|
||||
const data = await prisma.profile.findFirst({
|
||||
where: {
|
||||
id: profileId,
|
||||
},
|
||||
select: {
|
||||
userId: true,
|
||||
User: true,
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
alamat: true,
|
||||
jenisKelamin: true,
|
||||
imagesId: true,
|
||||
imagesBackgroundId: true,
|
||||
ImageProfile: true,
|
||||
ImagesBackground: true
|
||||
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
// console.log(data)
|
||||
return data;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { MODEL_PROFILE } from "../../model/interface";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export async function Profile_funEditById(data: MODEL_PROFILE) {
|
||||
const updt = await prisma.profile.update({
|
||||
where: {
|
||||
id: data.id,
|
||||
},
|
||||
data: {
|
||||
name: data.name,
|
||||
email: data.email,
|
||||
alamat: data.alamat,
|
||||
jenisKelamin: data.jenisKelamin,
|
||||
},
|
||||
});
|
||||
|
||||
if(!updt) return {status: 400, message: "Gagal update"}
|
||||
revalidatePath("/dev/katalog")
|
||||
return {
|
||||
status: 200,
|
||||
message: "Berhasil update"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
"use server";
|
||||
|
||||
import fs from "fs";
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import _ from "lodash";
|
||||
import { v4 } from "uuid";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export async function Profile_funUpdateBackground(profileId: string, file: FormData) {
|
||||
const findProfile = await prisma.profile.findFirst({
|
||||
where: {
|
||||
id: profileId,
|
||||
},
|
||||
});
|
||||
|
||||
const findBackground = await prisma.imagesBackground.findFirst({
|
||||
where: {
|
||||
id: findProfile?.imagesBackgroundId as string,
|
||||
},
|
||||
select: {
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
if (!findBackground) return { status: 400, message: "Foto tidak ditemukan" };
|
||||
if (findBackground) fs.unlinkSync(`./public/profile/background/${findBackground.url}`);
|
||||
|
||||
const gambarBackground: any = file.get("file");
|
||||
const fileName = gambarBackground.name;
|
||||
const fileExtension = _.lowerCase(gambarBackground.name.split(".").pop());
|
||||
const randomName = v4(fileName) + "." + fileExtension;
|
||||
|
||||
const uploadBG = await prisma.imagesBackground.update({
|
||||
where: {
|
||||
id: findProfile?.imagesBackgroundId as string,
|
||||
},
|
||||
data: {
|
||||
url: randomName,
|
||||
label: "PROFILE_BACKGROUND",
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!uploadBG) return { status: 400, message: "Gagal upload foto background" };
|
||||
const uploadPP_Folder = Buffer.from(await gambarBackground.arrayBuffer());
|
||||
fs.writeFileSync(`./public/profile/background/${uploadBG.url}`, uploadPP_Folder);
|
||||
revalidatePath("/dev/katalog");
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
message: "Update berhasil",
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
"use server";
|
||||
|
||||
import fs from "fs";
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import _ from "lodash";
|
||||
import { v4 } from "uuid";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export async function Profile_funUpdateFoto(profileId: string, file: FormData) {
|
||||
const findProfile = await prisma.profile.findFirst({
|
||||
where: {
|
||||
id: profileId,
|
||||
},
|
||||
});
|
||||
|
||||
const findFoto = await prisma.images.findFirst({
|
||||
where: {
|
||||
id: findProfile?.imagesId as string,
|
||||
},
|
||||
select: {
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
if (!findFoto) return { status: 400, message: "Foto tidak ditemukan" };
|
||||
if (findFoto) fs.unlinkSync(`./public/profile/foto/${findFoto.url}`);
|
||||
|
||||
const gambarProfile: any = file.get("file");
|
||||
const fileName = gambarProfile.name;
|
||||
const fileExtension = _.lowerCase(gambarProfile.name.split(".").pop());
|
||||
const randomName = v4(fileName) + "." + fileExtension;
|
||||
|
||||
const uploadPP = await prisma.images.update({
|
||||
where: {
|
||||
id: findProfile?.imagesId as string,
|
||||
},
|
||||
data: {
|
||||
url: randomName,
|
||||
label: "PROFILE_FOTO",
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!uploadPP) return { status: 400, message: "Gagal upload foto profile" };
|
||||
const uploadPP_Folder = Buffer.from(await gambarProfile.arrayBuffer());
|
||||
fs.writeFileSync(`./public/profile/foto/${uploadPP.url}`, uploadPP_Folder);
|
||||
revalidatePath("/dev/katalog");
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
message: "Update berhasil",
|
||||
};
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
import ProfileLayout from "./create/layout";
|
||||
import CreateProfile from "./create/view";
|
||||
import { getProfile } from "./api/get-profile";
|
||||
import EditProfileLayout from "./edit/layout";
|
||||
import EditProfileView from "./edit/view";
|
||||
import UploadFotoProfile from "./upload/view";
|
||||
import UploadFotoProfileLayout from "./upload/layout"
|
||||
import UploadFotoProfile from "./upload/foto_profile/view";
|
||||
import UploadFotoProfileLayout from "./upload/foto_profile/layout"
|
||||
import ProfileView from "./main/view";
|
||||
import Profile_UpdateFotoBackground from "./upload/foto_background";
|
||||
import LayoutProfile_UpdateFotoBackground from "./upload/foto_background/layout";
|
||||
|
||||
export {
|
||||
ProfileLayout,
|
||||
CreateProfile,
|
||||
getProfile,
|
||||
EditProfileView,
|
||||
EditProfileLayout,
|
||||
UploadFotoProfile,
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
import { Warna } from "@/app/lib/warna";
|
||||
import {
|
||||
ActionIcon,
|
||||
AspectRatio,
|
||||
Avatar,
|
||||
BackgroundImage,
|
||||
Box,
|
||||
Center,
|
||||
@@ -25,158 +27,207 @@ import {
|
||||
} from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
import { useAtom } from "jotai";
|
||||
import { ApiHipmi } from "@/app/lib/api";
|
||||
import { loadDataProfile } from "../fun/fun_get_profile";
|
||||
import { getFotoProfile } from "../api/get-foto-profile";
|
||||
import { gs_fotoProfile, gs_profile } from "../state/global_state";
|
||||
import { getProfile } from "..";
|
||||
import { MODEL_User_profile } from "@/app_modules/home/models/user_profile";
|
||||
import { funGetUserProfile } from "@/app_modules/fun/get_user_profile";
|
||||
import { MODEL_PROFILE_OLD } from "@/app_modules/home/model/user_profile";
|
||||
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||
import { MODEL_PROFILE } from "../model/interface";
|
||||
|
||||
export default function ProfileView({ user }: { user: MODEL_User_profile }) {
|
||||
export default function ProfileView({
|
||||
profile,
|
||||
userLoginId,
|
||||
}: {
|
||||
profile: MODEL_PROFILE;
|
||||
userLoginId: string;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [stateUser, setStateUser] = useState(user);
|
||||
useShallowEffect(() => {
|
||||
funGetUserProfile(user.id ?? "").then(setStateUser as any);
|
||||
}, []);
|
||||
// const [data, setData] = useState(profile);
|
||||
// useShallowEffect(() => {
|
||||
// funGetUserProfile(user.id ?? "").then(setProfile as any);
|
||||
// }, []);
|
||||
|
||||
if (!stateUser) return <></>;
|
||||
// if (!profile) return <></>;
|
||||
return (
|
||||
<>
|
||||
{/* Background dan foto */}
|
||||
<Box>
|
||||
<Paper bg={"gray"} p={"md"}>
|
||||
<Image alt="" src={"/aset/logo.png"} />
|
||||
</Paper>
|
||||
<Center>
|
||||
<Paper
|
||||
radius={100}
|
||||
h={105}
|
||||
w={105}
|
||||
sx={{
|
||||
borderStyle: "solid",
|
||||
borderRadius: "100%",
|
||||
borderWidth: 2,
|
||||
marginBottom: 10,
|
||||
paddingBottom: 10,
|
||||
position: "absolute",
|
||||
zIndex: 0,
|
||||
}}
|
||||
>
|
||||
<Center h={101}>
|
||||
{stateUser.Profile?.ImageProfile?.url && (
|
||||
<Image
|
||||
src={ApiHipmi.get_foto + stateUser.Profile?.ImageProfile?.url}
|
||||
alt=""
|
||||
radius={100}
|
||||
width={100}
|
||||
height={100}
|
||||
/>
|
||||
)}
|
||||
{/* <pre>{JSON.stringify(profile, null,2)}</pre> */}
|
||||
<Paper p={"sm"} bg={"gray.1"} shadow="lg" withBorder>
|
||||
{/* Background dan foto */}
|
||||
<Box>
|
||||
<AspectRatio ratio={16 / 9}>
|
||||
<Paper radius={"sm"} shadow="md">
|
||||
<Image
|
||||
radius={"sm"}
|
||||
height={210}
|
||||
alt=""
|
||||
src={
|
||||
RouterProfile.api_url_background +
|
||||
`${profile.ImagesBackground.url}`
|
||||
}
|
||||
/>
|
||||
</Paper>
|
||||
</AspectRatio>
|
||||
{profile.User.id === userLoginId ? (
|
||||
<ActionIcon
|
||||
ml={325}
|
||||
mt={-10}
|
||||
bg={"gray.5"}
|
||||
variant="transparent"
|
||||
radius={50}
|
||||
onClick={() =>
|
||||
router.push(
|
||||
RouterProfile.update_foto_background + `${profile.id}`
|
||||
)
|
||||
}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
zIndex: 2,
|
||||
border: "1px",
|
||||
borderStyle: "solid",
|
||||
}}
|
||||
>
|
||||
<IconCamera color="black" size={20} />
|
||||
</ActionIcon>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
|
||||
<Center>
|
||||
<Box
|
||||
sx={{
|
||||
marginBottom: 10,
|
||||
paddingBottom: 10,
|
||||
position: "absolute",
|
||||
zIndex: 0,
|
||||
}}
|
||||
>
|
||||
<Avatar
|
||||
bg={"gray.2"}
|
||||
sx={{
|
||||
borderStyle: "solid",
|
||||
borderColor: "black",
|
||||
borderWidth: "1px",
|
||||
}}
|
||||
src={RouterProfile.api_url_foto + `${profile.ImageProfile.url}`}
|
||||
size={100}
|
||||
radius={"100%"}
|
||||
/>
|
||||
</Box>
|
||||
</Center>
|
||||
|
||||
{profile.User.id === userLoginId ? (
|
||||
<Center>
|
||||
<ActionIcon
|
||||
mr={-70}
|
||||
mt={15}
|
||||
variant="transparent"
|
||||
bg={"gray.5"}
|
||||
radius={50}
|
||||
onClick={() =>
|
||||
router.push(
|
||||
RouterProfile.update_foto_profile + `${profile.id}`
|
||||
)
|
||||
}
|
||||
sx={{
|
||||
position: "relative",
|
||||
border: "1px",
|
||||
borderStyle: "solid",
|
||||
}}
|
||||
>
|
||||
<IconCamera color="black" size={20} />
|
||||
</ActionIcon>
|
||||
</Center>
|
||||
</Paper>
|
||||
</Center>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Center>
|
||||
<ActionIcon
|
||||
mr={-70}
|
||||
mt={15}
|
||||
variant="transparent"
|
||||
bg={"gray"}
|
||||
radius={50}
|
||||
onClick={() => router.push(`/dev/profile/upload/${stateUser.Profile?.id}`)}
|
||||
sx={{ position: "relative" }}
|
||||
>
|
||||
<IconCamera color="black" size={20} />
|
||||
</ActionIcon>
|
||||
</Center>
|
||||
</Box>
|
||||
{/* Username dan Nama */}
|
||||
|
||||
{/* Username dan Nama */}
|
||||
<Group position="apart">
|
||||
<Flex direction={"column"} mt={"lg"}>
|
||||
<Text fz={"lg"} fw={"bold"}>
|
||||
{stateUser.Profile?.name}
|
||||
</Text>
|
||||
<Text fz={"xs"}>@{stateUser.username}</Text>
|
||||
<Group position="apart">
|
||||
<Flex direction={"column"} mt={"lg"}>
|
||||
<Text fz={"lg"} fw={"bold"}>
|
||||
{profile.name}
|
||||
</Text>
|
||||
<Text fz={"xs"}>@{profile.User.username}</Text>
|
||||
</Flex>
|
||||
{profile.User.id === userLoginId ? (
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
onClick={() => {
|
||||
router.push(RouterProfile.edit + `${profile.id}`);
|
||||
}}
|
||||
>
|
||||
<IconEditCircle color={Warna.hijau_muda} />
|
||||
</ActionIcon>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</Group>
|
||||
|
||||
{/* Info user: nomor, email dll */}
|
||||
<Flex direction={"column"} pt={"lg"}>
|
||||
<Grid>
|
||||
<Grid.Col span={"content"}>
|
||||
<IconAddressBook />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text>
|
||||
{" "}
|
||||
<Text>+{profile.User.nomor}</Text>
|
||||
</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<Grid.Col span={"content"}>
|
||||
<IconMail />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text>
|
||||
{" "}
|
||||
<Text> {profile.email}</Text>
|
||||
</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<Grid.Col span={"content"}>
|
||||
<IconHome />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text> {profile.alamat}</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
{(() => {
|
||||
if (profile.jenisKelamin === "Laki - laki") {
|
||||
return (
|
||||
<>
|
||||
<Grid>
|
||||
<Grid.Col span={"content"}>
|
||||
<IconGenderMale />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text> {profile.jenisKelamin}</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
<Grid>
|
||||
<Grid.Col span={"content"}>
|
||||
<IconGenderFemale />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text> {profile.jenisKelamin}</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
}
|
||||
})()}
|
||||
</Flex>
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
onClick={() => {
|
||||
router.push(`/dev/profile/edit/${stateUser.id}`);
|
||||
}}
|
||||
>
|
||||
<IconEditCircle color={Warna.hijau_muda} size={20} />
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
|
||||
{/* Info user: nomor, email dll */}
|
||||
<Flex direction={"column"} pt={"lg"}>
|
||||
<Grid>
|
||||
<Grid.Col span={"content"}>
|
||||
<IconAddressBook />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text>
|
||||
{" "}
|
||||
<Text>+{stateUser.nomor}</Text>
|
||||
</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<Grid.Col span={"content"}>
|
||||
<IconMail />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text>
|
||||
{" "}
|
||||
<Text> {stateUser.Profile?.email}</Text>
|
||||
</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
<Grid>
|
||||
<Grid.Col span={"content"}>
|
||||
<IconHome />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text> {stateUser.Profile?.alamat}</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
{(() => {
|
||||
if (stateUser.Profile?.jenisKelamin === "Laki - laki") {
|
||||
return (
|
||||
<>
|
||||
<Grid>
|
||||
<Grid.Col span={"content"}>
|
||||
<IconGenderMale />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text> {stateUser.Profile?.jenisKelamin}</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
<Grid>
|
||||
<Grid.Col span={"content"}>
|
||||
<IconGenderFemale />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Text> {stateUser.Profile?.jenisKelamin}</Text>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
}
|
||||
})()}
|
||||
</Flex>
|
||||
</Paper>
|
||||
|
||||
{/* <pre>{JSON.stringify(profile, null, 2)}</pre> */}
|
||||
</>
|
||||
|
||||
19
src/app_modules/katalog/profile/model/interface.ts
Normal file
19
src/app_modules/katalog/profile/model/interface.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { MODEL_USER } from "@/app_modules/home/model/interface";
|
||||
import { MODEL_IMAGES } from "@/app_modules/models/interface";
|
||||
|
||||
export interface MODEL_PROFILE {
|
||||
userId: string;
|
||||
User: MODEL_USER;
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
alamat: string;
|
||||
jenisKelamin: string;
|
||||
active: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ImageProfile: MODEL_IMAGES;
|
||||
imagesId: string;
|
||||
ImagesBackground: MODEL_IMAGES;
|
||||
imagesBackgroundId: string;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import { atomWithStorage } from "jotai/utils";
|
||||
import { getProfile } from "..";
|
||||
|
||||
export const gs_profile = atomWithStorage<any | null>("gs_profile", null);
|
||||
export const gs_fotoProfile = atomWithStorage<any | null>("gs_fotoProfile" , null)
|
||||
|
||||
114
src/app_modules/katalog/profile/upload/foto_background/index.tsx
Normal file
114
src/app_modules/katalog/profile/upload/foto_background/index.tsx
Normal file
@@ -0,0 +1,114 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
AspectRatio,
|
||||
Button,
|
||||
Center,
|
||||
FileButton,
|
||||
Image,
|
||||
Paper,
|
||||
Stack,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||
import { MODEL_PROFILE } from "../../model/interface";
|
||||
import { IconCamera } from "@tabler/icons-react";
|
||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Profile_funUpdateFoto } from "../../fun/update/fun_update_foto_profile";
|
||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
||||
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/component_global/notif_global/notifikasi_peringatan";
|
||||
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
|
||||
import { Profile_funUpdateBackground } from "../../fun/update/fun_update_background";
|
||||
|
||||
export default function Profile_UpdateFotoBackground({
|
||||
dataProfile,
|
||||
}: {
|
||||
dataProfile: MODEL_PROFILE;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [profile, setProfile] = useState(dataProfile);
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [image, setImage] = useState<any | null>(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack spacing={"xl"}>
|
||||
<Paper p={"sm"} withBorder radius={"sm"} shadow="">
|
||||
<Stack>
|
||||
<AspectRatio ratio={16 / 9}>
|
||||
<Image
|
||||
alt="Foto"
|
||||
src={
|
||||
image
|
||||
? image
|
||||
: RouterProfile.api_background_profile +
|
||||
profile.imagesBackgroundId
|
||||
}
|
||||
/>
|
||||
</AspectRatio>
|
||||
<Center>
|
||||
<FileButton
|
||||
onChange={async (files: any | null) => {
|
||||
try {
|
||||
const buffer = URL.createObjectURL(
|
||||
new Blob([new Uint8Array(await files.arrayBuffer())])
|
||||
);
|
||||
// console.log(buffer, "ini buffer");
|
||||
// console.log(files, " ini file");
|
||||
setImage(buffer);
|
||||
setFile(files);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}}
|
||||
accept="image/png,image/jpeg"
|
||||
>
|
||||
{(props) => (
|
||||
<Button
|
||||
{...props}
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
w={150}
|
||||
leftIcon={<IconCamera />}
|
||||
compact
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
)}
|
||||
</FileButton>
|
||||
</Center>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
<Button
|
||||
radius={"xl"}
|
||||
onClick={() => onUpdate(router, profile.id, file as any)}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function onUpdate(
|
||||
router: AppRouterInstance,
|
||||
profileId: string,
|
||||
file: FormData
|
||||
) {
|
||||
const gambar = new FormData();
|
||||
gambar.append("file", file as any);
|
||||
|
||||
await Profile_funUpdateBackground(profileId, gambar).then((res) => {
|
||||
if (res.status === 200) {
|
||||
ComponentGlobal_NotifikasiBerhasil(res.message);
|
||||
router.back();
|
||||
} else {
|
||||
ComponentGlobal_NotifikasiGagal(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
ActionIcon,
|
||||
AppShell,
|
||||
FileButton,
|
||||
Flex,
|
||||
Footer,
|
||||
Group,
|
||||
Header,
|
||||
Text,
|
||||
} from "@mantine/core";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import ComponentKatalog_HeaderTamplate from "@/app_modules/katalog/component/header_tamplate";
|
||||
|
||||
export default function LayoutProfile_UpdateFotoBackground({
|
||||
children,
|
||||
|
||||
}: {
|
||||
children: any;
|
||||
|
||||
}) {
|
||||
const router = useRouter();
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppShell
|
||||
header={<ComponentKatalog_HeaderTamplate title="Update Background" />}
|
||||
>
|
||||
{children}
|
||||
</AppShell>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
ActionIcon,
|
||||
AppShell,
|
||||
FileButton,
|
||||
Flex,
|
||||
Footer,
|
||||
Group,
|
||||
Header,
|
||||
Text,
|
||||
} from "@mantine/core";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import ComponentKatalog_HeaderTamplate from "@/app_modules/katalog/component/header_tamplate";
|
||||
|
||||
export default function UploadFotoProfileLayout({
|
||||
children,
|
||||
profileId,
|
||||
}: {
|
||||
children: any;
|
||||
profileId: any;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [profile, setProfile] = useState(profileId);
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppShell
|
||||
header={<ComponentKatalog_HeaderTamplate title="Update Foto" />}
|
||||
>
|
||||
{children}
|
||||
</AppShell>
|
||||
</>
|
||||
);
|
||||
}
|
||||
109
src/app_modules/katalog/profile/upload/foto_profile/view.tsx
Normal file
109
src/app_modules/katalog/profile/upload/foto_profile/view.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
AspectRatio,
|
||||
Button,
|
||||
Center,
|
||||
FileButton,
|
||||
Image,
|
||||
Paper,
|
||||
Stack,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import { useState } from "react";
|
||||
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||
import { MODEL_PROFILE } from "../../model/interface";
|
||||
import { IconCamera } from "@tabler/icons-react";
|
||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Profile_funUpdateFoto } from "../../fun/update/fun_update_foto_profile";
|
||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
||||
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
|
||||
|
||||
export default function UploadFotoProfile({
|
||||
dataProfile,
|
||||
}: {
|
||||
dataProfile: MODEL_PROFILE;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [profile, setProfile] = useState(dataProfile);
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [image, setImage] = useState<any | null>(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack spacing={"xl"}>
|
||||
<Paper p={"sm"} withBorder radius={"sm"} shadow="">
|
||||
<Stack>
|
||||
<AspectRatio ratio={1 / 1}>
|
||||
<Image
|
||||
alt="Foto"
|
||||
src={
|
||||
image
|
||||
? image
|
||||
: RouterProfile.api_foto_profile + profile.imagesId
|
||||
}
|
||||
/>
|
||||
</AspectRatio>
|
||||
<Center>
|
||||
<FileButton
|
||||
onChange={async (files: any | null) => {
|
||||
try {
|
||||
const buffer = URL.createObjectURL(
|
||||
new Blob([new Uint8Array(await files.arrayBuffer())])
|
||||
);
|
||||
// console.log(buffer, "ini buffer");
|
||||
// console.log(files, " ini file");
|
||||
setImage(buffer);
|
||||
setFile(files);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}}
|
||||
accept="image/png,image/jpeg"
|
||||
>
|
||||
{(props) => (
|
||||
<Button
|
||||
{...props}
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
w={150}
|
||||
leftIcon={<IconCamera />}
|
||||
compact
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
)}
|
||||
</FileButton>
|
||||
</Center>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
<Button
|
||||
radius={"xl"}
|
||||
onClick={() => onUpdate(router, profile.id, file as any)}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function onUpdate(
|
||||
router: AppRouterInstance,
|
||||
profileId: string,
|
||||
file: FormData
|
||||
) {
|
||||
const gambar = new FormData();
|
||||
gambar.append("file", file as any);
|
||||
|
||||
await Profile_funUpdateFoto(profileId, gambar).then((res) => {
|
||||
if (res.status === 200) {
|
||||
ComponentGlobal_NotifikasiBerhasil(res.message);
|
||||
router.back();
|
||||
} else {
|
||||
ComponentGlobal_NotifikasiGagal(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
ActionIcon,
|
||||
AppShell,
|
||||
FileButton,
|
||||
Flex,
|
||||
Footer,
|
||||
Group,
|
||||
Header,
|
||||
Text,
|
||||
} from "@mantine/core";
|
||||
import { IconArrowLeft, IconUpload } from "@tabler/icons-react";
|
||||
import { useAtom } from "jotai";
|
||||
import toast from "react-simple-toasts";
|
||||
import { gs_profile } from "../state/global_state";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { loadDataProfile } from "../fun/fun_get_profile";
|
||||
import { funUploadFoto } from "../fun/upload_foto";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function UploadFotoProfileLayout({
|
||||
children,
|
||||
profileId
|
||||
}: {
|
||||
children: any;
|
||||
profileId: any
|
||||
}) {
|
||||
const router = useRouter()
|
||||
const [profile, setProfile] = useState(profileId)
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{JSON.stringify(profileId)}
|
||||
<AppShell
|
||||
header={
|
||||
<Header height={50} px={"sm"}>
|
||||
<Group position="apart" h={50}>
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
onClick={() => router.push(`/dev/katalog/${profile}`)}
|
||||
>
|
||||
<IconArrowLeft />
|
||||
</ActionIcon>
|
||||
<Text>Upload Foto Profile</Text>
|
||||
<ActionIcon variant="transparent"></ActionIcon>
|
||||
</Group>
|
||||
</Header>
|
||||
}
|
||||
footer={
|
||||
<Footer height={70}>
|
||||
<Flex align={"center"} justify={"center"} h={70} gap={"xl"}>
|
||||
<Flex align={"center"} justify={"center"} h={70}>
|
||||
<Flex direction={"column"} align={"center"}>
|
||||
<FileButton
|
||||
onChange={async (files) => {
|
||||
const id = profile
|
||||
|
||||
if (!files) return toast("File Kosong");
|
||||
const fd = new FormData();
|
||||
fd.append("file", files);
|
||||
|
||||
const upFoto = await funUploadFoto(fd, id);
|
||||
if (upFoto.success) {
|
||||
toast("Upload berhasil");
|
||||
router.push(`/dev/katalog/${profile}`)
|
||||
// loadDataProfile(valUser.id, setUser, setProfile);
|
||||
}
|
||||
}}
|
||||
accept="image/png,image/jpeg,image/webp"
|
||||
>
|
||||
{(props) => (
|
||||
<ActionIcon {...props}>
|
||||
<IconUpload />
|
||||
</ActionIcon>
|
||||
)}
|
||||
</FileButton>
|
||||
<Text fz={"sm"} fw={"bold"}>
|
||||
Upload
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
{/* */}
|
||||
</Footer>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
{/* {JSON.stringify(profile)} */}
|
||||
</AppShell>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { AspectRatio, FileButton, Image, Paper, Title } from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { useAtom } from "jotai";
|
||||
import { loadDataProfile } from "../fun/fun_get_profile";
|
||||
import { gs_fotoProfile, gs_profile } from "../state/global_state";
|
||||
import { getFotoProfile } from "../api/get-foto-profile";
|
||||
import { useState } from "react";
|
||||
import { ApiHipmi } from "@/app/lib/api";
|
||||
import { myConsole } from "@/app/fun/my_console";
|
||||
|
||||
export default function UploadFotoProfile({imageUrl}: {imageUrl: any}) {
|
||||
const [img, setImg] = useState(imageUrl)
|
||||
return (
|
||||
<>
|
||||
{/* {JSON.stringify(foto)} */}
|
||||
<AspectRatio ratio={1 / 1} >
|
||||
<Paper p={"lg"} shadow="xl">
|
||||
{img ? <Image alt="" src={`/img/${img}`} /> : <Image alt="" src={"/aset/avatar.png"} />}
|
||||
</Paper>
|
||||
</AspectRatio>
|
||||
{/* {JSON.stringify(profile)} */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user