fix edit portofolio
This commit is contained in:
@@ -13,6 +13,18 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
|
|||||||
id: id,
|
id: id,
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
|
Portofolio_BidangDanSubBidangBisnis: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
MasterSubBidangBisnis: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
masterBidangBisnisId: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
MasterBidangBisnis: {
|
MasterBidangBisnis: {
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
@@ -84,10 +96,26 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
|
|||||||
const { id } = params;
|
const { id } = params;
|
||||||
const { data } = await request.json();
|
const { data } = await request.json();
|
||||||
|
|
||||||
const udpateData = await prisma.portofolio.update({
|
const checkData = await prisma.portofolio.findUnique({
|
||||||
where: {
|
where: { id },
|
||||||
id: id,
|
include: {
|
||||||
|
Portofolio_BidangDanSubBidangBisnis: true,
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!checkData) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "Data tidak ditemukan",
|
||||||
|
},
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update data utama portofolio
|
||||||
|
const updatePortofolio = await prisma.portofolio.update({
|
||||||
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
namaBisnis: data.namaBisnis,
|
namaBisnis: data.namaBisnis,
|
||||||
alamatKantor: data.alamatKantor,
|
alamatKantor: data.alamatKantor,
|
||||||
@@ -97,25 +125,77 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!udpateData)
|
const bidangBerubah =
|
||||||
return NextResponse.json(
|
checkData.masterBidangBisnisId !== data.masterBidangBisnisId;
|
||||||
{
|
|
||||||
success: false,
|
if (bidangBerubah) {
|
||||||
message: "Gagal update data",
|
// Bidang berubah → hapus semua sub bidang lama
|
||||||
},
|
await prisma.portofolio_BidangDanSubBidangBisnis.deleteMany({
|
||||||
{ status: 400 }
|
where: { portofolioId: id },
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tambahkan sub bidang baru
|
||||||
|
for (const sub of data.subBidang) {
|
||||||
|
await prisma.portofolio_BidangDanSubBidangBisnis.create({
|
||||||
|
data: {
|
||||||
|
portofolioId: id,
|
||||||
|
masterBidangBisnisId: data.masterBidangBisnisId,
|
||||||
|
masterSubBidangBisnisId: sub.MasterSubBidangBisnis.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Bidang tidak berubah → sinkronisasi sub bidang
|
||||||
|
|
||||||
|
const existingSub = checkData.Portofolio_BidangDanSubBidangBisnis;
|
||||||
|
|
||||||
|
const incomingIds = data.subBidang.map(
|
||||||
|
(sub: any) => sub.MasterSubBidangBisnis.id
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const existingIds = existingSub.map(
|
||||||
|
(item) => item.masterSubBidangBisnisId
|
||||||
|
);
|
||||||
|
|
||||||
|
// 1. Hapus sub bidang yang sudah tidak dipilih
|
||||||
|
const toDelete = existingSub.filter(
|
||||||
|
(item) => !incomingIds.includes(item.masterSubBidangBisnisId)
|
||||||
|
);
|
||||||
|
|
||||||
|
await prisma.portofolio_BidangDanSubBidangBisnis.deleteMany({
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
in: toDelete.map((item) => item.id),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Tambahkan sub bidang baru yang belum ada di DB
|
||||||
|
const toCreate = data.subBidang.filter(
|
||||||
|
(sub: any) => !existingIds.includes(sub.MasterSubBidangBisnis.id)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const sub of toCreate) {
|
||||||
|
await prisma.portofolio_BidangDanSubBidangBisnis.create({
|
||||||
|
data: {
|
||||||
|
portofolioId: id,
|
||||||
|
masterBidangBisnisId: data.masterBidangBisnisId,
|
||||||
|
masterSubBidangBisnisId: sub.MasterSubBidangBisnis.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
success: true,
|
success: true,
|
||||||
message: "Berhasil mendapatkan data",
|
message: "Berhasil update data",
|
||||||
data: udpateData,
|
data: updatePortofolio,
|
||||||
},
|
},
|
||||||
|
|
||||||
{ status: 200 }
|
{ status: 200 }
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
backendLogger.error("Error update data portofolio", error);
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
@@ -127,6 +207,8 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function POST(request: Request, { params }: { params: { id: string } }) {
|
async function POST(request: Request, { params }: { params: { id: string } }) {
|
||||||
if (request.method !== "POST") {
|
if (request.method !== "POST") {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
@@ -156,7 +238,6 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (let i of data.subBidang) {
|
for (let i of data.subBidang) {
|
||||||
// console.log("sub bidang", i.id)
|
|
||||||
const createSubBidang =
|
const createSubBidang =
|
||||||
await prisma.portofolio_BidangDanSubBidangBisnis.create({
|
await prisma.portofolio_BidangDanSubBidangBisnis.create({
|
||||||
data: {
|
data: {
|
||||||
@@ -166,7 +247,6 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (!createSubBidang)
|
if (!createSubBidang)
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Portofolio_EditDataBisnis } from "@/app_modules/katalog/portofolio";
|
import { Portofolio_EditDataBisnis } from "@/app_modules/katalog/portofolio";
|
||||||
|
import Portofolio_V3_EditDataBisnis from "@/app_modules/katalog/portofolio/edit/data/ui_new_edit_data";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Portofolio_EditDataBisnis />
|
{/* <Portofolio_EditDataBisnis /> */}
|
||||||
|
<Portofolio_V3_EditDataBisnis/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import { Portofolio_ComponentButtonSelanjutnya } from "../component";
|
|||||||
import { apiGetSubBidangBisnis } from "../lib/api_portofolio";
|
import { apiGetSubBidangBisnis } from "../lib/api_portofolio";
|
||||||
import { MODEL_PORTOFOLIO_BIDANG_BISNIS } from "../model/interface";
|
import { MODEL_PORTOFOLIO_BIDANG_BISNIS } from "../model/interface";
|
||||||
|
|
||||||
|
|
||||||
export default function Portofolio_V3_Create() {
|
export default function Portofolio_V3_Create() {
|
||||||
const params = useParams<{ id: string }>();
|
const params = useParams<{ id: string }>();
|
||||||
const profileId = params.id;
|
const profileId = params.id;
|
||||||
@@ -172,9 +173,6 @@ export default function Portofolio_V3_Create() {
|
|||||||
setDataPortofolio({
|
setDataPortofolio({
|
||||||
...dataPortofolio,
|
...dataPortofolio,
|
||||||
masterBidangBisnisId: val,
|
masterBidangBisnisId: val,
|
||||||
// masterSubBidangBisnisId: isSameBidang
|
|
||||||
// ? dataPortofolio.masterSubBidangBisnisId
|
|
||||||
// : "",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Jika berbeda bidang, reset sub bidang ke satu input kosong
|
// Jika berbeda bidang, reset sub bidang ke satu input kosong
|
||||||
|
|||||||
@@ -0,0 +1,610 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { MainColor } from "@/app_modules/_global/color/color_pallet";
|
||||||
|
import ComponentGlobal_ErrorInput from "@/app_modules/_global/component/error_input";
|
||||||
|
import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
|
||||||
|
import { apiGetMasterBidangBisnis } from "@/app_modules/_global/lib/api_fetch_master";
|
||||||
|
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global";
|
||||||
|
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
|
||||||
|
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
|
||||||
|
import { clientLogger } from "@/util/clientLogger";
|
||||||
|
import {
|
||||||
|
ActionIcon,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Grid,
|
||||||
|
Select,
|
||||||
|
Stack,
|
||||||
|
Styles,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
Textarea,
|
||||||
|
} from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { PhoneInput } from "react-international-phone";
|
||||||
|
import {
|
||||||
|
apiGetPortofolioById,
|
||||||
|
apiUpdatePortofolioById,
|
||||||
|
} from "../../component/api_fetch_portofolio";
|
||||||
|
import { Portofolio_SkeletonEditDataBisnis } from "../../component/skeleton_view";
|
||||||
|
import {
|
||||||
|
MODEL_PORTOFOLIO,
|
||||||
|
MODEL_PORTOFOLIO_BIDANG_BISNIS,
|
||||||
|
} from "../../model/interface";
|
||||||
|
import { ISUB_BIDANG_BISNIS } from "@/app_modules/model_global/portofolio";
|
||||||
|
import { apiGetSubBidangBisnis } from "../../lib/api_portofolio";
|
||||||
|
import { BaseSelectStylesNames } from "@mantine/core/lib/Select/types";
|
||||||
|
import { IconPlus, IconRowRemove, IconTrash } from "@tabler/icons-react";
|
||||||
|
import Component_V3_Label_TextInput from "@/app_modules/_global/component/new/comp_V3_label_text_input";
|
||||||
|
|
||||||
|
interface SubBidangSelected {
|
||||||
|
id: string;
|
||||||
|
MasterSubBidangBisnis: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IUpdatePortofoli {
|
||||||
|
namaBisnis: string;
|
||||||
|
alamatKantor: string;
|
||||||
|
tlpn: string;
|
||||||
|
deskripsi: string;
|
||||||
|
masterBidangBisnisId: string;
|
||||||
|
subBidang: SubBidangSelected[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Portofolio_EditDataBisnis() {
|
||||||
|
const router = useRouter();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const params = useParams<{ id: string }>();
|
||||||
|
const portofolioId = params.id;
|
||||||
|
const [data, setData] = useState<MODEL_PORTOFOLIO | null>(null);
|
||||||
|
const [listBidang, setListBidang] = useState<
|
||||||
|
MODEL_PORTOFOLIO_BIDANG_BISNIS[]
|
||||||
|
>([]);
|
||||||
|
|
||||||
|
const [listSubBidang, setListSubBidang] = useState<
|
||||||
|
ISUB_BIDANG_BISNIS[] | null
|
||||||
|
>(null);
|
||||||
|
|
||||||
|
const [selectedSubBidang, setSelectedSubBidang] = useState<
|
||||||
|
ISUB_BIDANG_BISNIS[] | null
|
||||||
|
>(null);
|
||||||
|
|
||||||
|
const [listSubBidangSelected, setListSubBidangSelected] = useState<
|
||||||
|
SubBidangSelected[]
|
||||||
|
>([
|
||||||
|
{
|
||||||
|
id: "",
|
||||||
|
MasterSubBidangBisnis: {
|
||||||
|
id: "",
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
onLoadData();
|
||||||
|
onLoadBidang();
|
||||||
|
onLoadMasterSubBidangBisnis();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const respone = await apiGetPortofolioById({
|
||||||
|
id: portofolioId,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (respone.success) {
|
||||||
|
setData(respone.data);
|
||||||
|
|
||||||
|
// Cek apakah ada sub bidang bisnis yang terpilih
|
||||||
|
const subBidangData = respone.data.Portofolio_BidangDanSubBidangBisnis;
|
||||||
|
|
||||||
|
// Jika ada sub bidang, gunakan data tersebut
|
||||||
|
if (subBidangData && subBidangData.length > 0) {
|
||||||
|
setListSubBidangSelected(subBidangData);
|
||||||
|
} else {
|
||||||
|
// Jika tidak ada sub bidang yang terpilih sebelumnya, tetap inisialisasi dengan array kosong
|
||||||
|
setListSubBidangSelected([
|
||||||
|
{
|
||||||
|
id: "",
|
||||||
|
MasterSubBidangBisnis: {
|
||||||
|
id: "",
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bisnisId = respone.data.MasterBidangBisnis.id;
|
||||||
|
if (bisnisId) {
|
||||||
|
handlerLoadSelectedSubBidang({ id: bisnisId });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setData(null);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
clientLogger.error("Error get data portofolio", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onLoadBidang = async () => {
|
||||||
|
try {
|
||||||
|
const respone = await apiGetMasterBidangBisnis();
|
||||||
|
|
||||||
|
if (respone.success) {
|
||||||
|
setListBidang(respone.data);
|
||||||
|
} else {
|
||||||
|
setListBidang([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
clientLogger.error("Error get data master bidang bisnis", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function onLoadMasterSubBidangBisnis() {
|
||||||
|
try {
|
||||||
|
const response = await apiGetSubBidangBisnis({});
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setListSubBidang(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error on load master sub bidang bisnis", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const validateData = async (data: any) => {
|
||||||
|
if (_.values(data).includes("")) {
|
||||||
|
return "Lengkapi data";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data?.tlpn?.length < 8) {
|
||||||
|
return "Nomor telepon minimal 8 digit";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validasi sub bidang bisnis yang dipilih
|
||||||
|
// Pastikan setidaknya satu sub bidang dipilih
|
||||||
|
const validSubBidangCount = listSubBidangSelected.filter(
|
||||||
|
(item) => item.MasterSubBidangBisnis.id
|
||||||
|
).length;
|
||||||
|
|
||||||
|
if (validSubBidangCount === 0) {
|
||||||
|
return "Pilih minimal satu sub bidang bisnis";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const hanldeUpadteData = async (data: any) => {
|
||||||
|
try {
|
||||||
|
// Filter list sub bidang yang dipilih (hanya ambil yang memiliki id)
|
||||||
|
const validSubBidang = listSubBidangSelected.filter(
|
||||||
|
(item) => item.MasterSubBidangBisnis.id
|
||||||
|
);
|
||||||
|
|
||||||
|
const newData: IUpdatePortofoli = {
|
||||||
|
namaBisnis: data?.namaBisnis,
|
||||||
|
alamatKantor: data?.alamatKantor,
|
||||||
|
tlpn: data?.tlpn,
|
||||||
|
deskripsi: data?.deskripsi,
|
||||||
|
masterBidangBisnisId: data?.MasterBidangBisnis.id,
|
||||||
|
subBidang: validSubBidang, // Hanya kirim sub bidang yang valid
|
||||||
|
};
|
||||||
|
|
||||||
|
const respone = await apiUpdatePortofolioById({
|
||||||
|
data: newData,
|
||||||
|
id: portofolioId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return respone;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error update data portofolio", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const submitUpdate = async () => {
|
||||||
|
const validate = await validateData(data);
|
||||||
|
if (validate) {
|
||||||
|
ComponentGlobal_NotifikasiPeringatan(validate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const updateData = await hanldeUpadteData(data);
|
||||||
|
|
||||||
|
if (updateData.success) {
|
||||||
|
ComponentGlobal_NotifikasiBerhasil(updateData.message);
|
||||||
|
router.back();
|
||||||
|
} else {
|
||||||
|
setLoading(false);
|
||||||
|
ComponentGlobal_NotifikasiGagal(updateData.message);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setLoading(false);
|
||||||
|
console.error("Error update data portofolio", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const baseStyles: Styles<BaseSelectStylesNames, Record<string, any>> = {
|
||||||
|
label: {
|
||||||
|
color: MainColor.white,
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
backgroundColor: MainColor.white,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handler untuk perubahan bidang bisnis
|
||||||
|
const handleBidangBisnisChange = (val: string) => {
|
||||||
|
const isSameBidang = data?.MasterBidangBisnis?.id === val;
|
||||||
|
|
||||||
|
setData({
|
||||||
|
...(data as any),
|
||||||
|
MasterBidangBisnis: {
|
||||||
|
id: val,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reset sub bidang jika ganti bidang
|
||||||
|
if (!isSameBidang) {
|
||||||
|
setListSubBidangSelected([
|
||||||
|
{
|
||||||
|
id: "",
|
||||||
|
MasterSubBidangBisnis: { id: "", name: "" },
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
handlerLoadSelectedSubBidang({ id: val });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handler untuk saat komponen pertama kali load
|
||||||
|
const handlerLoadSelectedSubBidang = ({ id }: { id: string }) => {
|
||||||
|
if (!listSubBidang) return;
|
||||||
|
|
||||||
|
const filteredSubBidang = listSubBidang.filter(
|
||||||
|
(item) => item.masterBidangBisnisId === id
|
||||||
|
);
|
||||||
|
|
||||||
|
setSelectedSubBidang(filteredSubBidang);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handler untuk menambah sub bidang bisnis
|
||||||
|
const handleAddSubBidang = () => {
|
||||||
|
setListSubBidangSelected([
|
||||||
|
...listSubBidangSelected,
|
||||||
|
{
|
||||||
|
id: "",
|
||||||
|
MasterSubBidangBisnis: { id: "", name: "" },
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handler untuk menghapus sub bidang bisnis
|
||||||
|
const handleRemoveSubBidang = (index: number) => {
|
||||||
|
if (listSubBidangSelected.length <= 1) return;
|
||||||
|
|
||||||
|
const updatedList = [...listSubBidangSelected];
|
||||||
|
updatedList.splice(index, 1);
|
||||||
|
setListSubBidangSelected(updatedList);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handler untuk update sub bidang
|
||||||
|
const handleSubBidangChange = (val: string, index: number) => {
|
||||||
|
const selected = selectedSubBidang?.find((s) => s.id === val);
|
||||||
|
const list = _.cloneDeep(listSubBidangSelected);
|
||||||
|
|
||||||
|
list[index] = {
|
||||||
|
id: "",
|
||||||
|
MasterSubBidangBisnis: selected || {
|
||||||
|
id: val,
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
setListSubBidangSelected(list);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Effect untuk mengupdate selectedSubBidang saat listSubBidang berubah
|
||||||
|
useShallowEffect(() => {
|
||||||
|
if (data?.MasterBidangBisnis?.id && listSubBidang) {
|
||||||
|
handlerLoadSelectedSubBidang({ id: data.MasterBidangBisnis.id });
|
||||||
|
}
|
||||||
|
}, [listSubBidang, data?.MasterBidangBisnis?.id]);
|
||||||
|
|
||||||
|
if (!data || !listBidang || !listSubBidang)
|
||||||
|
return <Portofolio_SkeletonEditDataBisnis />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack spacing={50} p={"sm"}>
|
||||||
|
<Stack>
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
...baseStyles,
|
||||||
|
required: {
|
||||||
|
color: MainColor.red,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
value={data?.namaBisnis}
|
||||||
|
label="Nama Bisnis"
|
||||||
|
placeholder="Nama bisnis"
|
||||||
|
maxLength={100}
|
||||||
|
error={
|
||||||
|
data?.namaBisnis === "" ? (
|
||||||
|
<ComponentGlobal_ErrorInput text="Masukan nama bisnis" />
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
namaBisnis: val.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Select Bidang dan Sub Bidang */}
|
||||||
|
<Select
|
||||||
|
styles={{
|
||||||
|
...baseStyles,
|
||||||
|
required: {
|
||||||
|
color: MainColor.red,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
value={data?.MasterBidangBisnis.id}
|
||||||
|
label="Bidang Bisnis"
|
||||||
|
placeholder="Pilih salah satu bidang bisnis"
|
||||||
|
data={listBidang.map((e) => ({
|
||||||
|
value: e.id,
|
||||||
|
label: e.name,
|
||||||
|
}))}
|
||||||
|
onChange={handleBidangBisnisChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack spacing={0}>
|
||||||
|
{listSubBidangSelected.map((e, index) => {
|
||||||
|
// Filter data untuk select sub bidang, menghilangkan yang sudah dipilih kecuali untuk item ini sendiri
|
||||||
|
const selectedIds = listSubBidangSelected
|
||||||
|
.filter((_, i) => i !== index)
|
||||||
|
.map((s) => s.MasterSubBidangBisnis.id)
|
||||||
|
.filter((id) => id); // Filter hanya yang memiliki id (tidak kosong)
|
||||||
|
|
||||||
|
const availableSubBidangOptions = (selectedSubBidang || [])
|
||||||
|
.filter((sub) => {
|
||||||
|
// Tampilkan jika ini adalah opsi yang dipilih saat ini atau belum dipilih di sub bidang lainnya
|
||||||
|
return (
|
||||||
|
sub.id === e.MasterSubBidangBisnis.id ||
|
||||||
|
!selectedIds.includes(sub.id)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.map((sub) => ({
|
||||||
|
value: sub.id,
|
||||||
|
label: sub.name,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box key={index} style={{ position: "relative" }}>
|
||||||
|
<Stack>
|
||||||
|
<Stack spacing={5}>
|
||||||
|
<Grid align="center">
|
||||||
|
<Grid.Col span={"auto"}>
|
||||||
|
<Select
|
||||||
|
styles={{
|
||||||
|
...baseStyles,
|
||||||
|
required: { color: MainColor.red },
|
||||||
|
dropdown: { backgroundColor: MainColor.white },
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
label={`Sub Bidang Bisnis ${index + 1}`}
|
||||||
|
placeholder={
|
||||||
|
selectedSubBidang && selectedSubBidang.length > 0
|
||||||
|
? "Pilih sub bidang bisnis"
|
||||||
|
: "Menunggu pilihan bidang bisnis"
|
||||||
|
}
|
||||||
|
value={e.MasterSubBidangBisnis.id}
|
||||||
|
data={availableSubBidangOptions}
|
||||||
|
onChange={(val) =>
|
||||||
|
handleSubBidangChange(val as any, index)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col
|
||||||
|
span={"content"}
|
||||||
|
style={{ alignSelf: "flex-end" }}
|
||||||
|
>
|
||||||
|
<Box>
|
||||||
|
{index > 0 ? (
|
||||||
|
<ActionIcon
|
||||||
|
variant="transparent"
|
||||||
|
onClick={() => handleRemoveSubBidang(index)}
|
||||||
|
>
|
||||||
|
<IconTrash color={MainColor.red} />
|
||||||
|
</ActionIcon>
|
||||||
|
) : (
|
||||||
|
<ActionIcon disabled variant="transparent" />
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
<Box style={{ alignSelf: "flex-start" }}>
|
||||||
|
{listSubBidangSelected.length > 1 &&
|
||||||
|
e.MasterSubBidangBisnis.id === "" ? (
|
||||||
|
<ComponentGlobal_ErrorInput text="Wajib dipilih" />
|
||||||
|
) : undefined}
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{/* Tombol untuk menghapus/menambah sub bidang bisnis */}
|
||||||
|
<Stack style={{ justifyContent: "space-between" }}>
|
||||||
|
{index === listSubBidangSelected.length - 1 && (
|
||||||
|
<Center>
|
||||||
|
<Button
|
||||||
|
radius={"xl"}
|
||||||
|
size={"xs"}
|
||||||
|
fz={10}
|
||||||
|
c={"black"}
|
||||||
|
leftIcon={<IconPlus size={15} />}
|
||||||
|
color={"yellow"}
|
||||||
|
bg={MainColor.yellow}
|
||||||
|
onClick={handleAddSubBidang}
|
||||||
|
disabled={
|
||||||
|
// Hanya disable jika tidak ada bidang bisnis utama yang dipilih
|
||||||
|
!data?.MasterBidangBisnis?.id ||
|
||||||
|
// Atau jika tidak ada sub bidang yang tersedia untuk dipilih
|
||||||
|
(selectedSubBidang &&
|
||||||
|
selectedSubBidang.length === 0) ||
|
||||||
|
// Atau jika semua sub bidang yang tersedia sudah dipilih
|
||||||
|
availableSubBidangOptions.length === 0
|
||||||
|
}
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-end",
|
||||||
|
marginLeft: "auto",
|
||||||
|
transition: "0.5s",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Tambah list
|
||||||
|
</Button>
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Stack>
|
||||||
|
{/* Select Bidang dan Sub Bidang */}
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
styles={{
|
||||||
|
...baseStyles,
|
||||||
|
required: {
|
||||||
|
color: MainColor.red,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
withAsterisk
|
||||||
|
value={data?.alamatKantor}
|
||||||
|
label="Alamat Kantor"
|
||||||
|
placeholder="Alamat kantor"
|
||||||
|
maxLength={100}
|
||||||
|
error={
|
||||||
|
data?.alamatKantor === "" ? (
|
||||||
|
<ComponentGlobal_ErrorInput text="Masukan alamat kantor" />
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
alamatKantor: val.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack spacing={5}>
|
||||||
|
<Component_V3_Label_TextInput text="Nomor Telepon" />
|
||||||
|
|
||||||
|
<PhoneInput
|
||||||
|
value={data?.tlpn}
|
||||||
|
placeholder="Nomor telepon"
|
||||||
|
countrySelectorStyleProps={{
|
||||||
|
buttonStyle: {
|
||||||
|
backgroundColor: MainColor.login,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
inputStyle={{ width: "100%", backgroundColor: MainColor.white }}
|
||||||
|
defaultCountry="id"
|
||||||
|
onChange={(val) => {
|
||||||
|
const valPhone = val.substring(1);
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
tlpn: valPhone,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{data?.tlpn === "" ? (
|
||||||
|
<ComponentGlobal_ErrorInput text="Masukan nomor telepon" />
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack spacing={5}>
|
||||||
|
<Textarea
|
||||||
|
styles={{
|
||||||
|
...baseStyles,
|
||||||
|
required: {
|
||||||
|
color: MainColor.red,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
autosize
|
||||||
|
minRows={2}
|
||||||
|
maxRows={5}
|
||||||
|
withAsterisk
|
||||||
|
value={data?.deskripsi}
|
||||||
|
label="Deskripsi"
|
||||||
|
placeholder="Deskripsi singkat mengenai usaha"
|
||||||
|
maxLength={300}
|
||||||
|
error={
|
||||||
|
data.deskripsi === "" ? (
|
||||||
|
<ComponentGlobal_ErrorInput text="Masukan deskripsi" />
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
deskripsi: val.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ComponentGlobal_InputCountDown
|
||||||
|
maxInput={300}
|
||||||
|
lengthInput={data?.deskripsi.length as any}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
disabled={
|
||||||
|
_.values(data).includes("") ||
|
||||||
|
// Disable tombol update hanya jika tidak ada sub bidang yang dipilih
|
||||||
|
!listSubBidangSelected.some(
|
||||||
|
(item) => item.MasterSubBidangBisnis.id !== ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
radius={"xl"}
|
||||||
|
loading={loading ? true : false}
|
||||||
|
loaderPosition="center"
|
||||||
|
onClick={() => {
|
||||||
|
submitUpdate();
|
||||||
|
}}
|
||||||
|
bg={MainColor.yellow}
|
||||||
|
color={"yellow"}
|
||||||
|
c={"black"}
|
||||||
|
style={{
|
||||||
|
transition: "0.5s",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ import { MODEL_USER } from "@/app_modules/home/model/interface";
|
|||||||
import { MODEL_IMAGES } from "@/app_modules/model_global/interface";
|
import { MODEL_IMAGES } from "@/app_modules/model_global/interface";
|
||||||
import { MODEL_PROFILE } from "../../profile/model/interface";
|
import { MODEL_PROFILE } from "../../profile/model/interface";
|
||||||
import { MODEL_MAP } from "@/app_modules/map/lib/interface";
|
import { MODEL_MAP } from "@/app_modules/map/lib/interface";
|
||||||
|
import { ISUB_BIDANG_BISNIS } from "@/app_modules/model_global/portofolio";
|
||||||
|
import { Prisma } from "@prisma/client";
|
||||||
|
|
||||||
export interface MODEL_PORTOFOLIO {
|
export interface MODEL_PORTOFOLIO {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -12,6 +14,7 @@ export interface MODEL_PORTOFOLIO {
|
|||||||
active: boolean;
|
active: boolean;
|
||||||
MasterBidangBisnis: MODEL_PORTOFOLIO_BIDANG_BISNIS;
|
MasterBidangBisnis: MODEL_PORTOFOLIO_BIDANG_BISNIS;
|
||||||
masterBidangBisnisId: string;
|
masterBidangBisnisId: string;
|
||||||
|
Portofolio_BidangDanSubBidangBisnis: Portofolio_BidangDanSubBidangBisnis;
|
||||||
profileId: string;
|
profileId: string;
|
||||||
Logo: MODEL_LOGO;
|
Logo: MODEL_LOGO;
|
||||||
logoId: string;
|
logoId: string;
|
||||||
@@ -34,7 +37,7 @@ export interface MODEL_PORTOFOLIO_BIDANG_BISNIS {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
slug: string
|
slug: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MODEL_PORTOFOLIO_MEDSOS {
|
export interface MODEL_PORTOFOLIO_MEDSOS {
|
||||||
@@ -49,3 +52,29 @@ export interface MODEL_PORTOFOLIO_MEDSOS {
|
|||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
portofolioId: string;
|
portofolioId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Portofolio_BidangDanSubBidangBisnis =
|
||||||
|
Prisma.Portofolio_BidangDanSubBidangBisnisGetPayload<{
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
masterBidangBisnisId?: true,
|
||||||
|
masterSubBidangBisnisId?: true,
|
||||||
|
isActive: true
|
||||||
|
MasterBidangBisnis: {
|
||||||
|
select: {
|
||||||
|
id?: true;
|
||||||
|
name?: true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
MasterSubBidangBisnis: {
|
||||||
|
select: {
|
||||||
|
id?: true;
|
||||||
|
name?: true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
// include: {
|
||||||
|
|
||||||
|
// };
|
||||||
|
}>;
|
||||||
|
|||||||
15
types/env.d.ts
vendored
Normal file
15
types/env.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
declare namespace NodeJS {
|
||||||
|
interface ProcessEnv {
|
||||||
|
DATABASE_URL?: string;
|
||||||
|
WIBU_PWD?: string;
|
||||||
|
Client_KEY?: string;
|
||||||
|
Server_KEY?: string;
|
||||||
|
MAPBOX_TOKEN?: string;
|
||||||
|
WS_APIKEY?: string;
|
||||||
|
NEXT_PUBLIC_WIBU_REALTIME_TOKEN?: string;
|
||||||
|
NEXT_PUBLIC_BASE_TOKEN_KEY?: string;
|
||||||
|
NEXT_PUBLIC_BASE_SESSION_KEY?: string;
|
||||||
|
NEXT_PUBLIC_API_URL?: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user