Deskripsi:
- Upload foto profil ke storage
- Upload background profile ke storge
## No Issue
This commit is contained in:
2024-09-25 14:04:18 +08:00
parent 5670feb08c
commit 827b7c7bc1
54 changed files with 812 additions and 936 deletions

View File

@@ -95,6 +95,8 @@ model Profile {
Portofolio Portofolio[]
ImagesBackground ImagesBackground? @relation(fields: [imagesBackgroundId], references: [id])
imagesBackgroundId String? @unique
imageId String?
imageBackgroundId String?
}
model Images {
@@ -925,7 +927,7 @@ model BusinessMaps {
Portofolio Portofolio? @relation(fields: [portofolioId], references: [id])
portofolioId String? @unique
imageId String?
pinId String?
pinId String?
}
// Kategori App

View File

@@ -1,9 +1,35 @@
"use client";
import { Box, Center, Image, Loader, Text } from "@mantine/core";
import {
ActionIcon,
Avatar,
Box,
Center,
Image,
Loader,
Text,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useState } from "react";
export default function Page() {
return (
<>
<Box p={"lg"} bg={"gray"} h={"100vh"}>
<Center h={"100%"}>
<ActionIcon bg={"blue"}>
<Avatar
size={100}
radius={"100%"}
src={
// "https://wibu-storage.wibudev.com/api/files/cm1efheqx005vkp7jo7lqarnf"
"/aset/global/avatar.png"
}
/>
</ActionIcon>
</Center>
</Box>
</>
);
return (
<>
<LoadImage

View File

@@ -1,8 +1,18 @@
import { CreatePortofolio, CreatePortofolioLayout, PortofolioLayout } from "@/app_modules/katalog/portofolio";
import { CreatePortofolioLayout } from "@/app_modules/katalog/portofolio";
import React from "react";
export default async function Layout({children, params}: {children: React.ReactNode, params: {id: string}}) {
return<>
<CreatePortofolioLayout profileId={params.id}>{children}</CreatePortofolioLayout>
export default async function Layout({
children,
params,
}: {
children: React.ReactNode;
params: { id: string };
}) {
return (
<>
<CreatePortofolioLayout profileId={params.id}>
{children}
</CreatePortofolioLayout>
</>
}
);
}

View File

@@ -2,13 +2,14 @@ import { CreatePortofolio } from "@/app_modules/katalog/portofolio";
import { Portofolio_getMasterBidangBisnis } from "@/app_modules/katalog/portofolio/fun/master/get_bidang_bisnis";
export default async function Page({ params }: { params: { id: string } }) {
const profileId = params.id;
const bidangBisnis = await Portofolio_getMasterBidangBisnis();
return (
<>
<CreatePortofolio
bidangBisnis={bidangBisnis as any}
profileId={params.id}
profileId={profileId}
/>
</>
);

View File

@@ -2,11 +2,9 @@ import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { CreateProfile } from "@/app_modules/katalog/profile";
export default async function Page() {
const userLoginId = await funGetUserIdByToken();
return (
<>
<CreateProfile userLoginId={userLoginId} />
<CreateProfile />
</>
);
}

View File

@@ -1,7 +1,14 @@
const APIs = {
GET: "https://wibu-storage.wibudev.com/api/files/",
/**
*
* @param fileId | file id from wibu storage , atau bisa disimpan di DB
* @param size | file size 10 - 1000 , tergantung ukuran file dan kebutuhan saar di tampilkan
* @type {string}
*/
GET: ({ fileId, size }: { fileId: string; size?: string }) =>
size
? `https://wibu-storage.wibudev.com/api/files/${fileId}-size-${size}`
: `https://wibu-storage.wibudev.com/api/files/${fileId}`,
};
export default APIs
export default APIs;

View File

@@ -0,0 +1,44 @@
"use client";
import { Button, FileButton } from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
import { MainColor } from "../color";
export function ComponentGlobal_ButtonUploadFileImage({
onSetFile,
onSetImage,
}: {
onSetFile: File | any;
onSetImage: any | null;
}) {
return (
<FileButton
onChange={async (files: any | null) => {
try {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
onSetFile(files);
onSetImage(buffer);
} catch (error) {
console.log(error);
}
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
radius={"xl"}
leftIcon={<IconCamera />}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload
</Button>
)}
</FileButton>
);
}

View File

@@ -1,14 +1,28 @@
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import { Box } from "@mantine/core";
/**
*
* @param children
* @tutorial |
<AspectRatio ratio={1 / 1} mt={5} maw={300} mx={"auto"} >
<Image
style={{ maxHeight: 250 }}
alt="Avatar"
src={image ? image : APIs.GET({ fileId: profile.imageId as any })}/>
</AspectRatio>
* @returns folllow like this
*/
export function ComponentGlobal_BoxUploadImage({
children,
height,
}: {
children: React.ReactNode;
height?: number;
}) {
return (
<>
<ComponentGlobal_CardStyles height={300}>
<ComponentGlobal_CardStyles height={height ? height : 300}>
<Box
style={{
height: "100%",

View File

@@ -5,14 +5,17 @@ import { useShallowEffect } from "@mantine/hooks";
import { useState } from "react";
import ComponentGlobal_Loader from "./loader";
type IRadius = "xs" | "sm" | "md" | "lg" | "xl";
export function ComponentGlobal_LoadImage({
url,
maw,
h,
radius,
}: {
url: string;
maw?: number;
maw?: number | string;
h?: number;
radius?: IRadius;
}) {
const [isImage, setIsImage] = useState<boolean | null>(null);
@@ -34,7 +37,7 @@ export function ComponentGlobal_LoadImage({
if (isImage === null)
return (
<Center h={h ? h : 250}>
<Center h={250}>
<ComponentGlobal_Loader variant="dots" size={50} />
</Center>
);
@@ -42,7 +45,7 @@ export function ComponentGlobal_LoadImage({
if (!isImage)
return (
<>
<Center h={250}>
<Center h={250} >
<Image
alt="No Image"
maw={150}
@@ -56,24 +59,18 @@ export function ComponentGlobal_LoadImage({
return (
<>
{h ? (
<Image
height={h}
alt="Image"
maw={maw ? maw : 200}
m={"auto"}
p={"xs"}
src={url}
/>
) : (
<Image
alt="Image"
maw={maw ? maw : 200}
m={"auto"}
p={"xs"}
src={url}
/>
)}
<Box h={h ? h : 250}>
<Center h={"100%"}>
<Image
radius={radius ? radius : 0}
alt="Image"
maw={maw ? maw : 200}
m={"auto"}
p={"xs"}
src={url}
/>
</Center>
</Box>
</>
);
}

View File

@@ -1,3 +1,4 @@
import { ComponentGlobal_ButtonUploadFileImage } from "../button/comp_button_upload_photo";
import ComponentGlobal_BoxInformation from "./box_information";
import ComponentGlobal_AvatarAndAuthorName from "./comp_author_name_and_avatar";
import { ComponentGlobal_BoxUploadImage } from "./comp_box_upload_image";
@@ -6,6 +7,7 @@ import { ComponentGlobal_LoadImage } from "./comp_load_image";
import ComponentGlobal_CardLoadingOverlay from "./comp_loading_card";
import ComponentGlobal_TampilanAngkaRatusan from "./comp_tampilan_angka_ratusan";
import ComponentGlobal_TampilanRupiah from "./comp_tampilan_rupiah";
import ComponentGlobal_ErrorInput from "./error_input";
import ComponentGlobal_InputCountDown from "./input_countdown";
export { ComponentGlobal_TampilanRupiah };
@@ -17,3 +19,5 @@ export { ComponentGlobal_InputCountDown };
export { ComponentGlobal_CardStyles };
export { ComponentGlobal_BoxUploadImage };
export { ComponentGlobal_LoadImage };
export { ComponentGlobal_ErrorInput };
export { ComponentGlobal_ButtonUploadFileImage };

View File

@@ -19,7 +19,13 @@ export default function AdminJob_DetailPoster({
<Stack>
<ComponentAdminGlobal_BackButton />
<Center>
<Image onLoad={() => setLoading(false)} alt="Foto" src={APIs.GET + imageId} mah={500} maw={300} />
<Image
onLoad={() => setLoading(false)}
alt="Foto"
src={APIs.GET({ fileId: imageId })}
mah={500}
maw={300}
/>
{isLoading ? (
<Center h={"100%"}>
<ComponentGlobal_Loader size={30} variant="dots" />

View File

@@ -49,7 +49,7 @@ export function ComponentAdminMap_DetailDataDrawer({
radius={"md"}
width={300}
alt="Photo"
src={APIs.GET + data?.imageId}
src={APIs.GET({ fileId: data?.imageId as string })}
/>
</AspectRatio>

View File

@@ -90,8 +90,8 @@ export function UiAdminMap_MapBoxView({
}}
src={
e.pinId === null
? APIs.GET + e.Portofolio.logoId
: APIs.GET + e.pinId
? APIs.GET({ fileId: e.Portofolio.logoId })
: APIs.GET({ fileId: e.pinId })
}
/>
</Stack>

View File

@@ -2,11 +2,15 @@
import prisma from "@/app/lib/prisma";
export async function auth_funDeleteAktivasiKodeOtpById(otpId: string) {
export async function auth_funDeleteAktivasiKodeOtpById({
nomor,
}: {
nomor: string;
}) {
// console.log(otpId);
const updt = await prisma.kodeOtp.delete({
const updt = await prisma.kodeOtp.deleteMany({
where: {
id: otpId,
nomor: nomor,
},
});

View File

@@ -13,6 +13,9 @@ export async function Auth_funRegister({
data: any;
HIPMI_PWD: string;
}) {
const pswd = process.env.WIBU_PWD as string;
const cekUsername = await prisma.user.findUnique({
where: {
username: data.username,
@@ -39,14 +42,14 @@ export async function Auth_funRegister({
username: create.username,
}),
{
password: HIPMI_PWD,
password: pswd,
}
);
cookies().set({
name: "ssn",
value: sealToken,
// maxAge: 60 * 60 * 24 * 7,
maxAge: 60 * 60 * 24 * 7,
});
try {

View File

@@ -13,6 +13,9 @@ export async function auth_funValidasi({
nomor: string;
HIPMI_PWD: string;
}) {
const pswd = process.env.WIBU_PWD as string;
const cekUser = await prisma.user.findUnique({
where: {
nomor: nomor,
@@ -34,7 +37,7 @@ export async function auth_funValidasi({
username: cekUser.username,
}),
{
password: HIPMI_PWD,
password: pswd,
}
);

View File

@@ -52,7 +52,7 @@ export default function Register({ dataOtp }: { dataOtp: any }) {
HIPMI_PWD: GlobalEnv.value?.WIBU_PWD as string,
});
if (res.status === 200) {
await auth_funDeleteAktivasiKodeOtpById(dataOtp.id).then((val) => {
await auth_funDeleteAktivasiKodeOtpById({ nomor: nomor }).then((val) => {
if (val.status === 200) {
ComponentGlobal_NotifikasiBerhasil(res.message);
setLoading(true);

View File

@@ -69,7 +69,9 @@ export default function Validasi({ dataOtp }: { dataOtp: any }) {
}
if (res.status === 401) {
const resAktivasi = await auth_funDeleteAktivasiKodeOtpById(dataOtp.id);
const resAktivasi = await auth_funDeleteAktivasiKodeOtpById({
nomor: nomor,
});
if (resAktivasi.status === 200) {
ComponentGlobal_NotifikasiPeringatan(res.message);
router.push(RouterAuth.login, { scroll: false });
@@ -77,6 +79,11 @@ export default function Validasi({ dataOtp }: { dataOtp: any }) {
}
}
async function onBack() {
await auth_funDeleteAktivasiKodeOtpById({ nomor: nomor });
router.back();
}
return (
<>
<BackgroundImage
@@ -93,7 +100,7 @@ export default function Validasi({ dataOtp }: { dataOtp: any }) {
top: 0,
}}
>
<ActionIcon variant="transparent" onClick={() => router.back()}>
<ActionIcon variant="transparent" onClick={() => onBack()}>
<IconChevronLeft color="white" />
</ActionIcon>
</Box>

View File

@@ -0,0 +1,63 @@
"use client";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { Avatar, Center } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useState } from "react";
export function Home_ComponentAvatarProfile({ url }: { url: string }) {
const [isImage, setIsImage] = useState<boolean | null>(null);
useShallowEffect(() => {
onLoadImage();
}, []);
async function onLoadImage() {
try {
const res = await fetch(url);
if (res.ok) {
return setIsImage(true);
}
setIsImage(false);
} catch (error) {
console.log(error);
}
}
if (isImage === null) {
<Center>
<ComponentGlobal_Loader />
</Center>;
}
if (!isImage) {
return (
<>
<Avatar
radius={"xl"}
size={25}
sx={{
borderStyle: "solid",
borderWidth: "0.5px",
borderColor: "white",
}}
/>
</>
);
}
return (
<>
<Avatar
radius={"xl"}
size={25}
sx={{
borderStyle: "solid",
borderWidth: "0.5px",
borderColor: "white",
}}
src={url}
/>
</>
);
}

View File

@@ -0,0 +1,3 @@
import { Home_ComponentAvatarProfile } from "./comp_avatar_profile";
export { Home_ComponentAvatarProfile };

View File

@@ -43,6 +43,8 @@ import { MODEL_JOB } from "@/app_modules/job/model/interface";
import { RouterForum } from "@/app/lib/router_hipmi/router_forum";
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import { RouterMap } from "@/app/lib/router_hipmi/router_map";
import { Home_ComponentAvatarProfile } from "./comp_avatar_profile";
import { APIs } from "@/app/lib";
export function Home_UiView({
dataUser,
@@ -341,18 +343,11 @@ export function Home_UiFooter({ dataUser }: { dataUser: MODEL_USER }) {
) : isLoadingProfil ? (
<Loader color={AccentColor.yellow} size={20} />
) : (
<Avatar
radius={"xl"}
size={25}
sx={{
borderStyle: "solid",
borderWidth: "0.5px",
borderColor: "white",
}}
src={
RouterProfile.api_foto_profile +
`${dataUser?.Profile.imagesId}`
}
<Home_ComponentAvatarProfile
url={APIs.GET({
fileId: dataUser?.Profile?.imageId as string,
size: "50"
})}
/>
)}
</ActionIcon>

View File

@@ -45,7 +45,9 @@ export default function ComponentJob_DetailData({
<Card.Section px={"xs"} pb={"lg"}>
<Stack spacing={"xl"}>
{data.imageId ? (
<ComponentGlobal_LoadImage url={APIs.GET + data?.imageId} />
<ComponentGlobal_LoadImage
url={APIs.GET({ fileId: data?.imageId })}
/>
) : (
// <Stack align="center">
// {isLoading ? (

View File

@@ -8,7 +8,7 @@ import {
Image,
Stack,
Text,
TextInput
TextInput,
} from "@mantine/core";
import { IconCamera, IconUpload } from "@tabler/icons-react";
import { useState } from "react";
@@ -19,11 +19,17 @@ import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_BoxUploadImage, ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import {
ComponentGlobal_BoxUploadImage,
ComponentGlobal_CardStyles,
} from "@/app_modules/_global/component";
import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
import dynamic from "next/dynamic";
import "react-quill/dist/quill.snow.css";
import { Job_ComponentBoxUploadImage, Job_ComponentButtonUpdate } from "../component";
import {
Job_ComponentBoxUploadImage,
Job_ComponentButtonUpdate,
} from "../component";
const ReactQuill = dynamic(
() => {
return import("react-quill");
@@ -52,7 +58,7 @@ export default function Job_Edit({ dataJob }: { dataJob: MODEL_JOB }) {
style={{ maxHeight: 250, margin: "auto", padding: "5px" }}
alt="Foto"
height={250}
src={img ? img : APIs.GET + value.imageId}
src={img ? img : APIs.GET({ fileId: value.imageId })}
/>
</AspectRatio>
) : (
@@ -201,5 +207,3 @@ export default function Job_Edit({ dataJob }: { dataJob: MODEL_JOB }) {
</>
);
}

View File

@@ -40,7 +40,7 @@ export default function Job_NonUserView({ data }: { data: MODEL_JOB }) {
<Image
radius={"sm"}
alt=""
src={APIs.GET + data.imageId}
src={APIs.GET({ fileId: data.imageId })}
maw={200}
/>
</Stack>

View File

@@ -1,4 +1,7 @@
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import {
RouterPortofolio,
RouterProfile,
} from "@/app/lib/router_hipmi/router_katalog";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import Component_Logout from "@/app_modules/auth/logout/view";
@@ -12,9 +15,10 @@ import {
} from "@mantine/core";
import {
IconEdit,
IconPencilPlus,
IconPhotoEdit,
IconPolaroid,
IconX
IconX,
} from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
@@ -41,16 +45,22 @@ export function ComponentKatalog_DrawerKatalog({
},
{
id: "2",
name: "Ubah Foto Profile",
name: "Ubah foto profile",
icon: <IconPhotoEdit />,
path: RouterProfile.update_foto_profile + profileId,
},
{
id: "3",
name: "Ubah Latar Belakang",
name: "Ubah latar belakang",
icon: <IconPolaroid />,
path: RouterProfile.update_foto_background + profileId,
},
{
id: "4",
name: "Tambah portofolio",
icon: <IconPencilPlus />,
path: RouterPortofolio.create + profileId,
},
];
return (
@@ -95,12 +105,16 @@ export function ComponentKatalog_DrawerKatalog({
variant="transparent"
c="white"
onClick={() => {
router.push(e.path);
router.push(e.path, { scroll: false });
setPageId(e?.id);
setIsLoading(true)
setIsLoading(true);
}}
>
{isLoading && e.id === pageId ? <ComponentGlobal_Loader /> : e.icon}
{isLoading && e.id === pageId ? (
<ComponentGlobal_Loader />
) : (
e.icon
)}
</ActionIcon>
<Text align="center" color="white">
{e.name}

View File

@@ -1,9 +1,8 @@
"use client";
import { Header, Group, ActionIcon, Text, Title } from "@mantine/core";
import { IconArrowLeft, IconChevronLeft } from "@tabler/icons-react";
import { ActionIcon, Group, Header, Title } from "@mantine/core";
import { IconChevronLeft } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
export default function ComponentKatalog_HeaderTamplate({
hideBack,

View File

@@ -0,0 +1,3 @@
import { validRegex } from "./regular_expressions";
export { validRegex };

View File

@@ -61,7 +61,10 @@ export function ComponentPortofolio_DetailDataMap({ mapId }: { mapId: any }) {
{ maxWidth: 600, cols: 1, spacing: "sm" },
]}
>
<ComponentGlobal_LoadImage maw={200} url={APIs.GET + data.imageId} />
<ComponentGlobal_LoadImage
maw={200}
url={APIs.GET({ fileId: data?.imageId })}
/>
{/* <Image
radius={"sm"}
mah={300}

View File

@@ -37,7 +37,9 @@ export default function Portofolio_EditLogoBisnis({
{img ? (
<Image maw={250} alt="Image" src={img} />
) : (
<ComponentGlobal_LoadImage url={APIs.GET + dataPorto.logoId} />
<ComponentGlobal_LoadImage
url={APIs.GET({ fileId: dataPorto.logoId })}
/>
)}
<Center>

View File

@@ -3,13 +3,12 @@ import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_LoadImage } from "@/app_modules/_global/component";
import {
AspectRatio,
Box,
Divider,
Grid,
Group,
Image,
Paper,
SimpleGrid,
Stack,
@@ -24,7 +23,6 @@ import {
IconPinned,
} from "@tabler/icons-react";
import { MODEL_PORTOFOLIO } from "../model/interface";
import { ComponentGlobal_LoadImage } from "@/app_modules/_global/component";
export function Portofolio_UiDetailData({
dataPorto,
@@ -65,7 +63,9 @@ export function Portofolio_UiDetailData({
>
<Box>
<Paper>
<ComponentGlobal_LoadImage url={APIs.GET + dataPorto.logoId}/>
<ComponentGlobal_LoadImage
url={APIs.GET({ fileId: dataPorto.logoId })}
/>
{/* <AspectRatio ratio={1 / 1} mah={250} mx={"auto"}>
<Image
// style={{ maxHeight: 200, margin: "auto", padding: "5px" }}

View File

@@ -99,7 +99,9 @@ function MapView({
<Stack spacing={0} align="center">
<Avatar
src={
data.pinId === null ? APIs.GET + logoId : APIs.GET + data.pinId
data.pinId === null
? APIs.GET({ fileId: logoId })
: APIs.GET({ fileId: data.pinId })
}
alt="Logo"
style={{

View File

@@ -0,0 +1,73 @@
import { MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { Box, Button } from "@mantine/core";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { profile_funUpdateBackground } from "../../fun/update/fun_update_background";
import { DIRECTORY_ID } from "@/app/lib";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
export function Profile_ComponentButtonUpdateBackgroundProfile({
profileId,
file,
}: {
profileId: string;
file: File;
}) {
const router = useRouter();
const [loading, setLoading] = useState(false);
async function onUpdate() {
const uploadFile = await funGlobal_UploadToStorage({
file: file,
dirId: DIRECTORY_ID.profile_background,
});
if (!uploadFile.success)
return ComponentGlobal_NotifikasiPeringatan("Gagal upload foto profile");
const res = await profile_funUpdateBackground({
profileId: profileId,
fileId: uploadFile.data.id,
});
if (res.status === 200) {
setLoading(true);
ComponentGlobal_NotifikasiBerhasil(res.message);
router.back();
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
}
return (
<>
<Box
style={{
display: "flex",
justifyContent: "center",
}}
>
<Button
style={{
transition: "all 0.3s ease",
position: "absolute",
bottom: 20,
width: 300,
}}
disabled={file ? false : true}
loading={loading ? true : false}
loaderPosition="center"
radius={"xl"}
onClick={() => onUpdate()}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Update
</Button>
</Box>
</>
);
}

View File

@@ -0,0 +1,76 @@
"use client";
import { MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { Box, Button, Center } from "@mantine/core";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { profile_funUpdatePhoto } from "../../fun";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
import { DIRECTORY_ID } from "@/app/lib";
export function Profile_ComponentButtonUpdatePhotoProfile({
file,
profileId,
}: {
file: File;
profileId: string;
}) {
const router = useRouter();
const [isLoading, setLoading] = useState(false);
async function onUpdate() {
const uploadPhoto = await funGlobal_UploadToStorage({
file: file,
dirId: DIRECTORY_ID.profile_foto,
});
if (!uploadPhoto.success)
return ComponentGlobal_NotifikasiPeringatan("Gagal upload foto profile");
const res = await profile_funUpdatePhoto({
fileId: uploadPhoto.data.id,
profileId: profileId,
});
if (res.status === 200) {
setLoading(true);
ComponentGlobal_NotifikasiBerhasil(res.message);
router.back();
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
}
return (
<>
<Box
style={{
display: "flex",
justifyContent: "center",
}}
>
<Button
style={{
transition: "all 0.3s ease",
position: "absolute",
bottom: 20,
width: 300,
}}
disabled={file ? false : true}
loading={isLoading ? true : false}
loaderPosition="center"
radius={"xl"}
onClick={() => {
onUpdate();
}}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Update
</Button>
</Box>
</>
);
}

View File

@@ -1,69 +1,81 @@
"use client";
import { DIRECTORY_ID } from "@/app/lib";
import { RouterHome } from "@/app/lib/router_hipmi/router_home";
import { MainColor, AccentColor } from "@/app_modules/_global/color";
import { AccentColor, MainColor } from "@/app_modules/_global/color";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
import {
ComponentGlobal_NotifikasiPeringatan,
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { validRegex } from "@/app_modules/katalog/component/regular_expressions";
import { Button } from "@mantine/core";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react";
import funCreateNewProfile from "../../fun/fun_create_profile";
import { MODEL_PROFILE } from "../../model/interface";
import { useRouter } from "next/navigation";
import { validRegex } from "@/app_modules/katalog/component";
export function Profile_ComponentCreateNewProfile({
value,
userLoginId,
filePP,
fileBg,
fileBG,
}: {
value: MODEL_PROFILE;
userLoginId: string;
filePP: FormData;
fileBg: FormData;
filePP: File;
fileBG: File;
}) {
const router = useRouter();
const [loading, setLoading] = useState(false);
async function onSubmit() {
const body = {
userId: userLoginId,
const newData = {
name: value.name,
email: value.email,
alamat: value.alamat,
jenisKelamin: value.jenisKelamin,
};
if (_.values(body).includes(""))
if (_.values(newData).includes(""))
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Data");
if (!body.email.match(validRegex)) return null;
if (!newData.email.match(validRegex)) return null;
const gambarPP = new FormData();
gambarPP.append("filePP", filePP as any);
const gambarBG = new FormData();
gambarBG.append("fileBG", fileBg as any);
if (!gambarPP)
if (filePP == null)
return ComponentGlobal_NotifikasiPeringatan("Lengkapi foto profile");
if (!gambarBG)
if (fileBG == null)
return ComponentGlobal_NotifikasiPeringatan(
"Lengkapi background profile"
);
await funCreateNewProfile(body as any, gambarPP, gambarBG).then((res) => {
if (res.status === 201) {
setLoading(true);
ComponentGlobal_NotifikasiBerhasil("Berhasil Membuat Profile", 3000);
router.push(RouterHome.main_home, { scroll: false });
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
const uploadPhoto = await funGlobal_UploadToStorage({
file: filePP,
dirId: DIRECTORY_ID.profile_foto,
});
if (!uploadPhoto.success)
return ComponentGlobal_NotifikasiPeringatan("Gagal upload foto profile");
const uploadBackground = await funGlobal_UploadToStorage({
file: fileBG,
dirId: DIRECTORY_ID.profile_background,
});
if (!uploadBackground.success)
return ComponentGlobal_NotifikasiPeringatan(
"Gagal upload background profile"
);
const create = await funCreateNewProfile({
data: newData as any,
imageId: uploadPhoto.data.id,
imageBackgroundId: uploadBackground.data.id,
});
if (create.status === 201) {
setLoading(true);
ComponentGlobal_NotifikasiBerhasil("Berhasil membuat profile", 3000);
router.push(RouterHome.main_home, { scroll: false });
} else {
ComponentGlobal_NotifikasiGagal(create.message);
}
}
return (

View File

@@ -0,0 +1,82 @@
"use client";
import { AccentColor } from "@/app_modules/_global/color";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { Avatar, Box, Center, Image, Paper, Skeleton } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { CSSProperties, useState } from "react";
export function Profile_ComponentAvatarProfile({
url,
style,
}: {
url: string;
style?: CSSProperties;
}) {
const [isImage, setIsImage] = useState<boolean | null>(null);
useShallowEffect(() => {
onLoadImage();
}, []);
async function onLoadImage() {
try {
const res = await fetch(url);
if (res.ok) {
return setIsImage(true);
}
setIsImage(false);
} catch (error) {
console.log(error);
}
}
if (isImage === null) {
return (
<Skeleton
style={{ borderStyle: "solid", borderColor: AccentColor.darkblue }}
radius={"50%"}
h={100}
w={100}
/>
);
}
if (!isImage) {
return (
<>
<Avatar
variant="outline"
size={100}
bg={"gray"}
radius={"50%"}
style={style}
>
<Image
alt="Avatar"
height={100}
width={100}
src={"/aset/global/avatar.png"}
/>
</Avatar>
</>
);
}
return (
<>
<Avatar
bg={"white"}
style={style}
radius={"50%"}
size={100}
sx={{
borderStyle: "solid",
borderWidth: "0.5px",
borderColor: "white",
}}
src={url}
/>
</>
);
}

View File

@@ -0,0 +1,55 @@
"use client";
import { AspectRatio, Box, Center, Image, Skeleton } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useState } from "react";
type IRadius = "xs" | "sm" | "md" | "lg" | "xl";
export function Profile_ComponentLoadBackgroundImage({
url,
radius,
}: {
url: string;
radius?: IRadius;
}) {
const [isImage, setIsImage] = useState<boolean | null>(null);
useShallowEffect(() => {
onLoadImage();
}, []);
async function onLoadImage() {
try {
const res = await fetch(url);
if (res.ok) {
return setIsImage(true);
}
setIsImage(false);
} catch (error) {
console.log(error);
}
}
if (isImage === null) return <Skeleton h={200} w={"100%"} />;
if (!isImage)
return (
<>
<Center h={200} bg={"white"} style={{borderRadius: "10px"}} >
<Image
alt="No Image"
maw={150}
m={"auto"}
p={"xs"}
src={"/aset/global/no-image.svg"}
/>
</Center>
</>
);
return (
<>
<Image height={200} radius={radius ? radius : 0} alt="Image" src={url} />
</>
);
}

View File

@@ -1,3 +1,11 @@
import { Profile_ComponentButtonUpdateBackgroundProfile } from "./button/comp_button_update_background_profile";
import { Profile_ComponentButtonUpdatePhotoProfile } from "./button/comp_button_update_photo_profile";
import { Profile_ComponentCreateNewProfile } from "./button/comp_create_new_profile";
import { Profile_ComponentAvatarProfile } from "./comp_load_avatar";
import { Profile_ComponentLoadBackgroundImage } from "./comp_load_background";
export {Profile_ComponentCreateNewProfile}
export { Profile_ComponentCreateNewProfile };
export { Profile_ComponentAvatarProfile };
export { Profile_ComponentLoadBackgroundImage };
export { Profile_ComponentButtonUpdateBackgroundProfile };
export { Profile_ComponentButtonUpdatePhotoProfile };

View File

@@ -1,10 +1,10 @@
"use client";
import { MainColor } from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_BoxUploadImage } from "@/app_modules/_global/component";
import ComponentGlobal_BoxInformation from "@/app_modules/_global/component/box_information";
import ComponentGlobal_ErrorInput from "@/app_modules/_global/component/error_input";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import {
ComponentGlobal_BoxInformation,
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ErrorInput,
} from "@/app_modules/_global/component";
import {
AspectRatio,
Avatar,
@@ -21,14 +21,12 @@ import {
} from "@mantine/core";
import { IconAt, IconCamera, IconUpload } from "@tabler/icons-react";
import { useState } from "react";
import { validRegex } from "../../component/regular_expressions";
import { Profile_ComponentCreateNewProfile } from "../_component";
import { validRegex } from "../../component";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
import { MainColor } from "@/app_modules/_global/color";
export default function CreateProfile({
userLoginId,
}: {
userLoginId: string;
}) {
export default function CreateProfile() {
const [filePP, setFilePP] = useState<File | null>(null);
const [imgPP, setImgPP] = useState<any | null>();
const [fileBG, setFileBG] = useState<File | null>(null);
@@ -45,7 +43,7 @@ export default function CreateProfile({
<>
<Stack px={"sm"} spacing={40}>
<Box>
<Stack spacing={"xs"}>
<Stack spacing={"lg"}>
<ComponentGlobal_BoxInformation informasi="Upload foto profile anda." />
<Center>
{imgPP ? (
@@ -78,6 +76,7 @@ export default function CreateProfile({
</Paper>
)}
</Center>
<Center>
<FileButton
onChange={async (files: any | null) => {
@@ -118,7 +117,7 @@ export default function CreateProfile({
</Box>
<Box>
<Stack spacing={"xs"}>
<Stack spacing={"lg"}>
<ComponentGlobal_BoxInformation informasi="Upload foto latar belakang profile anda." />
<ComponentGlobal_BoxUploadImage>
{imgBG ? (
@@ -257,9 +256,8 @@ export default function CreateProfile({
<Profile_ComponentCreateNewProfile
value={value as any}
userLoginId={userLoginId}
filePP={filePP as any}
fileBg={fileBG as any}
fileBG={fileBG as any}
/>
</Stack>
</Stack>

View File

@@ -7,82 +7,37 @@ import { v4 } from "uuid";
import fs from "fs";
import { revalidatePath } from "next/cache";
import { RouterHome } from "@/app/lib/router_hipmi/router_home";
import { Prisma } from "@prisma/client";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
export default async function funCreateNewProfile(
req: MODEL_PROFILE,
gambarPP: FormData,
gambarBG: FormData
) {
const body = req;
export default async function funCreateNewProfile({
data,
imageId,
imageBackgroundId,
}: {
data: Prisma.ProfileCreateInput;
imageId: string;
imageBackgroundId: string;
}) {
const userLoginId = await funGetUserIdByToken();
const findEmail = await prisma.profile.findUnique({
where: {
email: body.email,
email: data.email,
},
});
if (findEmail) return { status: 400, message: "Email telah digunakan" };
const gambarProfile: any = gambarPP.get("filePP");
if (gambarProfile === "null")
return { status: 400, message: "Lengkapi Foto Profile" };
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");
if (gambarBackground === "null")
return { status: 400, message: "Lengkapi Foto Background" };
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,
userId: userLoginId,
name: data.name,
email: data.email,
alamat: data.alamat,
jenisKelamin: data.jenisKelamin,
imageId: imageId,
imageBackgroundId: imageBackgroundId,
},
});

View File

@@ -7,18 +7,8 @@ export async function Profile_getOneProfileAndUserById(profileId: string) {
where: {
id: profileId,
},
select: {
userId: true,
include: {
User: true,
id: true,
name: true,
email: true,
alamat: true,
jenisKelamin: true,
imagesId: true,
imagesBackgroundId: true,
ImageProfile: true,
ImagesBackground: true,
},
});
// console.log(data)

View File

@@ -0,0 +1,3 @@
import { profile_funUpdatePhoto } from "./update/fun_update_foto_profile";
export { profile_funUpdatePhoto };

View File

@@ -1,47 +1,21 @@
"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 gambarBackground: any = file.get("file");
const fileName = gambarBackground.name;
const fileExtension = _.lowerCase(gambarBackground.name.split(".").pop());
const fRandomName = v4(fileName) + "." + fileExtension;
const uploadBG = await prisma.imagesBackground.create({
data: {
url: fRandomName,
label: "PROFILE_BACKGROUND",
},
select: {
id: true,
url: true,
},
});
if (!uploadBG)
return { status: 400, message: "Gagal upload gambar background" };
const uploadBG_Folder = Buffer.from(await gambarBackground.arrayBuffer());
fs.writeFileSync(
`./public/profile/background/${uploadBG.url}`,
uploadBG_Folder
);
revalidatePath("/dev/katalog");
export async function profile_funUpdateBackground({
profileId,
fileId,
}: {
profileId: string;
fileId: string;
}) {
const updateBackground = await prisma.profile.update({
where: {
id: profileId,
},
data: {
imagesBackgroundId: uploadBG.id,
imageBackgroundId: fileId,
},
});
@@ -53,50 +27,4 @@ export async function Profile_funUpdateBackground(
status: 200,
message: "Update berhasil",
};
// 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 uploadBG_Folder = Buffer.from(await gambarBackground.arrayBuffer());
// fs.writeFileSync(`./public/profile/background/${uploadBG.url}`, uploadBG_Folder);
// revalidatePath("/dev/katalog");
// return {
// status: 200,
// message: "Update berhasil",
// };
}

View File

@@ -1,38 +1,21 @@
"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 gambarProfile: any = file.get("file");
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);
export async function profile_funUpdatePhoto({
profileId,
fileId,
}: {
profileId: string;
fileId: string;
}) {
const updateProfile = await prisma.profile.update({
where: {
id: profileId,
},
data: {
imagesId: uploadPP.id,
imageId: fileId,
},
});
@@ -43,52 +26,4 @@ export async function Profile_funUpdateFoto(profileId: string, file: FormData) {
status: 200,
message: "Update berhasil",
};
// 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",
// };
}

View File

@@ -2,12 +2,14 @@ import ProfileLayout from "./create/layout";
import CreateProfile from "./create/view";
import EditProfileLayout from "./edit/layout";
import EditProfileView from "./edit/view";
import ProfileView from "./main/view_profile";
import UploadFotoProfile from "./upload/foto_profile";
import UploadFotoProfileLayout from "./upload/foto_profile/layout";
export {
CreateProfile, EditProfileLayout, EditProfileView, ProfileLayout, ProfileView, UploadFotoProfile,
UploadFotoProfileLayout
CreateProfile,
EditProfileLayout,
EditProfileView,
ProfileLayout,
UploadFotoProfile,
UploadFotoProfileLayout,
};

View File

@@ -1,276 +0,0 @@
"use client";
import { Warna } from "@/app/lib/warna";
import {
ActionIcon,
AspectRatio,
Avatar,
BackgroundImage,
Box,
Center,
Flex,
Grid,
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 { 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";
import { AccentColor, MainColor } from "@/app_modules/_global/color/color_pallet";
export default function ProfileView({
profile,
userLoginId,
}: {
profile: MODEL_PROFILE;
userLoginId: string;
}) {
const router = useRouter();
const [loadingPP, setLoadingPP] = useState(false);
const [loadingBG, setLoadingBG] = useState(false);
const [loadingEdit, setLoadingEdit] = useState(false);
return (
<>
{/* <pre>{JSON.stringify(profile, null,2)}</pre> */}
<Paper px={"md"} py={"sm"} shadow="lg" style={{
backgroundColor: MainColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
}}>
{/* Background dan foto */}
{/* Upload Background Profile */}
<Box>
<AspectRatio ratio={16 / 9}>
<Paper radius={"sm"} shadow="md">
<Image
mah={"100%"}
maw={"100%"}
alt="Background"
src={
profile?.ImagesBackground.url
? RouterProfile.api_url_background +
`${profile?.ImagesBackground.url}`
: "/aset/no-image.png"
}
/>
</Paper>
</AspectRatio>
{/* Upload Background Profile */}
{profile?.User.id === userLoginId ? (
<Center>
<ActionIcon
loading={loadingBG ? true : false}
ml={{ base: 300, sm: 500, md: 900, lg: 1000 }}
mt={-10}
bg={"gray.5"}
variant="transparent"
radius={50}
onClick={() => {
setLoadingBG(true);
router.push(
RouterProfile.update_foto_background + `${profile.id}`
);
}}
sx={{
position: "relative",
color: "gray",
border: "1px",
borderStyle: "solid",
}}
>
<IconCamera color="black" size={20} />
</ActionIcon>
</Center>
) : (
""
)}
{/* Foto Profile */}
<Center>
<Box
sx={{
marginBottom: 10,
paddingBottom: 10,
position: "absolute",
zIndex: 0,
}}
>
<Avatar
bg={"gray.2"}
sx={{
borderStyle: "solid",
borderColor: "gray",
borderWidth: "0.5px",
}}
src={
profile?.ImageProfile?.url
? RouterProfile.api_url_foto +
`${profile?.ImageProfile.url}`
: "/aset/global/avatar.png"
}
size={100}
radius={"100%"}
/>
</Box>
</Center>
{/* Upload Foto Profile */}
{profile?.User.id === userLoginId ? (
<Center>
<ActionIcon
loading={loadingPP ? true : false}
mr={-70}
mt={15}
variant="transparent"
bg={"gray.5"}
radius={50}
onClick={() => {
setLoadingPP(true);
router.push(
RouterProfile.update_foto_profile + `${profile.id}`
);
}}
sx={{
position: "relative",
border: "1px",
borderStyle: "solid",
}}
>
<IconCamera color="black" size={20} />
</ActionIcon>
</Center>
) : (
""
)}
</Box>
{/* Username dan Nama */}
<Grid>
<Grid.Col
span={"auto"}
pt={profile?.User.id === userLoginId ? 10 : 50}
>
<Stack spacing={0}>
<Text fz={"lg"} fw={"bold"} lineClamp={1}>
{profile?.name}
</Text>
<Text fz={"xs"} c={"dark.3"}>
@{profile?.User?.username}
</Text>
</Stack>
</Grid.Col>
<Grid.Col span={"content"}>
{profile?.User.id === userLoginId ? (
<ActionIcon
loading={loadingEdit ? true : false}
variant="transparent"
onClick={() => {
setLoadingEdit(true);
router.push(RouterProfile.edit + `${profile.id}`);
}}
>
<IconEditCircle color={Warna.hijau_muda} />
</ActionIcon>
) : (
""
)}
</Grid.Col>
</Grid>
{/* <Group
position="apart"
pt={profile?.User.id === userLoginId ? 0 : "xl"}
>
<Flex direction={"column"} mt={"lg"}></Flex>
</Group> */}
{/* Info user: nomor, email dll */}
<Stack spacing={"xs"} 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>
</>
);
}
})()}
</Stack>
</Paper>
{/* <pre>{JSON.stringify(profile, null, 2)}</pre> */}
</>
);
}

View File

@@ -16,4 +16,6 @@ export interface MODEL_PROFILE {
imagesId: string;
ImagesBackground: MODEL_IMAGES;
imagesBackgroundId: string;
imageId?: string;
imageBackgroundId?: string;
}

View File

@@ -1,138 +1,52 @@
"use client";
import { APIs } from "@/app/lib";
import {
AspectRatio,
Button,
Center,
FileButton,
Image,
Paper,
Stack,
} from "@mantine/core";
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
} from "@/app_modules/_global/component";
import { AspectRatio, Center, Image, Stack } from "@mantine/core";
import { useState } from "react";
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
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_funUpdateBackground } from "../../fun/update/fun_update_background";
import { Profile_ComponentButtonUpdateBackgroundProfile } from "../../_component";
import { MODEL_PROFILE } from "../../model/interface";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
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);
const [loading, setLoading] = useState(false);
return (
<>
<Stack spacing={"xl"}>
<Paper
p={"sm"}
radius={"sm"}
style={{
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
}}
>
<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())])
);
if (files.size > 2000000) {
ComponentGlobal_NotifikasiPeringatan(
"Maaf, Ukuran file terlalu besar, maximum 2mb",
3000
);
} else {
setImage(buffer);
setFile(files);
}
} catch (error) {
console.log(error);
}
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
radius={"xl"}
leftIcon={<IconCamera />}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload
</Button>
)}
</FileButton>
</Center>
</Stack>
</Paper>
<Stack px={"xs"}>
<ComponentGlobal_BoxUploadImage>
<AspectRatio ratio={1 / 1} mt={5} maw={300} mx={"auto"}>
<Image
style={{ maxHeight: 250 }}
alt="Background"
src={
image
? image
: APIs.GET({ fileId: profile.imageBackgroundId as any })
}
/>
</AspectRatio>
</ComponentGlobal_BoxUploadImage>
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFile}
onSetImage={setImage}
/>
</Center>
<Button
disabled={file ? false : true}
loading={loading ? true : false}
loaderPosition="center"
radius={"xl"}
onClick={() => onUpdate(router, profile.id, file as any, setLoading)}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Update
</Button>
<Profile_ComponentButtonUpdateBackgroundProfile
file={file as any}
profileId={profile.id}
/>
</Stack>
</>
);
}
async function onUpdate(
router: AppRouterInstance,
profileId: string,
file: FormData,
setLoading: any
) {
const gambar = new FormData();
gambar.append("file", file as any);
await Profile_funUpdateBackground(profileId, gambar).then((res) => {
if (res.status === 200) {
setLoading(true);
ComponentGlobal_NotifikasiBerhasil(res.message);
router.back();
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
});
}

View File

@@ -1,137 +1,47 @@
"use client";
import { APIs } from "@/app/lib";
import {
AspectRatio,
Button,
Center,
FileButton,
Image,
Paper,
Stack,
Title,
} from "@mantine/core";
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
} from "@/app_modules/_global/component";
import { AspectRatio, Center, Image, Stack } from "@mantine/core";
import { useState } from "react";
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import { Profile_ComponentButtonUpdatePhotoProfile } from "../../_component";
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/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
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);
const [loading, setLoading] = useState(false);
return (
<>
<Stack spacing={"xl"}>
<Paper
p={"sm"}
radius={"sm"}
style={{
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
}}
>
<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())])
);
if (files.size > 2000000) {
ComponentGlobal_NotifikasiPeringatan(
"Maaf, Ukuran file terlalu besar, maximum 2mb",
3000
);
} else {
setImage(buffer);
setFile(files);
}
} catch (error) {
console.log(error);
}
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
radius={"xl"}
leftIcon={<IconCamera />}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload
</Button>
)}
</FileButton>
</Center>
</Stack>
</Paper>
<Button
disabled={file ? false : true}
loading={loading ? true : false}
loaderPosition="center"
radius={"xl"}
onClick={() => {
onUpdate(router, profile.id, file as any, setLoading);
}}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Update
</Button>
<Stack px={"xs"}>
<ComponentGlobal_BoxUploadImage>
<AspectRatio ratio={1 / 1} mt={5} maw={300} mx={"auto"}>
<Image
style={{ maxHeight: 250 }}
alt="Avatar"
src={image ? image : APIs.GET({ fileId: profile.imageId as any })}
/>
</AspectRatio>
</ComponentGlobal_BoxUploadImage>
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFile}
onSetImage={setImage}
/>
</Center>
<Profile_ComponentButtonUpdatePhotoProfile
file={file as any}
profileId={profile.id}
/>
</Stack>
</>
);
}
async function onUpdate(
router: AppRouterInstance,
profileId: string,
file: FormData,
setLoading: any
) {
const gambar = new FormData();
gambar.append("file", file as any);
await Profile_funUpdateFoto(profileId, gambar).then((res) => {
if (res.status === 200) {
setLoading(true);
ComponentGlobal_NotifikasiBerhasil(res.message);
router.back();
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
});
}

View File

@@ -48,10 +48,10 @@ export function Portofolio_UiListView({
}}
>
<Stack spacing={"sm"}>
<Group position="apart">
<ActionIcon variant="transparent" disabled></ActionIcon>
<Group position="center">
<Title order={4}>Portofolio</Title>
{profile?.User.id === userLoginId ? (
{/* {profile?.User.id === userLoginId ? (
<ActionIcon
variant="transparent"
onClick={() => {
@@ -69,7 +69,7 @@ export function Portofolio_UiListView({
</ActionIcon>
) : (
<ActionIcon variant="transparent" disabled></ActionIcon>
)}
)} */}
</Group>
<Stack

View File

@@ -1,24 +1,8 @@
"use client";
import {
MainColor,
AccentColor,
} from "@/app_modules/_global/color/color_pallet";
import {
Avatar,
Box,
Center,
Group,
Image,
Paper,
Stack,
Text,
ThemeIcon,
} from "@mantine/core";
import { MODEL_PROFILE } from "../profile/model/interface";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import { APIs } from "@/app/lib";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import { Box, Center, Group, Stack, Text, ThemeIcon } from "@mantine/core";
import {
IconBrandGmail,
IconGenderFemale,
@@ -26,6 +10,13 @@ import {
IconHome,
IconPhone,
} from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import {
Profile_ComponentAvatarProfile,
Profile_ComponentLoadBackgroundImage,
} from "../profile/_component";
import { MODEL_PROFILE } from "../profile/model/interface";
export function Profile_UiView({
profile,
@@ -76,17 +67,19 @@ export function Profile_UiView({
}}
>
<Box>
<Image
<Profile_ComponentLoadBackgroundImage
url={APIs.GET({
fileId: profile.imageBackgroundId as string,
})}
radius="sm"
/>
{/* <Image
radius={"sm"}
height={200}
alt="Background"
src={
profile?.ImagesBackground.url
? RouterProfile.api_url_background +
`${profile?.ImagesBackground.url}`
: "/aset/no-image.png"
}
/>
src={APIs.GET({ fileId: profile.imageBackgroundId as string })}
/> */}
<Box
sx={{
position: "relative",
@@ -97,22 +90,27 @@ export function Profile_UiView({
}}
>
<Center>
<Avatar
<Profile_ComponentAvatarProfile
url={APIs.GET({ fileId: profile.imageId as any, size: "200" })}
style={{
borderStyle: "solid",
borderColor: AccentColor.darkblue,
borderWidth: "2px",
}}
/>
{/* <Avatar
bg={"gray.2"}
sx={{
borderStyle: "solid",
borderColor: "gray",
borderWidth: "0.5px",
borderColor: AccentColor.darkblue,
borderWidth: "2px",
}}
src={
profile?.ImageProfile?.url
? RouterProfile.api_url_foto +
`${profile?.ImageProfile.url}`
: "/aset/global/avatar.png"
APIs.GET({fileId: profile.imageId as any})
}
size={100}
radius={"100%"}
/>
/> */}
</Center>
<Stack align="center" c={"white"} mt={"xs"} spacing={0}>
<Text fw={"bold"} lineClamp={1}>
@@ -128,7 +126,7 @@ export function Profile_UiView({
<Box>
<Stack spacing={"xs"}>
{listInformation.map((e, i) => (
<Group key={i} align="flex-start">
<Group key={i} align="flex-start">
<ThemeIcon
style={{
backgroundColor: "transparent",
@@ -136,20 +134,13 @@ export function Profile_UiView({
>
{e.icon}
</ThemeIcon>
<Box w={"85%"} >
<Box w={"85%"}>
<Text fw={"bold"}>{e?.value}</Text>
</Box>
</Group>
))}
</Stack>
</Box>
{/* <pre
style={{
color: "white",
}}
>
{JSON.stringify(profile, null, 2)}
</pre> */}
</Stack>
</>
);

View File

@@ -61,7 +61,9 @@ export function ComponentMap_DetailData({ mapId }: { mapId: any }) {
{ maxWidth: 600, cols: 1, spacing: "sm" },
]}
>
<ComponentGlobal_LoadImage url={APIs.GET + data?.imageId} />
<ComponentGlobal_LoadImage
url={APIs.GET({ fileId: data?.imageId })}
/>
{/* <Image radius={"sm"} mah={300} maw={200} alt="Photo" src={} /> */}
<Box>
<Grid>

View File

@@ -72,8 +72,8 @@ export function UiMap_CustomPin({
radius={"100%"}
src={
data.pinId === null
? APIs.GET + data.Portofolio.logoId
: APIs.GET + data.pinId
? APIs.GET({ fileId: data.Portofolio.logoId })
: APIs.GET({ fileId: data.pinId })
}
style={{
border: `2px solid ${AccentColor.skyblue}`,
@@ -155,8 +155,8 @@ export function UiMap_CustomPin({
imgPin
? imgPin
: data.pinId === null
? APIs.GET + data.Portofolio.logoId
: APIs.GET + data.pinId
? APIs.GET({ fileId: data.Portofolio.logoId })
: APIs.GET({ fileId: data.pinId })
}
style={{
border: `2px solid ${AccentColor.softblue}`,

View File

@@ -36,7 +36,10 @@ import { map_funEditMap } from "../fun/edit/fun_edit_map";
import { defaultMapZoom } from "../lib/default_lat_long";
import { MODEL_MAP } from "../lib/interface";
import { APIs } from "@/app/lib";
import { ComponentGlobal_BoxUploadImage, ComponentGlobal_LoadImage } from "@/app_modules/_global/component";
import {
ComponentGlobal_BoxUploadImage,
ComponentGlobal_LoadImage,
} from "@/app_modules/_global/component";
import { ComponentMap_ButtonUpdateDataMap } from "../_component";
export function UiMap_EditMap({
@@ -90,8 +93,8 @@ export function UiMap_EditMap({
<Avatar
src={
data.pinId === null
? APIs.GET + dataMap.Portofolio.logoId
: APIs.GET + data.pinId
? APIs.GET({ fileId: dataMap.Portofolio.logoId })
: APIs.GET({ fileId: data.pinId })
}
alt="Logo"
style={{
@@ -148,8 +151,7 @@ export function UiMap_EditMap({
</AspectRatio>
) : (
<ComponentGlobal_LoadImage
url={APIs.GET + data.imageId}
url={APIs.GET({ fileId: data.imageId })}
/>
)}
</ComponentGlobal_BoxUploadImage>
@@ -235,5 +237,3 @@ export function UiMap_EditMap({
</>
);
}

View File

@@ -91,8 +91,8 @@ export function UiMap_MapBoxView({
}}
src={
e.pinId === null
? APIs.GET + e.Portofolio.logoId
: APIs.GET + e.pinId
? APIs.GET({ fileId: e.Portofolio.logoId })
: APIs.GET({ fileId: e.pinId })
}
/>
</Stack>