Desc:
- Fitur Detail investasi
- Fitur Proses investasi
- Fitur upload bukti trnsfer
# No issue
This commit is contained in:
2023-10-20 17:52:36 +08:00
parent bff07e84b1
commit cdd09e6fbf
24 changed files with 532 additions and 61 deletions

0
coba.js Normal file
View File

View File

@@ -28,6 +28,7 @@
"iron-session": "^6.3.1",
"jotai": "^2.4.3",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"next": "^13.5.4-canary.8",
"postcss": "8.4.27",
"react": "18.2.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

View File

@@ -6,34 +6,27 @@ export async function GET(
req: NextRequest,
{ params }: { params: { id: string } }
) {
const data = await prisma.images.findUnique({
where: {
id: params.id,
},
select: {
url: true,
},
});
console.log(params.id)
const data = await prisma.images.findUnique({
where: {
id: params.id,
},
select: {
url: true,
},
});
console.log(data)
// return data
if (!fs.existsSync(`./public/investasi/${data?.url}`)) {
const fl = fs.readFileSync(`./public/aset/no-img.png`);
return new NextResponse(fl, {
headers: {
"Content-Type": "image/png",
},
});
}
const fl = fs.readFileSync(`./public/investasi/${data?.url}`);
if (!fs.existsSync(`./public/investasi/${data?.url}`)) {
const fl = fs.readFileSync(`./public/aset/no-img.png`);
return new NextResponse(fl, {
headers: {
"Content-Type": "image/png",
},
});
}
const fl = fs.readFileSync(`./public/investasi/${data?.url}`);
return new NextResponse(fl, {
headers: {
"Content-Type": "image/png",
},
});
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -152,10 +152,14 @@ export default function HomeView({ user }: { user: USER_PROFILE }) {
h={100}
withBorder
onClick={() => {
if(e.link === ""){
toast(e.name)
if (stateUser.Profile === null) {
return toast("Lengkapi Profile Anda !");
} else {
return router.push(e.link)
if (e.link === "") {
toast(e.name);
} else {
return router.push(e.link);
}
}
}}
>

View File

@@ -58,20 +58,21 @@ export default function InvestasiCreate({
masterPembagianDevidenId: value.pembagianDevidenId,
masterPencarianInvestorId: value.pencarianInvestorId,
};
if (_.values(body).includes("")) return toast("Lengkapi data");
if (!fl) return toast("File Kosong");
// if (_.values(body).includes("")) return toast("Lengkapi data");
// if (!fl) return toast("File Kosong");
const fd = new FormData();
fd.append("file", fl);
// 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);
}
});
return router.push("/dev/investasi/main");
// 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);
// }
// });
}
return (

View File

@@ -0,0 +1,41 @@
"use client";
import HeaderTamplate from "@/app_modules/component/header_tamplate";
import { ActionIcon, AppShell, Group, Header, Text } from "@mantine/core";
import { IconArrowLeft, IconEdit } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { title } from "process";
import React from "react";
export default function LayoutDetailInvestasi({
children,
}: {
children: React.ReactNode;
}) {
const router = useRouter();
return (
<>
<AppShell
header={
<Header height={50}>
<Group h={50} position="apart" px={"md"}>
<ActionIcon variant="transparent" onClick={() => {
router.back()
}}>
<IconArrowLeft />
</ActionIcon>
<Text>Detail Investasi</Text>
<ActionIcon variant="transparent" disabled onClick={() => {
router.replace("")
}}>
{/* <IconEdit /> */}
</ActionIcon>
</Group>
</Header>
}
>
{children}
</AppShell>
</>
);
}

View File

@@ -0,0 +1,152 @@
"use client";
import { Warna } from "@/app/lib/warna";
import {
ActionIcon,
AspectRatio,
Avatar,
Box,
Button,
Center,
Flex,
Grid,
Group,
Image,
Paper,
Slider,
Stack,
Text,
Title,
} from "@mantine/core";
import {
IconBookDownload,
IconFileDescription,
IconSpeakerphone,
} from "@tabler/icons-react";
import { useRouter } from "next/navigation";
export default function DetailInvestasi() {
const router = useRouter();
const listBox = [
{
id: 1,
name: "Prospektus",
icon: <IconBookDownload size={70} />,
route: "",
},
{
id: 2,
name: "Dokumen",
icon: <IconFileDescription size={70} />,
route: "",
},
{
id: 3,
name: "Berita",
icon: <IconSpeakerphone size={70} />,
route: "",
},
];
return (
<>
<Group position="apart" mb={"md"}>
<Flex align={"center"} gap={"xs"}>
<Avatar src={"/aset/avatar.png"} />
<Text>Username</Text>
</Flex>
<Text>Sisa waktu : 20 Hari</Text>
</Group>
<Paper withBorder mb={"md"}>
<AspectRatio ratio={16 / 9}>
<Image alt="" src={"/aset/no-img.png"} />
</AspectRatio>
</Paper>
{/* Title dan Persentase */}
<Box mb={"md"}>
<Title order={4} mb={"xs"}>
Judul Proyek
</Title>
<Slider
disabled
size={10}
value={60}
marks={[{ value: 60, label: "60%" }]}
/>
</Box>
{/* Rincian Data */}
<Grid p={"md"} mb={"md"}>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>Terkumpul</Text>
<Text>Rp. </Text>
</Box>
<Box>
<Text>Dana Dibutuhkan</Text>
<Text>Rp. </Text>
</Box>
<Box>
<Text>Harga Per Lembar</Text>
<Text>Rp. </Text>
</Box>
<Box>
<Text>Jadwal Pembagian</Text>
<Text>3 Bulan </Text>
</Box>
</Stack>
</Grid.Col>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>Investor</Text>
<Text>4657</Text>
</Box>
<Box>
<Text>ROI</Text>
<Text>%</Text>
</Box>
<Box>
<Text>Total Lembar</Text>
<Text>0</Text>
</Box>
<Box>
<Text>Pembagian Deviden</Text>
<Text>Selamanya</Text>
</Box>
</Stack>
</Grid.Col>
</Grid>
{/* List Box */}
<Grid mb={"md"}>
{listBox.map((e) => (
<Grid.Col span={"auto"} key={e.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>
<Center mb={"md"}>
<Button
radius={50}
w={350}
bg={Warna.biru}
onClick={() => router.push("/dev/investasi/proses_investasi")}
>
Investasi
</Button>
</Center>
</>
);
}

View File

@@ -0,0 +1,36 @@
[
{
"id": "clny2l8e20002tlagig62qv50",
"title": "Event EO",
"targetDana": "20000",
"hargaLembar": "1000",
"totalLembar": "200",
"roi": "7",
"active": true,
"createdAt": "2023-10-20T03:47:19.610Z",
"updatedAt": "2023-10-20T03:47:19.610Z",
"authorId": "clntsruqk0002tlrfyc9vzhxx",
"masterPeriodeDevidenId": "Akhir Project",
"masterPembagianDevidenId": "3",
"masterPencarianInvestorId": "60",
"imagesId": "clny2l8dj0000tlagcpsi9dmz",
"persentase": 40
},
{
"id": "clnxyjc0r0002tlamg8fn9ubk",
"title": "Subway ",
"targetDana": "1600000000",
"hargaLembar": "1000",
"totalLembar": "1600000",
"roi": "6",
"active": true,
"createdAt": "2023-10-20T01:53:52.539Z",
"updatedAt": "2023-10-20T01:53:52.539Z",
"authorId": "clntxvesu0002tlnbz030gx30",
"masterPeriodeDevidenId": "Selamanya",
"masterPembagianDevidenId": "6",
"masterPencarianInvestorId": "30",
"imagesId": "clnxyjc070000tlamc5jmsqse",
"persentase": 60
}
]

View File

@@ -4,6 +4,12 @@ import InvestasiCreate from "./create/view";
import InvestasiCreateLayout from "./create/layout";
import UploadGambarInvestasi from "./upload/view";
import LayoutUploadGambarInvestasi from "./upload/layout";
import DetailInvestasi from "./detail/view";
import LayoutDetailInvestasi from "./detail/layout";
import ProsesInvestasi from "./proses_investasi/view";
import LayoutProsesInvestasi from "./proses_investasi/layout";
import UploadBuktiTransferInvestasi from "./upload_bukti/view";
import LayoutBuktiTransferInvestasi from "./upload_bukti/layout";
export {
MainInvestasi,
@@ -12,4 +18,10 @@ export {
InvestasiCreateLayout,
UploadGambarInvestasi,
LayoutUploadGambarInvestasi,
DetailInvestasi,
LayoutDetailInvestasi,
ProsesInvestasi,
LayoutProsesInvestasi,
UploadBuktiTransferInvestasi,
LayoutBuktiTransferInvestasi,
};

View File

@@ -20,6 +20,8 @@ import {
Title,
} from "@mantine/core";
import { useRouter } from "next/navigation";
import dataDummy from "../dummy/data_dummy.json"
import moment from "moment"
export default function MainInvestasi({
listData,
@@ -35,9 +37,9 @@ export default function MainInvestasi({
const router = useRouter();
return (
<>
<pre>{/* {JSON.stringify(listData, null, 2)} */}</pre>
{listData.map((e) => (
<Card key={e.id} p={"md"} withBorder mb={"lg"}>
{/* <pre>{JSON.stringify(listData, null, 2)}</pre> */}
{dataDummy.map((e) => (
<Card key={e.id} withBorder mb={"lg"} onClick={() => router.push(`/dev/investasi/detail/${e.id}`)}>
<CardSection p={"xs"}>
<AspectRatio ratio={16 / 9}>
{e.imagesId ? (
@@ -52,13 +54,14 @@ export default function MainInvestasi({
<Box mt={"md"}>
<Slider
size={10}
disabled
labelAlwaysOn
marks={[
// { value: 25, label: '25%' },
// { value: 50, label: '50%' },
// { value: 75, label: '75%' },
{ value: 100, label: "100%" },
]}
value={e.persentase}
marks={
[
{value: e.persentase, label: e.persentase + `%`}
]
}
/>
<Title order={4}>{e.title}</Title>
</Box>
@@ -94,7 +97,7 @@ export default function MainInvestasi({
<Divider />
<CardSection p={"md"}>
<Group position="right">
<Text>Selesai</Text>
<Text>{moment(e.createdAt).fromNow()}</Text>
</Group>
</CardSection>
</Card>

View File

@@ -0,0 +1,17 @@
export interface DUMMY_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

@@ -0,0 +1,21 @@
"use client";
import HeaderTamplate from "@/app_modules/component/header_tamplate";
import { AppShell } from "@mantine/core";
import React from "react";
export default function LayoutProsesInvestasi({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
<AppShell
header={
<HeaderTamplate title="Proses Investasi"/>
}
>{children}</AppShell>
</>
);
}

View File

@@ -0,0 +1,90 @@
"use client";
import { Warna } from "@/app/lib/warna";
import {
ActionIcon,
Box,
Button,
Center,
Divider,
Grid,
Group,
Text,
Title,
} from "@mantine/core";
import { useCounter } from "@mantine/hooks";
import {
IconMinus,
IconNumber10Small,
IconPlus,
IconRefresh,
} from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react";
export default function ProsesInvestasi() {
const [count, handlers] = useCounter(0, { min: 1, max: 100 });
const [hargaLembar, setHargaLembar] = useState(1000);
const router = useRouter()
// const formatter = new Intl.NumberFormat("", {
// style: 'currency',
// currency: 'RP',
// });
return (
<>
<Box px={"md"}>
<Group position="apart" mb={"md"}>
<Text>Lembar Saham</Text>
<Group position="center">
<ActionIcon variant="filled" radius={50} onClick={handlers.reset}>
<IconRefresh />
</ActionIcon>
<ActionIcon
variant="filled"
radius={50}
onClick={handlers.increment}
>
<IconPlus />
</ActionIcon>
<Text>{count}</Text>
<ActionIcon
variant="filled"
radius={50}
onClick={handlers.decrement}
>
<IconMinus />
</ActionIcon>
<ActionIcon
variant="filled"
radius={50}
onClick={() => handlers.set(100)}
>
<IconNumber10Small />
</ActionIcon>
</Group>
</Group>
<Group position="apart" mb={"md"}>
<Text>Harga Perlembar</Text>
<Text fz={23}>Rp.{hargaLembar} </Text>
</Group>
<Divider />
<Group position="apart" mb={"md"}>
<Text>Total Harga</Text>
<Text fz={25}>Rp.{hargaLembar * count} </Text>
</Group>
<Center>
<Button w={350} radius={50} bg={Warna.biru} onClick={()=>router.push("/dev/investasi/upload_bukti") }>Proses</Button>
</Center>
</Box>
</>
);
}

View File

@@ -0,0 +1,19 @@
"use client";
import HeaderTamplate from "@/app_modules/component/header_tamplate";
import { AppShell } from "@mantine/core";
import React from "react";
export default function LayoutBuktiTransferInvestasi({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
<AppShell header={<HeaderTamplate title="Upload Bukti Transfer" />}>
{children}
</AppShell>
</>
);
}

View File

@@ -0,0 +1,29 @@
"use client"
import { Warna } from "@/app/lib/warna"
import { Button, CopyButton, Grid, Group, Text } from "@mantine/core"
export default function UploadBuktiTransferInvestasi(){
return<>
<Grid align="center">
<Grid.Col span={"auto"}>
<Text>Rekening</Text>
</Grid.Col>
<Grid.Col span={"auto"}>
<Text>908765467897654567</Text>
</Grid.Col>
<Grid.Col span={"auto"}>
<CopyButton value="908765467897654567">
{({ copied, copy }) => (
<Button compact radius={50} color={copied ? 'teal' : 'blue'} onClick={copy}>
{copied ? 'Copied url' : 'Copy url'}
</Button>
)}
</CopyButton>
</Grid.Col>
</Grid>
</>
}

View File

@@ -1,13 +1,17 @@
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
}
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

@@ -2526,6 +2526,11 @@ minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.5:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
moment@^2.29.4:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"