Merge pull request #238 from bipproduction/bagas/13-jan-25

Fix uploaded image : Profile, Portofolio, Job
This commit is contained in:
Bagasbanuna02
2025-01-14 11:02:59 +08:00
committed by GitHub
32 changed files with 593 additions and 879 deletions

View File

@@ -3,18 +3,18 @@ import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
import sharp from "sharp";
export async function POST(request: Request) {
let fixFormData;
const formData = await request.formData();
const file: any = formData.get("file");
const mimeType = file.type;
console.log("MIME Type:", mimeType);
const valueOfDir = formData.get("dirId");
const keyOfDirectory = await funGetDirectoryNameByValue({
value: valueOfDir as string,
});
if (request.method === "POST") {
let fixFormData;
const file: any = formData.get("file");
const mimeType = file.type;
// console.log("MIME Type:", mimeType);
try {
if (mimeType != "application/pdf") {
// Resize ukuran

View File

@@ -1,9 +1,6 @@
import { DIRECTORY_ID, prisma } from "@/app/lib";
import { NextResponse } from "next/server";
import fs from "fs";
import { funGlobal_DeleteFileById } from "@/app_modules/_global/fun";
import { apiDeleteImageById } from "@/app_modules/_global/lib/api_image";
import { prisma } from "@/app/lib";
import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// GET ONE DATA PORTOFOLIO BY ID PORTOFOLIO

View File

@@ -1,6 +1,6 @@
const DIRECTORY_ID = {
profile_foto: "cm5ni43ub001pxpug0qw4p11e",
profile_background: "cm5ni4hnq001l12p9gpagxgtv",
profile_foto: "cm0x93rgo000jbp5tj8baoaus",
profile_background: "cm0x93ze8000lbp5t1a8uc9wl",
portofolio_logo: "cm0yjl6ug000310njwmk6j0tx",
map_pin: "cm0yjq8up000710njv5klra32",
map_image: "cm0yjqnxl000910njplqho07w",

View File

@@ -20,8 +20,8 @@ if (process.env.NODE_ENV !== "production") {
}
process.on("SIGINT", async () => {
console.log("Disconnecting PrismaClient...");
await prisma.$disconnect();3
// console.log("Disconnecting PrismaClient...");
await prisma.$disconnect();
process.exit(0);
});

View File

@@ -1,52 +0,0 @@
"use server";
import _ from "lodash";
// import { v4 } from "uuid";
import fs from "fs";
import sharp from "sharp";
export default async function fun_upload({
file,
dirId,
}: {
file: File;
dirId: string;
}) {
// const file: any = formData.get("file");
// const fName = file.name;
// const fileSize = file.size;
// // Convert ke KB
// const fileSizeInKB = fileSize / 1024;
// // Convert ke MB
// const fileSizeInMB = fileSize / (1024 * 1024);
// console.log(`Ukuran file dalam bytes: ${fileSize}`);
// console.log(`Ukuran file dalam KB: ${fileSizeInKB.toFixed(2)} KB`);
// console.log(`Ukuran file dalam MB: ${fileSizeInMB.toFixed(2)} MB`);
const imageBuffer = await file.arrayBuffer();
const resize = await sharp(imageBuffer).resize(2000).toBuffer();
const newFile = Buffer.from(resize);
console.log("file new",newFile);
// fs.writeFileSync(`./public/upload/${fName}`, upFolder as any);
const formData = new FormData();
formData.append("file", file);
formData.append("dirId", dirId);
// const upload = await fetch("/api/image/upload", {
// method: "POST",
// body: formData,
// });
// const res = await upload.json();
// if (upload.ok) {
// return { success: true, data: res.data, message: res.message };
// } else {
// return { success: false, data: {}, message: res.message };
// }
}

View File

@@ -2,9 +2,7 @@
import { MainColor } from "@/app_modules/_global/color";
import { ComponentGlobal_BoxUploadImage } from "@/app_modules/_global/component";
import { MAX_SIZE } from "@/app_modules/_global/lib";
import { PemberitahuanMaksimalFile } from "@/app_modules/_global/lib/max_size";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
import {
UIGlobal_LayoutHeaderTamplate,
UIGlobal_LayoutTamplate,
@@ -20,8 +18,6 @@ import {
} from "@mantine/core";
import { IconImageInPicture, IconUpload } from "@tabler/icons-react";
import { useState } from "react";
import fun_upload from "./fun_upload";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
export default function Page() {
return (

View File

@@ -2,15 +2,16 @@
import { clientLogger } from "@/util/clientLogger";
import { Button, FileButton } from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
import { IconUpload } from "@tabler/icons-react";
import { useState } from "react";
import { MainColor } from "../color";
import { AccentColor, MainColor } from "../color";
import { ComponentGlobal_NotifikasiPeringatan } from "../notif_global";
export function ComponentGlobal_ButtonUploadFileImage({
onSetFile,
onSetImage,
}: {
onSetFile: File | any;
onSetFile: File | null | any;
onSetImage: any | null;
}) {
const [isLoading, setIsLoading] = useState(false);
@@ -24,20 +25,20 @@ export function ComponentGlobal_ButtonUploadFileImage({
new Blob([new Uint8Array(await files.arrayBuffer())])
);
// if (files.size > MAX_SIZE) {
// ComponentGlobal_NotifikasiPeringatan(PemberitahuanMaksimalFile);
// return;
// } else {
// }
if (files.size > 100 * 1024 * 1024) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("File terlalu besar");
}
onSetFile(files);
onSetImage(buffer);
setIsLoading(false);
} catch (error) {
clientLogger.error("Upload image error:", error);
} finally {
setIsLoading(false);
clientLogger.error("Upload error:", error);
}
}}
accept="image/png,image/jpeg"
accept="image/png,image/png,image/jpeg,image/gif"
>
{(props) => (
<Button
@@ -45,10 +46,12 @@ export function ComponentGlobal_ButtonUploadFileImage({
loading={isLoading}
loaderPosition="center"
radius={"xl"}
leftIcon={<IconCamera />}
bg={MainColor.yellow}
color="yellow"
c={"black"}
style={{
backgroundColor: MainColor.yellow,
border: `1px solid ${AccentColor.yellow}`,
}}
leftIcon={<IconUpload color="black" size={20} />}
c={MainColor.darkblue}
>
Upload
</Button>

View File

@@ -1,5 +1,6 @@
import { Center, Grid, Group, Paper, Stack, Text, Title } from "@mantine/core";
import { AccentColor, MainColor } from "../color/color_pallet";
import { IconInfoCircle } from "@tabler/icons-react";
export default function ComponentGlobal_BoxInformation({
informasi,
@@ -36,18 +37,18 @@ export default function ComponentGlobal_BoxInformation({
</Text>
</Stack>
) : (
<Group>
<Text fz={fonsize ? fonsize : 12} c={"red"} fw={"bold"}>
*{" "}
<Grid>
<Grid.Col span={1}>
<IconInfoCircle color={MainColor.white} />
</Grid.Col>
<Grid.Col span={10}>
<Text span inherit c={MainColor.white} fw={"normal"}>
{informasi}
</Text>
</Text>
</Group>
</Grid.Col>
</Grid>
)}
</Paper>
</>
);
}

View File

@@ -1,6 +1,6 @@
import { clientLogger } from "@/util/clientLogger";
export async function funGlobal_DeleteFileById({
export async function funDeteleteFileById({
fileId,
dirId,
}: {
@@ -8,9 +8,23 @@ export async function funGlobal_DeleteFileById({
dirId?: string;
}) {
try {
const tokenResponse = await fetch("/api/get-cookie");
if (!tokenResponse.ok) {
throw new Error("Failed to get token");
}
const { token } = await tokenResponse.json();
if (!token) {
return { success: false, message: "Token not found" };
}
const res = await fetch("/api/image/delete", {
method: "DELETE",
body: JSON.stringify({ fileId, dirId }),
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
const data = await res.json();

View File

@@ -1,7 +1,7 @@
import { funGlobal_DeleteFileById } from "./delete/fun_delete_file_by_id";
import { funGlobal_UploadToStorage } from "./upload/fun_upload_to_storage";
import { funDeteleteFileById } from "./delete/fun_delete_file_by_id";
import { funUploadFileToStorage } from "./upload/fun_upload_to_storage";
import { funValidasiUploadCreatedFile } from "./upload/fun_validasi_upload_created_file";
export { funGlobal_UploadToStorage };
export { funGlobal_DeleteFileById };
export { funUploadFileToStorage as funGlobal_UploadToStorage };
export { funDeteleteFileById as funGlobal_DeleteFileById };
export { funValidasiUploadCreatedFile };

View File

@@ -1,55 +1,40 @@
import { TokenStorage } from "@/app/lib/token";
export async function funGlobal_UploadToStorage({
export async function funUploadFileToStorage({
file,
dirId,
}: {
file: File;
dirId: string;
}) {
const Env_WS_APIKEY = TokenStorage.value;
try {
const tokenResponse = await fetch("/api/get-cookie");
if (!tokenResponse.ok) {
throw new Error("Failed to get token");
}
const { token } = await tokenResponse.json();
const allowedMimeTypes = [
"image/heif", // Format HEIF standar
"image/heic", // Format HEIF untuk container HEIC
"image/heif-sequence", // Untuk sequence/animasi HEIF
"image/heic-sequence", // Untuk sequence/animasi HEIC
"image/png",
"image/jpeg",
"image/gif",
"text/csv",
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"text/plain",
];
if (!token) {
return { success: false, message: "Token not found" };
}
// if (!allowedMimeTypes.includes(file.type)) console.log("File tidak sesuai");
if (!allowedMimeTypes.includes(file.type)) {
console.error("File tidak sesuai");
return { success: false, message: "File type not allowed" };
}
const formData = new FormData();
formData.append("file", file);
formData.append("dirId", dirId);
if (file.size > 100 * 1024 * 1024) {
console.error("File terlalu besar");
return { success: false, message: "File size exceeds limit" };
}
const formData = new FormData();
formData.append("file", file);
formData.append("dirId", dirId);
const upload = await fetch("/api/image/upload", {
method: "POST",
body: formData,
headers: {
Authorization: `Bearer ${token}`,
},
});
const upload = await fetch("/api/image/upload", {
method: "POST",
body: formData,
});
const res = await upload.json();
const res = await upload.json();
if (upload.ok) {
return { success: true, data: res.data, message: res.message };
} else {
return { success: false, data: {}, message: res.message };
return upload.ok
? { success: true, data: res.data, message: res.message }
: { success: false, data: {}, message: res.message };
} catch (error) {
console.log(error);
return { success: false, message: "An unexpected error occurred" };
}
}

View File

@@ -2,8 +2,8 @@ import { clientLogger } from "@/util/clientLogger";
import { MAX_SIZE } from "../../lib";
import { PemberitahuanMaksimalFile } from "../../lib/max_size";
import { ComponentGlobal_NotifikasiPeringatan } from "../../notif_global";
import { funGlobal_DeleteFileById } from "../delete/fun_delete_file_by_id";
import { funGlobal_UploadToStorage } from "./fun_upload_to_storage";
import { funDeteleteFileById } from "../delete/fun_delete_file_by_id";
import { funUploadFileToStorage } from "./fun_upload_to_storage";
export async function funValidasiUploadCreatedFile({
files,
@@ -31,7 +31,7 @@ export async function funValidasiUploadCreatedFile({
}
if (fileId != "") {
const deleteFotoProfile = await funGlobal_DeleteFileById({
const deleteFotoProfile = await funDeteleteFileById({
fileId: fileId,
dirId: dirId,
});
@@ -49,7 +49,7 @@ export async function funValidasiUploadCreatedFile({
onSetFileId("");
onSetImageBuffer(null);
const uploadPhoto = await funGlobal_UploadToStorage({
const uploadPhoto = await funUploadFileToStorage({
file: files,
dirId: dirId,
});
@@ -73,7 +73,7 @@ export async function funValidasiUploadCreatedFile({
}
}
} else {
const uploadPhoto = await funGlobal_UploadToStorage({
const uploadPhoto = await funUploadFileToStorage({
file: files,
dirId: dirId,
});

View File

@@ -1,16 +0,0 @@
export const apiDeleteImageById = async ({
fileId,
dirId,
}: {
fileId: string;
dirId?: string;
}) => {
const response = await fetch(`/api/image/delete`, {
method: "DELETE",
body: JSON.stringify({ fileId, dirId }),
});
console.log("delete api =>", await response.json());
return await response.json().catch(() => null);
};

View File

@@ -11,6 +11,7 @@ import {
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { notifikasiToAdmin_funCreate } from "@/app_modules/notifikasi/fun";
import { clientLogger } from "@/util/clientLogger";
import { Button } from "@mantine/core";
import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
@@ -19,7 +20,6 @@ import { WibuRealtime } from "wibu-pkg";
import { job_funCreateNoFile, job_funCreateWithFile } from "../../fun";
import { gs_job_hot_menu } from "../../global_state";
import { MODEL_JOB } from "../../model/interface";
import { envs } from "@/lib/envs";
function Job_ComponentButtonSaveCreate({
value,
@@ -71,6 +71,8 @@ function Job_ComponentButtonSaveCreate({
ComponentGlobal_NotifikasiBerhasil(createNoFile.message);
}
} else {
setIsLoading(false);
ComponentGlobal_NotifikasiGagal(createNoFile.message);
}
} else {
@@ -80,6 +82,7 @@ function Job_ComponentButtonSaveCreate({
});
if (!uploadFile.success) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
return;
}
@@ -120,15 +123,13 @@ function Job_ComponentButtonSaveCreate({
ComponentGlobal_NotifikasiBerhasil(createWithFile.message);
}
} else {
setIsLoading(false);
ComponentGlobal_NotifikasiGagal(createWithFile.message);
}
}
} catch (error) {
console.log(error);
} finally {
if (window.location.pathname !== RouterJob.status({ id: "2" })) {
setIsLoading(false);
}
setIsLoading(false);
clientLogger.error("Error create job", error);
}
}

View File

@@ -17,6 +17,7 @@ import { useState } from "react";
import { job_EditById } from "../../fun/edit/fun_edit_by_id";
import { gs_job_hot_menu } from "../../global_state";
import { MODEL_JOB } from "../../model/interface";
import { clientLogger } from "@/util/clientLogger";
export function Job_ComponentButtonUpdateData({
value,
@@ -32,41 +33,56 @@ export function Job_ComponentButtonUpdateData({
const [opened, { open, close }] = useDisclosure(false);
async function onUpdate() {
if (file === null) {
const update = await job_EditById({
data: value,
});
if (update.status !== 200)
return ComponentGlobal_NotifikasiGagal(update.message);
} else {
const uploadFile = await funGlobal_UploadToStorage({
file: file,
dirId: DIRECTORY_ID.job_image,
});
try {
setIsLoading(true);
if (!uploadFile.success)
return ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
if (value.imageId !== null) {
const delFile = await funGlobal_DeleteFileById({
fileId: value.imageId,
if (file === null) {
const update = await job_EditById({
data: value,
});
if (!delFile.success)
ComponentGlobal_NotifikasiPeringatan("Gagal hapus gambar lama");
if (update.status !== 200)
return ComponentGlobal_NotifikasiGagal(update.message);
} else {
const uploadFile = await funGlobal_UploadToStorage({
file: file,
dirId: DIRECTORY_ID.job_image,
});
if (!uploadFile.success) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
return;
}
if (value.imageId !== null) {
const delFile = await funGlobal_DeleteFileById({
fileId: value.imageId,
});
if (!delFile.success) {
clientLogger.error("Error delete file:", delFile.message);
}
}
const updateWithFile = await job_EditById({
data: value,
fileId: uploadFile.data.id,
});
if (updateWithFile.status !== 200) {
setIsLoading(false);
ComponentGlobal_NotifikasiGagal(updateWithFile.message);
return;
}
}
const updateWithFile = await job_EditById({
data: value,
fileId: uploadFile.data.id,
});
if (updateWithFile.status !== 200)
return ComponentGlobal_NotifikasiGagal(updateWithFile.message);
setHotMenu(2);
ComponentGlobal_NotifikasiBerhasil("Berhasil Update");
router.back();
} catch (error) {
setIsLoading(false);
clientLogger.error("Error update job:", error);
ComponentGlobal_NotifikasiGagal("Gagal update job");
}
setHotMenu(2);
setIsLoading(true);
router.back();
return ComponentGlobal_NotifikasiBerhasil("Berhasil Update");
}
return (

View File

@@ -2,15 +2,13 @@
import {
AspectRatio,
Button,
Center,
FileButton,
Image,
Stack,
Text,
TextInput,
} from "@mantine/core";
import { IconCamera, IconUpload } from "@tabler/icons-react";
import { IconPhoto } from "@tabler/icons-react";
import dynamic from "next/dynamic";
import { useState } from "react";
import "react-quill/dist/quill.snow.css";
@@ -21,22 +19,15 @@ const ReactQuill = dynamic(
{ ssr: false }
);
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import {
ComponentGlobal_BoxInformation,
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
ComponentGlobal_CardStyles,
ComponentGlobal_InputCountDown,
} from "@/app_modules/_global/component";
import { Job_ComponentButtonSaveCreate } from "../component";
import { defaultDeskripsi, defaultSyarat } from "../component/default_value";
import { MAX_SIZE } from "@/app_modules/_global/lib";
import { PemberitahuanMaksimalFile } from "@/app_modules/_global/lib/max_size";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
export default function Job_Create() {
const [value, setValue] = useState({
@@ -55,7 +46,7 @@ export default function Job_Create() {
<Stack>
<ComponentGlobal_BoxInformation informasi="Poster atau gambar lowongan kerja bersifat opsional, tidak wajib untuk dimasukkan dan upload lah gambar yang sesuai dengan deskripsi lowongan kerja. " />
<Stack spacing={"xs"}>
<Stack spacing={0}>
<ComponentGlobal_BoxUploadImage>
{img ? (
<AspectRatio ratio={1 / 1} mah={265} mx={"auto"}>
@@ -68,53 +59,16 @@ export default function Job_Create() {
</AspectRatio>
) : (
<Stack justify="center" align="center" h={"100%"}>
<IconUpload color="white" />
<Text fz={10} fs={"italic"} c={"white"} fw={"bold"}>
Upload Gambar
</Text>
<IconPhoto size={100} />
</Stack>
)}
</ComponentGlobal_BoxUploadImage>
<Center>
<FileButton
onChange={async (files: any | null) => {
try {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
if (files.size > MAX_SIZE) {
ComponentGlobal_NotifikasiPeringatan(
PemberitahuanMaksimalFile
);
setImg(null);
return;
}
setImg(buffer);
setFile(files);
} catch (error) {
console.log(error);
}
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
radius={"xl"}
w={100}
style={{
backgroundColor: MainColor.yellow,
border: `1px solid ${AccentColor.yellow}`,
}}
>
<IconCamera color="black" />
</Button>
)}
</FileButton>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFile}
onSetImage={setImg}
/>
</Center>
</Stack>

View File

@@ -10,28 +10,25 @@ import {
Text,
TextInput,
} from "@mantine/core";
import { IconCamera, IconUpload } from "@tabler/icons-react";
import { IconCamera } from "@tabler/icons-react";
import { useState } from "react";
import { MODEL_JOB } from "../model/interface";
import { APIs } from "@/app/lib";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import {
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
ComponentGlobal_CardStyles,
ComponentGlobal_LoadImage,
ComponentGlobal_LoadImageCustom,
} from "@/app_modules/_global/component";
import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
import { IconPhoto } from "@tabler/icons-react";
import dynamic from "next/dynamic";
import "react-quill/dist/quill.snow.css";
import {
Job_ComponentBoxUploadImage,
Job_ComponentButtonUpdate,
} from "../component";
import { Job_ComponentButtonUpdate } from "../component";
const ReactQuill = dynamic(
() => {
return import("react-quill");
@@ -51,7 +48,7 @@ export default function Job_Edit({ dataJob }: { dataJob: MODEL_JOB }) {
return (
<>
<Stack>
<Stack spacing={"xs"}>
<Stack spacing={0}>
<ComponentGlobal_BoxUploadImage>
{img ? (
<AspectRatio ratio={1 / 1} mt={5} maw={300} mx={"auto"}>
@@ -66,44 +63,16 @@ export default function Job_Edit({ dataJob }: { dataJob: MODEL_JOB }) {
<ComponentGlobal_LoadImage fileId={data.imageId} />
) : (
<Stack justify="center" align="center" h={"100%"}>
<IconUpload color="white" />
<Text fz={10} fs={"italic"} c={"white"} fw={"bold"}>
Upload Gambar
</Text>
<IconPhoto size={100} />
</Stack>
)}
</ComponentGlobal_BoxUploadImage>
<Center>
<FileButton
onChange={async (files: any | null) => {
try {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
setImg(buffer);
setFile(files);
} catch (error) {
console.log(error);
}
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
radius={"xl"}
w={100}
style={{
backgroundColor: MainColor.yellow,
border: `1px solid ${AccentColor.yellow}`,
}}
>
<IconCamera color="black" />
</Button>
)}
</FileButton>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFile}
onSetImage={setImg}
/>
</Center>
</Stack>

View File

@@ -1,22 +1,22 @@
"use client";
import { AccentColor, MainColor } from "@/app_modules/_global/color";
import { MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { Button } from "@mantine/core";
import { Box, Button } from "@mantine/core";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { DIRECTORY_ID } from "@/app/lib";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
import { DIRECTORY_ID } from "@/app/lib";
import { portofolio_funEditLogoBisnisById } from "../../fun";
import { clientLogger } from "@/util/clientLogger";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { portofolio_funEditLogoBisnisById } from "../../fun";
export function ComponentPortofolio_ButtonEditLogoBisnis({
file,
@@ -33,16 +33,6 @@ export function ComponentPortofolio_ButtonEditLogoBisnis({
try {
setLoading(true);
const deleteLogo = await funGlobal_DeleteFileById({
fileId: fileRemoveId,
dirId: DIRECTORY_ID.portofolio_logo,
});
if (!deleteLogo.success) {
setLoading(false);
clientLogger.error("Error delete logo", deleteLogo.message);
}
const uploadFileToStorage = await funGlobal_UploadToStorage({
file: file,
dirId: DIRECTORY_ID.portofolio_logo,
@@ -53,9 +43,21 @@ export function ComponentPortofolio_ButtonEditLogoBisnis({
ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
return;
}
const deleteLogo = await funGlobal_DeleteFileById({
fileId: fileRemoveId,
dirId: DIRECTORY_ID.portofolio_logo,
});
if (!deleteLogo.success) {
setLoading(false);
clientLogger.error("Error delete logo", deleteLogo.message);
}
const logoId = uploadFileToStorage.data.id;
const res = await portofolio_funEditLogoBisnisById({
portofolioId: portofolioId,
logoId: uploadFileToStorage.data.id,
logoId: logoId,
});
if (res.status === 200) {
@@ -73,8 +75,16 @@ export function ComponentPortofolio_ButtonEditLogoBisnis({
return (
<>
{file ? (
<Box
p={"xs"}
bg={"red"}
style={{
display: "flex",
justifyContent: "center",
}}
>
<Button
disabled={file === null}
loaderPosition="center"
loading={loading}
radius={"xl"}
@@ -83,17 +93,15 @@ export function ComponentPortofolio_ButtonEditLogoBisnis({
color="yellow"
c={"black"}
style={{
width: "100%",
transition: "0.5s",
border: `1px solid ${AccentColor.yellow}`,
position: "absolute",
bottom: 20,
}}
>
Simpan
</Button>
) : (
<Button disabled radius={"xl"}>
Simpan
</Button>
)}
</Box>
</>
);
}

View File

@@ -9,6 +9,9 @@ import { MODEL_PORTOFOLIO_OLD } from "@/app_modules/model_global/portofolio";
import { Button } from "@mantine/core";
import _ from "lodash";
import { DIRECTORY_ID } from "@/app/lib";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
import { clientLogger } from "@/util/clientLogger";
import { useRouter } from "next/navigation";
import { useState } from "react";
import funCreatePortofolio from "../../fun/fun_create_portofolio";
@@ -17,12 +20,12 @@ export function Portofolio_ComponentButtonSelanjutnya({
profileId,
dataPortofolio,
dataMedsos,
imageId,
file,
}: {
profileId: string;
dataPortofolio: MODEL_PORTOFOLIO_OLD;
dataMedsos: any;
imageId: string;
file: File;
}) {
const router = useRouter();
const [loading, setLoading] = useState(false);
@@ -48,31 +51,45 @@ export function Portofolio_ComponentButtonSelanjutnya({
try {
setLoading(true);
const uploadFile = await funGlobal_UploadToStorage({
file: file,
dirId: DIRECTORY_ID.portofolio_logo,
});
if (!uploadFile.success) {
setLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
return;
}
const fileId = uploadFile.data.id;
const res = await funCreatePortofolio({
profileId: profileId,
data: dataPortofolio as any,
medsos: dataMedsos,
fileId: imageId,
fileId: fileId,
});
if (res.status === 201) {
ComponentGlobal_NotifikasiBerhasil("Berhasil disimpan");
router.replace(RouterMap.create + res.id, { scroll: false });
} else {
setLoading(false);
ComponentGlobal_NotifikasiGagal("Gagal disimpan");
}
} catch (error) {
console.error(error);
} finally {
setLoading(false);
clientLogger.error("Error create portofolio", error);
}
}
return (
<>
<Button
disabled={_.values(dataPortofolio).includes("") || imageId == ""}
disabled={_.values(dataPortofolio).includes("") || file === null}
mt={"md"}
radius={50}
loading={loading ? true : false}
loading={loading}
loaderPosition="center"
onClick={() => {
onSubmit();

View File

@@ -1,9 +1,20 @@
"use client";
import { DIRECTORY_ID } from "@/app/lib";
import { MainColor } from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_BoxUploadImage } from "@/app_modules/_global/component";
import {
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
} from "@/app_modules/_global/component";
import ComponentGlobal_BoxInformation from "@/app_modules/_global/component/box_information";
import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
import { MAX_SIZE } from "@/app_modules/_global/lib";
import { PemberitahuanMaksimalFile } from "@/app_modules/_global/lib/max_size";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
import { BIDANG_BISNIS_OLD } from "@/app_modules/model_global/portofolio";
import {
AspectRatio,
@@ -18,20 +29,12 @@ import {
Textarea,
Title,
} from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
import { IconCamera, IconPhoto } from "@tabler/icons-react";
import _ from "lodash";
import { useState } from "react";
import { Portofolio_ComponentButtonSelanjutnya } from "../component";
import { MAX_SIZE } from "@/app_modules/_global/lib";
import { PemberitahuanMaksimalFile } from "@/app_modules/_global/lib/max_size";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
import { DIRECTORY_ID } from "@/app/lib";
import { PhoneInput } from "react-international-phone";
import "react-international-phone/style.css";
import { Portofolio_ComponentButtonSelanjutnya } from "../component";
export default function CreatePortofolio({
bidangBisnis,
@@ -56,16 +59,15 @@ export default function CreatePortofolio({
tiktok: "",
});
const [file, setFile] = useState<File | null>(null);
const [img, setImg] = useState<any | null>(null);
const [imageId, setImageId] = useState("");
return (
<>
{/* {JSON.stringify(profileId)} */}
<Stack px={"sm"} mb={"lg"} spacing={50}>
<Stack spacing={"sm"}>
<ComponentGlobal_BoxInformation informasi="Lengkapi Data Bisnis" />
<ComponentGlobal_BoxInformation informasi="Lengkapi data bisnis" />
<TextInput
styles={{
label: {
@@ -101,8 +103,8 @@ export default function CreatePortofolio({
color: MainColor.red,
},
dropdown: {
backgroundColor: MainColor.white
}
backgroundColor: MainColor.white,
},
}}
withAsterisk
label="Bidang Bisnis"
@@ -156,7 +158,7 @@ export default function CreatePortofolio({
countrySelectorStyleProps={{
buttonStyle: {
backgroundColor: MainColor.login,
}
},
}}
inputStyle={{ width: "100%", backgroundColor: MainColor.login }}
defaultCountry="id"
@@ -205,7 +207,7 @@ export default function CreatePortofolio({
</Stack>
<Stack>
<ComponentGlobal_BoxInformation informasi="Upload Logo Bisnis Anda" />
<ComponentGlobal_BoxInformation informasi="Upload logo bisnis anda untuk ditampilkan dalam portofolio " />
<ComponentGlobal_BoxUploadImage>
{img ? (
<AspectRatio ratio={1 / 1} mah={265} mx={"auto"}>
@@ -218,17 +220,19 @@ export default function CreatePortofolio({
</AspectRatio>
) : (
<Stack spacing={5} justify="center" align="center" h={"100%"}>
<Title c={MainColor.white} order={3}>
Upload Logo Bisnis
</Title>
<Text c={MainColor.white} fs={"italic"} fz={10} align="center">
Masukan logo bisnis anda untuk ditampilkan dalam portofolio
</Text>
<IconPhoto size={100} />
</Stack>
)}
</ComponentGlobal_BoxUploadImage>
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFile}
onSetImage={setImg}
/>
</Center>
{/* <Center>
<FileButton
onChange={async (files: any | null) => {
try {
@@ -310,7 +314,7 @@ export default function CreatePortofolio({
</Button>
)}
</FileButton>
</Center>
</Center> */}
</Stack>
<Stack>
@@ -416,7 +420,8 @@ export default function CreatePortofolio({
dataPortofolio={dataPortofolio as any}
dataMedsos={dataMedsos}
profileId={profileId}
imageId={imageId}
//
file={file as File}
/>
</Stack>
</>

View File

@@ -1,19 +1,16 @@
"use client";
import { APIs } from "@/app/lib";
import {
AccentColor,
MainColor,
AccentColor
} from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_LoadImage } from "@/app_modules/_global/component";
import { Button, Center, FileButton, Image, Paper, Stack } from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
import {
ComponentGlobal_ButtonUploadFileImage,
ComponentGlobal_LoadImage,
} from "@/app_modules/_global/component";
import { Center, Image, Paper, Stack } from "@mantine/core";
import { useState } from "react";
import { MODEL_PORTOFOLIO } from "../../model/interface";
import { ComponentPortofolio_ButtonEditLogoBisnis } from "../../component";
import { MAX_SIZE } from "@/app_modules/_global/lib";
import { PemberitahuanMaksimalFile } from "@/app_modules/_global/lib/max_size";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
import { MODEL_PORTOFOLIO } from "../../model/interface";
export default function Portofolio_EditLogoBisnis({
dataPorto,
@@ -26,61 +23,30 @@ export default function Portofolio_EditLogoBisnis({
return (
<>
<Stack spacing={"xl"} px={"sm"}>
<Paper
p={"sm"}
style={{
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px ",
padding: "15px",
color: "white",
}}
>
<Stack align="center">
<Stack>
<Paper
p={"sm"}
style={{
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px ",
padding: "15px",
color: "white",
}}
>
{img ? (
<Image maw={250} alt="Image" src={img} />
) : (
<ComponentGlobal_LoadImage fileId={dataPorto.logoId} />
)}
<Center>
<FileButton
onChange={async (files: any | null) => {
try {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
if (files.size > MAX_SIZE) {
ComponentGlobal_NotifikasiPeringatan(
PemberitahuanMaksimalFile
);
} else {
setImg(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>
</Paper>
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFile}
onSetImage={setImg}
/>
</Center>
</Stack>
<ComponentPortofolio_ButtonEditLogoBisnis
file={file as any}
portofolioId={dataPorto.id}

View File

@@ -1,29 +1,31 @@
"use client";
import { DIRECTORY_ID } from "@/app/lib";
import { RouterHome } from "@/app/lib/router_hipmi/router_home";
import { AccentColor, MainColor } from "@/app_modules/_global/color";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { emailRegex } from "@/app_modules/katalog/component/regular_expressions";
import { clientLogger } from "@/util/clientLogger";
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 { clientLogger } from "@/util/clientLogger";
export function Profile_ComponentCreateNewProfile({
value,
fotoProfileId,
backgroundProfileId,
filePP,
fileBG,
}: {
value: MODEL_PROFILE;
fotoProfileId: string;
backgroundProfileId: string;
filePP: File;
fileBG: File;
}) {
const router = useRouter();
const [loading, setLoading] = useState(false);
@@ -40,19 +42,42 @@ export function Profile_ComponentCreateNewProfile({
if (!newData.email.match(emailRegex))
return ComponentGlobal_NotifikasiPeringatan("Format email salah");
if (fotoProfileId == "")
if (filePP == null)
return ComponentGlobal_NotifikasiPeringatan("Lengkapi foto profile");
if (backgroundProfileId == null)
if (fileBG == null)
return ComponentGlobal_NotifikasiPeringatan(
"Lengkapi background profile"
);
try {
setLoading(true);
const uploadPhoto = await funGlobal_UploadToStorage({
file: filePP,
dirId: DIRECTORY_ID.profile_foto,
});
if (!uploadPhoto.success) {
setLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
return;
}
const uploadBackground = await funGlobal_UploadToStorage({
file: fileBG,
dirId: DIRECTORY_ID.profile_background,
});
if (!uploadBackground.success) {
setLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
return;
}
const create = await funCreateNewProfile({
data: newData as any,
imageId: fotoProfileId,
imageBackgroundId: backgroundProfileId,
imageId: uploadPhoto.data.id,
imageBackgroundId: uploadBackground.data.id,
});
if (create.status === 201) {
@@ -61,16 +86,16 @@ export function Profile_ComponentCreateNewProfile({
}
if (create.status === 400) {
setLoading(true);
setLoading(false);
ComponentGlobal_NotifikasiGagal(create.message);
}
if (create.status === 500) {
setLoading(true);
setLoading(false);
ComponentGlobal_NotifikasiGagal(create.message);
}
} catch (error) {
setLoading(true);
setLoading(false);
clientLogger.error("Error create new profile:", error);
}
}

View File

@@ -1,5 +1,6 @@
"use client";
import { MainColor } from "@/app_modules/_global/color";
import { ComponentGlobal_ErrorInput } from "@/app_modules/_global/component";
import { Select, Stack, TextInput } from "@mantine/core";
import { IconAt } from "@tabler/icons-react";
@@ -8,13 +9,12 @@ import { emailRegex } from "../../component/regular_expressions";
import { Profile_ComponentCreateNewProfile } from "../_component";
import Profile_ViewUploadBackground from "./view_upload_background";
import Profile_ViewUploadFoto from "./view_upload_foto";
import { MainColor } from "@/app_modules/_global/color";
export default function CreateProfile() {
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 [fotoProfileId, setFotoProfileId] = useState("");
const [backgroundProfileId, setBackgroundProfileId] = useState("");
const [value, setValue] = useState({
name: "",
@@ -29,15 +29,15 @@ export default function CreateProfile() {
<Profile_ViewUploadFoto
imgPP={imgPP}
onSetImgPP={setImgPP}
fotoProfileId={fotoProfileId}
onSetFotoProfileId={setFotoProfileId}
filePP={filePP}
onSetFilePP={setFilePP}
/>
<Profile_ViewUploadBackground
imgBG={imgBG}
backgroundProfileId={backgroundProfileId}
onSetImgBG={setImgBG}
onSetBackgroundProfileId={setBackgroundProfileId}
fileBG={fileBG}
onSetFileBG={setFileBG}
/>
<Stack mb={"lg"}>
@@ -106,7 +106,7 @@ export default function CreateProfile() {
label: { color: MainColor.white },
input: { backgroundColor: MainColor.white },
required: { color: MainColor.red },
dropdown: { backgroundColor: MainColor.white }
dropdown: { backgroundColor: MainColor.white },
}}
withAsterisk
label="Jenis Kelamin"
@@ -125,8 +125,8 @@ export default function CreateProfile() {
<Profile_ComponentCreateNewProfile
value={value as any}
fotoProfileId={fotoProfileId}
backgroundProfileId={backgroundProfileId}
filePP={filePP as File}
fileBG={fileBG as File}
/>
</Stack>
</Stack>

View File

@@ -1,38 +1,28 @@
import { DIRECTORY_ID } from "@/app/lib";
import { MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_BoxInformation,
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
} from "@/app_modules/_global/component";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
import { clientLogger } from "@/util/clientLogger";
import {
AspectRatio,
Box,
Button,
Center,
FileButton,
Image,
Stack,
Text
Stack
} from "@mantine/core";
import { IconCamera, IconUpload } from "@tabler/icons-react";
import { IconPhoto } from "@tabler/icons-react";
import { useState } from "react";
export default function Profile_ViewUploadBackground({
imgBG,
onSetImgBG,
backgroundProfileId,
onSetBackgroundProfileId,
fileBG,
onSetFileBG,
}: {
imgBG: string;
onSetImgBG: (img: string | null) => void;
backgroundProfileId: string;
onSetBackgroundProfileId: (id: string) => void;
fileBG: File | null;
onSetFileBG: (file: File | null) => void;
}) {
const [isLoading, setLoading] = useState(false);
@@ -53,110 +43,16 @@ export default function Profile_ViewUploadBackground({
</AspectRatio>
) : (
<Stack justify="center" align="center" h={"100%"}>
<IconUpload color="white" />
<Text fz={"xs"} c={"white"}>
Upload Background
</Text>
<IconPhoto size={100} />
</Stack>
)}
</ComponentGlobal_BoxUploadImage>
<Center>
<FileButton
onChange={async (files: any | null) => {
try {
setLoading(true);
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
// if (files.size > MAX_SIZE) {
// ComponentGlobal_NotifikasiPeringatan(
// PemberitahuanMaksimalFile
// );
// onSetImgBG(null);
// return;
// }
if (backgroundProfileId != "") {
const deleteFotoBg = await funGlobal_DeleteFileById({
fileId: backgroundProfileId,
dirId: DIRECTORY_ID.profile_background,
});
if (!deleteFotoBg.success) {
clientLogger.error(
"Client failed delete background:" +
deleteFotoBg.message
);
return;
}
if (deleteFotoBg.success) {
onSetBackgroundProfileId("");
onSetImgBG(null);
const uploadBackground = await funGlobal_UploadToStorage({
file: files,
dirId: DIRECTORY_ID.profile_background,
});
if (!uploadBackground.success) {
clientLogger.error(
"Client failed upload background:" +
uploadBackground.message
);
return;
}
if (uploadBackground.success) {
onSetBackgroundProfileId(uploadBackground.data.id);
onSetImgBG(buffer);
} else {
ComponentGlobal_NotifikasiPeringatan(
"Gagal upload background profile"
);
}
}
} else {
const uploadBackground = await funGlobal_UploadToStorage({
file: files,
dirId: DIRECTORY_ID.profile_background,
});
if (uploadBackground.success) {
onSetBackgroundProfileId(uploadBackground.data.id);
onSetImgBG(buffer);
} else {
ComponentGlobal_NotifikasiPeringatan(
"Gagal upload background profile"
);
}
}
} catch (error) {
clientLogger.error("Client error upload background:", error);
} finally {
setLoading(false);
}
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
loading={isLoading}
loaderPosition="center"
radius={"xl"}
leftIcon={<IconCamera />}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload
</Button>
)}
</FileButton>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={onSetFileBG}
onSetImage={onSetImgBG}
/>
</Center>
</Stack>
</Box>

View File

@@ -1,42 +1,35 @@
import { DIRECTORY_ID } from "@/app/lib";
import { MainColor } from "@/app_modules/_global/color";
import { ComponentGlobal_BoxInformation } from "@/app_modules/_global/component";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
import { clientLogger } from "@/util/clientLogger";
ComponentGlobal_BoxInformation,
ComponentGlobal_ButtonUploadFileImage,
} from "@/app_modules/_global/component";
import {
Avatar,
Box,
Button,
Center,
FileButton,
Paper,
Stack
} from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
import { useState } from "react";
export default function Profile_ViewUploadFoto({
imgPP,
onSetImgPP,
fotoProfileId,
onSetFotoProfileId,
filePP,
onSetFilePP,
}: {
imgPP: string | null | undefined;
onSetImgPP: (img: string | null) => void;
fotoProfileId: string;
onSetFotoProfileId: (id: string) => void;
filePP: File | null;
onSetFilePP: (file: File | null) => void;
}) {
const [isLoadingButton, setLoadingButton] = useState(false);
const [isLoading, setLoading] = useState(false);
return (
<>
<Box>
<Stack spacing={"lg"}>
<ComponentGlobal_BoxInformation informasi="Upload foto profile anda dengan ukuran maksimal file 3 MB." />
<ComponentGlobal_BoxInformation informasi="Upload foto profile anda." />
<Center>
{imgPP != undefined || imgPP != null ? (
<Paper shadow="lg" radius={"100%"}>
@@ -70,6 +63,13 @@ export default function Profile_ViewUploadFoto({
</Center>
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={onSetFilePP}
onSetImage={onSetImgPP}
/>
</Center>
{/* <Center>
<FileButton
onChange={async (files: any | null) => {
try {
@@ -186,7 +186,7 @@ export default function Profile_ViewUploadFoto({
</Button>
)}
</FileButton>
</Center>
</Center> */}
</Stack>
</Box>
</>

View File

@@ -41,6 +41,7 @@ export default function UploadFotoProfile({
onSetImage={setImage}
/>
</Center>
<Profile_ComponentButtonUpdatePhotoProfile
file={file as any}
profileId={profile.id}

View File

@@ -4,24 +4,27 @@ import { MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { Button } from "@mantine/core";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { map_funCreatePin } from "../../fun/create/fun_create_pin";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
import { DIRECTORY_ID } from "@/app/lib";
export function ComponentMap_ButtonSavePin({
namePin,
lat,
long,
portofolioId,
imageId,
file,
}: {
namePin: string;
lat: string;
long: string;
portofolioId: string;
imageId: string;
file: File;
}) {
const router = useRouter();
const [loading, setLoading] = useState(false);
@@ -30,6 +33,19 @@ export function ComponentMap_ButtonSavePin({
try {
setLoading(true);
const uploadFile = await funGlobal_UploadToStorage({
file: file,
dirId: DIRECTORY_ID.map_image,
});
if (!uploadFile.success) {
setLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
return;
}
const imageId = uploadFile.data.id;
const res = await map_funCreatePin({
data: {
latitude: lat as any,
@@ -45,9 +61,9 @@ export function ComponentMap_ButtonSavePin({
? (ComponentGlobal_NotifikasiBerhasil(res.message), router.back())
: ComponentGlobal_NotifikasiGagal(res.message);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
console.error(error);
}
}
@@ -57,7 +73,7 @@ export function ComponentMap_ButtonSavePin({
loading={loading}
my={"xl"}
style={{ transition: "0.5s" }}
disabled={namePin === "" || imageId == "" ? true : false}
disabled={namePin === "" || file === null}
radius={"xl"}
loaderPosition="center"
bg={MainColor.yellow}

View File

@@ -33,6 +33,17 @@ export function ComponentMap_ButtonUpdateDataMap({
setIsLoading(true);
if (file !== null) {
const uploadFileToStorage = await funGlobal_UploadToStorage({
file: file,
dirId: DIRECTORY_ID.map_image,
});
if (!uploadFileToStorage.success) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
return;
}
const deleteLogo = await funGlobal_DeleteFileById({
fileId: data.imageId,
dirId: DIRECTORY_ID.map_image,
@@ -43,16 +54,6 @@ export function ComponentMap_ButtonUpdateDataMap({
clientLogger.error("Error delete logo", deleteLogo.message);
}
const uploadFileToStorage = await funGlobal_UploadToStorage({
file: file,
dirId: DIRECTORY_ID.map_image,
});
if (!uploadFileToStorage.success) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
return;
}
const res = await map_funEditMap({
data: data,
fileId: uploadFileToStorage.data.id,
@@ -91,7 +92,7 @@ export function ComponentMap_ButtonUpdateDataMap({
loading={isLoading}
mb={"xl"}
style={{ transition: "0.5s" }}
disabled={data.namePin === "" ? true : false}
disabled={data.namePin === "" || file === null}
radius={"xl"}
bg={MainColor.yellow}
color="yellow"

View File

@@ -1,10 +1,19 @@
"use client";
import { DIRECTORY_ID } from "@/app/lib";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_BoxUploadImage } from "@/app_modules/_global/component";
import {
ComponentGlobal_BoxInformation,
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
} from "@/app_modules/_global/component";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
import { MAX_SIZE } from "@/app_modules/_global/lib";
import { PemberitahuanMaksimalFile } from "@/app_modules/_global/lib/max_size";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
@@ -16,11 +25,9 @@ import {
Image,
Paper,
Stack,
Text,
TextInput,
Title,
} from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
import { IconCamera, IconPhoto } from "@tabler/icons-react";
import _ from "lodash";
import { useState } from "react";
import Map, {
@@ -31,11 +38,6 @@ import Map, {
} from "react-map-gl";
import { ComponentMap_ButtonSavePin } from "../_component";
import { defaultLatLong, defaultMapZoom } from "../lib/default_lat_long";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
import { DIRECTORY_ID } from "@/app/lib";
export function UiMap_CreatePin({
mapboxToken,
@@ -47,85 +49,92 @@ export function UiMap_CreatePin({
const [[lat, long], setLatLong] = useState([0, 0]);
const [isPin, setIsPin] = useState(false);
const [namePin, setNamePin] = useState("");
const [file, setFile] = useState<File | null>(null);
const [img, setImg] = useState<any | null>(null);
const [imageId, setImageId] = useState("");
return (
<>
<Stack>
<Map
mapboxAccessToken={mapboxToken}
mapStyle={"mapbox://styles/mapbox/streets-v11"}
initialViewState={{
latitude: defaultLatLong[0],
longitude: defaultLatLong[1],
zoom: defaultMapZoom,
}}
style={{
cursor: "pointer",
width: "100%",
height: "60vh",
borderRadius: "10px",
}}
onClick={(a) => {
setLatLong([a.lngLat.lat, a.lngLat.lng]);
setIsPin(true);
}}
attributionControl={false}
>
<Marker
<Stack spacing={50}>
{/* Map Pin */}
<Stack spacing={"sm"}>
<ComponentGlobal_BoxInformation informasi="Tentukan lokasi pin map dengan klik pada peta." />
<Map
mapboxAccessToken={mapboxToken}
mapStyle={"mapbox://styles/mapbox/streets-v11"}
initialViewState={{
latitude: defaultLatLong[0],
longitude: defaultLatLong[1],
zoom: defaultMapZoom,
}}
style={{
color: "red",
width: 40,
// height: 40,
cursor: "pointer",
width: "100%",
height: "60vh",
borderRadius: "10px",
}}
latitude={lat}
longitude={long}
anchor="bottom"
onClick={(a) => {
setLatLong([a.lngLat.lat, a.lngLat.lng]);
setIsPin(true);
}}
attributionControl={false}
>
<Stack spacing={0}>
<Image
w={"100%"}
alt="image"
src="https://cdn-icons-png.flaticon.com/512/5860/5860579.png"
/>
</Stack>
</Marker>
<NavigationControl />
<ScaleControl position="top-left" />
<AttributionControl customAttribution="Map design by PT. Bali Interaktif Perkasa" />
</Map>
<Marker
style={{
color: "red",
width: 40,
// height: 40,
cursor: "pointer",
}}
latitude={lat}
longitude={long}
anchor="bottom"
>
<Stack spacing={0}>
<Image
w={"100%"}
alt="image"
src="https://cdn-icons-png.flaticon.com/512/5860/5860579.png"
/>
</Stack>
</Marker>
<NavigationControl />
<ScaleControl position="top-left" />
<AttributionControl customAttribution="Map design by PT. Bali Interaktif Perkasa" />
</Map>
<Paper
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
color: "white",
}}
>
<TextInput
disabled={isPin ? false : true}
style={{ transition: "0.5s" }}
styles={{ label: { color: isPin ? MainColor.white : "gray" },
input: {
backgroundColor: MainColor.white
},
required: {
color: MainColor.red,
} }}
label="Nama Pin"
placeholder="Masukan nama pin map"
withAsterisk
onChange={(val) => {
setNamePin(_.startCase(val.currentTarget.value));
<Paper
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
color: "white",
}}
/>
</Paper>
>
<TextInput
disabled={isPin ? false : true}
style={{ transition: "0.5s" }}
styles={{
label: { color: isPin ? MainColor.white : "gray" },
input: {
backgroundColor: MainColor.white,
},
required: {
color: MainColor.red,
},
}}
label="Nama Pin"
placeholder="Masukan nama pin map"
withAsterisk
onChange={(val) => {
setNamePin(_.startCase(val.currentTarget.value));
}}
/>
</Paper>
</Stack>
<Stack>
<Stack spacing={"sm"}>
<ComponentGlobal_BoxInformation informasi="Upload foto lokasi bisnis anda untuk ditampilkan dalam detail map." />
<ComponentGlobal_BoxUploadImage>
{img ? (
<AspectRatio ratio={1 / 1} mah={265} mx={"auto"}>
@@ -138,100 +147,16 @@ export function UiMap_CreatePin({
</AspectRatio>
) : (
<Stack spacing={5} justify="center" align="center" h={"100%"}>
<Title c={MainColor.white} order={3}>Foto Lokasi Bisnis</Title>
<Text c={MainColor.white} fs={"italic"} fz={10} align="center">
Upload foto lokasi bisnis anda untuk ditampilkan dalam detail
map
</Text>
<IconPhoto size={100} />
</Stack>
)}
</ComponentGlobal_BoxUploadImage>
<Center>
<FileButton
onChange={async (files: any | null) => {
try {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
if (files.size > MAX_SIZE) {
setImg(null);
ComponentGlobal_NotifikasiPeringatan(
PemberitahuanMaksimalFile,
3000
);
return;
}
// if (files.size > MAX_SIZE) {
// setImg(null);
// ComponentGlobal_NotifikasiPeringatan(
// PemberitahuanMaksimalFile,
// 3000
// );
// } else {
// setImg(buffer);
// }
if (imageId != "") {
const deletePhoto = await funGlobal_DeleteFileById({
fileId: imageId,
});
if (deletePhoto.success) {
setImageId("");
const uploadPhoto = await funGlobal_UploadToStorage({
file: files,
dirId: DIRECTORY_ID.map_image,
});
if (uploadPhoto.success) {
setImageId(uploadPhoto.data.id);
setImg(buffer);
} else {
ComponentGlobal_NotifikasiPeringatan(
"Gagal upload gambar"
);
}
}
} else {
const uploadPhoto = await funGlobal_UploadToStorage({
file: files,
dirId: DIRECTORY_ID.map_image,
});
if (uploadPhoto.success) {
setImageId(uploadPhoto.data.id);
setImg(buffer);
} else {
ComponentGlobal_NotifikasiPeringatan(
"Gagal upload gambar"
);
}
}
} catch (error) {
console.log(error);
}
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
disabled={isPin ? false : true}
{...props}
radius={"xl"}
leftIcon={<IconCamera />}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload
</Button>
)}
</FileButton>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFile}
onSetImage={setImg}
/>
</Center>
</Stack>
@@ -240,7 +165,7 @@ export function UiMap_CreatePin({
lat={lat as any}
long={long as any}
portofolioId={portofolioId}
imageId={imageId}
file={file as File}
/>
</Stack>
</>

View File

@@ -1,18 +1,22 @@
"use client";
import { RouterPortofolio } from "@/app/lib/router_hipmi/router_katalog";
import { RouterMap } from "@/app/lib/router_hipmi/router_map";
import { APIs, DIRECTORY_ID } from "@/app/lib";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_ButtonUploadFileImage } from "@/app_modules/_global/component";
import ComponentGlobal_BoxInformation from "@/app_modules/_global/component/box_information";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
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 { Avatar, Button, Center, FileButton, Stack } from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
import { clientLogger } from "@/util/clientLogger";
import { Avatar, Button, Center, Stack } from "@mantine/core";
import { useRouter } from "next/navigation";
import { useState } from "react";
import {
@@ -25,14 +29,6 @@ import {
import { map_funCustomPinMap } from "../fun";
import { defaultMapZoom } from "../lib/default_lat_long";
import { MODEL_MAP } from "../lib/interface";
import { APIs, DIRECTORY_ID } from "@/app/lib";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
import { MAX_SIZE } from "@/app_modules/_global/lib";
import { PemberitahuanMaksimalFile } from "@/app_modules/_global/lib/max_size";
import { clientLogger } from "@/util/clientLogger";
export function UiMap_CustomPin({
dataMap,
@@ -55,7 +51,7 @@ export function UiMap_CustomPin({
<Stack>
<ComponentGlobal_BoxInformation
informasi={
"Pin map akan secara otomatis menampilkan logo pada porotofolio ini, jika anda ingin melakukan custom silahkan upload logo pin baru anda !"
"Pin map akan secara otomatis menampilkan logo pada porotofolio ini, jika anda ingin melakukan custom silahkan upload logo pin baru anda."
}
/>
@@ -90,40 +86,10 @@ export function UiMap_CustomPin({
)}
<Center>
<FileButton
onChange={async (files: any | null) => {
try {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
if (files.size > MAX_SIZE) {
ComponentGlobal_NotifikasiPeringatan(
PemberitahuanMaksimalFile,
3000
);
} else {
setImgPin(buffer);
setFilePin(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>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFilePin}
onSetImage={setImgPin}
/>
</Center>
</Stack>
@@ -201,14 +167,6 @@ function ButtonSimpan({
async function onCustom() {
try {
setLoading(true);
const deletePin = await funGlobal_DeleteFileById({
fileId: fileRemoveId,
dirId: DIRECTORY_ID.map_pin,
});
if (!deletePin.success) {
setLoading(false);
clientLogger.error("Error delete logo", deletePin.message);
}
const uploadFileToStorage = await funGlobal_UploadToStorage({
file: filePin,
@@ -221,6 +179,15 @@ function ButtonSimpan({
return;
}
const deletePin = await funGlobal_DeleteFileById({
fileId: fileRemoveId,
dirId: DIRECTORY_ID.map_pin,
});
if (!deletePin.success) {
setLoading(false);
clientLogger.error("Error delete logo", deletePin.message);
}
const res = await map_funCustomPinMap({
mapId: mapId,
fileId: uploadFileToStorage.data.id,

View File

@@ -7,6 +7,7 @@ import {
} from "@/app_modules/_global/color/color_pallet";
import {
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
ComponentGlobal_LoadImage,
} from "@/app_modules/_global/component";
import ComponentGlobal_BoxInformation from "@/app_modules/_global/component/box_information";
@@ -49,89 +50,100 @@ export function UiMap_EditMap({
return (
<>
<Stack spacing={30} px={"sm"}>
<Map
mapboxAccessToken={mapboxToken}
mapStyle={"mapbox://styles/mapbox/streets-v11"}
initialViewState={{
latitude: data.latitude,
longitude: data.longitude,
zoom: defaultMapZoom,
}}
style={{
cursor: "pointer",
width: "100%",
height: "60vh",
borderRadius: "10px",
}}
onClick={(a) => {
setData({
...data,
latitude: a.lngLat.lat,
longitude: a.lngLat.lng,
});
}}
attributionControl={false}
>
<Marker
style={{
color: "red",
width: 40,
// height: 40,
cursor: "pointer",
<Stack spacing={50} px={"sm"}>
<Stack spacing={"sm"}>
<ComponentGlobal_BoxInformation informasi="Tentukan lokasi pin map dengan klik pada peta." />
<Map
mapboxAccessToken={mapboxToken}
mapStyle={"mapbox://styles/mapbox/streets-v11"}
initialViewState={{
latitude: data.latitude,
longitude: data.longitude,
zoom: defaultMapZoom,
}}
latitude={data.latitude}
longitude={data.longitude}
anchor="bottom"
>
<Avatar
src={
data.pinId === null
? APIs.GET({ fileId: dataMap.Portofolio.logoId, size: "400" })
: APIs.GET({ fileId: data.pinId, size: "400" })
}
alt="Logo"
style={{
border: `2px solid ${AccentColor.softblue}`,
backgroundColor: "white",
borderRadius: "100%",
}}
/>
</Marker>
<NavigationControl />
<ScaleControl position="top-left" />
<AttributionControl customAttribution="Map design by PT. Bali Interaktif Perkasa" />
</Map>
<Paper
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
color: "white",
}}
>
<TextInput
style={{ transition: "0.5s", }}
styles={{ label: { color: MainColor.white }, required: { color: MainColor.red }, input: { backgroundColor: MainColor.white } }}
label="Nama Pin"
placeholder="Masukan nama pin map"
value={data.namePin}
withAsterisk
onChange={(val) => {
style={{
cursor: "pointer",
width: "100%",
height: "60vh",
borderRadius: "10px",
}}
onClick={(a) => {
setData({
...data,
namePin: val.currentTarget.value,
latitude: a.lngLat.lat,
longitude: a.lngLat.lng,
});
}}
/>
</Paper>
attributionControl={false}
>
<Marker
style={{
color: "red",
width: 40,
// height: 40,
cursor: "pointer",
}}
latitude={data.latitude}
longitude={data.longitude}
anchor="bottom"
>
<Avatar
src={
data.pinId === null
? APIs.GET({
fileId: dataMap.Portofolio.logoId,
size: "400",
})
: APIs.GET({ fileId: data.pinId, size: "400" })
}
alt="Logo"
style={{
border: `2px solid ${AccentColor.softblue}`,
backgroundColor: "white",
borderRadius: "100%",
}}
/>
</Marker>
<NavigationControl />
<ScaleControl position="top-left" />
<AttributionControl customAttribution="Map design by PT. Bali Interaktif Perkasa" />
</Map>
<Paper
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
color: "white",
}}
>
<TextInput
style={{ transition: "0.5s" }}
styles={{
label: { color: MainColor.white },
required: { color: MainColor.red },
input: { backgroundColor: MainColor.white },
}}
label="Nama Pin"
placeholder="Masukan nama pin map"
value={data.namePin}
withAsterisk
onChange={(val) => {
setData({
...data,
namePin: val.currentTarget.value,
});
}}
/>
</Paper>
</Stack>
{/* Photo Usaha */}
<Stack spacing={"xs"}>
<ComponentGlobal_BoxInformation informasi="Masukan photo toko atau tempat usaha anda !" />
<ComponentGlobal_BoxInformation informasi="Upload foto lokasi bisnis anda untuk ditampilkan dalam detail map." />
<ComponentGlobal_BoxUploadImage>
{img ? (
@@ -144,6 +156,13 @@ export function UiMap_EditMap({
</ComponentGlobal_BoxUploadImage>
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFile}
onSetImage={setImg}
/>
</Center>
{/* <Center>
<FileButton
onChange={async (files: any | null) => {
try {
@@ -178,7 +197,7 @@ export function UiMap_EditMap({
</Button>
)}
</FileButton>
</Center>
</Center> */}
</Stack>
<ComponentMap_ButtonUpdateDataMap data={data as any} file={file} />

View File

@@ -29,7 +29,7 @@ const middlewareConfig: MiddlewareConfig = {
"/api/collaboration/*",
"/api/notifikasi/*",
"/api/logs/*",
"/api/image/*",
// "/api/image/*",
"/api/job/*",
"/api/auth/*",
"/api/origin-url",