Merge pull request #241 from bipproduction/join

Fix function upload image & API
This commit is contained in:
Bagasbanuna02
2025-01-16 12:31:06 +08:00
committed by GitHub
88 changed files with 2353 additions and 2468 deletions

View File

@@ -2,6 +2,8 @@
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
## [1.2.40](https://github.com/bipproduction/hipmi/compare/v1.2.39...v1.2.40) (2025-01-16)
## [1.2.39](https://github.com/bipproduction/hipmi/compare/v1.2.38...v1.2.39) (2025-01-12)
## [1.2.38](https://github.com/bipproduction/hipmi/compare/v1.2.37...v1.2.38) (2025-01-03)

View File

@@ -1,16 +1,16 @@
{
"name": "hipmi",
"version": "1.2.39",
"version": "1.2.40",
"private": true,
"prisma": {
"seed": "npx tsx prisma/seed.ts --yes"
"seed": "bun prisma/seed.ts"
},
"scripts": {
"dev": "bun --bun run next dev --experimental-https",
"build": "NODE_OPTIONS='--max-old-space-size=2048' bun --bun run next build",
"build:dev": "bun --bun run next build",
"start": "bun --bun run next start",
"lint": "bun --bun run next lint",
"dev": "next dev --experimental-https",
"build": "next build",
"build:dev": "next build",
"start": "next start",
"lint": "next lint",
"ver": "bunx commit-and-tag-version -- --prerelease"
},
"dependencies": {

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

@@ -2,38 +2,48 @@ import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
// GET ONE DATA INVESTASI BY ID
export async function GET(request: Request, context: { params: { id: string } }) {
try {
const { id } = context.params
const data = await prisma.investasi.findUnique({
where: {
id: id,
},
select: {
id: true,
title: true,
targetDana: true,
hargaLembar: true,
totalLembar: true,
roi: true,
countDown: true,
catatan: true,
sisaLembar: true,
imageId: true,
masterPencarianInvestorId: true,
masterPeriodeDevidenId: true,
masterPembagianDevidenId: true,
}
});
export async function GET(
request: Request,
context: { params: { id: string } }
) {
try {
const { id } = context.params;
const data = await prisma.investasi.findUnique({
where: {
id: id,
},
include: {
author: {
include: {
Profile: true,
},
},
Investasi_Invoice: true,
MasterStatusInvestasi: true,
BeritaInvestasi: true,
DokumenInvestasi: true,
ProspektusInvestasi: true,
MasterPembagianDeviden: true,
MasterPencarianInvestor: true,
MasterPeriodeDeviden: true,
MasterProgresInvestasi: true,
},
});
return NextResponse.json({ success: true, message: "Berhasil mendapatkan data", data }, { status: 200 });
}
catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal mendapatkan data, coba lagi nanti ", reason: (error as Error).message, }, { status: 500 });
}
}
return NextResponse.json(
{ success: true, message: "Berhasil mendapatkan data", data },
{ status: 200 }
);
} catch (error) {
console.error(error);
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan data, coba lagi nanti ",
reason: (error as Error).message,
},
{ status: 500 }
);
}
}

View File

@@ -0,0 +1,85 @@
import { prisma } from "@/app/lib";
import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
export async function GET(
request: Request,
context: { params: { id: string } }
) {
// if (request.method === "GET") {
// return NextResponse.json(
// { success: false, message: "Method not allowed" },
// { status: 405 }
// );
// }
try {
let fixData;
const { id } = context.params;
const { searchParams } = new URL(request.url);
const kategori: string | null = searchParams.get("kategori");
const page = searchParams.get("page");
const takeData = 10;
const skipData = Number(page) * takeData - takeData;
if (!kategori) {
fixData = await prisma.beritaInvestasi.findFirst({
where: {
id: id,
},
include: {
investasi: {
select: {
authorId: true,
},
},
},
});
} else if (kategori == "get-all") {
fixData = await prisma.beritaInvestasi.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
investasiId: id,
active: true,
},
});
}
await prisma.$disconnect();
return NextResponse.json(
{ success: true, message: "Success get data news", data: fixData },
{ status: 200 }
);
} catch (error) {
await prisma.$disconnect();
backendLogger.error("Error get data news", error);
return NextResponse.json(
{
success: false,
message: "Failed to get data, try again later",
reason: (error as Error).message,
},
{ status: 500 }
);
}
}
async function main({ id }: { id: string }) {
const fixData = await prisma.beritaInvestasi.findMany({
take: 10,
skip: 0,
orderBy: {
updatedAt: "desc",
},
where: {
investasiId: id.trim(),
active: true,
},
});
console.log("data sebelum disconnect>>", fixData);
}

View File

