database investasi

# feat:
- Create investasi
- Edit investasi
- Ubah status investasi
- Masukan berita
### No issue
This commit is contained in:
2023-11-07 21:22:53 +08:00
parent 9fcbba24e3
commit b662b714ad
88 changed files with 1386 additions and 637 deletions

View File

@@ -121,15 +121,15 @@ model Investasi {
ImageInvestasi Images? @relation(fields: [imagesId], references: [id])
imagesId String? @unique
ProspektusInvestasi ProspektusInvestasi?
DokumenInvestasi DokumenInvestasi? @relation(fields: [dokumenInvestasiId], references: [id])
dokumenInvestasiId String?
BeritaInvestasi BeritaInvestasi? @relation(fields: [beritaInvestasiId], references: [id])
beritaInvestasiId String?
ProspektusInvestasi ProspektusInvestasi?
DokumenInvestasi DokumenInvestasi? @relation(fields: [dokumenInvestasiId], references: [id])
dokumenInvestasiId String?
SahamTerbeli SahamTerbeli? @relation(fields: [sahamTerbeliId], references: [id])
sahamTerbeliId String?
MasterStatusInvestasi MasterStatusInvestasi? @relation(fields: [masterStatusInvestasiId], references: [id])
masterStatusInvestasiId String? @default("1")
BeritaInvestasi BeritaInvestasi[]
}
model MasterPencarianInvestor {
@@ -189,15 +189,16 @@ model DokumenInvestasi {
}
model BeritaInvestasi {
id String @id @default(cuid())
id String @id @default(cuid())
title String
deskripsi String
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
investasi Investasi[]
ImageBerita Images? @relation(fields: [imagesId], references: [id])
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
ImageBerita Images? @relation(fields: [imagesId], references: [id])
imagesId String?
investasi Investasi @relation(fields: [investasiId], references: [id])
investasiId String
}
model SahamTerbeli {

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

View File

@@ -90,23 +90,23 @@ export async function GET(req: Request) {
});
}
// for (let i of statusInvestasi) {
// await prisma.masterStatusInvestasi.upsert({
// where: {
// id: i.id,
// },
// create: {
// id: i.id,
// name: i.name,
// color: i.color,
// },
// update: {
// id: i.id,
// name: i.name,
// color: i.color,
// },
// });
// }
for (let i of statusInvestasi) {
await prisma.masterStatusInvestasi.upsert({
where: {
id: i.id,
},
create: {
id: i.id,
name: i.name,
color: i.color,
},
update: {
id: i.id,
name: i.name,
color: i.color,
},
});
}
return NextResponse.json({ success: true });
}

View File

@@ -4,9 +4,10 @@ import { cookies } from "next/headers";
import yaml from "yaml";
import fs from "fs";
import { funCreateInvestasi } from "@/app_modules/investasi/fun/fun_create_investasi";
import getPencarianInvestor from "@/app_modules/investasi/fun/get_pencarian_investor";
import getPeriodeDeviden from "@/app_modules/investasi/fun/get_periode_deviden";
import getPembagianDeviden from "@/app_modules/investasi/fun/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 getPembagianDeviden from "@/app_modules/investasi/fun/master/get_pembagian_deviden";
import getStatusInvestasi from "@/app_modules/investasi/fun/master/get_status_investasi";
const config = yaml.parse(fs.readFileSync("config.yaml").toString());
@@ -21,8 +22,8 @@ export default async function Page() {
const pencarianInvestor = await getPencarianInvestor();
const periodeDeviden = await getPeriodeDeviden();
const pembagianDeviden = await getPembagianDeviden();
const statusInvestasi = await getStatusInvestasi();
// console.log(pembagianDeviden)
return (
<>

View File

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

View File

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

View File

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

View File

@@ -1,8 +0,0 @@
import { CreateBeritaInvestasi } from "@/app_modules/investasi";
export default async function Page() {
return<>
<CreateBeritaInvestasi/>
</>
}

View File

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

View File

@@ -0,0 +1,13 @@
import { DetailDraftInvestasi } 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)
return<>
<DetailDraftInvestasi dataInvestasi={dataInvestasi}/>
</>
}

View File

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

View File

@@ -1,8 +0,0 @@
import { DetailDraftInvestasi } from "@/app_modules/investasi";
export default async function Page() {
return<>
<DetailDraftInvestasi/>
</>
}

View File

@@ -0,0 +1,12 @@
import { DetailReviewInvestasi } 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<>
<DetailReviewInvestasi dataInvestasi={dataInvestasi as any}/>
</>
}

View File

@@ -1,7 +0,0 @@
import { DetailReviewInvestasi } from "@/app_modules/investasi";
export default async function Page() {
return<>
<DetailReviewInvestasi/>
</>
}

View File

@@ -1,7 +1,10 @@
import { EditBeritaInvestasi } from "@/app_modules/investasi";
import getOneBeritaInvestasiById from "@/app_modules/investasi/fun/get_one_berita_by_id";
export default async function Page(params:any) {
export default async function Page({params}: {params: {id: string}}) {
const dataBerita = await getOneBeritaInvestasiById(params.id)
// console.log(dataBerita)
return<>
<EditBeritaInvestasi/>
<EditBeritaInvestasi dataBerita={dataBerita as any}/>
</>
}

View File

@@ -1,9 +1,24 @@
import { EditIntroInvestasi } from "@/app_modules/investasi";
import getOneInvestasiById from "@/app_modules/investasi/fun/get_one_investasi_by_id";
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";
export default async function Page({ params }: { params: { id: string } }) {
const dataInvestasi = await getOneInvestasiById(params.id)
const listPencarian = await getPencarianInvestor()
const listPeriode = await getPeriodeDeviden()
const listPembagian = await getPembagianDeviden()
return (
<>
<EditIntroInvestasi />
<EditIntroInvestasi
dataInvestasi={dataInvestasi as any}
listPencarian={listPencarian as any}
listPeriode={listPeriode as any}
listPembagian={listPembagian as any}
/>
</>
);
}

View File

@@ -3,12 +3,14 @@ import React from "react";
export default async function Layout({
children,
params
}: {
children: React.ReactNode;
params: { id: string };
}) {
return (
<>
<LayoutListEditBeritaInvestasi>{children}</LayoutListEditBeritaInvestasi>
<LayoutListEditBeritaInvestasi idInves={params.id}>{children}</LayoutListEditBeritaInvestasi>
</>
);
}

View File

@@ -1,9 +1,15 @@
import { ListEditBeritaInvestasi } 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 (
<>
<ListEditBeritaInvestasi id={params.id} />
<ListEditBeritaInvestasi dataInvestasi={dataInvestasi as any} />
</>
);
}

View File