@@ -0,0 +1,61 @@
import { prisma } from "@/app/lib";
import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
export async function GET(
request: Request,
context: { params: { id: string } }
) {
if (request.method === "GET") {
try {
let fixData;
const { id } = context.params;
const { searchParams } = new URL(request.url);
const kategori = searchParams.get("kategori");
const page = searchParams.get("page");
const takeData = 10;
const skipData = Number(page) * takeData - takeData;
if (kategori == null) {
fixData = await prisma.dokumenInvestasi.findFirst({
where: {
id: id,
},
});
} else if (kategori == "get-all") {
fixData = await prisma.dokumenInvestasi.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
investasiId: id,
active: true,
},
});
}
await prisma.$disconnect();
return NextResponse.json(
{ success: true, message: "Success get data document", data: fixData },
{ status: 200 }
);
} catch (error) {
backendLogger.error("Error get data document", error);
return NextResponse.json(
{
success: false,
message: "Failed to get data, try again later",
reason: (error as Error).message,
},
{ status: 500 }
);
}
}
return NextResponse.json(
{ success: false, message: "Method not allowed" },
{ status: 405 }
);
}

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,12 +1,12 @@
import { investasi_funGetOneBeritaById } from "@/app_modules/investasi/_fun";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { Investasi_UiDetailBerita } from "@/app_modules/investasi/_ui";
export default async function Page({ params }: { params: { id: string } }) {
const beritaId = params.id;
const dataBerita = await investasi_funGetOneBeritaById({ beritaId });
export default async function Page() {
const userLoginId = await funGetUserIdByToken();
return (
<>
<Investasi_UiDetailBerita dataBerita={dataBerita} />
<Investasi_UiDetailBerita userLoginId={userLoginId} />
</>
);
}

View File

@@ -1,14 +1,9 @@
import { investasi_funGetBeritaById } from "@/app_modules/investasi/_fun";
import { Investasi_UiDaftarBerita } from "@/app_modules/investasi/_ui";
export default async function Page({ params }: { params: { id: string } }) {
const investasiId = params.id;
const dataBerita = await investasi_funGetBeritaById({ investasiId });
export default async function Page() {
return (
<>
<Investasi_UiDaftarBerita dataBerita={dataBerita} />
<Investasi_UiDaftarBerita />
</>
);
}

View File

@@ -1,17 +1,9 @@
import { investasi_funGetBeritaById } from "@/app_modules/investasi/_fun";
import { Investasi_UiRekapBerita } from "@/app_modules/investasi/_ui";
export default async function Page({ params }: { params: { id: string } }) {
const investasiId = params.id;
const dataBerita = await investasi_funGetBeritaById({ investasiId });
export default async function Page() {
return (
<>
<Investasi_UiRekapBerita
investasiId={investasiId}
dataBerita={dataBerita}
/>
<Investasi_UiRekapBerita />
</>
);
}

View File

@@ -1,10 +1,9 @@
import { Investasi_UiCreateBerita } from "@/app_modules/investasi/_ui";
export default async function Page({ params }: { params: { id: string } }) {
const investasiId = params.id;
export default async function Page() {
return (
<>
<Investasi_UiCreateBerita investasiId={investasiId} />
<Investasi_UiCreateBerita />
</>
);
}

View File

@@ -1,11 +1,9 @@
import { Investasi_UiCreateDocument } from "@/app_modules/investasi/_ui";
export default async function Page({ params }: { params: { id: string } }) {
const investasiId = params.id;
export default async function Page() {
return (
<>
<Investasi_UiCreateDocument investasiId={investasiId} />
<Investasi_UiCreateDocument />
</>
);
}

View File

@@ -1,21 +1,9 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { investasi_funGetOneInvestasiById } from "@/app_modules/investasi/_fun";
import { Investasi_UiDetailPortofolio } from "@/app_modules/investasi/_ui";
export default async function Page({ params }: { params: { id: string } }) {
const investasiId = params.id;
const userLoginId = await funGetUserIdByToken();
const dataPortofolio = await investasi_funGetOneInvestasiById({
investasiId,
});
export default async function Page() {
return (
<>
<Investasi_UiDetailPortofolio
dataInvestasi={dataPortofolio as any}
userLoginId={userLoginId as string}
/>
<Investasi_UiDetailPortofolio />
</>
);
}

View File

@@ -1,21 +1,9 @@
import {
investasi_funGetAllDocumentById
} from "@/app_modules/investasi/_fun";
import { Investasi_UiDaftarDokmen } from "@/app_modules/investasi/_ui";
export default async function Page({ params }: { params: { id: string } }) {
const investasiId = params.id;
const dataDokumen = await investasi_funGetAllDocumentById({
investasiId: investasiId,
page: 1,
});
export default async function Page() {
return (
<>
<Investasi_UiDaftarDokmen
dataDokumen={dataDokumen}
investasiId={investasiId}
/>
<Investasi_UiDaftarDokmen />
</>
);
}

View File

@@ -1,19 +1,9 @@
import { investasi_funGetAllDocumentById } from "@/app_modules/investasi/_fun";
import { Investasi_UiRekapDokumen } from "@/app_modules/investasi/_ui";
export default async function Page({ params }: { params: { id: string } }) {
const investasiId = params.id;
const dataDokumen = await investasi_funGetAllDocumentById({
investasiId,
page: 1,
});
export default async function Page() {
return (
<>
<Investasi_UiRekapDokumen
investasiId={investasiId}
dataDokumen={dataDokumen}
/>
<Investasi_UiRekapDokumen />
</>
);
}

View File

@@ -1,38 +1,8 @@
import { investasi_funGetOneInvestasiById } from "@/app_modules/investasi/_fun";
import { Investasi_UiEditInvestasi, Investasi_UiEditInvestasiNew } from "@/app_modules/investasi/_ui";
import getPembagianDeviden from "@/app_modules/investasi/fun/master/get_pembagian_deviden";
import getPencarianInvestor from "@/app_modules/investasi/fun/master/get_pencarian_investor";
import getPeriodeDeviden from "@/app_modules/investasi/fun/master/get_periode_deviden";
import _ from "lodash";
export default async function Page({ params }: { params: { id: string } }) {
// const investasiId = params.id;
// const allData = await investasi_funGetOneInvestasiById({ investasiId });
// const dataInvestasi = _.omit(allData, [
// "BeritaInvestasi",
// "DokumenInvestasi",
// "MasterPembagianDeviden",
// "MasterPencarianInvestor",
// "MasterProgresInvestasi",
// "MasterStatusInvestasi",
// "ProspektusInvestasi",
// "MasterPeriodeDeviden",
// "author",
// ]);
// const listPencarian = await getPencarianInvestor();
// const listPeriode = await getPeriodeDeviden();
// const listPembagian = await getPembagianDeviden();
import { Investasi_UiEditInvestasiNew } from "@/app_modules/investasi/_ui";
export default async function Page() {
return (
<>
{/* <Investasi_UiEditInvestasi
dataInvestasi={dataInvestasi}
pembagianDeviden={listPembagian}
pencarianInvestor={listPencarian}
periodeDeviden={listPeriode}
/> */}
<Investasi_UiEditInvestasiNew />
</>
);

View File

@@ -1,14 +1,9 @@
import { investasi_funGetOneDocumentById } from "@/app_modules/investasi/_fun";
import { Investasi_UiEditDokumen } from "@/app_modules/investasi/_ui";
export default async function Page({ params }: { params: { id: string } }) {
const documentId = params.id;
const dataDokumen = await investasi_funGetOneDocumentById({ documentId });
export default async function Page() {
return (
<>
<Investasi_UiEditDokumen dataDokumen={dataDokumen} />
<Investasi_UiEditDokumen/>
</>
);
}

View File

@@ -1,11 +1,10 @@
import { Investasi_UiEditProspektus } from "@/app_modules/investasi/_ui";
export default async function Page({ params }: { params: { id: string } }) {
const investasiId = params.id;
export default async function Page() {
return (
<>
<Investasi_UiEditProspektus investasiId={investasiId} />
<Investasi_UiEditProspektus />
</>
);
}

View File

@@ -1,8 +0,0 @@
import { LayoutEditDokumenInvestasi } from "@/app_modules/investasi";
import React from "react";
export default async function Layout({children, params}: {children: React.ReactNode, params: {id: string}}) {
return<>
<LayoutEditDokumenInvestasi idInves={params.id}>{children}</LayoutEditDokumenInvestasi>
</>
}

View File

@@ -1,10 +0,0 @@
import { EditDokumenInvestasi } from "@/app_modules/investasi";
import getOneInvestasiById from "@/app_modules/investasi/fun/get_one_investasi_by_id";
export default async function Page({params}: {params: {id: string}}) {
const dataInvestasi = await getOneInvestasiById(params.id)
// console.log(dataInvestasi)
return<>
<EditDokumenInvestasi dataInvestasi={dataInvestasi as any} />
</>
}

View File

@@ -1,21 +0,0 @@
import { LayoutEditProspektusInvestasi } from "@/app_modules/investasi";
import getOneInvestasiById from "@/app_modules/investasi/fun/get_one_investasi_by_id";
import React from "react";
export default async function Layout({
children,
params,
}: {
children: React.ReactNode;
params: { id: string };
}) {
const dataInvestasi = await getOneInvestasiById(params.id);
return (
<>
<LayoutEditProspektusInvestasi dataInvestasi={dataInvestasi as any}>
{children}
</LayoutEditProspektusInvestasi>
</>
);
}

View File

@@ -1,12 +0,0 @@
import { EditProspektusInvestasi } from "@/app_modules/investasi";
import getOneInvestasiById from "@/app_modules/investasi/fun/get_one_investasi_by_id";
export default async function Page({ params }: { params: { id: string } }) {
const dataInvestasi = await getOneInvestasiById(params.id);
// console.log(dataInvestasi);
return (
<>
<EditProspektusInvestasi dataInvestasi={dataInvestasi as any} />
</>
);
}

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

@@ -1,3 +1,4 @@
import { useDisclosure } from "@mantine/hooks";
import { PrismaClient } from "@prisma/client";
// Singleton PrismaClient untuk pengembangan
@@ -20,8 +21,9 @@ if (process.env.NODE_ENV !== "production") {
}
process.on("SIGINT", async () => {
console.log("Disconnecting PrismaClient...");
await prisma.$disconnect();3
// console.log("Start in Disconnecting PrismaClient...");
const disconnect = await prisma.$disconnect();
// console.log("End of Disconnecting PrismaClient...", 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,16 +2,23 @@
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,
text,
icon,
accept,
}: {
onSetFile: File | any;
onSetImage: any | null;
onSetFile: File | null | any;
onSetImage?: any | null;
text?: string;
icon?: string | any
accept?: string;
}) {
const [isLoading, setIsLoading] = useState(false);
@@ -24,20 +31,21 @@ 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");
return
}
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={accept ? accept : "image/png,image/png,image/jpeg,image/gif"}
>
{(props) => (
<Button
@@ -45,12 +53,14 @@ 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={icon ? icon : <IconUpload color="black" size={20} />}
c={MainColor.darkblue}
>
Upload
{text ? text : "Upload"}
</Button>
)}
</FileButton>

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,24 @@ export default function ComponentGlobal_BoxInformation({
</Text>
</Stack>
) : (
<Group>
<Text fz={fonsize ? fonsize : 12} c={"red"} fw={"bold"}>
*{" "}
<Text span inherit c={MainColor.white} fw={"normal"}>
<Grid>
<Grid.Col span={1}>
<IconInfoCircle color={MainColor.white} />
</Grid.Col>
<Grid.Col span={10}>
<Text
fz={fonsize ? fonsize : 12}
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) {
return { success: false, message: "Token not found" };
}
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

@@ -65,6 +65,7 @@ export function Investasi_ComponentButtonCreateNewInvestasi({
dirId: DIRECTORY_ID.investasi_prospektus,
});
if (!uploadFilePdf.success) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload file pdf");
return;
}
@@ -104,17 +105,16 @@ export function Investasi_ComponentButtonCreateNewInvestasi({
router.push(NEW_RouterInvestasi.portofolio({ id: "2" }));
setActiveTab("Review");
setHotMenu(1);
setIsLoading(true);
ComponentGlobal_NotifikasiBerhasil(res.message);
}
} else {
setIsLoading(false);
ComponentGlobal_NotifikasiGagal(res.message);
}
} catch (error) {
clientLogger.error("Error create new investasi", error);
} finally {
setIsLoading(false);
}
clientLogger.error("Error create new investasi", error);
}
}
return (

View File

@@ -6,11 +6,15 @@ import {
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { DIRECTORY_ID } from "@/app/lib";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
import _ from "lodash";
import { investasi_funUpdateInvestasi } from "../../_fun";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { clientLogger } from "@/util/clientLogger";
export function Investasi_ComponentButtonUpdateDataInvestasi({
data,
@@ -37,11 +41,21 @@ export function Investasi_ComponentButtonUpdateDataInvestasi({
file: file as any,
dirId: DIRECTORY_ID.investasi_image,
});
if (!uploadImage.success) {
setIsLoading(false);
return ComponentGlobal_NotifikasiPeringatan("Gagal upload file gambar");
}
const deleteFile = await funGlobal_DeleteFileById({
fileId: data.imageId,
});
if (!deleteFile.success) {
setIsLoading(false);
clientLogger.error("Error delete file:", deleteFile.message);
}
const updtWithImage = await investasi_funUpdateInvestasi({
data: data,
imageId: uploadImage.data.id,

View File

@@ -17,7 +17,7 @@ import {
Text,
} from "@mantine/core";
import { IconDots, IconEdit, IconTrash } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { MODEL_INVESTASI_DOKUMEN } from "../../_lib/interface";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
@@ -30,6 +30,8 @@ import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { apiGetDokumenInvestasiById } from "../../_lib/api_interface";
import { clientLogger } from "@/util/clientLogger";
export function Investasi_ComponentCardRekapDocument({
data,
@@ -38,6 +40,9 @@ export function Investasi_ComponentCardRekapDocument({
data: MODEL_INVESTASI_DOKUMEN;
onSetData: (val: any) => any[];
}) {
const params = useParams<{ id: string }>();
const investasiId = params.id;
const router = useRouter();
const [openDrawer, setOpenDrawer] = useState(false);
const [isLoadingEdit, setIsLoadingEdit] = useState(false);
@@ -63,18 +68,22 @@ export function Investasi_ComponentCardRekapDocument({
if (deleteFromDB.status !== 200) {
ComponentGlobal_NotifikasiPeringatan(deleteFromDB.message);
return;
}
ComponentGlobal_NotifikasiBerhasil(deleteFromDB.message);
setOpenModal(false);
const loadData = await investasi_funGetAllDocumentById({
investasiId: data.investasiId,
page: 1,
const respone = await apiGetDokumenInvestasiById({
id: investasiId,
kategori: "get-all",
page: "1",
});
onSetData(loadData);
if (respone.success) {
onSetData(respone.data);
}
} catch (error) {
console.log(error);
clientLogger.error("Error hapus dokumen", error);
} finally {
setIsLoadingDelete(false);
}

View File

@@ -0,0 +1,46 @@
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
import { Box, Center, Stack } from "@mantine/core";
export { Investasi_SkeletonEditProspektus, Investasi_SkeletonListDokumen };
function Investasi_SkeletonEditProspektus() {
return (
<>
<Stack>
<CustomSkeleton h={70} radius={"md"} />
<CustomSkeleton h={70} radius={"md"} />
<Center>
<CustomSkeleton h={40} w={100} radius={"xl"} />
</Center>
<Box
style={{
display: "flex",
justifyContent: "center",
}}
>
<Box
style={{
transition: "all 0.3s ease",
position: "absolute",
bottom: 20,
width: "90%",
}}
>
<CustomSkeleton h={40} width={"100%"} radius={"xl"} />
</Box>
</Box>
</Stack>
</>
);
}
function Investasi_SkeletonListDokumen() {
return (
<>
<Stack>
<CustomSkeleton h={70} radius={"md"} />
<CustomSkeleton h={70} radius={"md"} />
</Stack>
</>
);
}

View File

@@ -1,13 +1,17 @@
"use server"
"use server";
import { prisma } from "@/app/lib"
import { prisma } from "@/app/lib";
export async function investasi_funGetOneDocumentById({ documentId }: { documentId: string }) {
const data = await prisma.dokumenInvestasi.findFirst({
where: {
id: documentId
}
})
export async function investasi_funGetOneDocumentById({
documentId,
}: {
documentId: string;
}) {
const data = await prisma.dokumenInvestasi.findFirst({
where: {
id: documentId,
},
});
return data
}
return data;
}

View File

@@ -1,3 +1,19 @@
import { data } from "autoprefixer";
export const apiGetOneInvestasiById = async ({ id }: { id: string }) => {
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
if (!token) return await token.json().catch(() => null);
const response = await fetch(`/api/new/investasi/${id}`, {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"Access-Control-Allow-Origin": "*",
Authorization: `Bearer ${token}`,
},
});
return await response.json().catch(() => null);
};
export const apiGetMasterInvestasi = async (path?: string) => {
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
if (!token) return await token.json().catch(() => null);
@@ -14,21 +30,6 @@ export const apiGetMasterInvestasi = async (path?: string) => {
return await response.json().catch(() => null);
};
export const apiGetOneInvestasiById = async (path: string) => {
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
if (!token) return await token.json().catch(() => null);
const response = await fetch(`/api/new/investasi/${path}`, {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"Access-Control-Allow-Origin": "*",
Authorization: `Bearer ${token}`,
},
});
return await response.json().catch(() => null);
};
export const apiGetAllInvestasi = async (path?: string) => {
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
if (!token) return await token.json().catch(() => null);
@@ -62,3 +63,55 @@ export const apiGetAllSahamSaya = async (path?: string) => {
);
return await response.json().catch(() => null);
};
export const apiGetDokumenInvestasiById = async ({
id,
kategori,
page,
}: {
id: string;
kategori?: undefined | "get-all";
page?: string;
}) => {
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
if (!token) return await token.json().catch(() => null);
const response = await fetch(
`/api/new/investasi/dokumen/${id}${kategori ? `?kategori=${kategori}&page=${page}` : ""}`,
{
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"Access-Control-Allow-Origin": "*",
Authorization: `Bearer ${token}`,
},
}
);
return await response.json().catch(() => null);
};
export const apiGetBeritaInvestasiById = async ({
id,
kategori,
page,
}: {
id: string;
kategori?: undefined | "get-all";
page?: string;
}) => {
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
if (!token) return await token.json().catch(() => null);
const onCategory = kategori ? `?kategori=${kategori}&page=${page}` : "";
const response = await fetch(`/api/new/investasi/berita/${id}${onCategory}`, {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"Access-Control-Allow-Origin": "*",
Authorization: `Bearer ${token}`,
},
});
return await response.json().catch(() => null);
};

View File

@@ -6,17 +6,13 @@ import {
} from "@/app_modules/_global/ui";
import { Investasi_ViewCreateBerita } from "../../_view";
export function Investasi_UiCreateBerita({
investasiId,
}: {
investasiId: string;
}) {
export function Investasi_UiCreateBerita() {
return (
<>
<UIGlobal_LayoutTamplate
header={<UIGlobal_LayoutHeaderTamplate title="Tambah Berita" />}
>
<Investasi_ViewCreateBerita investasiId={investasiId} />
<Investasi_ViewCreateBerita />
</UIGlobal_LayoutTamplate>
</>
);

View File

@@ -3,13 +3,13 @@
import { UIGlobal_LayoutHeaderTamplate, UIGlobal_LayoutTamplate } from "@/app_modules/_global/ui"
import { Investasi_ViewCreateDocument } from "../../_view";
export function Investasi_UiCreateDocument({ investasiId }: { investasiId : string}) {
export function Investasi_UiCreateDocument() {
return (
<>
<UIGlobal_LayoutTamplate
header={<UIGlobal_LayoutHeaderTamplate title="Tambah Dokumen" />}
>
<Investasi_ViewCreateDocument investasiId={investasiId}/>
<Investasi_ViewCreateDocument />
</UIGlobal_LayoutTamplate>
</>
);

View File

@@ -10,40 +10,82 @@ import {
UIGlobal_DrawerCustom,
UIGlobal_LayoutHeaderTamplate,
UIGlobal_LayoutTamplate,
UIGlobal_Modal
UIGlobal_Modal,
} from "@/app_modules/_global/ui";
import { ActionIcon, Button, Center, Stack, Text } from "@mantine/core";
import { IconDotsVertical, IconTrash } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { investasi_funDeleteBerita } from "../../_fun";
import { Investasi_ViewDetailBerita } from "../../_view";
import { DIRECTORY_ID } from "@/app/lib";
import { clientLogger } from "@/util/clientLogger";
import { useShallowEffect } from "@mantine/hooks";
import { apiGetBeritaInvestasiById } from "../../_lib/api_interface";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
export function Investasi_UiDetailBerita({
userLoginId,
}: {
userLoginId: string;
}) {
const params = useParams<{ id: string }>();
const id = params.id;
export function Investasi_UiDetailBerita({ dataBerita }: { dataBerita: any }) {
const router = useRouter();
const [openDrawer, setOpenDrawer] = useState(false);
const [openModal, setOpenModal] = useState(false);
const [data, setData] = useState(dataBerita);
const [data, setData] = useState<any | null>(null);
const [isLoading, setLoading] = useState(false);
async function onDelete() {
const del = await investasi_funDeleteBerita({
beritaId: dataBerita.id,
});
useShallowEffect(() => {
onLoadData();
}, []);
if (del.status === 200) {
const deleteImage = await funGlobal_DeleteFileById({
fileId: data.imageId,
async function onLoadData() {
try {
const respone = await apiGetBeritaInvestasiById({
id: id,
});
if (!deleteImage.success) {
ComponentGlobal_NotifikasiPeringatan("Gagal hapus gambar ");
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get detail berita", error);
}
}
ComponentGlobal_NotifikasiBerhasil(del.message);
setOpenModal(false);
router.back();
} else {
ComponentGlobal_NotifikasiGagal(del.message);
async function onDelete() {
try {
setLoading(true);
const del = await investasi_funDeleteBerita({
beritaId: id,
});
if (del.status === 200) {
if (data.imageId != null) {
const deleteImage = await funGlobal_DeleteFileById({
fileId: data.imageId,
dirId: DIRECTORY_ID.investasi_berita,
});
if (!deleteImage.success) {
setLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal hapus gambar ");
}
}
router.back();
ComponentGlobal_NotifikasiBerhasil(del.message);
setOpenModal(false);
} else {
setLoading(false);
ComponentGlobal_NotifikasiGagal(del.message);
}
} catch (error) {
setLoading(false);
clientLogger.error("Error delete berita", error);
}
}
@@ -54,17 +96,21 @@ export function Investasi_UiDetailBerita({ dataBerita }: { dataBerita: any }) {
<UIGlobal_LayoutHeaderTamplate
title="Detail Berita"
customButtonRight={
<ActionIcon
variant="transparent"
onClick={() => setOpenDrawer(true)}
>
<IconDotsVertical color="white" />
</ActionIcon>
data && userLoginId === data.investasi.authorId ? (
<ActionIcon
variant="transparent"
onClick={() => setOpenDrawer(true)}
>
<IconDotsVertical color="white" />
</ActionIcon>
) : (
""
)
}
/>
}
>
<Investasi_ViewDetailBerita dataBerita={data} />
<Investasi_ViewDetailBerita />
</UIGlobal_LayoutTamplate>
<UIGlobal_DrawerCustom
@@ -100,6 +146,8 @@ export function Investasi_UiDetailBerita({ dataBerita }: { dataBerita: any }) {
}
buttonKanan={
<Button
loaderPosition="center"
loading={isLoading}
radius="xl"
color="red"
onClick={() => {

View File

@@ -6,16 +6,12 @@ import {
} from "@/app_modules/_global/ui";
import { Investasi_ViewDaftarBerita } from "../../_view";
export function Investasi_UiDaftarBerita({
dataBerita,
}: {
dataBerita: any[];
}) {
export function Investasi_UiDaftarBerita() {
return (
<UIGlobal_LayoutTamplate
header={<UIGlobal_LayoutHeaderTamplate title="Daftar Berita" />}
>
<Investasi_ViewDaftarBerita dataBerita={dataBerita} />
<Investasi_ViewDaftarBerita />
</UIGlobal_LayoutTamplate>
);
}

View File

@@ -6,22 +6,13 @@ import {
} from "@/app_modules/_global/ui";
import { Investasi_ViewDaftarDokumen } from "../../_view";
export function Investasi_UiDaftarDokmen({
dataDokumen,
investasiId,
}: {
dataDokumen: any[];
investasiId: string
}) {
export function Investasi_UiDaftarDokmen() {
return (
<>
<UIGlobal_LayoutTamplate
header={<UIGlobal_LayoutHeaderTamplate title="Daftar Dokumen" />}
>
<Investasi_ViewDaftarDokumen
dataDokumen={dataDokumen}
investasiId={investasiId}
/>
<Investasi_ViewDaftarDokumen />
</UIGlobal_LayoutTamplate>
</>
);

View File

@@ -1,63 +1,93 @@
"use client";
import { NEW_RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import { MainColor } from "@/app_modules/_global/color";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import {
UIGlobal_Drawer,
UIGlobal_DrawerCustom,
UIGlobal_LayoutHeaderTamplate,
UIGlobal_LayoutTamplate,
} from "@/app_modules/_global/ui";
import { ActionIcon, Box, SimpleGrid, Stack, Text } from "@mantine/core";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
import { clientLogger } from "@/util/clientLogger";
import { ActionIcon, SimpleGrid, Stack, Text } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import {
IconCategoryPlus,
IconDotsVertical,
IconEdit,
IconFilePencil,
} from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { apiGetOneInvestasiById } from "../../_lib/api_interface";
import { MODEL_INVESTASI } from "../../_lib/interface";
import {
Investasi_ViewDetailDraft,
Investasi_ViewDetailReject,
Investasi_ViewDetailReview,
} from "../../_view";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { MainColor } from "@/app_modules/_global/color";
export function Investasi_UiDetailPortofolio({
dataInvestasi,
userLoginId,
}: {
dataInvestasi: MODEL_INVESTASI;
userLoginId: string;
}) {
export function Investasi_UiDetailPortofolio() {
const params = useParams<{ id: string }>();
const investasiId = params.id;
const router = useRouter();
const [isLoading, setLoading] = useState(false);
const [pageId, setPageId] = useState("");
const [openDrawer, setOpenDrawer] = useState(false);
const [data, setData] = useState<any>(dataInvestasi);
const [data, setData] = useState<MODEL_INVESTASI | null>(null);
const listPage = [
{
id: "1",
name: "Edit Investasi",
icon: <IconEdit />,
path: NEW_RouterInvestasi.edit_investasi({ id: data.id }),
path: NEW_RouterInvestasi.edit_investasi({ id: investasiId }),
},
{
id: "2",
name: "Edit Prospektus",
icon: <IconFilePencil />,
path: NEW_RouterInvestasi.edit_prospektus({ id: data.id }),
path: NEW_RouterInvestasi.edit_prospektus({ id: investasiId }),
},
{
id: "3",
name: "Tambah & Edit Dokumen",
icon: <IconCategoryPlus />,
path: NEW_RouterInvestasi.rekap_dokumen({ id: data.id }),
path: NEW_RouterInvestasi.rekap_dokumen({ id: investasiId }),
},
];
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
const respone = await apiGetOneInvestasiById({
id: investasiId,
});
if (respone.success) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get detail investasi:", error);
}
}
if (data === null) {
return (
<>
<UIGlobal_LayoutTamplate
header={<UIGlobal_LayoutHeaderTamplate title={`Detail`} />}
>
<CustomSkeleton height={"80vh"} />
</UIGlobal_LayoutTamplate>
</>
);
}
if (data.masterStatusInvestasiId == "3")
return (
<>
@@ -76,15 +106,9 @@ export function Investasi_UiDetailPortofolio({
/>
}
>
<Investasi_ViewDetailDraft dataInvestasi={dataInvestasi} />
<Investasi_ViewDetailDraft dataInvestasi={data} />
</UIGlobal_LayoutTamplate>
{/* <UIGlobal_Drawer
opened={openDrawer}
close={() => setOpenDrawer(false)}
component={listPage}
/> */}
<UIGlobal_DrawerCustom
opened={openDrawer}
close={() => setOpenDrawer(false)}
@@ -98,9 +122,7 @@ export function Investasi_UiDetailPortofolio({
onClick={() => {
setPageId(e?.id);
setLoading(true);
if (e.id === "1") {
setData({});
}
router.push(e?.path, { scroll: false });
}}
>
@@ -125,16 +147,16 @@ export function Investasi_UiDetailPortofolio({
<UIGlobal_LayoutTamplate
header={
<UIGlobal_LayoutHeaderTamplate
title={`Detail ${dataInvestasi.MasterStatusInvestasi.name}`}
title={`Detail ${data.MasterStatusInvestasi.name}`}
/>
}
>
{dataInvestasi.masterStatusInvestasiId === "2" && (
<Investasi_ViewDetailReview dataInvestasi={dataInvestasi} />
{data.masterStatusInvestasiId === "2" && (
<Investasi_ViewDetailReview dataInvestasi={data} />
)}
{dataInvestasi.masterStatusInvestasiId === "4" && (
<Investasi_ViewDetailReject dataInvestasi={dataInvestasi} />
{data.masterStatusInvestasiId === "4" && (
<Investasi_ViewDetailReject dataInvestasi={data} />
)}
</UIGlobal_LayoutTamplate>
);

View File

@@ -1,5 +1,6 @@
"use client";
import { NEW_RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import {
UIGlobal_Drawer,
UIGlobal_LayoutHeaderTamplate,
@@ -7,19 +8,13 @@ import {
} from "@/app_modules/_global/ui";
import { ActionIcon } from "@mantine/core";
import { IconCirclePlus, IconDotsVertical } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useParams } from "next/navigation";
import { useState } from "react";
import { Investasi_ViewRekapBerita } from "../../_view";
import { NEW_RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
export function Investasi_UiRekapBerita({
investasiId,
dataBerita,
}: {
investasiId: string;
dataBerita: any[]
}) {
const router = useRouter();
export function Investasi_UiRekapBerita() {
const params = useParams<{ id: string }>();
const investasiId = params.id;
const [openDrawer, setOpenDrawer] = useState(false);
const listPage = [
@@ -32,32 +27,32 @@ export function Investasi_UiRekapBerita({
];
return (
<UIGlobal_LayoutTamplate
header={
<UIGlobal_LayoutHeaderTamplate
title="Rekap Berita"
customButtonRight={
<ActionIcon
variant="transparent"
onClick={() => {
setOpenDrawer(true);
}}
>
<IconDotsVertical color="white" />
</ActionIcon>
}
/>
}
>
<Investasi_ViewRekapBerita dataBerita={dataBerita} />
<>
<UIGlobal_LayoutTamplate
header={
<UIGlobal_LayoutHeaderTamplate
title="Rekap Berita"
customButtonRight={
<ActionIcon
variant="transparent"
onClick={() => {
setOpenDrawer(true);
}}
>
<IconDotsVertical color="white" />
</ActionIcon>
}
/>
}
>
<Investasi_ViewRekapBerita />
</UIGlobal_LayoutTamplate>
<UIGlobal_Drawer
opened={openDrawer}
close={() => setOpenDrawer(false)}
component={listPage}
/>
</UIGlobal_LayoutTamplate>
</>
);
}

View File

@@ -10,16 +10,13 @@ import { ActionIcon } from "@mantine/core";
import { IconCirclePlus, IconDotsVertical } from "@tabler/icons-react";
import { useState } from "react";
import { Investasi_ViewRekapDokumen } from "../../_view";
import { useParams } from "next/navigation";
export function Investasi_UiRekapDokumen() {
const params = useParams<{ id: string }>();
const investasiId = params.id;
export function Investasi_UiRekapDokumen({
investasiId,
dataDokumen,
}: {
investasiId: string;
dataDokumen: any[]
}) {
const [openDrawer, setOpenDrawer] = useState(false);
const listPage = [
{
id: "1",
@@ -47,8 +44,6 @@ export function Investasi_UiRekapDokumen({
}
>
<Investasi_ViewRekapDokumen
dataDokumen={dataDokumen}
investasiId={investasiId}
/>
</UIGlobal_LayoutTamplate>

View File

@@ -6,13 +6,13 @@ import {
} from "@/app_modules/_global/ui";
import { Investasi_ViewEditDokumen } from "../../_view";
export function Investasi_UiEditDokumen({ dataDokumen }: { dataDokumen: any }) {
export function Investasi_UiEditDokumen() {
return (
<>
<UIGlobal_LayoutTamplate
header={<UIGlobal_LayoutHeaderTamplate title="Edit Dokumen" />}
>
<Investasi_ViewEditDokumen dataDokumen={dataDokumen} />
<Investasi_ViewEditDokumen />
</UIGlobal_LayoutTamplate>
</>
);

View File

@@ -1,6 +1,7 @@
"use client";
import { UIGlobal_LayoutHeaderTamplate, UIGlobal_LayoutTamplate, } from "@/app_modules/_global/ui";
import { Investasi_ViewEditInvestasiNew } from "../../_view/edit/vew_edit_investasi_new";
import { Investasi_ViewEditInvestasiNew } from "../../_view/edit/view_edit_investasi_new";
export function Investasi_UiEditInvestasiNew() {
return (

View File

@@ -6,17 +6,13 @@ import {
} from "@/app_modules/_global/ui";
import { Investasi_ViewEditProspektus } from "../../_view";
export function Investasi_UiEditProspektus({
investasiId,
}: {
investasiId: string;
}) {
export function Investasi_UiEditProspektus() {
return (
<>
<UIGlobal_LayoutTamplate
header={<UIGlobal_LayoutHeaderTamplate title="Edit Prospektus" />}
>
<Investasi_ViewEditProspektus investasiId={investasiId} />
<Investasi_ViewEditProspektus />
</UIGlobal_LayoutTamplate>
</>
);

View File

@@ -1,39 +1,37 @@
import { AccentColor, MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_BoxInformation,
ComponentGlobal_BoxUploadImage,
ComponentGlobal_InputCountDown,
} from "@/app_modules/_global/component";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import {
AspectRatio,
Button,
Center,
FileButton,
Image,
Stack,
Text,
TextInput,
Textarea,
} from "@mantine/core";
import { IconCamera, IconUpload } from "@tabler/icons-react";
import { DIRECTORY_ID } from "@/app/lib";
import { MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_BoxInformation,
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
ComponentGlobal_InputCountDown,
} from "@/app_modules/_global/component";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiGagal,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { clientLogger } from "@/util/clientLogger";
import {
AspectRatio,
Button,
Center,
Image,
Stack,
TextInput,
Textarea,
} from "@mantine/core";
import { Prisma } from "@prisma/client";
import { useRouter } from "next/navigation";
import { IconPhoto } from "@tabler/icons-react";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { investasi_funCreateBerita } from "../../_fun";
export function Investasi_ViewCreateBerita({
investasiId,
}: {
investasiId: string;
}) {
export function Investasi_ViewCreateBerita() {
const params = useParams<{ id: string }>();
const investasiId = params.id;
const router = useRouter();
const [file, setFile] = useState<File | null>(null);
const [img, setImg] = useState<any | null>();
@@ -48,9 +46,6 @@ export function Investasi_ViewCreateBerita({
});
async function onCreate() {
if (data.data.title == "" || data.data.deskripsi == "")
return ComponentGlobal_NotifikasiPeringatan("Lengkapi data");
try {
setIsLoading(true);
if (file != null) {
@@ -59,32 +54,39 @@ export function Investasi_ViewCreateBerita({
dirId: DIRECTORY_ID.investasi_berita,
});
if (!uploadFile.success)
return ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
if (!uploadFile.success) {
ComponentGlobal_NotifikasiPeringatan("Gagal upload gambar");
return;
}
const createWithFile = await investasi_funCreateBerita({
data: data.data as any,
fileId: uploadFile.data.id,
});
createWithFile.status === 201
? (ComponentGlobal_NotifikasiBerhasil(createWithFile.message),
router.back())
: ComponentGlobal_NotifikasiGagal(createWithFile.message);
if (createWithFile.status === 201) {
ComponentGlobal_NotifikasiBerhasil(createWithFile.message);
router.back();
} else {
setIsLoading(false);
ComponentGlobal_NotifikasiGagal(createWithFile.message);
}
} else {
const createNoFile = await investasi_funCreateBerita({
data: data.data as any,
});
createNoFile.status === 201
? (ComponentGlobal_NotifikasiBerhasil(createNoFile.message),
router.back())
: ComponentGlobal_NotifikasiGagal(createNoFile.message);
if (createNoFile.status === 201) {
ComponentGlobal_NotifikasiBerhasil(createNoFile.message);
router.back();
} else {
setIsLoading(false);
ComponentGlobal_NotifikasiGagal(createNoFile.message);
}
}
} catch (error) {
console.log(error);
} finally {
setIsLoading(false);
clientLogger.error("Error create news", error);
}
}
@@ -106,43 +108,16 @@ export function Investasi_ViewCreateBerita({
</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())])
);
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>
@@ -187,6 +162,10 @@ export function Investasi_ViewCreateBerita({
</Stack>
<Button
disabled={data.data.title === "" || data.data.deskripsi === ""}
style={{
transition: "all 0.5s",
}}
loaderPosition="center"
loading={isLoading}
my={"md"}

View File

@@ -1,51 +1,53 @@
import { DIRECTORY_ID } from "@/app/lib";
import { MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_BoxInformation,
ComponentGlobal_ButtonUploadFileImage,
ComponentGlobal_CardStyles,
} from "@/app_modules/_global/component";
import {
Stack,
Grid,
Center,
Group,
FileButton,
Button,
Text,
TextInput,
} from "@mantine/core";
import { IconCircleCheck, IconCamera } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { investasi_funCreateDocument } from "../../_fun";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
import { DIRECTORY_ID } from "@/app/lib";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { clientLogger } from "@/util/clientLogger";
import {
Box,
Button,
Center,
Grid,
Stack,
Text,
TextInput,
} from "@mantine/core";
import { IconCircleCheck, IconFileTypePdf } from "@tabler/icons-react";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { investasi_funCreateDocument } from "../../_fun";
export function Investasi_ViewCreateDocument() {
const params = useParams<{ id: string }>();
const investasiId = params.id;
export function Investasi_ViewCreateDocument({
investasiId,
}: {
investasiId: string;
}) {
const router = useRouter();
const [filePdf, setFilePdf] = useState<File | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [title, setTitle] = useState("");
async function onCreate() {
setIsLoading(true);
const uploadFileDokumen = await funGlobal_UploadToStorage({
file: filePdf as any,
dirId: DIRECTORY_ID.investasi_dokumen,
});
if (!uploadFileDokumen.success) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload file pdf");
}
try {
setIsLoading(true);
const uploadFileDokumen = await funGlobal_UploadToStorage({
file: filePdf as any,
dirId: DIRECTORY_ID.investasi_dokumen,
});
if (!uploadFileDokumen.success) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload file pdf");
return;
}
const create = await investasi_funCreateDocument({
data: {
investasiId: investasiId,
@@ -54,15 +56,17 @@ export function Investasi_ViewCreateDocument({
},
});
if (create.status !== 201)
if (create.status !== 201) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan(create.message);
return;
}
router.back();
ComponentGlobal_NotifikasiBerhasil(create.message);
router.back();
} catch (error) {
console.log(error);
} finally {
setIsLoading(false);
clientLogger.error("Error create document", error);
}
}
@@ -73,6 +77,7 @@ export function Investasi_ViewCreateDocument({
<Stack>
<TextInput
withAsterisk
label="Judul Dokumen"
placeholder="Masukan judul dokumen"
styles={{
@@ -84,9 +89,9 @@ export function Investasi_ViewCreateDocument({
/>
<ComponentGlobal_CardStyles marginBottom={"0px"}>
{!filePdf ? (
<Text lineClamp={1} align="center" c={"gray"}>
Upload Dokumen
</Text>
<Stack justify="center" align="center" h={"100%"}>
<IconFileTypePdf size={40} color="gray" />
</Stack>
) : (
<Grid align="center">
<Grid.Col span={2}></Grid.Col>
@@ -104,55 +109,43 @@ export function Investasi_ViewCreateDocument({
)}
</ComponentGlobal_CardStyles>
<Group position="center">
<FileButton
accept={"application/pdf"}
onChange={async (files: any) => {
try {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
setFilePdf(files);
} catch (error) {
console.log(error);
}
}}
>
{(props) => (
<Button
leftIcon={<IconCamera />}
{...props}
radius={"xl"}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload Dokumen
</Button>
)}
</FileButton>
</Group>
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFilePdf}
accept="application/pdf"
text="Upload Dokumen"
/>
</Center>
</Stack>
<Button
loaderPosition="center"
loading={isLoading}
disabled={filePdf === null || title === ""}
mt={50}
radius={50}
bg={MainColor.yellow}
color="yellow"
c={"black"}
<Box
style={{
transition: "0.5s",
}}
onClick={() => {
onCreate();
display: "flex",
justifyContent: "center",
}}
>
Simpan
</Button>
<Button
loaderPosition="center"
loading={isLoading}
disabled={filePdf === null || title === ""}
mt={50}
radius={50}
bg={MainColor.yellow}
color="yellow"
c={"black"}
style={{
transition: "0.5s",
position: "absolute",
bottom: 20,
width: "90%",
}}
onClick={() => {
onCreate();
}}
>
Simpan
</Button>
</Box>
</Stack>
</>
);

View File

@@ -3,29 +3,55 @@ import {
ComponentGlobal_LoadImageLandscape,
} from "@/app_modules/_global/component";
import { Stack, Text, Title } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { Prisma } from "@prisma/client";
import { useParams } from "next/navigation";
import { useState } from "react";
import { apiGetBeritaInvestasiById } from "../../_lib/api_interface";
import { clientLogger } from "@/util/clientLogger";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
export function Investasi_ViewDetailBerita({
dataBerita,
}: {
dataBerita: any;
}) {
const [data, setData] =
useState<Prisma.BeritaInvestasiGetPayload<{}>>(dataBerita);
type MODEL_DATA = Prisma.BeritaInvestasiGetPayload<{}>;
export function Investasi_ViewDetailBerita() {
const params = useParams<{ id: string }>();
const id = params.id;
const [data, setData] = useState<MODEL_DATA | null>(null);
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
const respone = await apiGetBeritaInvestasiById({
id: id,
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get detail berita", error);
}
}
if (!data) {
return <CustomSkeleton height={300} width={"100%"} />;
}
return (
<>
<ComponentGlobal_CardStyles>
<Stack>
{data.imageId == null ? (
""
) : (
<ComponentGlobal_LoadImageLandscape fileId={data.imageId} />
{data.imagesId && (
<ComponentGlobal_LoadImageLandscape
fileId={data.imageId as string}
/>
)}
<Title order={4} align="center">
{" "}
{data.title}
</Title>

View File

@@ -3,43 +3,104 @@ import {
ComponentGlobal_CardStyles,
ComponentGlobal_CardLoadingOverlay,
} from "@/app_modules/_global/component";
import { Box, Title } from "@mantine/core";
import { useRouter } from "next/navigation";
import { clientLogger } from "@/util/clientLogger";
import { Box, Center, Title } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { Investasi_SkeletonListDokumen } from "../../_component/skeleton_view";
import { apiGetBeritaInvestasiById } from "../../_lib/api_interface";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { ScrollOnly } from "next-scroll-loader";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import _ from "lodash";
export function Investasi_ViewDaftarBerita() {
const params = useParams<{ id: string }>();
const investasiId = params.id;
export function Investasi_ViewDaftarBerita({
dataBerita,
}: {
dataBerita: any[];
}) {
const router = useRouter();
const [data, setData] = useState(dataBerita);
const [data, setData] = useState<any[] | null>(null);
const [activePage, setActivePage] = useState(1);
const [visible, setVisible] = useState(false);
const [dataId, setDataId] = useState("");
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
const respone = await apiGetBeritaInvestasiById({
id: investasiId,
kategori: "get-all",
page: `${activePage}`,
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get daftar berita", error);
}
}
if (data === null) {
return <Investasi_SkeletonListDokumen />;
}
return (
<>
<Box>
{data.map((e, i) => (
<ComponentGlobal_CardStyles
key={i}
onClickHandler={() => {
router.push(NEW_RouterInvestasi.berita({ id: e.id }), {
scroll: false,
});
setVisible(true);
setDataId(e.id);
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
<Box>
<ScrollOnly
height="90vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData as any}
moreData={async () => {
try {
const respone = await apiGetBeritaInvestasiById({
id: investasiId,
kategori: "get-all",
page: `${activePage + 1}`,
});
if (respone.success) {
setActivePage((val) => val + 1);
return respone.data;
}
} catch (error) {
clientLogger.error("Error load data dokumen:", error);
}
}}
>
<Title order={6} lineClamp={1}>
{e.title}
</Title>
{visible && dataId === e.id && (
<ComponentGlobal_CardLoadingOverlay />
{(item) => (
<ComponentGlobal_CardStyles
onClickHandler={() => {
router.push(NEW_RouterInvestasi.berita({ id: item.id }), {
scroll: false,
});
setVisible(true);
}}
>
<Title order={6} lineClamp={1}>
{item.title}
</Title>
{visible && <ComponentGlobal_CardLoadingOverlay />}
</ComponentGlobal_CardStyles>
)}
</ComponentGlobal_CardStyles>
))}
</Box>
</ScrollOnly>
</Box>
)}
</>
);
}

View File

@@ -7,17 +7,43 @@ import { useState } from "react";
import { Investasi_ComponentCardDaftarDocument } from "../../_component";
import { investasi_funGetAllDocumentById } from "../../_fun";
import { MODEL_INVESTASI_DOKUMEN } from "../../_lib/interface";
import { useParams } from "next/navigation";
import { Investasi_SkeletonListDokumen } from "../../_component/skeleton_view";
import { clientLogger } from "@/util/clientLogger";
import { apiGetDokumenInvestasiById } from "../../_lib/api_interface";
import { useShallowEffect } from "@mantine/hooks";
export function Investasi_ViewDaftarDokumen({
dataDokumen,
investasiId,
}: {
dataDokumen: any[];
investasiId: string;
}) {
const [data, setData] = useState<MODEL_INVESTASI_DOKUMEN[]>(dataDokumen);
export function Investasi_ViewDaftarDokumen() {
const params = useParams<{ id: string }>();
const investasiId = params.id;
const [data, setData] = useState<MODEL_INVESTASI_DOKUMEN[] | null>(null);
const [activePage, setActivePage] = useState(1);
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
const respone = await apiGetDokumenInvestasiById({
id: investasiId,
kategori: "get-all",
page: `${activePage}`,
});
if (respone.success) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get data dokumen", error);
}
}
if (data === null) {
return <Investasi_SkeletonListDokumen />;
}
return (
<>
<Stack>
@@ -34,16 +60,23 @@ export function Investasi_ViewDaftarDokumen({
</Center>
)}
data={data}
setData={setData}
setData={setData as any}
moreData={async () => {
const loadData = await investasi_funGetAllDocumentById({
investasiId: investasiId,
page: activePage + 1,
});
try {
const respone = await apiGetDokumenInvestasiById({
id: investasiId,
kategori: "get-all",
page: `${activePage + 1}`,
});
setActivePage((val) => val + 1);
if (respone.success) {
setActivePage((val) => val + 1);
return loadData;
return respone.data;
}
} catch (error) {
clientLogger.error("Error load data dokumen:", error);
}
}}
>
{(item) => (

View File

@@ -1,45 +1,108 @@
"use client";
import { NEW_RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import {
ComponentGlobal_CardLoadingOverlay,
ComponentGlobal_CardStyles,
} from "@/app_modules/_global/component";
import { Box, Group, Title } from "@mantine/core";
import { useRouter } from "next/navigation";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { clientLogger } from "@/util/clientLogger";
import { Box, Center, Title } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { Investasi_SkeletonListDokumen } from "../../_component/skeleton_view";
import { apiGetBeritaInvestasiById } from "../../_lib/api_interface";
export function Investasi_ViewRekapBerita() {
const params = useParams<{ id: string }>();
const investasiId = params.id;
export function Investasi_ViewRekapBerita({
dataBerita,
}: {
dataBerita: any[];
}) {
const router = useRouter();
const [data, setData] = useState(dataBerita);
const [data, setData] = useState<any[] | null>(null);
const [activePage, setActivePage] = useState(1);
const [visible, setVisible] = useState(false);
const [dataId, setDataId] = useState("");
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
const respone = await apiGetBeritaInvestasiById({
id: investasiId,
kategori: "get-all",
page: `${activePage}`,
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get data berita", error);
}
}
if (data === null) {
return <Investasi_SkeletonListDokumen />;
}
return (
<>
<Box>
{data.map((e, i) => (
<ComponentGlobal_CardStyles
key={i}
onClickHandler={() => {
router.push(NEW_RouterInvestasi.berita({ id: e.id }), {
scroll: false,
});
setVisible(true);
setDataId(e.id);
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
<Box>
<ScrollOnly
height="90vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData as any}
moreData={async () => {
try {
const respone = await apiGetBeritaInvestasiById({
id: investasiId,
kategori: "get-all",
page: `${activePage + 1}`,
});
if (respone.success) {
setActivePage((val) => val + 1);
return respone.data;
}
} catch (error) {
clientLogger.error("Error load data dokumen:", error);
}
}}
>
<Title order={6} lineClamp={1}>
{e.title}
</Title>
{visible && dataId === e.id && (
<ComponentGlobal_CardLoadingOverlay />
{(item) => (
<ComponentGlobal_CardStyles
onClickHandler={() => {
router.push(NEW_RouterInvestasi.berita({ id: item.id }), {
scroll: false,
});
setVisible(true);
}}
>
<Title order={6} lineClamp={1}>
{item.title}
</Title>
{visible && (
<ComponentGlobal_CardLoadingOverlay />
)}
</ComponentGlobal_CardStyles>
)}
</ComponentGlobal_CardStyles>
))}
</Box>
</ScrollOnly>
</Box>
)}
</>
);
}

View File

@@ -8,17 +8,41 @@ import { Investasi_ComponentCardRekapDocument } from "../../_component";
import { investasi_funGetAllDocumentById } from "../../_fun";
import { MODEL_INVESTASI_DOKUMEN } from "../../_lib/interface";
import { useShallowEffect } from "@mantine/hooks";
import { useParams } from "next/navigation";
import { apiGetDokumenInvestasiById } from "../../_lib/api_interface";
import { Investasi_SkeletonListDokumen } from "../../_component/skeleton_view";
import { clientLogger } from "@/util/clientLogger";
export function Investasi_ViewRekapDokumen({
dataDokumen,
investasiId,
}: {
dataDokumen: any[];
investasiId: string;
}) {
const [data, setData] = useState<MODEL_INVESTASI_DOKUMEN[]>(dataDokumen);
export function Investasi_ViewRekapDokumen() {
const params = useParams<{ id: string }>();
const investasiId = params.id;
const [data, setData] = useState<MODEL_INVESTASI_DOKUMEN[] | null>(null);
const [activePage, setActivePage] = useState(1);
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
const respone = await apiGetDokumenInvestasiById({
id: investasiId,
kategori: "get-all",
page: `${activePage}`,
});
if (respone.success) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get data dokumen", error);
}
}
if (data === null) {
return <Investasi_SkeletonListDokumen />;
}
return (
<>
@@ -34,16 +58,23 @@ export function Investasi_ViewRekapDokumen({
</Center>
)}
data={data}
setData={setData}
setData={setData as any}
moreData={async () => {
const loadData = await investasi_funGetAllDocumentById({
investasiId: investasiId,
page: activePage + 1,
});
try {
const respone = await apiGetDokumenInvestasiById({
id: investasiId,
kategori: "get-all",
page: `${activePage + 1}`,
});
setActivePage((val) => val + 1);
if (respone.success) {
setActivePage((val) => val + 1);
return loadData;
return respone.data;
}
} catch (error) {
clientLogger.error("Error load data dokumen:", error);
}
}}
>
{(item) => (

View File

@@ -1,420 +0,0 @@
import { MainColor } from "@/app_modules/_global/color";
import { ComponentGlobal_BoxInformation, ComponentGlobal_BoxUploadImage, ComponentGlobal_LoadImage, } from "@/app_modules/_global/component";
import { AspectRatio, Box, Button, FileButton, Group, Image, Select, Stack, Text, TextInput, } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconCamera } from "@tabler/icons-react";
import _ from "lodash";
import { useState } from "react";
import { Investasi_ComponentButtonUpdateDataInvestasi } from "../../_component";
import { apiGetMasterInvestasi, apiGetOneInvestasiById } from "../../_lib/api_interface";
import { IDataInvestasi } from "../../_lib/type_investasi";
import { useParams } from "next/navigation";
import SkeletonEditInvestasi from "./skeleton_edit_investasi";
export function Investasi_ViewEditInvestasiNew() {
const param = useParams<{ id: string }>()
const [loading, setLoading] = useState(true)
const [loadingMasterInvestor, setLoadingMasterInvestor] = useState(true)
const [loadingMasterPeriodeDeviden, setLoadingMasterPeriodeDeviden] = useState(true)
const [loadingMasterPembagianDeviden, setLoadingMasterPembagianDeviden] = useState(true)
const [periodeDeviden, setPeriodeDeviden] = useState<any[]>([]);
const [pembagianDeviden, setPembagianDeviden] = useState<any[]>([]);
const [pencarianInvestor, setPencarianInvestor] = useState<any[]>([]);
const [data, setData] = useState<IDataInvestasi>();
const [file, setFile] = useState<File | null>(null);
const [img, setImg] = useState<any | null>();
const [target, setTarget] = useState("");
const [harga, setHarga] = useState("");
const [totalLembar, setTotalLembar] = useState<any>("");
async function onGetOneInvestasiById() {
try {
setLoading(true)
const response = await apiGetOneInvestasiById(param.id)
if (response.success) {
setData(response.data)
setTotalLembar(response.data.totalLembar)
}
} catch (error) {
console.error(error)
} finally {
setLoading(false)
}
}
async function onGetMasterInvestor() {
try {
setLoadingMasterInvestor(true)
const response = await apiGetMasterInvestasi("?cat=pencarian-investor")
if (response.success) {
setPencarianInvestor(response.data)
}
} catch (error) {
console.log(error)
} finally {
setLoadingMasterInvestor(false)
}
}
async function onGetMasterPeriodeDeviden() {
try {
setLoadingMasterPeriodeDeviden(true)
const response = await apiGetMasterInvestasi("?cat=periode-deviden")
if (response.success) {
setPeriodeDeviden(response.data)
}
} catch (error) {
console.log(error)
} finally {
setLoadingMasterPeriodeDeviden(false)
}
}
async function onGetMasterPembagianDeviden() {
try {
setLoadingMasterPembagianDeviden(true)
const response = await apiGetMasterInvestasi("?cat=pembagian-deviden")
if (response.success) {
setPembagianDeviden(response.data)
}
} catch (error) {
console.log(error)
} finally {
setLoadingMasterPembagianDeviden(false)
}
}
useShallowEffect(() => {
onGetOneInvestasiById()
onGetMasterInvestor()
onGetMasterPeriodeDeviden()
onGetMasterPembagianDeviden()
}, [])
async function onTotalLembar({ target, harga, }: { target?: number | any; harga?: number | any; }) {
if (target !== 0 && harga !== 0) {
const hasil: any = target / harga;
const result = _.floor(hasil === Infinity ? 0 : hasil);
setTotalLembar(result.toString());
}
}
return (
<>
<Stack px={"sm"}>
{
loading ?
<SkeletonEditInvestasi />
:
<>
<Stack spacing={0}>
<Box mb={"sm"}>
<ComponentGlobal_BoxInformation informasi="Gambar investasi bisa berupa ilustrasi, poster atau foto terkait investasi" />
</Box>
<ComponentGlobal_BoxUploadImage>
{img ? (
<AspectRatio ratio={1 / 1} mt={5} maw={300} mx={"auto"}>
<Image style={{ maxHeight: 250 }} alt="Avatar" src={img} />
</AspectRatio>
) : (
<ComponentGlobal_LoadImage maw={300} fileId={String(data?.imageId)} />
)}
</ComponentGlobal_BoxUploadImage>
{/* Upload Foto */}
<Group position="center">
<FileButton
onChange={async (files: any) => {
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}
leftIcon={<IconCamera color="black" />}
radius={50}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload Gambar
</Button>
)}
</FileButton>
</Group>
</Stack>
<TextInput
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white
},
required: {
color: MainColor.red
}
}}
withAsterisk
label="Judul Investasi"
placeholder="Judul investasi"
maxLength={100}
value={data?.title}
onChange={(val) => {
setData({
...data as any,
title: val.target.value,
});
}}
/>
<TextInput
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white
},
required: {
color: MainColor.red
}
}}
icon={<Text fw={"bold"}>Rp.</Text>}
min={0}
withAsterisk
label="Dana Dibutuhkan"
placeholder="0"
value={target ? target : data?.targetDana}
onChange={(val) => {
const match = val.currentTarget.value
.replace(/\./g, "")
.match(/^[0-9]+$/);
if (val.currentTarget.value === "") return setTarget(0 + "");
if (!match?.[0]) return null;
const nilai = val.currentTarget.value.replace(/\./g, "");
const targetNilai = Intl.NumberFormat("id-ID").format(+nilai);
onTotalLembar({
target: +nilai,
harga: +Number(data?.hargaLembar),
});
setTarget(targetNilai);
setData({
...data as any,
targetDana: nilai as string,
});
}}
/>
<TextInput
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white
},
required: {
color: MainColor.red
}
}}
icon={<Text fw={"bold"}>Rp.</Text>}
min={0}
withAsterisk
label="Harga Per Lembar"
placeholder="0"
value={harga ? harga : data?.hargaLembar}
onChange={(val) => {
try {
const match = val.currentTarget.value
.replace(/\./g, "")
.match(/^[0-9]+$/);
if (val.currentTarget.value === "") return setHarga(0 + "");
if (!match?.[0]) return null;
const nilai = val.currentTarget.value.replace(/\./g, "");
const targetNilai = Intl.NumberFormat("id-ID").format(+nilai);
onTotalLembar({
harga: +nilai,
target: +Number(data?.targetDana),
});
setHarga(targetNilai);
setData({
...data as any,
hargaLembar: nilai as string,
});
} catch (error) {
console.log(error);
}
}}
/>
<TextInput
description="*Total lembar dihitung dari, Target Dana / Harga Perlembar"
label="Total Lembar"
value={harga === "0" ? "0" : target === "0" ? "0" : totalLembar}
readOnly
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white
},
required: {
color: MainColor.red
}
}}
/>
<TextInput
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white
},
required: {
color: MainColor.red
}
}}
rightSection={
<Text fw={"bold"} c={"gray"}>
%
</Text>
}
withAsterisk
type="number"
label={"Rasio Keuntungan / ROI %"}
placeholder="Masukan rasio keuntungan"
value={data?.roi}
onChange={(val) => {
setData({
...data as any,
roi: val.target.value,
});
}}
/>
<Select
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white
},
required: {
color: MainColor.red
},
dropdown: {
backgroundColor: MainColor.white,
}
}}
withAsterisk
label="Pencarian Investor"
placeholder={loadingMasterInvestor ? "Loading..." : "Pilih batas waktu"}
data={pencarianInvestor.map((e) => ({
value: e.id,
label: e.name + " " + "hari",
}))}
value={data?.masterPencarianInvestorId}
onChange={(val) => {
setData({
...(data as any),
masterPencarianInvestorId: val,
});
}}
/>
<Select
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white
},
required: {
color: MainColor.red
},
dropdown: {
backgroundColor: MainColor.white,
}
}}
withAsterisk
label="Periode Deviden"
placeholder={loadingMasterPeriodeDeviden ? "Loading..." : "Pilih batas waktu"}
data={periodeDeviden.map((e) => ({ value: e.id, label: e.name }))}
value={data?.masterPeriodeDevidenId}
onChange={(val) => {
setData({
...(data as any),
masterPeriodeDevidenId: val,
});
}}
/>
<Select
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white
},
required: {
color: MainColor.red
},
dropdown: {
backgroundColor: MainColor.white,
}
}}
withAsterisk
label="Pembagian Deviden"
placeholder={loadingMasterPembagianDeviden ? "Loading..." : "Pilih batas waktu"}
data={pembagianDeviden.map((e) => ({
value: e.id,
label: e.name + " " + "bulan",
}))}
value={data?.masterPembagianDevidenId}
onChange={(val) => {
setData({
...(data as any),
masterPembagianDevidenId: val,
});
}}
/>
<Investasi_ComponentButtonUpdateDataInvestasi
data={data as any}
file={file as any}
totalLembar={totalLembar}
/>
</>
}
</Stack>
</>
);
}

View File

@@ -1,7 +1,8 @@
import { DIRECTORY_ID } from "@/app/lib";
import { MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_CardStyles
ComponentGlobal_ButtonUploadFileImage,
ComponentGlobal_CardStyles,
} from "@/app_modules/_global/component";
import {
funGlobal_DeleteFileById,
@@ -11,44 +12,62 @@ import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { clientLogger } from "@/util/clientLogger";
import {
Box,
Button,
Center,
FileButton,
Grid,
Group,
Stack,
Text,
TextInput,
} from "@mantine/core";
import { IconCamera, IconCircleCheck } from "@tabler/icons-react";
import { useShallowEffect } from "@mantine/hooks";
import { IconCircleCheck } from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { Investasi_SkeletonEditProspektus } from "../../_component/skeleton_view";
import { investasi_funUpdateDocument } from "../../_fun";
import { apiGetDokumenInvestasiById } from "../../_lib/api_interface";
import { MODEL_INVESTASI_DOKUMEN } from "../../_lib/interface";
export function Investasi_ViewEditDokumen({
dataDokumen,
}: {
dataDokumen: MODEL_INVESTASI_DOKUMEN;
}) {
export function Investasi_ViewEditDokumen() {
const params = useParams<{ id: string }>();
const dokumenId = params.id;
const router = useRouter();
const [filePdf, setFilePdf] = useState<File | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState(dataDokumen);
const [title, setTitle] = useState(data.title);
const [data, setData] = useState<MODEL_INVESTASI_DOKUMEN | null>(null);
// const [title, setTitle] = useState(data.title);
const [loading, setLoading] = useState(true);
useShallowEffect(() => {
onGetDataDokumenById();
}, []);
async function onGetDataDokumenById() {
try {
setLoading(true);
const response = await apiGetDokumenInvestasiById({
id: dokumenId,
});
if (response.success) {
console.log(response.data);
setData(response.data);
}
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
async function onUpdate() {
try {
setIsLoading(true);
if (filePdf) {
const delfile = await funGlobal_DeleteFileById({ fileId: data.fileId });
if (!delfile.success) {
ComponentGlobal_NotifikasiPeringatan("Gagal hapus file lama");
}
const uploadFile = await funGlobal_UploadToStorage({
file: filePdf,
dirId: DIRECTORY_ID.investasi_dokumen,
@@ -57,35 +76,52 @@ export function Investasi_ViewEditDokumen({
if (!uploadFile.success) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload file dokumen");
return;
}
const delfile = await funGlobal_DeleteFileById({
fileId: data?.fileId as any,
dirId: DIRECTORY_ID.investasi_dokumen,
});
if (!delfile.success) {
setIsLoading(false);
clientLogger.error("Gagal hapus file lama", delfile.message);
}
const updateWithFile = await investasi_funUpdateDocument({
data: data,
data: data as any,
fileId: uploadFile.data.id,
});
if (updateWithFile.status !== 200) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan(updateWithFile.message);
}
ComponentGlobal_NotifikasiBerhasil(updateWithFile.message);
router.back();
} else {
const updateNoFile = await investasi_funUpdateDocument({
data: data,
data: data as any,
});
if (updateNoFile.status !== 200) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan(updateNoFile.message);
}
ComponentGlobal_NotifikasiBerhasil(updateNoFile.message);
}
} catch (error) {
console.log(error);
} finally {
router.back();
setIsLoading(false);
clientLogger.error(" Error update dokumen", error);
}
}
if (loading) {
return <Investasi_SkeletonEditProspektus />;
}
return (
<>
<Stack spacing={"xl"} px={"sm"}>
@@ -95,18 +131,23 @@ export function Investasi_ViewEditDokumen({
<TextInput
label="Judul Dokumen"
placeholder="Masukan judul dokumen"
value={data.title}
value={data?.title}
styles={{
label: {
color: "white",
},
}}
onChange={(val) => setData({ ...data, title: val.target.value })}
onChange={(val) =>
setData({
...(data as any),
title: val.target.value,
})
}
/>
<ComponentGlobal_CardStyles marginBottom={"0px"}>
{!filePdf ? (
<Text lineClamp={1} align="center" c={"gray"}>
Dokumen {_.startCase(title)}.pdf
{_.startCase(data?.title)}.pdf
</Text>
) : (
<Grid align="center">
@@ -125,7 +166,15 @@ export function Investasi_ViewEditDokumen({
)}
</ComponentGlobal_CardStyles>
<Group position="center">
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFilePdf}
accept="application/pdf"
text="Upload dokumen"
/>
</Center>
{/* <Group position="center">
<FileButton
accept={"application/pdf"}
onChange={async (files: any) => {
@@ -153,27 +202,37 @@ export function Investasi_ViewEditDokumen({
</Button>
)}
</FileButton>
</Group>
</Group> */}
</Stack>
<Button
loaderPosition="center"
loading={isLoading}
disabled={data.title === ""}
mt={50}
radius={50}
bg={MainColor.yellow}
color="yellow"
c={"black"}
<Box
style={{
transition: "0.5s",
}}
onClick={() => {
onUpdate();
display: "flex",
justifyContent: "center",
}}
>
Update
</Button>
<Button
loaderPosition="center"
loading={isLoading}
disabled={data?.title === ""}
mt={50}
radius={50}
bg={MainColor.yellow}
color="yellow"
c={"black"}
style={{
transition: "0.5s",
position: "absolute",
bottom: 20,
width: "90%",
}}
onClick={() => {
onUpdate();
}}
>
Update
</Button>
</Box>
</Stack>
</>
);

View File

@@ -0,0 +1,465 @@
import { MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_BoxInformation,
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
ComponentGlobal_LoadImage,
} from "@/app_modules/_global/component";
import {
AspectRatio,
Box,
Button,
Center,
FileButton,
Group,
Image,
Select,
Stack,
Text,
TextInput,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconCamera } from "@tabler/icons-react";
import _ from "lodash";
import { useState } from "react";
import { Investasi_ComponentButtonUpdateDataInvestasi } from "../../_component";
import {
apiGetMasterInvestasi,
apiGetOneInvestasiById,
} from "../../_lib/api_interface";
import { IDataInvestasi } from "../../_lib/type_investasi";
import { useParams } from "next/navigation";
import SkeletonEditInvestasi from "./skeleton_edit_investasi";
export function Investasi_ViewEditInvestasiNew() {
const param = useParams<{ id: string }>();
const [loading, setLoading] = useState(true);
const [loadingMasterInvestor, setLoadingMasterInvestor] = useState(true);
const [loadingMasterPeriodeDeviden, setLoadingMasterPeriodeDeviden] =
useState(true);
const [loadingMasterPembagianDeviden, setLoadingMasterPembagianDeviden] =
useState(true);
const [periodeDeviden, setPeriodeDeviden] = useState<any[]>([]);
const [pembagianDeviden, setPembagianDeviden] = useState<any[]>([]);
const [pencarianInvestor, setPencarianInvestor] = useState<any[]>([]);
const [data, setData] = useState<IDataInvestasi>();
const [file, setFile] = useState<File | null>(null);
const [img, setImg] = useState<any | null>();
const [target, setTarget] = useState("");
const [harga, setHarga] = useState("");
const [totalLembar, setTotalLembar] = useState<any>("");
async function onGetOneInvestasiById() {
try {
setLoading(true);
const response = await apiGetOneInvestasiById({
id: param.id,
});
if (response.success) {
setData(response.data);
setTotalLembar(response.data.totalLembar);
}
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
async function onGetMasterInvestor() {
try {
setLoadingMasterInvestor(true);
const response = await apiGetMasterInvestasi("?cat=pencarian-investor");
if (response.success) {
setPencarianInvestor(response.data);
}
} catch (error) {
console.log(error);
} finally {
setLoadingMasterInvestor(false);
}
}
async function onGetMasterPeriodeDeviden() {
try {
setLoadingMasterPeriodeDeviden(true);
const response = await apiGetMasterInvestasi("?cat=periode-deviden");
if (response.success) {
setPeriodeDeviden(response.data);
}
} catch (error) {
console.log(error);
} finally {
setLoadingMasterPeriodeDeviden(false);
}
}
async function onGetMasterPembagianDeviden() {
try {
setLoadingMasterPembagianDeviden(true);
const response = await apiGetMasterInvestasi("?cat=pembagian-deviden");
if (response.success) {
setPembagianDeviden(response.data);
}
} catch (error) {
console.log(error);
} finally {
setLoadingMasterPembagianDeviden(false);
}
}
useShallowEffect(() => {
onGetOneInvestasiById();
onGetMasterInvestor();
onGetMasterPeriodeDeviden();
onGetMasterPembagianDeviden();
}, []);
async function onTotalLembar({
target,
harga,
}: {
target?: number | any;
harga?: number | any;
}) {
if (target !== 0 && harga !== 0) {
const hasil: any = target / harga;
const result = _.floor(hasil === Infinity ? 0 : hasil);
setTotalLembar(result.toString());
}
}
return (
<>
<Stack px={"sm"}>
{loading ? (
<SkeletonEditInvestasi />
) : (
<>
<Stack spacing={0}>
<Box mb={"sm"}>
<ComponentGlobal_BoxInformation informasi="Gambar investasi bisa berupa ilustrasi, poster atau foto terkait investasi" />
</Box>
<ComponentGlobal_BoxUploadImage>
{img ? (
<AspectRatio ratio={1 / 1} mt={5} maw={300} mx={"auto"}>
<Image style={{ maxHeight: 250 }} alt="Avatar" src={img} />
</AspectRatio>
) : (
<ComponentGlobal_LoadImage
maw={300}
fileId={String(data?.imageId)}
/>
)}
</ComponentGlobal_BoxUploadImage>
{/* Upload Foto */}
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFile}
onSetImage={setImg}
/>
</Center>
{/* <Group position="center">
<FileButton
onChange={async (files: any) => {
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}
leftIcon={<IconCamera color="black" />}
radius={50}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload Gambar
</Button>
)}
</FileButton>
</Group> */}
</Stack>
<TextInput
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white,
},
required: {
color: MainColor.red,
},
}}
withAsterisk
label="Judul Investasi"
placeholder="Judul investasi"
maxLength={100}
value={data?.title}
onChange={(val) => {
setData({
...(data as any),
title: val.target.value,
});
}}
/>
<TextInput
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white,
},
required: {
color: MainColor.red,
},
}}
icon={<Text fw={"bold"}>Rp.</Text>}
min={0}
withAsterisk
label="Dana Dibutuhkan"
placeholder="0"
value={target ? target : data?.targetDana}
onChange={(val) => {
const match = val.currentTarget.value
.replace(/\./g, "")
.match(/^[0-9]+$/);
if (val.currentTarget.value === "") return setTarget(0 + "");
if (!match?.[0]) return null;
const nilai = val.currentTarget.value.replace(/\./g, "");
const targetNilai = Intl.NumberFormat("id-ID").format(+nilai);
onTotalLembar({
target: +nilai,
harga: +Number(data?.hargaLembar),
});
setTarget(targetNilai);
setData({
...(data as any),
targetDana: nilai as string,
});
}}
/>
<TextInput
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white,
},
required: {
color: MainColor.red,
},
}}
icon={<Text fw={"bold"}>Rp.</Text>}
min={0}
withAsterisk
label="Harga Per Lembar"
placeholder="0"
value={harga ? harga : data?.hargaLembar}
onChange={(val) => {
try {
const match = val.currentTarget.value
.replace(/\./g, "")
.match(/^[0-9]+$/);
if (val.currentTarget.value === "") return setHarga(0 + "");
if (!match?.[0]) return null;
const nilai = val.currentTarget.value.replace(/\./g, "");
const targetNilai = Intl.NumberFormat("id-ID").format(+nilai);
onTotalLembar({
harga: +nilai,
target: +Number(data?.targetDana),
});
setHarga(targetNilai);
setData({
...(data as any),
hargaLembar: nilai as string,
});
} catch (error) {
console.log(error);
}
}}
/>
<TextInput
description="*Total lembar dihitung dari, Target Dana / Harga Perlembar"
label="Total Lembar"
value={harga === "0" ? "0" : target === "0" ? "0" : totalLembar}
readOnly
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white,
},
required: {
color: MainColor.red,
},
}}
/>
<TextInput
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white,
},
required: {
color: MainColor.red,
},
}}
rightSection={
<Text fw={"bold"} c={"gray"}>
%
</Text>
}
withAsterisk
type="number"
label={"Rasio Keuntungan / ROI %"}
placeholder="Masukan rasio keuntungan"
value={data?.roi}
onChange={(val) => {
setData({
...(data as any),
roi: val.target.value,
});
}}
/>
<Select
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white,
},
required: {
color: MainColor.red,
},
dropdown: {
backgroundColor: MainColor.white,
},
}}
withAsterisk
label="Pencarian Investor"
placeholder={
loadingMasterInvestor ? "Loading..." : "Pilih batas waktu"
}
data={pencarianInvestor.map((e) => ({
value: e.id,
label: e.name + " " + "hari",
}))}
value={data?.masterPencarianInvestorId}
onChange={(val) => {
setData({
...(data as any),
masterPencarianInvestorId: val,
});
}}
/>
<Select
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white,
},
required: {
color: MainColor.red,
},
dropdown: {
backgroundColor: MainColor.white,
},
}}
withAsterisk
label="Periode Deviden"
placeholder={
loadingMasterPeriodeDeviden ? "Loading..." : "Pilih batas waktu"
}
data={periodeDeviden.map((e) => ({ value: e.id, label: e.name }))}
value={data?.masterPeriodeDevidenId}
onChange={(val) => {
setData({
...(data as any),
masterPeriodeDevidenId: val,
});
}}
/>
<Select
styles={{
label: {
color: MainColor.white,
},
input: {
backgroundColor: MainColor.white,
},
required: {
color: MainColor.red,
},
dropdown: {
backgroundColor: MainColor.white,
},
}}
withAsterisk
label="Pembagian Deviden"
placeholder={
loadingMasterPembagianDeviden
? "Loading..."
: "Pilih batas waktu"
}
data={pembagianDeviden.map((e) => ({
value: e.id,
label: e.name + " " + "bulan",
}))}
value={data?.masterPembagianDevidenId}
onChange={(val) => {
setData({
...(data as any),
masterPembagianDevidenId: val,
});
}}
/>
<Investasi_ComponentButtonUpdateDataInvestasi
data={data as any}
file={file as any}
totalLembar={totalLembar}
/>
</>
)}
</Stack>
</>
);
}

View File

@@ -1,82 +1,120 @@
import { MainColor } from "@/app_modules/_global/color";
import {
ComponentGlobal_BoxInformation,
ComponentGlobal_ButtonUploadFileImage,
ComponentGlobal_CardStyles,
} from "@/app_modules/_global/component";
import {
Box,
Button,
Center,
FileButton,
Grid,
Group,
Stack,
Text
} from "@mantine/core";
import {
IconCamera,
IconCircleCheck
IconCircleCheck,
IconFileTypePdf
} from "@tabler/icons-react";
import { DIRECTORY_ID } from "@/app/lib";
import { funGlobal_UploadToStorage } from "@/app_modules/_global/fun";
import {
funGlobal_DeleteFileById,
funGlobal_UploadToStorage,
} from "@/app_modules/_global/fun";
import {
ComponentGlobal_NotifikasiBerhasil,
ComponentGlobal_NotifikasiPeringatan,
} from "@/app_modules/_global/notif_global";
import { useRouter } from "next/navigation";
import { clientLogger } from "@/util/clientLogger";
import { useShallowEffect } from "@mantine/hooks";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { Investasi_SkeletonEditProspektus } from "../../_component/skeleton_view";
import { investasi_funUpdateProspektus } from "../../_fun";
import { apiGetOneInvestasiById } from "../../_lib/api_interface";
export function Investasi_ViewEditProspektus({
investasiId,
}: {
investasiId: string;
}) {
export function Investasi_ViewEditProspektus() {
const params = useParams<{ id: string }>();
const investasiId = params.id;
const router = useRouter();
const [filePdf, setFilePdf] = useState<File | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [fileRemoveId, setFileRemoveId] = useState<string | null>(null);
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
const respone = await apiGetOneInvestasiById({
id: investasiId,
});
if (respone.success) {
setFileRemoveId(respone.data.prospektusFileId);
}
} catch (error) {
clientLogger.error("Error get data investasi:", error);
}
}
async function onUpload() {
setIsLoading(true);
const uploadFilePdf = await funGlobal_UploadToStorage({
file: filePdf as any,
dirId: DIRECTORY_ID.investasi_prospektus,
});
if (!uploadFilePdf.success) {
setIsLoading(false);
return ComponentGlobal_NotifikasiPeringatan("Gagal upload file pdf");
}
try {
setIsLoading(true);
const uploadFilePdf = await funGlobal_UploadToStorage({
file: filePdf as any,
dirId: DIRECTORY_ID.investasi_prospektus,
});
if (!uploadFilePdf.success) {
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload file pdf");
return;
}
const deleteFile = await funGlobal_DeleteFileById({
fileId: fileRemoveId as string,
dirId: DIRECTORY_ID.investasi_prospektus,
});
if (!deleteFile.success) {
setIsLoading(false);
clientLogger.error("Error delete file:", deleteFile.message);
}
const updte = await investasi_funUpdateProspektus({
fileId: uploadFilePdf.data.id,
investasiId: investasiId,
});
if (updte.status !== 200) {
return ComponentGlobal_NotifikasiPeringatan("Gagal update prospektus");
setIsLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal update prospektus");
return;
}
ComponentGlobal_NotifikasiBerhasil(updte.message);
router.back();
return ComponentGlobal_NotifikasiBerhasil(updte.message);
} catch (error) {
console.log(error);
} finally {
setIsLoading(false);
clientLogger.error("Error update prospektus:", error);
}
}
if (fileRemoveId == null) {
return <Investasi_SkeletonEditProspektus />;
}
return (
<>
<Stack spacing={"sm"}>
<ComponentGlobal_BoxInformation informasi="File prospektus wajib untuk diupload, agar calon investor paham dengan prospek investasi yang akan anda jalankan kedepan !" />
<ComponentGlobal_BoxInformation informasi="File prospektus wajib untuk diupload, agar calon investor paham dengan prospek investasi yang akan anda jalankan kedepan." />
<ComponentGlobal_CardStyles marginBottom={"0px"}>
{!filePdf ? (
<Text lineClamp={1} align="center" c={"gray"}>
Upload File Prospektus
</Text>
<Stack justify="center" align="center" h={"100%"}>
<IconFileTypePdf size={40} color="gray" />
</Stack>
) : (
<Grid align="center">
<Grid.Col span={2}></Grid.Col>
@@ -94,54 +132,43 @@ export function Investasi_ViewEditProspektus({
)}
</ComponentGlobal_CardStyles>
<Group position="center">
<FileButton
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFilePdf}
accept={"application/pdf"}
onChange={async (files: any) => {
try {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
text="Upload File"
/>
</Center>
setFilePdf(files);
} catch (error) {
console.log(error);
}
}}
>
{(props) => (
<Button
leftIcon={<IconCamera />}
{...props}
radius={"xl"}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload File
</Button>
)}
</FileButton>
</Group>
<Button
loaderPosition="center"
loading={isLoading}
disabled={filePdf === null}
mt={50}
radius={50}
bg={MainColor.yellow}
color="yellow"
c={"black"}
<Box
style={{
transition: "0.5s",
}}
onClick={() => {
onUpload();
display: "flex",
justifyContent: "center",
}}
>
Update
</Button>
<Button
px={"sm"}
loaderPosition="center"
loading={isLoading}
disabled={filePdf === null}
mt={50}
radius={50}
bg={MainColor.yellow}
color="yellow"
c={"black"}
style={{
transition: "all 0.3s ease",
position: "absolute",
bottom: 20,
width: "90%",
}}
onClick={() => {
onUpload();
}}
>
Update
</Button>
</Box>
</Stack>
</>
);

View File

@@ -32,6 +32,7 @@ import { IRealtimeData } from "@/app/lib/global_state";
import { notifikasiToAdmin_funCreate } from "@/app_modules/notifikasi/fun";
import { WibuRealtime } from "wibu-pkg";
import { clientLogger } from "@/util/clientLogger";
import { ComponentGlobal_ButtonUploadFileImage } from "@/app_modules/_global/component";
export function Investasi_ViewInvoice({
dataInvoice,
@@ -42,6 +43,7 @@ export function Investasi_ViewInvoice({
const [isLoading, setLoading] = useState(false);
const [data, setData] = useState(dataInvoice);
const [file, setFile] = useState<File | null>(null);
const [img, setImg] = useState<any | null>(null);
async function onUpload() {
try {
@@ -52,6 +54,7 @@ export function Investasi_ViewInvoice({
});
if (!uploadFileToStorage.success) {
setLoading(false);
ComponentGlobal_NotifikasiPeringatan("Gagal upload bukti transfer");
return;
}
@@ -62,6 +65,7 @@ export function Investasi_ViewInvoice({
});
if (res.status != 200) {
setLoading(false);
ComponentGlobal_NotifikasiGagal(res.message);
return;
}
@@ -93,9 +97,8 @@ export function Investasi_ViewInvoice({
});
}
} catch (error) {
clientLogger.error(" Error upload invoice", error);
} finally {
setLoading(false);
clientLogger.error(" Error upload invoice", error);
}
}
@@ -245,29 +248,10 @@ export function Investasi_ViewInvoice({
>
<Stack spacing={"sm"}>
<Center>
<FileButton
onChange={async (files: any | null) => {
try {
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>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFile}
accept="image/png,image/png,image/jpeg,application/pdf"
/>
</Center>
{file ? (
<Center>

View File

@@ -3,6 +3,7 @@ import { MainColor } from "@/app_modules/_global/color/color_pallet";
import {
ComponentGlobal_BoxInformation,
ComponentGlobal_BoxUploadImage,
ComponentGlobal_ButtonUploadFileImage,
ComponentGlobal_CardStyles,
} from "@/app_modules/_global/component";
import { MAX_SIZE } from "@/app_modules/_global/lib";
@@ -131,7 +132,7 @@ export default function InvestasiCreateNew() {
{/* Upload Image */}
<Stack spacing={0}>
<Box mb={"sm"}>
<ComponentGlobal_BoxInformation informasi="Gambar investasi bisa berupa ilustrasi, poster atau foto terkait investasi" />
<ComponentGlobal_BoxInformation informasi="Gambar investasi bisa berupa ilustrasi, poster atau foto terkait investasi." />
</Box>
<ComponentGlobal_BoxUploadImage>
{isLoadingImg ? (
@@ -155,7 +156,13 @@ export default function InvestasiCreateNew() {
</ComponentGlobal_BoxUploadImage>
{/* Upload Foto */}
<Group position="center">
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFileImage}
onSetImage={setImg}
/>
</Center>
{/* <Group position="center">
<FileButton
onChange={async (files: any) => {
try {
@@ -196,12 +203,12 @@ export default function InvestasiCreateNew() {
</Button>
)}
</FileButton>
</Group>
</Group> */}
</Stack>
{/* Upload File */}
<Stack spacing={"sm"}>
<ComponentGlobal_BoxInformation informasi="File prospektus wajib untuk diupload, agar calon investor paham dengan prospek investasi yang akan anda jalankan kedepan !" />
<ComponentGlobal_BoxInformation informasi="File prospektus wajib untuk diupload, agar calon investor paham dengan prospek investasi yang akan anda jalankan kedepannya." />
<ComponentGlobal_CardStyles marginBottom={"0px"}>
{isLoadingPdf ? (
<Stack justify="center" align="center" h={"100%"}>
@@ -228,7 +235,16 @@ export default function InvestasiCreateNew() {
)}
</ComponentGlobal_CardStyles>
<Group position="center">
<Center>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={setFilePdf}
onSetImage={setFPdf}
accept={"application/pdf"}
text="Upload File"
icon={<IconFileTypePdf size={20} />}
/>
</Center>
{/* <Group position="center">
<FileButton
accept={"application/pdf"}
onChange={async (files: any) => {
@@ -269,7 +285,7 @@ export default function InvestasiCreateNew() {
</Button>
)}
</FileButton>
</Group>
</Group> */}
</Stack>
<Stack>
@@ -283,7 +299,7 @@ export default function InvestasiCreateNew() {
},
input: {
backgroundColor: MainColor.white,
}
},
}}
withAsterisk
label="Judul Investasi"
@@ -307,7 +323,7 @@ export default function InvestasiCreateNew() {
},
input: {
backgroundColor: MainColor.white,
}
},
}}
icon={<Text fw={"bold"}>Rp.</Text>}
min={0}
@@ -350,7 +366,7 @@ export default function InvestasiCreateNew() {
},
input: {
backgroundColor: MainColor.white,
}
},
}}
icon={<Text fw={"bold"}>Rp.</Text>}
min={0}
@@ -403,7 +419,7 @@ export default function InvestasiCreateNew() {
},
input: {
backgroundColor: MainColor.white,
}
},
}}
/>
@@ -417,7 +433,7 @@ export default function InvestasiCreateNew() {
},
input: {
backgroundColor: MainColor.white,
}
},
}}
rightSection={
<Text fw={"bold"} c={"gray"}>

View File

@@ -1,60 +0,0 @@
"use client";
import { RouterInvestasi_OLD } from "@/app/lib/router_hipmi/router_investasi";
import UIGlobal_Drawer from "@/app_modules/_global/ui/ui_drawer";
import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_tamplate";
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate";
import { ActionIcon } from "@mantine/core";
import { IconDotsVertical, IconFilePlus } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import React from "react";
export default function LayoutEditDokumenInvestasi({
children,
idInves,
}: {
children: React.ReactNode;
idInves: string;
}) {
const router = useRouter();
const [isOpenDrawer, setIsOpenDrawer] = React.useState(false);
const listPage = [
{
id: "1",
name: "Tambah Dokumen",
icon: <IconFilePlus />,
path: RouterInvestasi_OLD.upload_dokumen + `${idInves}`,
},
];
return (
<>
<UIGlobal_LayoutTamplate
header={
<UIGlobal_LayoutHeaderTamplate
title="Daftar Dokumen"
// iconRight={<IconEdit />}
// routerRight={RouterInvestasi.upload_dokumen + `${idInves}`}
customButtonRight={
<ActionIcon
variant="transparent"
onClick={() => setIsOpenDrawer(true)}
>
<IconDotsVertical color="white" />
</ActionIcon>
}
/>
}
>
{children}
</UIGlobal_LayoutTamplate>
<UIGlobal_Drawer
opened={isOpenDrawer}
close={() => setIsOpenDrawer(false)}
component={listPage}
/>
</>
);
}

View File

@@ -1,87 +0,0 @@
"use client";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import { ActionIcon, Group, Paper, Text } from "@mantine/core";
import { IconFolderOpen, IconTrash, IconWorldShare } from "@tabler/icons-react";
import _ from "lodash";
import Link from "next/link";
import { useState } from "react";
import funDeleteDokumenInvestasi from "../fun/fun_delete_dokumen";
import funLoadDataInvestasi from "../fun/fun_load_data";
import { MODEL_INVESTASI } from "../_lib/interface";
import { IconFile } from "@tabler/icons-react";
import { IconFileTypePdf } from "@tabler/icons-react";
export default function EditDokumenInvestasi({
dataInvestasi,
}: {
dataInvestasi: MODEL_INVESTASI;
}) {
const [dokumen, setDokumen] = useState(dataInvestasi);
async function onDelete(id: string) {
await funDeleteDokumenInvestasi(id).then(async (res) => {
if (res.status === 200) {
ComponentGlobal_NotifikasiBerhasil(res.message);
const load = await funLoadDataInvestasi(dokumen.id);
setDokumen(load as any);
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
});
}
return (
<>
{!_.isEmpty(dokumen.DokumenInvestasi) ? (
dokumen.DokumenInvestasi.map((e) => (
<Paper
key={e.id}
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
color: "white",
marginBottom: "15px",
}}
>
<Group position="apart">
<Text lineClamp={1}>{e.title}</Text>
<Group position="center">
<Link href={`/file/${e.url}`} target="_blank">
<ActionIcon variant="transparent">
<IconFileTypePdf
style={{
color: MainColor.yellow,
}}
/>
</ActionIcon>
</Link>
<ActionIcon
variant="transparent"
onClick={() => {
onDelete(e.id);
}}
>
<IconTrash color="red" />
</ActionIcon>
</Group>
</Group>
</Paper>
))
) : (
<ComponentGlobal_IsEmptyData />
)}
{/* <Divider mt={"lg"} /> */}
</>
);
}

View File

@@ -1,30 +0,0 @@
"use client";
import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_tamplate";
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate";
import React from "react";
import { MODEL_INVESTASI } from "../_lib/interface";
export default function LayoutEditProspektusInvestasi({
children,
dataInvestasi,
}: {
children: React.ReactNode;
dataInvestasi: MODEL_INVESTASI;
}) {
return (
<>
<UIGlobal_LayoutTamplate
header={
<UIGlobal_LayoutHeaderTamplate
title="Edit Prospektus"
// icon={<IconEdit />}
// route2={RouterInvestasi.upload_prospektus + `${dataInvestasi.id}`}
/>
}
>
{children}
</UIGlobal_LayoutTamplate>
</>
);
}

View File

@@ -1,75 +0,0 @@
"use client";
import {
Paper,
Grid,
Center,
Title,
Divider,
Button,
Text,
Group,
FileButton,
FileInput,
Image,
AspectRatio,
Flex,
Stack,
Box,
} from "@mantine/core";
import { IconChevronRight, IconFileTypePdf } from "@tabler/icons-react";
import Link from "next/link";
import { useState } from "react";
import { MODEL_INVESTASI } from "../_lib/interface";
import { RouterInvestasi_OLD } from "@/app/lib/router_hipmi/router_investasi";
export default function EditProspektusInvestasi({
dataInvestasi,
}: {
dataInvestasi: MODEL_INVESTASI;
}) {
const [prospek, setProspek] = useState<MODEL_INVESTASI>(dataInvestasi);
return (
<>
{/* <pre>{JSON.stringify(prospek, null, 2)}</pre> */}
<Stack>
{prospek.ProspektusInvestasi != null ? (
<Link
href={RouterInvestasi_OLD.api_file_prospektus + `${prospek.ProspektusInvestasi.id}`}
target="_blank"
style={{ textDecorationLine: "none" }}
>
<Paper w={"100%"} bg={"gray"} mb={"md"}>
<Grid
align="center"
justify="center"
h={50}
px={"sm"}
onClick={() => ""}
>
<Grid.Col span={11}>
<Group>
{/* <IconFileTypePdf /> */}
<Text lineClamp={1}>Prospektus_{prospek.title}</Text>
</Group>
</Grid.Col>
<Grid.Col span={1}>
<Center>
<IconChevronRight />
</Center>
</Grid.Col>
</Grid>
</Paper>
</Link>
) : (
<Center>
<Title order={4}>Tidak ada file</Title>
</Center>
)}
{/* <Divider my={"lg"} /> */}
</Stack>
</>
);
}

View File

@@ -7,10 +7,6 @@ import PortofolioInvestasi from "./portofolio/view";
import LayoutPortofolioInvestasi from "./portofolio/layout";
import EditIntroInvestasi from "./edit_intro/view";
import LayoutEditIntroInvestasi from "./edit_intro/layout";
import EditProspektusInvestasi from "./edit_propektus/view";
import LayoutEditProspektusInvestasi from "./edit_propektus/layout";
import EditDokumenInvestasi from "./edit_dokumen/view";
import LayoutEditDokumenInvestasi from "./edit_dokumen/layout";
import EditBeritaInvestasi from "./edit_berita/view";
import LayoutEditBeritaInvestasi from "./edit_berita/layout";
import DetailPropektus from "./detail_prospektus/view";
@@ -58,10 +54,6 @@ export {
LayoutPortofolioInvestasi,
EditIntroInvestasi,
LayoutEditIntroInvestasi,
EditProspektusInvestasi,
LayoutEditProspektusInvestasi,
EditDokumenInvestasi,
LayoutEditDokumenInvestasi,
EditBeritaInvestasi,
LayoutEditBeritaInvestasi,
DetailPropektus,

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

@@ -2,36 +2,26 @@
import {
AspectRatio,
Button,
Center,
FileButton,
Image,
Stack,
Text,
TextInput,
} from "@mantine/core";
import { IconCamera, IconUpload } 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 +41,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 +56,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,29 @@
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";
import {
Avatar,
Box,
Button,
Center,
FileButton,
Paper,
Stack
} from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
ComponentGlobal_BoxInformation,
ComponentGlobal_ButtonUploadFileImage,
} from "@/app_modules/_global/component";
import { Avatar, Box, Center, Paper, Stack } from "@mantine/core";
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,122 +57,10 @@ export default function Profile_ViewUploadFoto({
</Center>
<Center>
<FileButton
onChange={async (files: any | null) => {
try {
setLoadingButton(true);
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
// if (files.size > MAX_SIZE) {
// ComponentGlobal_NotifikasiPeringatan(
// PemberitahuanMaksimalFile
// );
// onSetImgPP(null);
// return;
// }
if (fotoProfileId != "") {
try {
const deleteFotoProfile = await funGlobal_DeleteFileById({
fileId: fotoProfileId,
dirId: DIRECTORY_ID.profile_foto,
});
if (!deleteFotoProfile.success) {
clientLogger.error(
"Client failed delete photo profile:" +
deleteFotoProfile.message
);
return;
}
if (deleteFotoProfile.success) {
onSetFotoProfileId("");
onSetImgPP(null);
const uploadPhoto = await funGlobal_UploadToStorage({
file: files,
dirId: DIRECTORY_ID.profile_foto,
});
if (!uploadPhoto.success) {
clientLogger.error(
"Client failed upload photo profile::" +
uploadPhoto.message
);
return;
}
if (uploadPhoto.success) {
clientLogger.info(
"Client success upload foto profile"
);
onSetFotoProfileId(uploadPhoto.data.id);
onSetImgPP(buffer);
} else {
clientLogger.error(
"Client failed upload foto:",
uploadPhoto.message
);
ComponentGlobal_NotifikasiPeringatan(
"Gagal upload foto profile"
);
}
}
} catch (error) {
clientLogger.error("Client error upload foto:", error);
}
} else {
try {
const uploadPhoto = await funGlobal_UploadToStorage({
file: files,
dirId: DIRECTORY_ID.profile_foto,
});
if (uploadPhoto.success) {
clientLogger.info("Client success upload foto profile");
onSetFotoProfileId(uploadPhoto.data.id);
onSetImgPP(buffer);
} else {
clientLogger.error(
"Client failed upload foto:",
uploadPhoto.message
);
ComponentGlobal_NotifikasiPeringatan(
"Gagal upload foto profile"
);
}
} catch (error) {
clientLogger.error("Client error upload foto:", error);
}
}
} catch (error) {
clientLogger.error("Client error upload foto:", error);
} finally {
setLoadingButton(false);
}
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
loading={isLoadingButton}
loaderPosition="center"
radius={"xl"}
leftIcon={<IconCamera />}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Upload
</Button>
)}
</FileButton>
<ComponentGlobal_ButtonUploadFileImage
onSetFile={onSetFilePP}
onSetImage={onSetImgPP}
/>
</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

@@ -22,19 +22,19 @@ const middlewareConfig: MiddlewareConfig = {
// registarasiPath: "/register",
userPath: "/dev/home",
publicRoutes: [
// API
"/",
"/api/voting/*",
"/api/collaboration/*",
"/api/notifikasi/*",
"/api/logs/*",
"/api/image/*",
"/api/job/*",
"/api/auth/*",
"/api/origin-url",
// "/api/user",
"/api/event/*",
// "/api/image/*",
// "/api/user",
"/api/new/*",
// Akses awal
"/api/get-cookie",
"/api/user/activation",
@@ -103,7 +103,7 @@ export const middleware = async (req: NextRequest) => {
if (
isPublicRoute &&
pathname !== loginPath
pathname !== loginPath
// &&
// pathname !== validasiPath &&
// pathname !== registarasiPath

44
xhtml/index.html Normal file
View File

@@ -0,0 +1,44 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<!-- <img
id="pdf"
src="https://wibu-storage.wibudev.com/api/pdf-to-image?url=https://pdfobject.com/pdf/sample.pdf"
alt="pdf"
/> -->
<div id="pdfs"></div>
</body>
<script type="module">
(async () => {
const imagePdf = document.getElementById("pdf");
const pdfs = document.getElementById("pdfs");
const token =
"eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjp7ImlkIjoiY20wdXIxeXh3MDAwMDU2bnNqbHI2MTg3cCIsIm5hbWUiOiJiYWdhcyIsImVtYWlsIjoiYmFnYXNAZ21haWwuY29tIn0sImlhdCI6MTcyNTg3MTAzNiwiZXhwIjo0ODgxNjMxMDM2fQ.wFQLcrJj66wFeqIMYk2esMx3ULaHK6RFxkiToaLCuko";
const res = await fetch(
"https://wibu-storage.wibudev.com/api/pdf-to-image?url=https://wibu-storage.wibudev.com/api/files/cm5jgzg7d001dxpugxseb2ua0",
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
}
);
const jsonData = await res.json();
// console.log(JSON.stringify(jsonData.pages, null, 2));
// imagePdf.src = jsonData.pages[0].imageUrl;
for (let index = 0; index < jsonData.pages.length; index++) {
const element = jsonData.pages[index];
const img = document.createElement("img");
img.src = element.imageUrl;
pdfs.appendChild(img);
}
})();
</script>
</html>