@@ -1,8 +1,8 @@
import { MainInvestasi } from "@/app_modules/investasi";
import { getListAllInvestasi } from "@/app_modules/investasi/fun/get_list_all_investasi";
import getPembagianDeviden from "@/app_modules/investasi/fun/get_pembagian_deviden";
import getPencarianInvestor from "@/app_modules/investasi/fun/get_pencarian_investor";
import getPeriodeDeviden from "@/app_modules/investasi/fun/get_periode_deviden";
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";
export default async function Page() {
const data = await getListAllInvestasi()

View File

@@ -1,7 +1,28 @@
import { PortofolioInvestasi } from "@/app_modules/investasi";
import { cookies } from "next/headers";
import fs from "fs";
import yaml from "yaml";
import { unsealData } from "iron-session";
import getInvestasiById from "@/app_modules/investasi/fun/get_investasi_by_id";
import getStatusInvestasi from "@/app_modules/investasi/fun/master/get_status_investasi";
export default async function Page({params}: {params: {id: string}}) {
return<>
<PortofolioInvestasi/>
const config = yaml.parse(fs.readFileSync("config.yaml").toString());
export default async function Page() {
const c = cookies().get("ssn");
const tkn = JSON.parse(
await unsealData(c?.value as string, {
password: config.server.password,
})
);
const dataInvestasi = await getInvestasiById(tkn.id)
const listStatusInvestasi = await getStatusInvestasi()
// console.log(listStatusInvestasi)
return (
<>
<PortofolioInvestasi dataInvestasi={dataInvestasi as any} listStatusInvestasi={listStatusInvestasi as any} />
</>
}
);
}

View File

@@ -1,4 +1,5 @@
export const RouterInvestasi = {
api_gambar: "/api/investasi/gambar/",
//INVESTASI
main: "/dev/investasi/main",
main_porto: "/dev/investasi/main/portofolio",
@@ -16,6 +17,7 @@ export const RouterInvestasi = {
status_transaksi_gagal: "/dev/investasi/status_transaksi/gagal",
metode_transfer: "/dev/investasi/metode_transfer",
// edit //
edit: "/dev/investasi/edit/",
edit_intro: "/dev/investasi/edit_intro/",
edit_prospektus: "/dev/investasi/edit_prospektus/",
edit_dokumen: "/dev/investasi/edit_dokumen/",
@@ -25,13 +27,13 @@ export const RouterInvestasi = {
detail_prospektus: "/dev/investasi/detail_prospektus/",
detail_dokumen: "/dev/investasi/detail_dokumen/",
detail_berita: "/dev/investasi/detail_berita/",
detail_draft: "/dev/investasi/detail_portofolio/draft",
detail_draft: "/dev/investasi/detail_portofolio/draft/",
detail_publish: "/dev/investasi/detail_portofolio/publish",
detail_review: "/dev/investasi/detail_portofolio/review",
detail_review: "/dev/investasi/detail_portofolio/review/",
detail_reject: "/dev/investasi/detail_portofolio/reject",
// berita
berita: "/dev/investasi/berita/",
create_berita: "/dev/investasi/create_berita",
create_berita: "/dev/investasi/create_berita/",
list_edit_berita: "/dev/investasi/list_edit_berita/",
};

View File

@@ -22,7 +22,6 @@ export default function MainCrowd() {
return (
<>
<Stack>
<Paper bg={"gray"}>
<AspectRatio ratio={16 / 9}>
<Image alt="" src={"/aset/logo.png"} />
@@ -51,7 +50,6 @@ export default function MainCrowd() {
</Button>
</Stack>
</Stack>
</>
);
}

View File

@@ -2,16 +2,20 @@
import { ApiHipmi } from "@/app/lib/api";
import { Warna } from "@/app/lib/warna";
import { MODEL_ALL_MASTER } from "@/app_modules/models/model_AllMaster";
import { MODEL_DEFAULT_MASTER } from "@/app_modules/models/model_default_master";
import {
AspectRatio,
Box,
Button,
Center,
Divider,
FileButton,
Group,
Image,
NumberInput,
Select,
Stack,
Text,
TextInput,
} from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
@@ -32,23 +36,22 @@ export default function InvestasiCreate({
pembagianDeviden,
}: {
id: string;
pencarianInvestor: MODEL_ALL_MASTER[];
periodeDeviden: MODEL_ALL_MASTER[];
pembagianDeviden: MODEL_ALL_MASTER[];
pencarianInvestor: MODEL_DEFAULT_MASTER[];
periodeDeviden: MODEL_DEFAULT_MASTER[];
pembagianDeviden: MODEL_DEFAULT_MASTER[];
}) {
const router = useRouter();
const [fl, setFl] = useState<File | null>(null);
const [img, setImg] = useState<any | null>();
const [changeColor, setChangeColor] = useAtom(gs_investasiFooter);
const [activeTab, setActiveTab] = useAtom(gs_TabPortoInvestasi)
const [activeTab, setActiveTab] = useAtom(gs_TabPortoInvestasi);
const [totalLembar, setTotalLembar] = useState(0);
const [value, setValue] = useState({
title: "",
targetDana: "",
hargaLembar: "",
totalLembar: "",
roi: "",
targetDana: 0,
hargaLembar: 0,
roi: 0,
pencarianInvestorId: "",
periodeDevidenId: "",
pembagianDevidenId: "",
@@ -60,30 +63,35 @@ export default function InvestasiCreate({
title: value.title,
targetDana: value.targetDana,
hargaLembar: value.hargaLembar,
totalLembar: value.totalLembar,
totalLembar: totalLembar,
roi: value.roi,
masterPeriodeDevidenId: value.periodeDevidenId,
masterPembagianDevidenId: value.pembagianDevidenId,
masterPencarianInvestorId: value.pencarianInvestorId,
};
// toast("Berhasil disimpan")
setChangeColor(1);
setActiveTab("Draft")
return setTimeout(() => router.push(RouterInvestasi.dialog_create), 1000);
// if (_.values(body).includes("")) return toast("Lengkapi data");
// if (!fl) return toast("File Kosong");
// const fd = new FormData();
// fd.append("file", fl);
// await funCreateInvestasi(fd, body as any).then((res) => {
// if (res.status === 201) {
// toast(res.message);
// return router.push("/dev/investasi/main");
// } else {
// return toast(res.message);
// }
// });
if (_.values(body).includes("")) return toast("Lengkapi data");
if (!fl) return toast("File Kosong");
const fd = new FormData();
fd.append("file", fl);
await funCreateInvestasi(fd, body as any).then((res) => {
if (res.status === 201) {
// toast(res.message);
setChangeColor(1);
setActiveTab("Draft");
return router.push(RouterInvestasi.dialog_create)
} else {
return toast(res.message);
}
});
}
async function onTotalLembar(target: any, harga: any) {
const hasil: any = target / harga;
setTotalLembar(_.floor(hasil === Infinity ? 0 : hasil));
}
return (
@@ -122,103 +130,107 @@ export default function InvestasiCreate({
</FileButton>
</Group>
<Center>
<Box mt={"md"} w={350}>
<TextInput
label="Judul Proyek"
onChange={(val) => {
setValue({
...value,
title: val.target.value,
});
}}
/>
<TextInput
label="Dana Dibutuhan"
type="number"
onChange={(val) => {
setValue({
...value,
targetDana: val.target.value,
});
}}
/>
<TextInput
label="Harga Per Lember"
type="number"
onChange={(val: any) => {
setValue({
...value,
hargaLembar: val.target.value,
});
<Stack spacing={"sm"} px={"md"}>
<TextInput
withAsterisk
label="Judul Investasi"
onChange={(val) => {
setValue({
...value,
title: val.target.value,
});
}}
/>
<NumberInput
withAsterisk
type="number"
label="Dana Dibutuhkan"
onChange={(val: any) => {
setValue({
...value,
targetDana: val,
});
}}
/>
<NumberInput
label="Harga Per Lembar"
type="number"
onChange={(val) => {
//console.log(val)
setValue({
...value,
hargaLembar: +val,
});
onTotalLembar(value.targetDana, val);
}}
/>
<Stack spacing={3}>
<Text fz={"sm"} fw={500}>
Total Lembar
</Text>
<Stack spacing={0}>
<Text>{totalLembar}</Text>
<Divider />
</Stack>
<Text c={"red"} fz={10}>
*Total lembar dihitung dari, Target Dana : Harga Perlembar
</Text>
</Stack>
<NumberInput
withAsterisk
type="number"
label="Rasio Keuntungan / ROI"
onChange={(val: any) => {
setValue({
...value,
roi: val,
});
}}
/>
<Select
withAsterisk
label="Pencarian Investor"
data={pencarianInvestor.map((e) => ({
value: e.id,
label: e.name + " " + "hari",
}))}
onChange={(val) => {
setValue({
...(value as any),
pencarianInvestorId: val,
});
}}
/>
<Select
withAsterisk
label="Periode Deviden"
data={periodeDeviden.map((e) => ({ value: e.id, label: e.name }))}
onChange={(val) => {
setValue({
...(value as any),
periodeDevidenId: val,
});
}}
/>
<Select
withAsterisk
label="Pembagian Deviden"
data={pembagianDeviden.map((e) => ({
value: e.id,
label: e.name + " " + "bulan",
}))}
onChange={(val) => {
setValue({
...(value as any),
pembagianDevidenId: val,
});
}}
/>
</Stack>
const data : any = (value.targetDana as any) / val.target.value;
// setTL(data);
setValue({
...value,
totalLembar: data
});
}}
/>
<TextInput
label="Total Lembar"
type="number"
value={Math.floor(value.totalLembar as any)}
onChange={(val) => {
setValue({
...value,
totalLembar: val.target.value,
});
}}
/>
<TextInput
label="Rasio Keuntungan / ROI"
type="number"
onChange={(val) => {
setValue({
...value,
roi: val.target.value,
});
}}
/>
<Select
label="Pencarian Investor"
data={pencarianInvestor.map((e) => ({
value: e.id,
label: e.name,
}))}
onChange={(val) => {
setValue({
...(value as any),
pencarianInvestorId: val,
});
}}
/>
<Select
label="Periode Deviden"
data={periodeDeviden.map((e) => ({ value: e.id, label: e.name }))}
onChange={(val) => {
setValue({
...(value as any),
periodeDevidenId: val,
});
}}
/>
<Select
label="Pembagian Deviden"
data={pembagianDeviden.map((e) => ({
value: e.id,
label: e.name,
}))}
onChange={(val) => {
setValue({
...(value as any),
pembagianDevidenId: val,
});
}}
/>
</Box>
</Center>
<Center my={"lg"}>
<Button
w={300}

View File

@@ -11,31 +11,21 @@ import toast from "react-simple-toasts";
export default function LayoutCreateBeritaInvestasi({
children,
idInves
}: {
children: React.ReactNode;
idInves: string
}) {
const router = useRouter();
return (
<>
<AppShell
header={<HeaderTamplate title="Buat Berita" />}
footer={
<Footer height={70} sx={{ borderStyle: "none" }}>
<Center>
<Button
w={300}
radius={50}
bg={Warna.biru}
onClick={() => {
router.back()
toast("Berita tersimpan")
}}
>
Simpan
</Button>
</Center>
</Footer>
}
// footer={
// <Footer height={70} sx={{ borderStyle: "none" }}>
// </Footer>
// }
>
{children}
</AppShell>

View File

@@ -1,22 +1,125 @@
"use client"
"use client";
import { AspectRatio, Button, Center, Image, Stack, TextInput, Textarea, Title } from "@mantine/core"
import { IconUpload } from "@tabler/icons-react"
import { Warna } from "@/app/lib/warna";
import {
AspectRatio,
Button,
Center,
FileButton,
Group,
Image,
Stack,
TextInput,
Textarea,
Title,
} from "@mantine/core";
import { IconCamera, IconUpload } from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react";
import toast from "react-simple-toasts";
import funCreateBeritaInvestasi from "../fun/fun_create_berita";
export default function CreateBeritaInvestasi(){
return<>
<Stack>
export default function CreateBeritaInvestasi({idInves}: {idInves: string}) {
const router = useRouter();
const [fl, setFl] = useState<File | null>(null);
const [img, setImg] = useState<any | null>();
const [value, setValue] = useState({
title: "",
deskripsi: "",
investasiId: idInves
});
async function onCreate() {
const body = value;
if (_.values(body).includes("")) return toast("Lengkapi data");
if (!fl) return toast("File Kosong");
const fd = new FormData();
fd.append("file", fl);
await funCreateBeritaInvestasi(fd, body as any).then((res) => {
res.status === 201
? (toast(res.message), router.back())
: toast(res.message);
});
// router.back();
// toast("Berita tersimpan");
}
return (
<>
<Stack>
<AspectRatio ratio={16 / 9}>
<Image alt="" src={"/aset/no-img.png"} />
{img ? (
<Image alt="" src={img} />
) : (
<Image alt="" src={"/aset/no-img.png"} />
)}
</AspectRatio>
<Center>
<Button leftIcon={<IconUpload size={10} />} compact radius={50}>
Upload
</Button>
</Center>
<TextInput label="Judul berita" />
<Textarea label="Deskripsi" autosize minRows={2} maxRows={6} />
<Group position="center" mt={"md"}>
<FileButton
onChange={async (files: any) => {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
setImg(buffer);
setFl(files);
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
compact
{...props}
w={100}
radius={50}
bg={Warna.hijau_muda}
// onClick={() => router.push("/dev/investasi/upload")}
>
<IconCamera />
</Button>
)}
</FileButton>
</Group>
<TextInput
label="Judul berita"
onChange={(val) => {
setValue({
...value,
title: val.target.value,
});
}}
/>
<Textarea
label="Deskripsi"
autosize
minRows={2}
maxRows={6}
onChange={(val) => {
setValue({
...value,
deskripsi: val.target.value,
});
}}
/>
</Stack>
<Center mt={100}>
<Button
w={300}
radius={50}
bg={Warna.biru}
onClick={() => {
onCreate();
}}
>
Simpan
</Button>
</Center>
</>
}
);
}

View File

@@ -7,8 +7,10 @@ import React from "react";
export default function LayoutDetailDraftInvestasi({
children,
id
}: {
children: React.ReactNode;
id: string
}) {
return (
<>
@@ -17,7 +19,7 @@ export default function LayoutDetailDraftInvestasi({
<HeaderTamplate
title="Detail Draft"
icon={<IconEdit />}
route2={`/dev/investasi/edit/${1}`}
route2={`/dev/investasi/edit/${id}`}
/>
}
>

View File

@@ -28,10 +28,19 @@ import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import { gs_TabPortoInvestasi } from "../../g_state";
import toast from "react-simple-toasts";
import { MODEL_Investasi } from "../../model/model_investasi";
import { useState } from "react";
import _ from "lodash";
import funGantiStatusInvestasi from "../../fun/fun_ganti_status";
export default function DetailDraftInvestasi() {
export default function DetailDraftInvestasi({
dataInvestasi,
}: {
dataInvestasi: any;
}) {
const router = useRouter();
const [activeTab, setActiveTab] = useAtom(gs_TabPortoInvestasi)
const [activeTab, setActiveTab] = useAtom(gs_TabPortoInvestasi);
const [investasi, setInvestasi] = useState<MODEL_Investasi>(dataInvestasi);
const listBox = [
{
@@ -55,66 +64,68 @@ export default function DetailDraftInvestasi() {
];
async function onsubmit() {
toast("Review Berhasil Diajukan")
router.push(RouterInvestasi.portofolio)
setActiveTab("Review")
await funGantiStatusInvestasi(investasi.id, "2")
.then((res) => res)
.then((val) => {
if (val.status === 200) {
toast("Review Berhasil Diajukan");
router.push(RouterInvestasi.portofolio);
setActiveTab("Review");
} else {
toast("Error");
}
});
}
return (
<>
<Paper withBorder mb={"md"}>
<AspectRatio ratio={16 / 9}>
<Image alt="" src={"/aset/no-img.png"} />
<Image
alt=""
src={RouterInvestasi.api_gambar + `${investasi.imagesId}`}
/>
</AspectRatio>
</Paper>
{/* Title dan Persentase */}
<Box mb={"md"}>
<Center>
<Title order={4} mb={"xs"}>
Judul Proyek
{investasi.title}
</Title>
<Slider
disabled
size={10}
value={60}
marks={[{ value: 60, label: "60%" }]}
/>
</Box>
</Center>
{/* Rincian Data */}
<Grid p={"md"} mb={"md"}>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>Dana Dibutuhkan</Text>
<Text>Rp. </Text>
<Text>Rp. {investasi.targetDana}</Text>
</Box>
<Box>
<Text>Harga Per Lembar</Text>
<Text>Rp. </Text>
<Text>Rp. {investasi.hargaLembar}</Text>
</Box>
<Box>
<Text>Jadwal Pembagian</Text>
<Text>3 Bulan </Text>
<Text>{investasi.MasterPembagianDeviden.name} bulan </Text>
</Box>
</Stack>
</Grid.Col>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>ROI</Text>
<Text>%</Text>
<Text>{investasi.roi}%</Text>
</Box>
<Box>
<Text>Total Lembar</Text>
<Text>0</Text>
<Text>{investasi.totalLembar} lembar</Text>
</Box>
<Box>
<Text>Pembagian Deviden</Text>
<Text>Selamanya</Text>
<Text>{investasi.MasterPeriodeDeviden.name}</Text>
</Box>
</Stack>
</Grid.Col>
@@ -131,22 +142,6 @@ export default function DetailDraftInvestasi() {
Ajukan Review
</Button>
</Center>
{/* List Box */}
{/* <Grid mb={"md"}>
{listBox.map((e) => (
<Grid.Col span={"auto"} key={e.id} onClick={() => router.push(e.route + `${id}`)}>
<Paper h={100} w={100} bg={"gray.4"} withBorder py={"xs"}>
<Flex direction={"column"} align={"center"} justify={"center"}>
<Text fz={12}>{e.name}</Text>
<ActionIcon variant="transparent" size={60}>
{e.icon}
</ActionIcon>
</Flex>
</Paper>
</Grid.Col>
))}
</Grid> */}
</>
);
}

View File

@@ -28,10 +28,14 @@ import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import { gs_TabPortoInvestasi } from "../../g_state";
import toast from "react-simple-toasts";
import { MODEL_Investasi } from "../../model/model_investasi";
import funGantiStatusInvestasi from "../../fun/fun_ganti_status";
import { useState } from "react";
export default function DetailReviewInvestasi() {
export default function DetailReviewInvestasi({dataInvestasi}:{dataInvestasi: MODEL_Investasi}) {
const router = useRouter();
const [activeTab, setActiveTab] = useAtom(gs_TabPortoInvestasi);
const [investasi,setInvestasi] = useState<MODEL_Investasi>(dataInvestasi)
const listBox = [
{
@@ -55,30 +59,35 @@ export default function DetailReviewInvestasi() {
];
async function onsubmit() {
toast("Review Dibatalkan");
router.push(RouterInvestasi.portofolio);
setActiveTab("Draft");
await funGantiStatusInvestasi(investasi.id, "1")
.then((res) => res)
.then((val) => {
if (val.status === 200) {
toast("Review Dibatalkan");
router.push(RouterInvestasi.portofolio);
setActiveTab("Draft");
} else {
toast("Error");
}
});
}
return (
<>
<Paper withBorder mb={"md"}>
<AspectRatio ratio={16 / 9}>
<Image alt="" src={"/aset/no-img.png"} />
<Image
alt=""
src={RouterInvestasi.api_gambar + `${investasi.imagesId}`}
/>
</AspectRatio>
</Paper>
{/* Title dan Persentase */}
<Box mb={"md"}>
<Title order={4} mb={"xs"}>
Judul Proyek
{investasi.title}
</Title>
<Slider
disabled
size={10}
value={60}
marks={[{ value: 60, label: "60%" }]}
/>
</Box>
{/* Rincian Data */}
@@ -87,15 +96,15 @@ export default function DetailReviewInvestasi() {
<Stack>
<Box>
<Text>Dana Dibutuhkan</Text>
<Text>Rp. </Text>
<Text>Rp. {investasi.targetDana}</Text>
</Box>
<Box>
<Text>Harga Per Lembar</Text>
<Text>Rp. </Text>
<Text>Rp. {investasi.hargaLembar}</Text>
</Box>
<Box>
<Text>Jadwal Pembagian</Text>
<Text>3 Bulan </Text>
<Text>{investasi.MasterPembagianDeviden.name} Bulan </Text>
</Box>
</Stack>
</Grid.Col>
@@ -103,15 +112,15 @@ export default function DetailReviewInvestasi() {
<Stack>
<Box>
<Text>ROI</Text>
<Text>%</Text>
<Text>{investasi.roi} %</Text>
</Box>
<Box>
<Text>Total Lembar</Text>
<Text>0</Text>
<Text>{investasi.totalLembar} lembar</Text>
</Box>
<Box>
<Text>Pembagian Deviden</Text>
<Text>Selamanya</Text>
<Text>{investasi.MasterPeriodeDeviden.name}</Text>
</Box>
</Stack>
</Grid.Col>

View File

@@ -18,18 +18,11 @@ export default function LayoutEditBeritaInvestasi({
<>
<AppShell
header={<HeaderTamplate title="Edit Berita" />}
footer={
<Footer height={70} sx={{ borderStyle: "none" }}>
<Center>
<Button w={300} radius={50} bg={Warna.hijau_muda} color="green" onClick={() => {
router.back()
toast("Berita terupdate")
}}>
Update
</Button>
</Center>
</Footer>
}
// footer={
// <Footer height={70} sx={{ borderStyle: "none" }}>
// </Footer>
// }
>
{children}
</AppShell>

View File

@@ -4,30 +4,130 @@ import {
AspectRatio,
Button,
Center,
FileButton,
FileInput,
Group,
Image,
Stack,
Text,
TextInput,
Textarea,
} from "@mantine/core";
import { IconUpload } from "@tabler/icons-react";
import { IconCamera, IconUpload } from "@tabler/icons-react";
import {
MODEL_Investasi,
Model_Berita_Investasi,
} from "../model/model_investasi";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import { Warna } from "@/app/lib/warna";
import toast from "react-simple-toasts";
import _ from "lodash";
import funEditBeritaInvestasi from "../fun/fun_edit_berita";
import deleteBeritaInvestasi from "../fun/fun_delete_berita";
export default function EditBeritaInvestasi({
dataBerita,
}: {
dataBerita: Model_Berita_Investasi;
}) {
const router = useRouter();
const [edit, setEdit] = useState(dataBerita);
const [img, setImg] = useState<any | null>();
const [fl, setFl] = useState<File | null>(null);
async function onUpdate() {
const body = edit;
if (_.values(body).includes("")) return toast("Lengkapi data");
const fd = new FormData();
fd.append("file", fl as any);
await funEditBeritaInvestasi(fd, body).then(async (res) => {
if (res.status === 200) {
router.back();
} else {
toast(res.message)
}
});
}
export default function EditBeritaInvestasi() {
return (
<>
<Stack>
<AspectRatio ratio={16 / 9}>
<Image alt="" src={"/aset/no-img.png"} />
{img ? (
<Image alt="" src={img} />
) : (
<Image
alt=""
src={RouterInvestasi.api_gambar + `${edit.imagesId}`}
/>
)}
</AspectRatio>
<Center>
<Button leftIcon={<IconUpload size={10} />} compact radius={50}>
Upload
</Button>
</Center>
<TextInput label="Judul berita" />
<Textarea label="Deskripsi" autosize minRows={2} maxRows={6} />
<Group position="center" mt={"md"}>
<FileButton
onChange={async (files: any) => {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
setImg(buffer);
setFl(files);
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
radius={50}
bg={Warna.hijau_muda}
color="green"
>
<IconCamera />
</Button>
)}
</FileButton>
</Group>
<TextInput
label="Judul berita"
value={edit.title}
onChange={(val) => {
setEdit({
...edit,
title: val.target.value,
});
}}
/>
<Textarea
label="Deskripsi"
autosize
minRows={2}
maxRows={6}
value={edit.deskripsi}
onChange={(val) => {
setEdit({
...edit,
deskripsi: val.target.value,
});
}}
/>
</Stack>
<Center mt={100}>
<Button
w={300}
radius={50}
bg={Warna.hijau_muda}
color="green"
onClick={() => {
onUpdate();
}}
>
Update
</Button>
</Center>
</>
);
}

View File

@@ -16,6 +16,8 @@ import {
Select,
TextInput,
Image,
NumberInput,
Stack,
} from "@mantine/core";
import { IconCamera, IconChevronRight } from "@tabler/icons-react";
import Link from "next/link";
@@ -23,21 +25,57 @@ import { useRouter } from "next/navigation";
import { useState } from "react";
import toast from "react-simple-toasts";
import { MODEL_Investasi } from "../model/model_investasi";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import _ from "lodash";
import { MODEL_DEFAULT_MASTER } from "@/app_modules/models/model_default_master";
import funEditInvestasi from "../fun/fun_edit_investasi";
export default function EditIntroInvestasi() {
export default function EditIntroInvestasi({
dataInvestasi,
listPencarian,
listPeriode,
listPembagian,
}: {
dataInvestasi: MODEL_Investasi;
listPencarian: MODEL_DEFAULT_MASTER[];
listPeriode: MODEL_DEFAULT_MASTER[];
listPembagian: MODEL_DEFAULT_MASTER[];
}) {
const router = useRouter();
const [edit, setEdit] = useState(true);
const [edit_inves, setEdit_inves] = useState(dataInvestasi);
const [img, setImg] = useState<any | null>();
const [value, setValue] = useState({
title: "",
targetDana: "",
hargaLembar: "",
totalLembar: "",
roi: "",
pencarianInvestorId: "",
periodeDevidenId: "",
pembagianDevidenId: "",
});
const [fl, setFl] = useState<File | null>(null);
const [totalLembar, setTotalLembar] = useState<number | any>(
edit_inves.totalLembar
);
async function onTotalLembar(target: any, harga: any) {
const hasil: any = target / harga;
setTotalLembar(_.floor(hasil === Infinity ? 0 : hasil));
}
async function onUpdate() {
if (_.values(edit_inves).includes("")) return toast("Lengkapi data");
// if (!fl) return toast("File Kosong");
const fd = new FormData();
fd.append("file", fl as any);
// router.back()
// await funEditInvestasi(fd, edit_inves).then((res) =>
// res.status === 200 ? router.back() : toast(res.message)
// );
await funEditInvestasi(fd, edit_inves).then(async (res) => {
if (res.status === 200) {
toast(res.message);
router.replace(RouterInvestasi.edit + `${edit_inves.id}`);
} else {
toast(res.message);
}
});
}
return (
<>
@@ -46,7 +84,10 @@ export default function EditIntroInvestasi() {
{img ? (
<Image alt="" src={img} />
) : (
<Image alt="" src={"/aset/no-img.png"} />
<Image
alt=""
src={RouterInvestasi.api_gambar + `${edit_inves.imagesId}`}
/>
)}
</AspectRatio>
<Group position="center" mt={"md"}>
@@ -55,19 +96,13 @@ export default function EditIntroInvestasi() {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
// setImg(buffer);
// setFl(files);
setImg(buffer);
setFl(files);
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
w={350}
radius={50}
// bg={Warna.biru}
// onClick={() => router.push("/dev/investasi/upload")}
>
<Button {...props} w={350} radius={50}>
<IconCamera />
</Button>
)}
@@ -78,92 +113,117 @@ export default function EditIntroInvestasi() {
<Box mt={"md"} w={350}>
<TextInput
label="Judul Proyek"
placeholder={"Masukan Judul"}
value={edit_inves.title}
onChange={(val) => {
setValue({
...value,
setEdit_inves({
...edit_inves,
title: val.target.value,
});
}}
/>
<TextInput
<NumberInput
label="Dana Dibutuhan"
type="number"
value={+edit_inves.targetDana}
onChange={(val) => {
setValue({
...value,
targetDana: val.target.value,
setEdit_inves({
...edit_inves,
targetDana: val as any,
});
}}
/>
<TextInput
<NumberInput
label="Harga Per Lember"
type="number"
value={+edit_inves.hargaLembar}
onChange={(val) => {
setValue({
...value,
hargaLembar: val.target.value,
setEdit_inves({
...edit_inves,
hargaLembar: val as any,
});
onTotalLembar(edit_inves.targetDana, val);
}}
/>
<TextInput
label="Total Lembar"
type="number"
onChange={(val) => {
setValue({
...value,
totalLembar: val.target.value,
});
}}
/>
<TextInput
{/* Total Lembar */}
<Stack spacing={3}>
<Text fz={"sm"} fw={500}>
Total Lembar
</Text>
<Stack spacing={0}>
<Text>{totalLembar}</Text>
<Divider />
</Stack>
<Text c={"red"} fz={10}>
*Total lembar dihitung dari, Target Dana : Harga Perlembar
</Text>
</Stack>
<NumberInput
label="Rasio Keuntungan / ROI"
type="number"
value={+edit_inves.roi}
onChange={(val) => {
setValue({
...value,
roi: val.target.value,
setEdit_inves({
...edit_inves,
roi: val as any,
});
}}
/>
{/* Select Start */}
<Select
label="Pencarian Investor"
// data={pencarianInvestor.map((e) => ({
// value: e.id,
// label: e.name,
// }))}
data={[]}
data={listPencarian.map((e) => ({
value: e.id,
label: e.name + " " + "hari",
}))}
value={edit_inves.MasterPencarianInvestor.id}
onChange={(val) => {
setValue({
...(value as any),
pencarianInvestorId: val,
setEdit_inves({
...(edit_inves as any),
MasterPencarianInvestor: {
id: val,
},
});
}}
/>
<Select
label="Periode Deviden"
// data={periodeDeviden.map((e) => ({ value: e.id, label: e.name }))}
data={[]}
data={listPeriode.map((e) => ({
value: e.id,
label: e.name,
}))}
value={edit_inves.MasterPeriodeDeviden.id}
onChange={(val) => {
setValue({
...(value as any),
periodeDevidenId: val,
setEdit_inves({
...(edit_inves as any),
MasterPeriodeDeviden: {
id: val,
},
});
}}
/>
<Select
label="Pembagian Deviden"
// data={pembagianDeviden.map((e) => ({
// value: e.id,
// label: e.name,
// }))}
data={[]}
data={listPembagian.map((e) => ({
value: e.id,
label: e.name + " " + `${"bulan"}`,
}))}
value={edit_inves.MasterPembagianDeviden.id}
onChange={(val) => {
setValue({
...(value as any),
pembagianDevidenId: val,
setEdit_inves({
...(edit_inves as any),
MasterPembagianDeviden: {
id: val,
},
});
}}
/>
{/* Select End */}
</Box>
</Center>
<Center my={"lg"}>
@@ -172,9 +232,8 @@ export default function EditIntroInvestasi() {
radius={50}
bg={Warna.hijau_muda}
color="green"
// onClick={() => onSubmit() }
onClick={() => {
router.back(), toast("Data terupdate");
onUpdate();
}}
>
Update

View File

@@ -0,0 +1,62 @@
"use server";
import _ from "lodash";
import { MODEL_Investasi } from "../model/model_investasi";
import { v4 } from "uuid";
import prisma from "@/app/lib/prisma";
import fs from "fs";
import { revalidatePath } from "next/cache";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
export default async function funCreateBeritaInvestasi(
formData: FormData,
data: any
) {
const file: any = formData.get("file");
const fName = file.name;
const fExt = _.lowerCase(file.name.split(".").pop());
const fRandomName = v4(fName) + "." + fExt;
const upload = await prisma.images.create({
data: {
url: fRandomName,
},
select: {
id: true,
url: true,
},
});
if (!upload)
return {
status: 400,
message: "File Kosong",
};
const upFolder = Buffer.from(await file.arrayBuffer());
fs.writeFileSync(`./public/investasi/${upload.url}`, upFolder);
const createBerita = await prisma.beritaInvestasi.create({
data: {
title: data.title,
deskripsi: data.deskripsi,
imagesId: upload.id,
investasiId: data.investasiId
},
});
if (!createBerita)
return {
status: 400,
message: "Gagal Disimpan",
};
revalidatePath(RouterInvestasi.list_edit_berita);
return {
status: 201,
message: "Berhasil Disimpan",
};
}

View File

@@ -4,12 +4,16 @@ import prisma from "@/app/lib/prisma";
import _ from "lodash";
import { v4 } from "uuid";
import fs from "fs";
import { INVESTASI } from "@/app_modules/models/investasi";
import { revalidatePath } from "next/cache";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import { MODEL_Investasi } from "../model/model_investasi";
export async function funCreateInvestasi(formData: FormData, data: INVESTASI) {
export async function funCreateInvestasi(
formData: FormData,
data: MODEL_Investasi | any
) {
console.log(data)
const file: any = formData.get("file");
// console.log(file)
const fName = file.name;
const fExt = _.lowerCase(file.name.split(".").pop());
const fRandomName = v4(fName) + "." + fExt;
@@ -30,17 +34,6 @@ export async function funCreateInvestasi(formData: FormData, data: INVESTASI) {
message: "File Kosong",
};
// if (upload) {
// await prisma.investasi.update({
// where: {
// authorId: data.authorId,
// },
// data: {
// imagesId: upload.id,
// },
// });
// }
const upFolder = Buffer.from(await file.arrayBuffer());
fs.writeFileSync(`./public/investasi/${upload.url}`, upFolder);
@@ -48,14 +41,15 @@ export async function funCreateInvestasi(formData: FormData, data: INVESTASI) {
data: {
authorId: data.authorId,
title: data.title,
targetDana: data.targetDana,
hargaLembar: data.hargaLembar,
totalLembar: data.totalLembar,
roi: data.roi,
masterPembagianDevidenId: data.masterPembagianDevidenId,
masterPeriodeDevidenId: data.masterPeriodeDevidenId,
targetDana: data.targetDana.toString(),
hargaLembar: data.hargaLembar.toString(),
totalLembar: data.totalLembar.toString(),
roi: data.roi.toString(),
masterPembagianDevidenId: data.masterPeriodeDevidenId,
masterPeriodeDevidenId: data.masterPembagianDevidenId,
masterPencarianInvestorId: data.masterPencarianInvestorId,
imagesId: upload.id,
masterStatusInvestasiId: "1",
},
});
@@ -65,7 +59,7 @@ export async function funCreateInvestasi(formData: FormData, data: INVESTASI) {
message: "Gagal Disimpan",
};
revalidatePath("/dev/investasi/main");
revalidatePath(RouterInvestasi.main_porto);
return {
status: 201,

View File

@@ -0,0 +1,21 @@
"use server";
import prisma from "@/app/lib/prisma";
import { revalidatePath } from "next/cache";
export default async function funDeleteBeritaInvestasi(id: string, idInvestasi: string) {
const res = await prisma.beritaInvestasi.delete({
where: {
id: id,
},
});
if (!res) return { status: 400, message: "Gagal hapus" };
return {
status: 200,
message: "Berita terhapus",
};
}

View File

@@ -0,0 +1,54 @@
"use server";
import prisma from "@/app/lib/prisma";
import { Model_Berita_Investasi } from "../model/model_investasi";
import _ from "lodash";
import { v4 } from "uuid";
import fs from "fs";
import { revalidatePath } from "next/cache";
export default async function funEditBeritaInvestasi(
formData: FormData,
data: Model_Berita_Investasi
) {
const fl = formData.get("file");
if (fl !== "null") {
const file: any = formData.get("file");
const fName = file.name;
const fExt =
file && file.name ? _.lowerCase(file.name.split(".").pop()) : "";
const fRandomName = v4(fName) + "." + fExt;
const updateImage = await prisma.images.update({
where: {
id: data.imagesId,
},
data: {
url: fRandomName,
},
});
if (!updateImage) return { status: 400, message: "Gagal upload gambar" };
const upFolder = Buffer.from(await file.arrayBuffer());
fs.writeFileSync(`./public/investasi/${updateImage.url}`, upFolder);
revalidatePath("/dev/investasi/list_edit_berita");
}
const res = await prisma.beritaInvestasi.update({
where: {
id: data.id,
},
data: {
title: data.title,
deskripsi: data.deskripsi,
},
});
if (!res) return { status: 400, message: "Gagal Update" };
revalidatePath("/dev/investasi/list_edit_berita");
return {
status: 200,
message: "Berhasil Update",
};
}

View File

@@ -0,0 +1,99 @@
"use server";
import prisma from "@/app/lib/prisma";
import { MODEL_Investasi } from "../model/model_investasi";
import _ from "lodash";
import { v4 } from "uuid";
import fs from "fs";
import { revalidatePath } from "next/cache";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
async function up1(data: any) {}
async function up2(data: any, formData: any) {}
export default async function funEditInvestasi(
formData: FormData,
data: MODEL_Investasi
) {
const file = formData.get("file")?.length;
if (file === undefined) {
const file: any = formData.get("file");
const fName = file.name;
const fExt =
file && file.name ? _.lowerCase(file.name.split(".").pop()) : "";
const fRandomName = v4(fName) + "." + fExt;
const updateImage = await prisma.images.update({
where: {
id: data.imagesId,
},
data: {
url: fRandomName,
},
});
if (!updateImage) return { status: 400, message: "Gagal upload gambar" };
const upFolder = Buffer.from(await file.arrayBuffer());
fs.writeFileSync(`./public/investasi/${updateImage.url}`, upFolder);
const editInves = await prisma.investasi.update({
where: {
id: data.id,
},
data: {
title: data.title,
targetDana: data.targetDana,
hargaLembar: data.hargaLembar,
totalLembar: data.totalLembar,
roi: data.roi,
masterPencarianInvestorId: data.MasterPencarianInvestor.id,
masterPembagianDevidenId: data.MasterPembagianDeviden.id,
masterPeriodeDevidenId: data.MasterPeriodeDeviden.id,
},
});
if (!editInves) {
return {
status: 400,
message: "Gagal update",
};
}
revalidatePath(RouterInvestasi.detail_draft);
return {
status: 200,
message: "Berhasil Disimpan",
};
} else {
const editInves = await prisma.investasi.update({
where: {
id: data.id,
},
data: {
title: data.title,
targetDana: data.targetDana,
hargaLembar: data.hargaLembar,
totalLembar: data.totalLembar,
roi: data.roi,
masterPencarianInvestorId: data.MasterPencarianInvestor.id,
masterPembagianDevidenId: data.MasterPembagianDeviden.id,
masterPeriodeDevidenId: data.MasterPeriodeDeviden.id,
},
});
if (!editInves) {
return {
status: 400,
message: "Gagal update",
};
}
revalidatePath(RouterInvestasi.detail_draft);
return {
status: 200,
message: "Berhasil Disimpan",
};
}
}

View File

@@ -0,0 +1,23 @@
"use server";
import prisma from "@/app/lib/prisma";
import { revalidatePath } from "next/cache";
export default async function funGantiStatusInvestasi(id: string, val: string) {
const data = await prisma.investasi.update({
where: {
id: id,
},
data: {
masterStatusInvestasiId: val,
},
});
if(!data) return {status: 400}
revalidatePath("/dev/investasi/main/portofolio")
return {
status: 200
}
}

View File

@@ -0,0 +1,34 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function getInvestasiById(id: string) {
const data = await prisma.user.findUnique({
where: { id: id },
select: {
Investasi: {
select: {
id: true,
title: true,
authorId: true,
hargaLembar: true,
targetDana: true,
totalLembar: true,
roi: true,
active: true,
imagesId: true,
MasterStatusInvestasi: true,
BeritaInvestasi: true,
DokumenInvestasi: true,
ProspektusInvestasi: true,
MasterPembagianDeviden: true,
MasterPencarianInvestor: true,
MasterPeriodeDeviden: true,
SahamTerbeli: true,
},
},
},
});
return data?.Investasi;
}

View File

@@ -0,0 +1,12 @@
"use server"
import prisma from "@/app/lib/prisma"
export default async function getOneBeritaInvestasiById(id: string) {
const res = await prisma.beritaInvestasi.findUnique({
where: {
id: id
}
})
return res;
}

View File

@@ -0,0 +1,32 @@
"use server";
import prisma from "@/app/lib/prisma";
import { data } from "autoprefixer";
export default async function getOneInvestasiById(id: string) {
const data = await prisma.investasi.findUnique({
where: {
id: id,
},
select: {
id: true,
title: true,
authorId: true,
hargaLembar: true,
targetDana: true,
totalLembar: true,
roi: true,
active: true,
imagesId: true,
MasterStatusInvestasi: true,
BeritaInvestasi: true,
DokumenInvestasi: true,
ProspektusInvestasi: true,
MasterPembagianDeviden: true,
MasterPencarianInvestor: true,
MasterPeriodeDeviden: true,
SahamTerbeli: true,
},
});
return data;
}

View File

@@ -0,0 +1,14 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function getStatusInvestasi() {
const data = await prisma.masterStatusInvestasi.findMany({
select: {
id: true,
name: true,
color: true,
},
});
return data;
}

View File

@@ -1,23 +1,32 @@
"use client"
"use client";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi"
import HeaderTamplate from "@/app_modules/component/header_tamplate"
import { AppShell } from "@mantine/core"
import { IconPencilPlus } from "@tabler/icons-react"
import React from "react"
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import HeaderTamplate from "@/app_modules/component/header_tamplate";
import { AppShell } from "@mantine/core";
import { IconPencilPlus } from "@tabler/icons-react";
import React from "react";
import getOneInvestasiById from "../fun/get_one_investasi_by_id";
export default function LayoutListEditBeritaInvestasi({children}: {children: React.ReactNode}){
return<>
<AppShell
header={
<HeaderTamplate
title="List Berita"
icon={<IconPencilPlus />}
route2={RouterInvestasi.create_berita}
/>
}
>
export default function LayoutListEditBeritaInvestasi({
children,
idInves
}: {
children: React.ReactNode;
idInves: string
}) {
return (
<>
<AppShell
header={
<HeaderTamplate
title="List Berita"
icon={<IconPencilPlus />}
route2={RouterInvestasi.create_berita + `${idInves}`}
/>
}
>
{children}
</AppShell>
</AppShell>
</>
}
);
}

View File

@@ -4,6 +4,9 @@ import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import {
ActionIcon,
AspectRatio,
Box,
Center,
Divider,
Grid,
Group,
Image,
@@ -18,57 +21,104 @@ import { IconDots } from "@tabler/icons-react";
import moment from "moment";
import { useRouter } from "next/navigation";
import toast from "react-simple-toasts";
import { MODEL_Investasi } from "../model/model_investasi";
import { useState } from "react";
import _ from "lodash";
import deleteBeritaInvestasi from "../fun/fun_delete_berita";
import getOneInvestasiById from "../fun/get_one_investasi_by_id";
export default function ListEditBeritaInvestasi({ id }: { id: string }) {
export default function ListEditBeritaInvestasi({
dataInvestasi,
}: {
dataInvestasi: MODEL_Investasi;
}) {
const router = useRouter();
const [investasi, setInvestasi] = useState<MODEL_Investasi>(dataInvestasi);
async function onDelete(idBerita: string, idInvestasi: string) {
await deleteBeritaInvestasi(idBerita, idInvestasi).then((res) => {
if (res.status === 200) {
const data : MODEL_Investasi | any = getOneInvestasiById(idInvestasi)
setInvestasi(data as MODEL_Investasi);
toast(res.message);
} else {
toast(res.message);
}
});
}
if (!investasi) return <>data kosong</>;
return (
<>
<Paper w={"100%"} bg={"gray"} p={"sm"}>
<Stack spacing={"xs"}>
<Group position="apart">
<Title order={6}>Judul berita</Title>
<Menu position="left">
<Menu.Target>
<ActionIcon variant="transparent">
<IconDots color="black" />
</ActionIcon>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item
onClick={() =>
router.push(RouterInvestasi.edit_berita + `${id}`)
}
<Box>
{_.isEmpty(investasi.BeritaInvestasi) ? (
<Box>
<Center>
<Title order={6}>Berita Kosong</Title>
</Center>
<Divider />
</Box>
) : (
""
)}
</Box>
{investasi.BeritaInvestasi.map((v, k) => (
<Paper key={k} w={"100%"} bg={"gray"} p={"sm"} mb={"md"}>
<Stack spacing={"xs"}>
<Group position="apart">
<Box>
<Title order={6}>{v.title}</Title>
<Text fz={10}>{moment(v.createdAt).local().format("lll")}</Text>
</Box>
<Menu position="left">
<Menu.Target>
<ActionIcon variant="transparent">
<IconDots color="black" />
</ActionIcon>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item
onClick={() =>
router.push(RouterInvestasi.edit_berita + `${v.id}`)
}
>
Edit
</Menu.Item>
<Menu.Item
onClick={() => {
onDelete(v.id, dataInvestasi.id);
}}
>
Hapus
</Menu.Item>
</Menu.Dropdown>
</Menu>
</Group>
<Grid pt={5}>
<Grid.Col span={8}>
<Spoiler
fz={"xs"}
maxHeight={55}
showLabel="Selengkapnya"
hideLabel="Sembunyikan"
>
Edit
</Menu.Item>
<Menu.Item onClick={() => toast("Berita terhapus")}>
Hapus
</Menu.Item>
</Menu.Dropdown>
</Menu>
</Group>
<Grid pt={5}>
<Grid.Col span={8}>
<Spoiler
fz={"xs"}
maxHeight={50}
showLabel="Selengkapnya"
hideLabel="Sembunyikan"
>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quam
quaerat nulla autem rem rerum modi, saepe blanditiis delectus
illum sunt repudiandae inventore alias voluptas at! Nisi odio
eaque explicabo laudantium.
</Spoiler>
</Grid.Col>
<Grid.Col span={4}>
<AspectRatio ratio={16 / 9} h={50} w={100}>
<Image alt="" src={"/aset/no-img.png"} />
</AspectRatio>
</Grid.Col>
</Grid>
</Stack>
</Paper>
{v.deskripsi}
</Spoiler>
</Grid.Col>
<Grid.Col span={4}>
<AspectRatio ratio={16 / 9} h={50} w={100}>
<Paper radius={10}>
<Image
alt=""
src={RouterInvestasi.api_gambar + `${v.imagesId}`}
/>
</Paper>
</AspectRatio>
</Grid.Col>
</Grid>
</Stack>
</Paper>
))}
</>
);
}

View File

@@ -1,8 +1,7 @@
"use client";
import { ApiHipmi } from "@/app/lib/api";
import { INVESTASI } from "@/app_modules/models/investasi";
import { MODEL_ALL_MASTER } from "@/app_modules/models/model_AllMaster";
import { MODEL_DEFAULT_MASTER } from "@/app_modules/models/model_default_master";
import {
AspectRatio,
Badge,
@@ -24,6 +23,7 @@ import { useRouter } from "next/navigation";
import dataDummy from "../dummy/data_dummy.json";
import moment from "moment";
import { IconCheck, IconCircleCheck } from "@tabler/icons-react";
import { MODEL_Investasi } from "../model/model_investasi";
export default function MainInvestasi({
listData,
@@ -31,10 +31,10 @@ export default function MainInvestasi({
periodeDeviden,
pembagianDeviden,
}: {
listData: INVESTASI[];
pencarianInvestor: MODEL_ALL_MASTER[];
periodeDeviden: MODEL_ALL_MASTER[];
pembagianDeviden: MODEL_ALL_MASTER[];
listData: MODEL_Investasi[]
pencarianInvestor: MODEL_DEFAULT_MASTER[];
periodeDeviden: MODEL_DEFAULT_MASTER[];
pembagianDeviden: MODEL_DEFAULT_MASTER[];
}) {
const router = useRouter();

View File

@@ -0,0 +1,44 @@
export interface MODEL_Investasi {
id: string;
title: string;
targetDana: string;
hargaLembar: string;
totalLembar: string;
roi: string;
active: true;
createdAt: Date;
updatedAt: Date;
authorId: string;
imagesId: string,
MasterStatusInvestasi: MODEL_Status_investasi
BeritaInvestasi: Model_Berita_Investasi[],
DokumenInvestasi: null;
ProspektusInvestasi: null;
MasterPembagianDeviden: Model_All_Master
MasterPencarianInvestor: Model_All_Master
MasterPeriodeDeviden: Model_All_Master
SahamTerbeli: null;
}
export interface MODEL_Status_investasi {
id: string;
name: string;
color: string;
}
interface Model_All_Master {
id: string
name: string
active: boolean
}
export interface Model_Berita_Investasi {
id: string;
title: string,
deskripsi: string,
imagesId: string,
active: boolean,
createdAt: Date;
updatedAt: Date;
}

View File

@@ -42,165 +42,162 @@ import {
import { atomWithStorage } from "jotai/utils";
import { useAtom } from "jotai";
import { gs_TabPortoInvestasi } from "../g_state";
import {
MODEL_Investasi,
MODEL_Status_investasi,
} from "../model/model_investasi";
import _ from "lodash";
export default function PortofolioInvestasi() {
export default function PortofolioInvestasi({
dataInvestasi,
listStatusInvestasi,
}: {
dataInvestasi: any
listStatusInvestasi: any;
}) {
const router = useRouter();
const [activeTab, setActiveTab] = useAtom(gs_TabPortoInvestasi)
const listButton = [
{
id: 1,
name: "Draft",
color: "yellow",
},
{
id: 2,
name: "Review",
color: "orange",
},
{
id: 3,
name: "Publish",
color: "green",
},
{
id: 4,
name: "Reject",
color: "red",
},
];
const [activeTab, setActiveTab] = useAtom(gs_TabPortoInvestasi);
const [investasi, setInvestasi] = useState<MODEL_Investasi[]>(dataInvestasi);
const [status_inves, setStatus_inves] =
useState<MODEL_Status_investasi[]>(listStatusInvestasi);
return (
<>
<Tabs variant="pills" radius="xl" defaultValue="Draft" value={activeTab} onTabChange={setActiveTab}>
{/* <pre>{JSON.stringify(dataInvestasi, null, 2)}</pre> */}
<Tabs
variant="pills"
radius="xl"
defaultValue="Draft"
value={activeTab}
onTabChange={setActiveTab}
>
<Tabs.List>
{listButton.map((e) => (
<Tabs.Tab key={e.id} value={e.name} color={!activeTab ? "gray" : e.color} >
{status_inves.map((e) => (
<Tabs.Tab
key={e.id}
value={e.name}
color={!activeTab ? "gray" : e.color}
>
{e.name}
</Tabs.Tab>
))}
</Tabs.List>
<Divider my={"xs"}/>
{listButton.map((e) => (
<Tabs.Panel key={e.id} value={e.name} pt="xs">
<StatusPortofolio data={e} />
</Tabs.Panel>
))}
<Divider my={"xs"} />
<Tabs.Panel key={"1"} value="Draft">
<Draft data={investasi as any} />
</Tabs.Panel>
<Tabs.Panel key={"2"} value="Review">
<Review status={status_inves as any} data={investasi as any} />
</Tabs.Panel>
<Tabs.Panel key={"3"} value="Publish">
<Publish status={status_inves as any} />
</Tabs.Panel>
<Tabs.Panel key={"4"} value="Reject">
<Reject status={status_inves as any} />
</Tabs.Panel>
</Tabs>
</>
);
}
function StatusPortofolio({ data }: { data: any }) {
function Draft({ data }: { data: MODEL_Investasi[] }) {
const router = useRouter();
return (
<>
{(() => {
if (data.id === 1) {
return (
<>
<Draft data={data} />
</>
);
} else {
if (data.id === 2) {
return (
<>
<Review data={data} />
</>
);
} else {
if (data.id === 3) {
return (
<>
<Publish data={data} />
</>
);
} else {
return (
<>
<Reject data={data} />
</>
);
{data.map((e) =>
e.MasterStatusInvestasi.id === "1" ? (
<Card
key={e.id}
withBorder
mb={40}
bg={"gray.5"}
onClick={() =>
router.push(RouterInvestasi.detail_draft + `${e.id}`)
}
}
}
})()}
>
<CardSection p={"xs"}>
<AspectRatio ratio={16 / 9}>
<Image
alt=""
src={RouterInvestasi.api_gambar + `${e.imagesId}`}
/>
</AspectRatio>
</CardSection>
<CardSection p={"lg"}>
<Box>
<Title order={4}>{e.title}</Title>
</Box>
</CardSection>
<Divider />
<CardSection p={"md"}>
<Group position="center">
<Badge color="yellow" variant="dot">
Draft
</Badge>
</Group>
</CardSection>
</Card>
) : (
""
)
)}
</>
);
}
function Draft({ data }: { data: any }) {
function Review({
status,
data,
}: {
status: MODEL_Status_investasi;
data: MODEL_Investasi[];
}) {
const router = useRouter();
return (
<>
<Card
withBorder
mb={40}
bg={"gray.5"}
onClick={() => router.push(RouterInvestasi.detail_draft)}
>
<CardSection p={"xs"}>
<AspectRatio ratio={16 / 9}>
<Image alt="" src={"/aset/no-img.png"} />
</AspectRatio>
</CardSection>
{data.map((e) =>
e.MasterStatusInvestasi.id === "2" ? (
<Card
key={e.id}
withBorder
mb={40}
bg={"gray.5"}
onClick={() => router.push(RouterInvestasi.detail_review + `${e.id}`)}
>
<CardSection p={"xs"}>
<AspectRatio ratio={16 / 9}>
<Image
alt=""
src={RouterInvestasi.api_gambar + `${e.imagesId}`}
/>
</AspectRatio>
</CardSection>
<CardSection p={"lg"}>
<Box>
<Title order={4}>Judul Investasi</Title>
</Box>
</CardSection>
<Divider />
<CardSection p={"md"}>
<Group position="center">
<Badge color="yellow" variant="dot">
Draft
</Badge>
</Group>
</CardSection>
</Card>
<CardSection p={"lg"}>
<Box>
<Title order={4}>{e.title}</Title>
</Box>
</CardSection>
<Divider />
<CardSection p={"md"}>
<Group position="center">
<Badge color="yellow" variant="dot">
Review
</Badge>
</Group>
</CardSection>
</Card>
) : (
""
)
)}
</>
);
}
function Review({ data }: { data: any }) {
const router = useRouter();
return (
<>
<Card
withBorder
mb={40}
bg={"gray.5"}
onClick={() => router.push(RouterInvestasi.detail_review)}
>
<CardSection p={"xs"}>
<AspectRatio ratio={16 / 9}>
<Image alt="" src={"/aset/no-img.png"} />
</AspectRatio>
</CardSection>
<CardSection p={"lg"}>
<Box >
<Title order={4}>Judul Investasi</Title>
</Box>
</CardSection>
<Divider />
<CardSection p={"md"}>
<Group position="center">
<Badge color="orange" variant="dot">
{data.name}
</Badge>
</Group>
</CardSection>
</Card>
</>
);
}
function Publish({ data }: { data: any }) {
function Publish({ status }: { status: MODEL_Status_investasi }) {
const router = useRouter();
return (
<>
@@ -232,18 +229,17 @@ function Publish({ data }: { data: any }) {
<CardSection p={"md"}>
<Group position="apart">
<Badge color="green" variant="dot">
{data.name}
{status.name}
</Badge>
<Text>Sisa Waktu : 30 Hari</Text>
</Group>
</CardSection>
</Card>
</>
);
}
function Reject({ data }: { data: any }) {
function Reject({ status }: { status: MODEL_Status_investasi }) {
const router = useRouter();
return (
<>
@@ -268,7 +264,7 @@ function Reject({ data }: { data: any }) {
<CardSection p={"md"}>
<Group position="center">
<Badge color="red" variant="dot">
{data.name}
{status.name}
</Badge>
</Group>
</CardSection>

View File

@@ -1,17 +0,0 @@
export interface INVESTASI {
id: string;
authorId: string;
title: string;
targetDana: string;
hargaLembar: string;
totalLembar: string;
roi: string;
masterPeriodeDevidenId: string;
masterPembagianDevidenId: string;
masterPencarianInvestorId: string;
imagesId: string;
active: boolean;
createdAt: Date;
updatedAt: Date;
persentase: number
}

View File

@@ -1,4 +1,4 @@
export interface MODEL_ALL_MASTER {
export interface MODEL_DEFAULT_MASTER {
id: string,
name: string,
active: boolean,