## Deskripsi :
- Notifikasi investasi
## Issue : Gerbang pembayaran
This commit is contained in:
2024-08-12 10:20:28 +08:00
parent 7131e93a49
commit 6ffeb097e8
188 changed files with 4409 additions and 2488 deletions

View File

@@ -5,7 +5,11 @@ import { IconChevronLeft } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
export default function ComponentAdminGlobal_BackButton({path}:{path?:string}) {
export default function ComponentAdminGlobal_BackButton({
path,
}: {
path?: string;
}) {
const router = useRouter();
const [isLoading, setLoading] = useState(false);
@@ -17,18 +21,21 @@ export default function ComponentAdminGlobal_BackButton({path}:{path?:string}) {
// loading={isLoading ? true : false}
c={"gray"}
leftIcon={
isLoading ? <Loader size={"xs"} color={"gray"} /> : <IconChevronLeft />
isLoading ? (
<Loader size={"xs"} color={"gray"} />
) : (
<IconChevronLeft />
)
}
variant="white"
onClick={() => {
setLoading(true);
// setTimeout(() => , 3000);
if(path==null){
if (path == null) {
router.back();
}else{
router.push(path)
} else {
router.push(path);
}
}}
>
Kembali

View File

@@ -186,6 +186,7 @@ function TablePublish({ listPublish }: { listPublish: any }) {
}}
/>
</Group>
{isEmpty(data) ? (
<ComponentAdminGlobal_IsEmptyData />
) : (

View File

@@ -0,0 +1,50 @@
import { MODEL_USER } from "@/app_modules/home/model/interface";
import { Paper, Stack, Title, Grid, Text } from "@mantine/core";
export function ComponentAdminInvestasi_DetailDataAuthor({
data,
}: {
data: any;
}) {
return (
<Paper withBorder p={"lg"}>
<Stack>
<Title order={3}>Data User</Title>
<Stack spacing={"xs"}>
<Grid>
<Grid.Col span={6}>
<Text fw={"bold"}>Nama:</Text>
</Grid.Col>
<Grid.Col span={6}>
<Text>{data?.Profile?.name}</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={6}>
<Text fw={"bold"}>Username:</Text>
</Grid.Col>
<Grid.Col span={6}>
<Text>@{data?.username}</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={6}>
<Text fw={"bold"}>Nomor:</Text>
</Grid.Col>
<Grid.Col span={6}>
<Text>+ {data?.nomor}</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={6}>
<Text fw={"bold"}>Alamat:</Text>
</Grid.Col>
<Grid.Col span={6}>
<Text>{data?.Profile?.alamat}</Text>
</Grid.Col>
</Grid>
</Stack>
</Stack>
</Paper>
);
}

View File

@@ -0,0 +1,82 @@
import { Paper, Stack, Title, Grid, Box, Text } from "@mantine/core";
export function ComponentAdminInvestasi_DetailData({ data }: { data: any }) {
return (
<>
<Paper withBorder p={"lg"}>
<Stack>
<Title order={3}>Rincian Data Investasi</Title>
<Grid justify="center">
<Grid.Col span={6}>
<Stack>
<Box>
<Text>Judul</Text>
<Text fw={"bold"}>{data?.title}</Text>
</Box>
<Box>
<Text>Dana Dibutuhkan</Text>
<Text fw={"bold"}>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+data.targetDana)}
</Text>
</Box>
<Box>
<Text>Harga Per Lembar</Text>
<Text fw={"bold"}>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+data.hargaLembar)}{" "}
</Text>
</Box>
<Box>
<Text>Total Lembar</Text>
<Text fw={"bold"}>
{" "}
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+data.totalLembar)}{" "}
lembar
</Text>
</Box>
</Stack>
</Grid.Col>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>ROI</Text>
<Text fw={"bold"}>{data.roi} %</Text>
</Box>
<Box>
<Text>Pembagian Deviden</Text>
<Text fw={"bold"}>{data.MasterPeriodeDeviden.name}</Text>
</Box>
<Box>
<Text>Jadwal Pembagian</Text>
<Text fw={"bold"}>
{data.MasterPembagianDeviden.name} bulan{" "}
</Text>
</Box>
<Box>
<Text>Pencarian Investor</Text>
<Text fw={"bold"}>
{data.MasterPencarianInvestor.name} hari{" "}
</Text>
</Box>
</Stack>
</Grid.Col>
</Grid>
</Stack>
</Paper>
</>
);
}

View File

@@ -0,0 +1,28 @@
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import { Paper, Stack, Title, AspectRatio, Center, Image } from "@mantine/core";
export function ComponentAdminInvestasi_DetailGambar({imagesId}: {imagesId: any}) {
return (
<>
<Paper withBorder p={"lg"}>
<Stack>
<Title align="center" order={3}>
Gambar Proyek
</Title>
<AspectRatio ratio={1 / 1} mah={300}>
<Center>
<Image
style={{ borderRadius: "10px" }}
radius={"md"}
width={200}
alt=""
src={RouterInvestasi.api_gambar + `${imagesId}`}
/>
</Center>
</AspectRatio>
</Stack>
</Paper>
</>
);
}

View File

@@ -0,0 +1,99 @@
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import {
SimpleGrid,
Paper,
Stack,
Title,
Grid,
Group,
Button,
Text,
} from "@mantine/core";
import { IconFileTypePdf } from "@tabler/icons-react";
import _ from "lodash";
import Link from "next/link";
export function ComponentAdminInvestasi_UIDetailFile({
title,
dataProspektus,
listDokumen,
}: {
title: string;
dataProspektus: any;
listDokumen: any[];
}) {
return (
<>
<SimpleGrid
cols={1}
spacing="lg"
breakpoints={[
{ maxWidth: "62rem", cols: 1, spacing: "md" },
{ maxWidth: "48rem", cols: 1, spacing: "sm" },
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
]}
>
<Paper withBorder p={"lg"}>
<Stack>
<Title order={3}>File & Dokumen</Title>
<Stack spacing={50}>
{/* File */}
<Grid align="center">
<Grid.Col span={4}>
<Text fw={"bold"}>File:</Text>
</Grid.Col>
<Grid.Col span={8}>
<Group>
<IconFileTypePdf />
<Text>Prospek {title}</Text>
<Link
target="_blank"
href={
RouterInvestasi.api_file_prospektus +
`${dataProspektus === null ? "" : dataProspektus.id}`
}
>
<Button radius={50}>Lihat</Button>
</Link>
</Group>
</Grid.Col>
</Grid>
{/* Dokumen */}
<Grid>
<Grid.Col span={4}>
<Text fw={"bold"}>Dokumen:</Text>
</Grid.Col>
<Grid.Col span={8}>
<Stack>
{_.isEmpty(listDokumen) ? (
<Text>-</Text>
) : (
listDokumen.map((e: any) => (
<Paper key={e.id}>
<Group>
<IconFileTypePdf />
<Text>{e.title}</Text>
<Link
target="_blank"
href={
RouterInvestasi.api_file_dokumen + `${e.id}`
}
>
<Button radius={50}>Lihat</Button>
</Link>
</Group>
</Paper>
))
)}
</Stack>
</Grid.Col>
</Grid>
</Stack>
</Stack>
</Paper>
</SimpleGrid>
</>
);
}

View File

@@ -0,0 +1,159 @@
"use client";
import { MODEL_Investasi } from "@/app_modules/investasi/model/model_investasi";
import {
AspectRatio,
Box,
Center,
Grid,
Image,
List,
Paper,
SimpleGrid,
Stack,
Text,
ThemeIcon,
Title,
} from "@mantine/core";
import ComponentAdminGlobal_BackButton from "../../component_global/back_button";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import { IconCircleCheck, IconHome } from "@tabler/icons-react";
import investasi from "../../notifikasi/route_setting/investasi";
export function AdminInvestasi_DetailPublish({
data,
}: {
data: MODEL_Investasi;
}) {
return (
<>
<Stack>
<ComponentAdminGlobal_BackButton />
<SimpleGrid cols={2}>
<InformasiAuthor data={data} />
<InformasiDataInvestasi data={data} />
</SimpleGrid>
</Stack>
</>
);
}
function InformasiAuthor({ data }: { data: MODEL_Investasi }) {
return (
<>
<Paper withBorder>
<Stack p={"lg"} spacing={"xl"}>
<Title align="center" order={3}>
{data.title}
</Title>
<AspectRatio ratio={1 / 1} mah={300}>
<Center>
<Image
bg={"blue"}
style={{ borderRadius: "10px" }}
radius={"md"}
width={250}
alt=""
src={RouterInvestasi.api_gambar + `${data.imagesId}`}
/>
</Center>
</AspectRatio>
<Stack spacing={"sm"}>
<Title order={4}>Informasi pemilik</Title>
<List
spacing="xs"
size="sm"
center
icon={
<ThemeIcon color="teal" size={24} radius="xl">
<IconCircleCheck size="1rem" />
</ThemeIcon>
}
>
<List.Item>{data.author.username}</List.Item>
<List.Item>+{data.author.nomor}</List.Item>
<List.Item>{data.author.Profile.email}</List.Item>
</List>
</Stack>
</Stack>
</Paper>
</>
);
}
function InformasiDataInvestasi({ data }: { data: MODEL_Investasi }) {
return (
<>
<Paper withBorder p={"lg"}>
<Stack>
<Title order={3}>Rincian Data Investasi</Title>
<Grid justify="center">
<Grid.Col>
<Grid mt={"md"} justify="center">
<Grid.Col span={6}>
<Stack>
<Box>
<Text>Dana Dibutuhkan</Text>
<Text fw={"bold"}>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+data.targetDana)}
</Text>
</Box>
<Box>
<Text>Harga Per Lembar</Text>
<Text fw={"bold"}>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+data.hargaLembar)}{" "}
</Text>
</Box>
<Box>
<Text>Jadwal Pembagian</Text>
<Text fw={"bold"}>
{data.MasterPembagianDeviden.name} bulan{" "}
</Text>
</Box>
<Box>
<Text>Pencarian Investor</Text>
<Text fw={"bold"}>
{data.MasterPencarianInvestor.name} hari{" "}
</Text>
</Box>
</Stack>
</Grid.Col>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>ROI</Text>
<Text fw={"bold"}>{data.roi} %</Text>
</Box>
<Box>
<Text>Total Lembar</Text>
<Text fw={"bold"}>
{" "}
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+data.totalLembar)}{" "}
lembar
</Text>
</Box>
<Box>
<Text>Pembagian Deviden</Text>
<Text fw={"bold"}>{data.MasterPeriodeDeviden.name}</Text>
</Box>
</Stack>
</Grid.Col>
</Grid>
</Grid.Col>
</Grid>
</Stack>
</Paper>
</>
);
}

View File

@@ -0,0 +1,76 @@
"use client";
import { MODEL_Investasi } from "@/app_modules/investasi/model/model_investasi";
import {
Paper,
SimpleGrid,
Stack,
Text,
Title
} from "@mantine/core";
import ComponentAdminGlobal_BackButton from "../../component_global/back_button";
import { ComponentAdminInvestasi_DetailDataAuthor } from "../_component/detail_data_author";
import { ComponentAdminInvestasi_DetailData } from "../_component/detail_data_investasi";
import { ComponentAdminInvestasi_DetailGambar } from "../_component/detail_gambar_investasi";
import { ComponentAdminInvestasi_UIDetailFile } from "../_component/ui_detail_file";
export function AdminInvestasi_DetailReject({
data,
}: {
data: MODEL_Investasi;
}) {
return (
<>
<Stack px={"lg"}>
<ComponentAdminGlobal_BackButton />
<SimpleGrid
cols={3}
spacing="lg"
breakpoints={[
{ maxWidth: "62rem", cols: 3, spacing: "md" },
{ maxWidth: "48rem", cols: 2, spacing: "sm" },
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
]}
>
<Paper withBorder p={"lg"}>
<Stack>
<Title order={3} c={"red"}>
#{" "}
<Text span inherit c={"black"}>
Alasan penolakan
</Text>
</Title>
<Text>{data.catatan}</Text>
</Stack>
</Paper>
</SimpleGrid>
<SimpleGrid
cols={3}
spacing="lg"
breakpoints={[
{ maxWidth: "62rem", cols: 3, spacing: "md" },
{ maxWidth: "48rem", cols: 2, spacing: "sm" },
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
]}
>
{/* Data Author */}
<ComponentAdminInvestasi_DetailDataAuthor data={data.author} />
{/* Data Foto */}
<ComponentAdminInvestasi_DetailGambar imagesId={data.imagesId} />
{/* Data Detail */}
<ComponentAdminInvestasi_DetailData data={data} />
</SimpleGrid>
<ComponentAdminInvestasi_UIDetailFile
title={data.title}
dataProspektus={data.ProspektusInvestasi}
listDokumen={data.DokumenInvestasi}
/>
{/* <pre>{JSON.stringify(data, null, 2)}</pre> */}
</Stack>
</>
);
}

View File

@@ -1,173 +1,224 @@
"use client";
import { RouterHome } from "@/app/lib/router_hipmi/router_home";
import { RouterAdminInvestasi } from "@/app/lib/router_admin/router_admin_investasi";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import { Warna } from "@/app/lib/warna";
import funEditInvestasi from "@/app_modules/investasi/fun/fun_edit_investasi";
import funGantiStatusInvestasi from "@/app_modules/investasi/fun/fun_ganti_status";
import { gs_StatusPortoInvestasi } from "@/app_modules/investasi/g_state";
import { BeritaInvestasi } from "@/app_modules/investasi";
import { MODEL_Investasi } from "@/app_modules/investasi/model/model_investasi";
import { MODEL_PROFILE_OLD } from "@/app_modules/home/model/user_profile";
import mqtt_client from "@/util/mqtt_client";
import {
Group,
Flex,
Avatar,
Paper,
AspectRatio,
Box,
Title,
Slider,
Grid,
Stack,
ActionIcon,
Center,
Button,
Text,
Image,
Collapse,
Textarea,
Center,
Divider,
Mark,
Grid,
Group,
Image,
Modal,
Paper,
SimpleGrid,
Stack,
Text,
Textarea,
Title,
} from "@mantine/core";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { useShallowEffect } from "@mantine/hooks";
import {
IconAlertHexagonFilled,
IconBan,
IconBookDownload,
IconCheck,
IconChevronDown,
IconChevronLeft,
IconChevronRight,
IconFile,
IconFileDescription,
IconFileTypePdf,
IconPdf,
IconSpeakerphone,
} from "@tabler/icons-react";
import { useAtom } from "jotai";
import _ from "lodash";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState } from "react";
import toast, { toastConfig } from "react-simple-toasts";
import Admin_funRejectInvestasi from "../fun/fun_reject_investasi";
import { RouterAdminInvestasi_OLD } from "@/app/lib/router_hipmi/router_admin";
import "react-simple-toasts/dist/theme/dark.css";
import { BeritaInvestasi } from "@/app_modules/investasi";
import { ComponentAdminGlobal_NotifikasiBerhasil } from "../../component_global/admin_notifikasi/notifikasi_berhasil";
import { ComponentAdminGlobal_NotifikasiGagal } from "../../component_global/admin_notifikasi/notifikasi_gagal";
import { ComponentAdminGlobal_NotifikasiPeringatan } from "../../component_global/admin_notifikasi/notifikasi_peringatan";
import ComponentAdminGlobal_BackButton from "../../component_global/back_button";
import adminNotifikasi_funCreateToUser from "../../notifikasi/fun/create/fun_create_notif_user";
import { ComponentAdminInvestasi_DetailDataAuthor } from "../_component/detail_data_author";
import { ComponentAdminInvestasi_DetailData } from "../_component/detail_data_investasi";
import { ComponentAdminInvestasi_DetailGambar } from "../_component/detail_gambar_investasi";
import { ComponentAdminInvestasi_UIDetailFile } from "../_component/ui_detail_file";
import { adminInvestasi_funEditStatusPublishById } from "../fun/edit/fun_status_publish_by_id";
import Admin_funRejectInvestasi from "../fun/fun_reject_investasi";
import getOneInvestasiById from "@/app_modules/investasi/fun/get_one_investasi_by_id";
toastConfig({ theme: "dark" });
export default function Admin_KonfirmasiInvestasi({
export default function AdminInvestasi_DetailReview({
dataInvestasi,
dataUser,
}: {
dataInvestasi: MODEL_Investasi;
dataUser: MODEL_PROFILE_OLD;
}) {
const router = useRouter();
const [investasi, setInvestasi] = useState(dataInvestasi);
const [user, setUser] = useState(dataUser);
const [data, setData] = useState(dataInvestasi);
const [publish, setPublish] = useState(true);
const [opened, { toggle }] = useDisclosure(false);
const [catatan, setCatatan] = useState<string | number>("");
const [status, setStatus] = useAtom(gs_StatusPortoInvestasi);
const listBox = [
{
id: 1,
name: "Prospektus",
icon: <IconBookDownload size={70} />,
route: RouterInvestasi.detail_prospektus,
},
{
id: 2,
name: "Dokumen",
icon: <IconFileDescription size={70} />,
route: RouterInvestasi.detail_dokumen,
},
{
id: 3,
name: "Berita",
icon: <IconSpeakerphone size={70} />,
route: RouterInvestasi.berita,
},
];
const [openModal, setOpenModal] = useState(false);
const [isLoadingPublish, setIsLoadingPublish] = useState(false);
const [isLoadingReject, setIsLoadingReject] = useState(false);
useShallowEffect(() => {
cekStatusPublish();
}, []);
async function cekStatusPublish() {
if (investasi.MasterStatusInvestasi.id === "3") setPublish(false);
if (data.MasterStatusInvestasi.id === "3") setPublish(false);
}
async function onReject() {
const body = {
id: investasi.id,
catatan: investasi.catatan,
id: data.id,
catatan: data.catatan,
status: "4",
};
if (_.isEmpty(body.catatan)) return toast("Lengkapi alasan");
await Admin_funRejectInvestasi(body).then((res) => {
if (res.status === 200) {
toast(res.message);
router.back();
toggle();
} else {
toast(res.message);
if (_.isEmpty(body.catatan))
return ComponentAdminGlobal_NotifikasiPeringatan("Lengkapi alasan");
const res = await Admin_funRejectInvestasi(body);
if (res.status === 200) {
const dataNotif = {
appId: res.data?.id,
userId: res.data?.authorId,
pesan: res.data?.title,
status: res.data?.MasterStatusInvestasi?.name,
kategoriApp: "INVESTASI",
title: "Investasi anda di tolak !",
};
const notif = await adminNotifikasi_funCreateToUser({
data: dataNotif as any,
});
if (notif.status === 201) {
mqtt_client.publish(
"USER",
JSON.stringify({ userId: res?.data?.authorId, count: 1 })
);
}
});
const loadData = await getOneInvestasiById(data.id);
setData(loadData as any);
ComponentAdminGlobal_NotifikasiBerhasil(res.message);
router.back();
} else {
ComponentAdminGlobal_NotifikasiGagal(res.message);
}
}
async function onPublish() {
await funGantiStatusInvestasi(investasi.id, "3", "1").then((res) => {
if (res.status === 200) {
setTimeout(() => setPublish(false), 1000);
router.push(RouterAdminInvestasi_OLD.table_status_review);
toast("Proyek Investasi Di Publish");
}
const res = await adminInvestasi_funEditStatusPublishById({
investasiId: data.id,
statusId: "1",
progesInvestasiId: "1",
});
if (res.status === 200) {
const dataNotif = {
appId: res.data?.id,
userId: res.data?.authorId as any,
pesan: res.data?.title as any,
status: res.data?.MasterStatusInvestasi?.name as any,
kategoriApp: "INVESTASI",
title: "Investasi publish",
};
const notif = await adminNotifikasi_funCreateToUser({
data: dataNotif as any,
});
if (notif.status === 201) {
mqtt_client.publish(
"USER",
JSON.stringify({ userId: res?.data?.authorId, count: 1 })
);
mqtt_client.publish(
"Beranda_Investasi",
JSON.stringify({ update: true })
);
const loadData = await getOneInvestasiById(data.id);
setData(loadData as any);
ComponentAdminGlobal_NotifikasiBerhasil("Proyek Investasi Di Publish");
router.back();
// router.push(RouterAdminInvestasi_OLD.table_status_review);
}
} else {
ComponentAdminGlobal_NotifikasiGagal(res.message);
}
}
return (
<>
<Group position="apart" px={"md"}>
<Group>
<ActionIcon onClick={() => router.back()}>
<IconChevronLeft />
</ActionIcon>
<Flex align={"center"} gap={"xs"} pl={"lg"}>
{/* <Avatar
radius={50}
size={"md"}
src={
RouterProfile.api_foto +
`${user.Profile?.ImageProfile?.url}`
}
/> */}
<Text>{user.username}</Text>
</Flex>
<Stack px={"lg"}>
<Group position="apart">
<ComponentAdminGlobal_BackButton />
{data.masterStatusInvestasiId === "2" ? (
<Group>
<Button
loaderPosition="center"
loading={isLoadingPublish}
radius={"xl"}
color="green"
onClick={() => onPublish()}
>
Publish
</Button>
<Button
loaderPosition="center"
loading={isLoadingReject}
radius={"xl"}
color="red"
onClick={() => onReject()}
>
Reject
</Button>
</Group>
) : (
""
)}
</Group>
<SimpleGrid
cols={3}
spacing="lg"
breakpoints={[
{ maxWidth: "62rem", cols: 3, spacing: "md" },
{ maxWidth: "48rem", cols: 2, spacing: "sm" },
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
]}
>
{/* Data Author */}
<ComponentAdminInvestasi_DetailDataAuthor data={data.author} />
{/* Data Foto */}
<ComponentAdminInvestasi_DetailGambar imagesId={data.imagesId} />
{/* Data Detail */}
<ComponentAdminInvestasi_DetailData data={data} />
</SimpleGrid>
<ComponentAdminInvestasi_UIDetailFile
title={data.title}
dataProspektus={data.ProspektusInvestasi}
listDokumen={data.DokumenInvestasi}
/>
</Stack>
</>
);
return (
<>
<Group position="apart" px={"md"}>
<ComponentAdminGlobal_BackButton
path={RouterAdminInvestasi.table_review}
/>
<Group>
{" "}
<Center>
{!publish || investasi.MasterStatusInvestasi.id === "4" ? (
{!publish || data.MasterStatusInvestasi.id === "4" ? (
""
) : (
// <Button
// radius={50}
// leftIcon={<IconBan />}
// bg={"orange"}
// color="orange"
// onClick={() => {
// setTimeout(() => setPublish(true), 1000);
// toast("Proyek Investasi Di Non-Aktifkan");
// }}
// >
// Non - aktifkan
// </Button>
<Button
radius={50}
bg={"green"}
@@ -181,14 +232,14 @@ export default function Admin_KonfirmasiInvestasi({
</Button>
)}
</Center>
{investasi.MasterStatusInvestasi.id === "3" ? (
{data.MasterStatusInvestasi.id === "3" ? (
""
) : (
<Button
radius={50}
bg={"red"}
color="red"
onClick={toggle}
onClick={() => setOpenModal(true)}
rightIcon={<IconAlertHexagonFilled />}
>
Reject
@@ -205,14 +256,14 @@ export default function Admin_KonfirmasiInvestasi({
{/* Title */}
<Center my={"sm"}>
<Title order={4} mb={"xs"}>
{investasi.title}
{data.title}
</Title>
</Center>
<Paper withBorder mb={"md"} mah={300} maw={400} mx={"auto"} p={5}>
<AspectRatio ratio={16 / 9}>
<Image
alt=""
src={RouterInvestasi.api_gambar + `${investasi.imagesId}`}
src={RouterInvestasi.api_gambar + `${data.imagesId}`}
/>
</AspectRatio>
</Paper>
@@ -229,7 +280,7 @@ export default function Admin_KonfirmasiInvestasi({
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+investasi.targetDana)}
}).format(+data.targetDana)}
</Text>
</Box>
<Box>
@@ -238,16 +289,16 @@ export default function Admin_KonfirmasiInvestasi({
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+investasi.hargaLembar)}{" "}
}).format(+data.hargaLembar)}{" "}
</Text>
</Box>
<Box>
<Text>Jadwal Pembagian</Text>
<Text>{investasi.MasterPembagianDeviden.name} bulan </Text>
<Text>{data.MasterPembagianDeviden.name} bulan </Text>
</Box>
<Box>
<Text>Pencarian Investor</Text>
<Text>{investasi.MasterPencarianInvestor.name} hari </Text>
<Text>{data.MasterPencarianInvestor.name} hari </Text>
</Box>
</Stack>
</Grid.Col>
@@ -255,7 +306,7 @@ export default function Admin_KonfirmasiInvestasi({
<Stack>
<Box>
<Text>ROI</Text>
<Text>{investasi.roi} %</Text>
<Text>{data.roi} %</Text>
</Box>
<Box>
<Text>Total Lembar</Text>
@@ -263,13 +314,13 @@ export default function Admin_KonfirmasiInvestasi({
{" "}
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+investasi.totalLembar)}{" "}
}).format(+data.totalLembar)}{" "}
lembar
</Text>
</Box>
<Box>
<Text>Pembagian Deviden</Text>
<Text>{investasi.MasterPeriodeDeviden.name}</Text>
<Text>{data.MasterPeriodeDeviden.name}</Text>
</Box>
</Stack>
</Grid.Col>
@@ -280,7 +331,7 @@ export default function Admin_KonfirmasiInvestasi({
<Grid>
<Grid.Col span={6}>
{/* Note */}
{!publish || investasi.MasterStatusInvestasi.id === "4" ? (
{!publish || data.MasterStatusInvestasi.id === "4" ? (
""
) : (
<Stack spacing={0}>
@@ -294,9 +345,9 @@ export default function Admin_KonfirmasiInvestasi({
</Stack>
)}
{publish &&
investasi.MasterStatusInvestasi.id === "3" &&
_.isEmpty(investasi.BeritaInvestasi) ? (
<BeritaInvestasi dataInvestasi={investasi} />
data.MasterStatusInvestasi.id === "3" &&
_.isEmpty(data.BeritaInvestasi) ? (
<BeritaInvestasi dataInvestasi={data} />
) : (
""
)}
@@ -309,21 +360,21 @@ export default function Admin_KonfirmasiInvestasi({
{/* Prospektus */}
<Stack spacing={0}>
<Title order={6}>Prospektus :</Title>
{investasi.ProspektusInvestasi === null ? (
{data.ProspektusInvestasi === null ? (
<Text>Tidak ada file</Text>
) : (
<Paper p={"xs"}>
<Group>
<IconFileTypePdf />
<Text>Prospektus_{investasi.title}</Text>
<Text>Prospektus_{data.title}</Text>
<Link
target="_blank"
href={
RouterInvestasi.api_file_prospektus +
`${
investasi.ProspektusInvestasi === null
data.ProspektusInvestasi === null
? ""
: investasi.ProspektusInvestasi.id
: data.ProspektusInvestasi.id
}`
}
>
@@ -339,10 +390,10 @@ export default function Admin_KonfirmasiInvestasi({
{/* Dokumen */}
<Stack spacing={0}>
<Title order={6}>Dokumen :</Title>
{_.isEmpty(investasi.DokumenInvestasi) ? (
{_.isEmpty(data.DokumenInvestasi) ? (
<Text>Tidak ada dokumen</Text>
) : (
investasi.DokumenInvestasi.map((e) => (
data.DokumenInvestasi.map((e) => (
<Paper p={"xs"} key={e.id}>
<Group>
<IconFileTypePdf />
@@ -367,8 +418,8 @@ export default function Admin_KonfirmasiInvestasi({
<Modal
centered
opened={opened}
onClose={toggle}
opened={openModal}
onClose={() => setOpenModal(false)}
// withCloseButton={false}
title="Masukan alasan penolakan"
>
@@ -377,10 +428,10 @@ export default function Admin_KonfirmasiInvestasi({
autosize
minRows={2}
maxRows={4}
value={investasi.catatan === null ? [] : investasi.catatan}
value={data.catatan === null ? [] : data.catatan}
onChange={(val) =>
setInvestasi({
...investasi,
setData({
...data,
catatan: val.target.value,
})
}

View File

@@ -0,0 +1,46 @@
"use server";
import prisma from "@/app/lib/prisma";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import { revalidatePath } from "next/cache";
export async function adminInvestasi_funEditStatusPublishById({
investasiId,
statusId,
progesInvestasiId,
}: {
investasiId: string;
statusId: string;
progesInvestasiId: string;
}) {
const publishTime = new Date();
const res = await prisma.investasi.update({
where: {
id: investasiId,
},
data: {
countDown: publishTime,
masterStatusInvestasiId: statusId,
masterProgresInvestasiId: progesInvestasiId,
},
select: {
id: true,
title: true,
authorId: true,
MasterStatusInvestasi: {
select: {
name: true,
},
},
}
});
if (!res) return { status: 400, message: "Gagal Update" };
revalidatePath(RouterInvestasi.portofolio);
return {
data: res,
status: 200,
message: "Publish Berhasil",
};
}

View File

@@ -1,26 +1,36 @@
"use server"
"use server";
import prisma from "@/app/lib/prisma"
import { RouterAdminInvestasi_OLD } from "@/app/lib/router_hipmi/router_admin"
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi"
import { revalidatePath } from "next/cache"
import prisma from "@/app/lib/prisma";
import { RouterAdminInvestasi } from "@/app/lib/router_admin/router_admin_investasi";
import { revalidatePath } from "next/cache";
export default async function Admin_funRejectInvestasi(data: any) {
// console.log(data)
// console.log(data)
const res = await prisma.investasi.update({
where: { id: data.id },
data: {
masterStatusInvestasiId: data.status,
catatan: data.catatan
}
})
if(!res) return {status: 400, message: "Gagal reject"}
const res = await prisma.investasi.update({
where: { id: data.id },
data: {
masterStatusInvestasiId: data.status,
catatan: data.catatan,
},
select: {
id: true,
title: true,
authorId: true,
MasterStatusInvestasi: {
select: {
name: true,
},
},
},
});
if (!res) return { status: 400, message: "Gagal reject" };
revalidatePath(RouterAdminInvestasi_OLD.main_investasi)
revalidatePath(RouterAdminInvestasi.detail_review);
return {
status: 200,
message: "Reject berhasil"
}
}
return {
data: res,
status: 200,
message: "Reject berhasil",
};
}

View File

@@ -0,0 +1,71 @@
"use server";
import prisma from "@/app/lib/prisma";
import { ceil } from "lodash";
export async function adminInvestasi_funGetAllPublish({
page,
search,
}: {
page: number;
search?: string;
}) {
const takeData = 10;
const skipData = page * takeData - takeData;
const data = await prisma.investasi.findMany({
take: takeData,
skip: skipData,
orderBy: {
countDown: "desc",
},
where: {
active: true,
masterStatusInvestasiId: "1",
title: {
contains: search,
mode: "insensitive",
},
},
select: {
id: true,
title: true,
authorId: true,
hargaLembar: true,
targetDana: true,
totalLembar: true,
roi: true,
active: true,
imagesId: true,
catatan: true,
MasterStatusInvestasi: true,
BeritaInvestasi: true,
DokumenInvestasi: true,
ProspektusInvestasi: true,
MasterPembagianDeviden: true,
MasterPencarianInvestor: true,
MasterPeriodeDeviden: true,
author: true,
progress: true,
sisaLembar: true,
},
});
const nCount = await prisma.investasi.count({
where: {
active: true,
masterStatusInvestasiId: "1",
title: {
contains: search,
mode: "insensitive",
},
},
});
const allData = {
data: data,
nPage: ceil(nCount / takeData),
};
return allData;
}

View File

@@ -0,0 +1,61 @@
"use server";
import prisma from "@/app/lib/prisma";
import { ceil } from "lodash";
export async function adminInvestasi_funGetAllReject({
page,
search,
}: {
page: number;
search?: string;
}) {
const takeData = 10;
const skipData = page * takeData - takeData;
const data = await prisma.investasi.findMany({
take: takeData,
skip: skipData,
orderBy: {
createdAt: "desc",
},
where: {
active: true,
masterStatusInvestasiId: "4",
title: {
contains: search,
mode: "insensitive",
},
},
select: {
id: true,
title: true,
authorId: true,
hargaLembar: true,
targetDana: true,
totalLembar: true,
roi: true,
active: true,
author: true,
catatan: true,
},
});
const nCount = await prisma.investasi.count({
where: {
active: true,
masterStatusInvestasiId: "4",
title: {
contains: search,
mode: "insensitive",
},
},
});
const allData = {
data: data,
nPage: ceil(nCount / takeData),
};
return allData;
}

View File

@@ -0,0 +1,60 @@
"use server";
import prisma from "@/app/lib/prisma";
import { ceil } from "lodash";
export async function adminInvestasi_funGetAllReview({
page,
search,
}: {
page: number;
search?: string;
}) {
const takeData = 10;
const skipData = page * takeData - takeData;
const data = await prisma.investasi.findMany({
take: takeData,
skip: skipData,
orderBy: {
createdAt: "desc",
},
where: {
active: true,
masterStatusInvestasiId: "2",
title: {
contains: search,
mode: "insensitive",
},
},
select: {
id: true,
title: true,
authorId: true,
hargaLembar: true,
targetDana: true,
totalLembar: true,
roi: true,
active: true,
author: true,
},
});
const nCount = await prisma.investasi.count({
where: {
active: true,
masterStatusInvestasiId: "2",
title: {
contains: search,
mode: "insensitive",
},
},
});
const allData = {
data: data,
nPage: ceil(nCount / takeData),
};
return allData;
}

View File

@@ -1,7 +1,7 @@
import Admin_Investasi from "./main/view";
import Admin_HalamanAksi from "./halaman_aksi/view";
import Admin_LayoutHalamanAksi from "./halaman_aksi/layout";
import Admin_KonfirmasiInvestasi from "./konfirmasi/view";
import AdminInvestasi_DetailReview from "./detail/detail_review";
import Admin_LayoutKonfirmasiInvestasi from "./konfirmasi/layout";
import Admin_BuktiTransferInvestasi from "./bukti_transfer/view";
import Admin_LayoutBuktiTransferInvestasi from "./bukti_transfer/layout";
@@ -10,12 +10,15 @@ import Admin_LayoutStatusTransferInvesatasi from "./status_transfer/layout";
import Admin_TableReviewInvestasi from "./main/table_review";
import Admin_TablePublishInvestasi from "./main/table_publish";
import Admin_TableRejectInvestasi from "./main/table_reject";
import { AdminInvestasi_DetailPublish } from "./detail/detail_publish";
import { AdminInvestasi_DetailReject } from "./detail/detail_reject";
export {
Admin_Investasi,
Admin_HalamanAksi,
Admin_LayoutHalamanAksi,
Admin_KonfirmasiInvestasi,
AdminInvestasi_DetailReview as Admin_KonfirmasiInvestasi,
Admin_LayoutKonfirmasiInvestasi,
Admin_BuktiTransferInvestasi,
Admin_LayoutBuktiTransferInvestasi,
@@ -24,4 +27,6 @@ export {
Admin_TablePublishInvestasi,
Admin_TableReviewInvestasi,
Admin_TableRejectInvestasi,
AdminInvestasi_DetailPublish,
AdminInvestasi_DetailReject,
};

View File

@@ -11,7 +11,9 @@ export default function Admin_LayoutKonfirmasiInvestasi({
}) {
return (
<>
<AppShell header={<ComponentGlobal_HeaderTamplate title="Konfimasi Investasi" />}>
<AppShell
header={<ComponentGlobal_HeaderTamplate title="Konfimasi Investasi" />}
>
{children}
</AppShell>
</>

View File

@@ -2,116 +2,189 @@
import { RouterAdminInvestasi_OLD } from "@/app/lib/router_hipmi/router_admin";
import { MODEL_Investasi } from "@/app_modules/investasi/model/model_investasi";
import {
Badge,
ActionIcon,
Box,
ScrollArea,
Table,
Tooltip,
Stack,
Avatar,
Group,
Text,
Button,
Center,
Group,
Pagination,
Paper,
ScrollArea,
Stack,
Table,
Text,
TextInput,
Title
} from "@mantine/core";
import { IconChevronLeft, IconEyeCheck } from "@tabler/icons-react";
import { IconEdit, IconEye } from "@tabler/icons-react";
import { IconSearch } from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react";
import ComponentAdminGlobal_HeaderTamplate from "../../component_global/header_tamplate";
import ComponentAdminGlobal_IsEmptyData from "../../component_global/is_empty_data";
import { adminInvestasi_funGetAllPublish } from "../fun/get/get_all_publish";
import { RouterAdminInvestasi } from "@/app/lib/router_admin/router_admin_investasi";
export default function Admin_TablePublishInvestasi({
dataInvestsi,
}: {
dataInvestsi: MODEL_Investasi[];
}) {
const [investasi, setInvestasi] = useState(dataInvestsi);
const router = useRouter();
// console.log(investasi);
const tableBody = investasi.map((e) =>
e.MasterStatusInvestasi.id === "3" ? (
<tr key={e.id}>
<td>
<Group position="left">
<Avatar variant="outline" radius={"xl"} />
<Text>{e.author.username}</Text>
</Group>
</td>
<td>{e.title}</td>
<td>
<Center> {e.progress} %</Center>
</td>
<td>
<Center> {new Intl.NumberFormat("id-ID", {maximumFractionDigits: 10}).format(+e.sisaLembar)}</Center>
</td>
<td>
<Center> {new Intl.NumberFormat("id-ID", {maximumFractionDigits: 10}).format(+e.totalLembar)}</Center>
</td>
<td>
<Center>
<Tooltip label="Detail" withArrow position="bottom">
<ActionIcon
variant="transparent"
onClick={() =>
router.push(RouterAdminInvestasi_OLD.konfirmasi + `${e.id}`)
}
>
<IconEyeCheck color="green" />
</ActionIcon>
</Tooltip>
</Center>
</td>
</tr>
) : (
""
)
);
return (
<>
<Stack>
<ActionIcon variant="outline" onClick={() => router.push(RouterAdminInvestasi_OLD.main_investasi)}>
<IconChevronLeft />
</ActionIcon>
<Box>
<ScrollArea w={"100%"}>
{/* <Title order={5} mb={5}>
List Publish
</Title> */}
<Badge color="green" variant="light" radius={0} size={"xl"}>
Publish
</Badge>
<Table
withBorder
highlightOnHover
verticalSpacing={"md"}
horizontalSpacing={"md"}
>
<thead>
<tr>
<th>Username</th>
<th>Nama Proyek Investasi</th>
<th>
<Center>Progres</Center>
</th>
<th>
<Center>Sisa Saham</Center>
</th>
<th>
<Center>Total Saham</Center>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{tableBody}</tbody>
</Table>
</ScrollArea>
</Box>
<ComponentAdminGlobal_HeaderTamplate name="Investasi" />
<TableView listData={dataInvestsi} />
{/* <pre>{JSON.stringify(listPublish, null, 2)}</pre> */}
</Stack>
</>
);
}
function TableView({ listData }: { listData: any }) {
const router = useRouter();
const [data, setData] = useState<MODEL_Investasi[]>(listData.data);
const [nPage, setNPage] = useState(listData.nPage);
const [activePage, setActivePage] = useState(1);
const [isSearch, setSearch] = useState("");
async function onSearch(s: string) {
setSearch(s);
setActivePage(1);
const loadData = await adminInvestasi_funGetAllPublish({
page: 1,
search: s,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
async function onPageClick(p: any) {
setActivePage(p);
const loadData = await adminInvestasi_funGetAllPublish({
search: isSearch,
page: p,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
const tableBody = data.map((e) => (
<tr key={e.id}>
<td>
<Center w={200}>
<Text lineClamp={1}>{e.author.username}</Text>
</Center>
</td>
<td>
<Center w={400}>
<Text lineClamp={1}>{e.title}</Text>
</Center>
</td>
<td>
<Center w={200}>{_.toNumber(e.progress).toFixed(2)} %</Center>
</td>
<td>
<Center w={200}>
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+e.sisaLembar)}
</Center>
</td>
<td>
<Center w={200}>
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+e.totalLembar)}
</Center>
</td>
<td>
<Center w={200}>
<Button
bg={"green"}
color="green"
radius={"xl"}
onClick={() =>
router.push(RouterAdminInvestasi.detail_publish +`${e.id}`)
}
>
Detail
</Button>
</Center>
</td>
</tr>
));
return (
<>
<Stack spacing={"xs"} h={"100%"}>
<Group
position="apart"
bg={"green.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4} c={"black"}>
Publish
</Title>
<TextInput
icon={<IconSearch size={20} />}
radius={"xl"}
placeholder="Cari nama proyek"
onChange={(val) => {
onSearch(val.currentTarget.value);
}}
/>
</Group>
{_.isEmpty(data) ? (
<ComponentAdminGlobal_IsEmptyData />
) : (
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
<Table
verticalSpacing={"md"}
horizontalSpacing={"md"}
p={"md"}
w={"100%"}
h={"100%"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center w={200}>Username</Center>
</th>
<th>
<Center w={400}>Nama Proyek</Center>
</th>
<th>
<Center w={200}>Progres</Center>
</th>
<th>
<Center w={200}>Sisa Saham</Center>
</th>
<th>
<Center w={200}>Total Saham</Center>
</th>
<th>
<Center w={200}>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{tableBody}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}>
<Pagination
value={activePage}
total={nPage}
onChange={(val) => {
onPageClick(val);
}}
/>
</Center>
</Paper>
)}
</Stack>
</>
);

View File

@@ -13,11 +13,21 @@ import {
Avatar,
Group,
Text,
Button,
Pagination,
Paper,
TextInput,
Title,
} from "@mantine/core";
import { IconChevronLeft, IconEdit } from "@tabler/icons-react";
import { IconChevronLeft, IconEdit, IconSearch } from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react";
import ComponentAdminGlobal_HeaderTamplate from "../../component_global/header_tamplate";
import ComponentAdminGlobal_IsEmptyData from "../../component_global/is_empty_data";
import { adminInvestasi_funGetAllReview } from "../fun/get/get_all_review";
import { adminInvestasi_funGetAllReject } from "../fun/get/get_all_reject";
import { RouterAdminInvestasi } from "@/app/lib/router_admin/router_admin_investasi";
export default function Admin_TableRejectInvestasi({
dataInvestsi,
@@ -27,6 +37,15 @@ export default function Admin_TableRejectInvestasi({
const [investasi, setInvestasi] = useState(dataInvestsi);
const router = useRouter();
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Investasi" />
<TableView listData={dataInvestsi} />
</Stack>
</>
);
const tableBody = investasi.map((e) =>
e.MasterStatusInvestasi.id === "4" ? (
<tr key={e.id}>
@@ -61,8 +80,10 @@ export default function Admin_TableRejectInvestasi({
return (
<>
<Stack>
<ActionIcon variant="outline" onClick={() => router.push(RouterAdminInvestasi_OLD.main_investasi)}>
<ActionIcon
variant="outline"
onClick={() => router.push(RouterAdminInvestasi_OLD.main_investasi)}
>
<IconChevronLeft />
</ActionIcon>
<Box>
@@ -94,3 +115,136 @@ export default function Admin_TableRejectInvestasi({
</>
);
}
function TableView({ listData }: { listData: any }) {
const router = useRouter();
const [data, setData] = useState<MODEL_Investasi[]>(listData.data);
const [nPage, setNPage] = useState(listData.nPage);
const [activePage, setActivePage] = useState(1);
const [isSearch, setSearch] = useState("");
async function onSearch(s: string) {
setSearch(s);
setActivePage(1);
const loadData = await adminInvestasi_funGetAllReject({
page: 1,
search: s,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
async function onPageClick(p: any) {
setActivePage(p);
const loadData = await adminInvestasi_funGetAllReject({
search: isSearch,
page: p,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
const tableBody = data.map((e) => (
<tr key={e.id}>
<td>
<Center w={200}>
<Text lineClamp={1}>{e.author.username}</Text>
</Center>
</td>
<td>
<Center w={400}>
<Text lineClamp={1}>{e.title}</Text>
</Center>
</td>
<td>
<Center w={400}>
<Text lineClamp={1}>{e.catatan}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Button
color="orange"
radius={"xl"}
onClick={() =>
router.push(RouterAdminInvestasi.detail_reject + `${e.id}`)
}
>
Detail
</Button>
</Center>
</td>
</tr>
));
return (
<>
<Stack spacing={"xs"} h={"100%"}>
<Group
position="apart"
bg={"red.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4} c={"black"}>
Reject
</Title>
<TextInput
icon={<IconSearch size={20} />}
radius={"xl"}
placeholder="Cari nama proyek"
onChange={(val) => {
onSearch(val.currentTarget.value);
}}
/>
</Group>
{_.isEmpty(data) ? (
<ComponentAdminGlobal_IsEmptyData />
) : (
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
<Table
verticalSpacing={"md"}
horizontalSpacing={"md"}
p={"md"}
w={"100%"}
h={"100%"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center w={200}>Username</Center>
</th>
<th>
<Center w={400}>Nama Proyek</Center>
</th>
<th>
<Center w={400}>Catatan Penolakan</Center>
</th>
<th>
<Center w={200}>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{tableBody}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}>
<Pagination
value={activePage}
total={nPage}
onChange={(val) => {
onPageClick(val);
}}
/>
</Center>
</Paper>
)}
</Stack>
</>
);
}

View File

@@ -1,4 +1,5 @@
"use client";
import { RouterAdminInvestasi } from "@/app/lib/router_admin/router_admin_investasi";
import { RouterAdminInvestasi_OLD } from "@/app/lib/router_hipmi/router_admin";
import { MODEL_Investasi } from "@/app_modules/investasi/model/model_investasi";
import {
@@ -13,85 +14,184 @@ import {
Avatar,
Text,
Center,
Button,
Pagination,
Paper,
TextInput,
Title,
} from "@mantine/core";
import { IconChevronLeft, IconEdit } from "@tabler/icons-react";
import { IconChevronLeft, IconEdit, IconSearch } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import ComponentAdminGlobal_HeaderTamplate from "../../component_global/header_tamplate";
import { adminInvestasi_funGetAllReview } from "../fun/get/get_all_review";
import _ from "lodash";
import ComponentAdminGlobal_IsEmptyData from "../../component_global/is_empty_data";
import ComponentAdminGlobal_TampilanRupiahDonasi from "../../component_global/tampilan_rupiah";
export default function Admin_TableReviewInvestasi({
dataInvestsi,
}: {
dataInvestsi: MODEL_Investasi[];
}) {
const [investasi, setInvestasi] = useState(dataInvestsi);
const router = useRouter();
const tableBody = investasi.map((e) =>
e.MasterStatusInvestasi.id === "2" ? (
<tr key={e.id}>
<td>
<Group position="left">
<Avatar variant="outline" radius={"xl"} />
<Text>{e.author.username}</Text>
</Group>
</td>
<td>
{e.title}
</td>
<td>
<Center>
{e.ProspektusInvestasi === null ? (
<Badge color="red">Unavailable</Badge>
) : (
<Badge variant="dot" color="green">
Available
</Badge>
)}
</Center>
</td>
<td>
<Center>
<Tooltip label="Konfirmasi" withArrow position="bottom">
<ActionIcon
variant="transparent"
onClick={() =>
router.push(RouterAdminInvestasi_OLD.konfirmasi + `${e.id}`)
}
>
<IconEdit color="green" />
</ActionIcon>
</Tooltip>
</Center>
</td>
</tr>
) : (
""
)
);
return (
<>
<Stack>
<ActionIcon variant="outline" onClick={() => router.push(RouterAdminInvestasi_OLD.main_investasi)}>
<IconChevronLeft />
</ActionIcon>
<Box>
<ScrollArea w={"100%"}>
<Badge color="orange" variant="light" radius={0} size={"xl"}>
Review
</Badge>
<Table withBorder highlightOnHover verticalSpacing={"md"} horizontalSpacing={"md"}>
<thead>
<tr>
<th>Username</th>
<th>Nama Proyek Investasi</th>
<th><Center>File Prospektus</Center></th>
<th><Center>Aksi</Center></th>
</tr>
</thead>
<tbody>{tableBody}</tbody>
</Table>
</ScrollArea>
</Box>
<ComponentAdminGlobal_HeaderTamplate name="Investasi" />
<TableView listData={dataInvestsi} />
</Stack>
</>
);
}
function TableView({ listData }: { listData: any }) {
const router = useRouter();
const [data, setData] = useState<MODEL_Investasi[]>(listData.data);
const [nPage, setNPage] = useState(listData.nPage);
const [activePage, setActivePage] = useState(1);
const [isSearch, setSearch] = useState("");
async function onSearch(s: string) {
setSearch(s);
setActivePage(1);
const loadData = await adminInvestasi_funGetAllReview({
page: 1,
search: s,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
async function onPageClick(p: any) {
setActivePage(p);
const loadData = await adminInvestasi_funGetAllReview({
search: isSearch,
page: p,
});
setData(loadData.data as any);
setNPage(loadData.nPage);
}
const tableBody = data.map((e) => (
<tr key={e.id}>
<td>
<Center w={200}>
<Text lineClamp={1}>{e.author.username}</Text>
</Center>
</td>
<td>
<Center w={400}>
<Text lineClamp={1}>{e.title}</Text>
</Center>
</td>
<td>
<Center w={200}>
<Text lineClamp={1}>{e.roi} %</Text>
</Center>
</td>
<td>
<Center w={200}>
<ComponentAdminGlobal_TampilanRupiahDonasi
nominal={_.toNumber(e.targetDana)}
/>
</Center>
</td>
<td>
<Center w={200}>
<ComponentAdminGlobal_TampilanRupiahDonasi
nominal={_.toNumber(e.hargaLembar)}
/>
</Center>
</td>
<td>
<Center w={200}>
<Button
color="orange"
radius={"xl"}
onClick={() =>
router.push(RouterAdminInvestasi_OLD.konfirmasi + `${e.id}`)
}
>
Detail
</Button>
</Center>
</td>
</tr>
));
return (
<>
<Stack spacing={"xs"} h={"100%"}>
<Group
position="apart"
bg={"orange.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4} c={"black"}>
Review
</Title>
<TextInput
icon={<IconSearch size={20} />}
radius={"xl"}
placeholder="Cari nama proyek"
onChange={(val) => {
onSearch(val.currentTarget.value);
}}
/>
</Group>
{_.isEmpty(data) ? (
<ComponentAdminGlobal_IsEmptyData />
) : (
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
<ScrollArea w={"100%"} h={"90%"} offsetScrollbars>
<Table
verticalSpacing={"md"}
horizontalSpacing={"md"}
p={"md"}
w={"100%"}
h={"100%"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center w={200}>Username</Center>
</th>
<th>
<Center w={400}>Nama Proyek</Center>
</th>
<th>
<Center w={200}>ROI</Center>
</th>
<th>
<Center w={200}>Target Dana</Center>
</th>
<th>
<Center w={200}>Harga Perlembar</Center>
</th>
<th>
<Center w={200}>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{tableBody}</tbody>
</Table>
</ScrollArea>
<Center mt={"xl"}>
<Pagination
value={activePage}
total={nPage}
onChange={(val) => {
onPageClick(val);
}}
/>
</Center>
</Paper>
)}
</Stack>
</>
);

View File

@@ -61,12 +61,13 @@ export default function Admin_Investasi({
const router = useRouter();
const listBox = [
{
id: 1,
name: "Draft",
jumlah: countDraft,
link: "",
color: "yellow",
name: "Publish",
jumlah: countPublish,
link: RouterAdminInvestasi_OLD.table_status_publish,
color: "green",
},
{
id: 2,
@@ -77,13 +78,6 @@ export default function Admin_Investasi({
},
{
id: 3,
name: "Publish",
jumlah: countPublish,
link: RouterAdminInvestasi_OLD.table_status_publish,
color: "green",
},
{
id: 4,
name: "Reject",
jumlah: countReject,
link: RouterAdminInvestasi_OLD.table_status_reject,
@@ -97,7 +91,7 @@ export default function Admin_Investasi({
<ComponentAdminGlobal_HeaderTamplate name="Investasi" />
<SimpleGrid
cols={4}
cols={3}
spacing="lg"
breakpoints={[
{ maxWidth: "62rem", cols: 4, spacing: "lg" },

View File

@@ -54,6 +54,7 @@ import adminNotifikasi_findRouterForum from "./notifikasi/route_setting/forum";
import { adminNotifikasi_findRouterVoting } from "./notifikasi/route_setting/voting";
import { adminNotifikasi_findRouterEvent } from "./notifikasi/route_setting/event";
import adminNotifikasi_findRouterDonasi from "./notifikasi/route_setting/donasi";
import { ComponentAdmin_UIDrawerNotifikasi } from "./notifikasi/ui_drawer_notifikasi";
export default function AdminLayout({
children,
@@ -326,7 +327,7 @@ export default function AdminLayout({
position="right"
size={"xs"}
>
<DrawerNotifikasi
<ComponentAdmin_UIDrawerNotifikasi
data={dataNotif}
onLoadReadNotif={(val: any) => {
setDataNotif(val);
@@ -345,194 +346,4 @@ export default function AdminLayout({
);
}
function DrawerNotifikasi({
data,
onLoadReadNotif,
onChangeNavbar,
onToggleNavbar,
onLoadCountNotif,
}: {
data: MODEL_NOTIFIKASI[];
onLoadReadNotif: (val: any) => void;
onChangeNavbar: (val: any) => void;
onToggleNavbar: (val: any) => void;
onLoadCountNotif: (val: any) => void;
}) {
const router = useRouter();
if (_.isEmpty(data)) {
return (
<>
<Center>
<Text c={"gray"} fz={"xs"}>
Tidak ada notifikasi
</Text>
</Center>
</>
);
}
return (
<>
<Paper h={"100%"}>
<Stack>
{data.map((e, i) => (
<Card
style={{
transition: "0.5s",
}}
key={e?.id}
// withBorder
bg={e?.isRead ? "gray.1" : "gray.4"}
sx={{
borderColor: "gray",
borderStyle: "solid",
borderWidth: "0.5px",
":hover": {
backgroundColor: "#C1C2C5",
},
}}
onClick={async () => {
// JOB
e?.kategoriApp === "JOB" &&
adminNotifikasi_findRouterJob({
data: e,
router: router,
onChangeNavbar: (val: any) => {
onChangeNavbar(val);
},
onToggleNavbar: onToggleNavbar,
});
// FORUM
e?.kategoriApp === "FORUM" &&
adminNotifikasi_findRouterForum({
data: e,
router: router,
onChangeNavbar(val) {
onChangeNavbar(val);
},
onToggleNavbar(val) {
onToggleNavbar(val);
},
});
// VOTE
e?.kategoriApp === "VOTING" &&
adminNotifikasi_findRouterVoting({
data: e,
router: router,
onChangeNavbar(val) {
onChangeNavbar(val);
},
onToggleNavbar(val) {
onToggleNavbar(val);
},
});
e?.kategoriApp === "EVENT" &&
adminNotifikasi_findRouterEvent({
data: e,
router: router,
onChangeNavbar(val) {
onChangeNavbar(val);
},
onToggleNavbar(val) {
onToggleNavbar(val);
},
});
e.kategoriApp === "DONASI" && adminNotifikasi_findRouterDonasi({
data: e,
router: router,
onChangeNavbar(val) {
onChangeNavbar(val);
},
onToggleNavbar(val) {
onToggleNavbar(val);
},
})
const updateIsRead = await adminNotifikasi_funUpdateIsReadById({
notifId: e?.id,
});
if (updateIsRead) {
const loadCountNotif =
await adminNotifikasi_countNotifikasi();
onLoadCountNotif(loadCountNotif);
const loadDataNotif = await adminNotifikasi_getByUserId();
onLoadReadNotif(loadDataNotif);
} else {
return null;
}
// callBackIsNotifikasi(false);
}}
>
<Card.Section p={"sm"}>
<Stack spacing={"xs"}>
<Group position="apart">
<Text fw={"bold"} fz={10}>
# {e?.kategoriApp}
</Text>
{e?.status ? (
<Badge fz={10} size="sm">
{e?.status}
</Badge>
) : (
""
)}
</Group>
<Divider color="gray.3" />
</Stack>
</Card.Section>
<Card.Section px={"sm"} pb={"sm"}>
<Stack spacing={0}>
<Text lineClamp={2} fw={"bold"} fz={"xs"}>
{e?.title}
</Text>
<Text lineClamp={2} fz={"xs"}>
{e?.pesan}
</Text>
</Stack>
</Card.Section>
<Card.Section p={"sm"}>
<Group position="apart">
<Text fz={10} color="gray">
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "long",
}).format(e?.createdAt)}
<Text span inherit fz={10} color="gray">
{", "}
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.createdAt)}
</Text>
</Text>
{e?.isRead ? (
<Group spacing={5}>
<IconChecks color="gray" size={10} />
<Text fz={10} color="gray">
Sudah dilihat
</Text>
</Group>
) : (
<Group spacing={5}>
<IconCheck color="gray" size={10} />
<Text fz={10} color="gray">
Belum dilihat
</Text>
</Group>
)}
</Group>
</Card.Section>
</Card>
))}
</Stack>
</Paper>
</>
);
}

View File

@@ -1,2 +0,0 @@
// test notif

View File

@@ -0,0 +1,43 @@
import { RouterAdminDonasi } from "@/app/lib/router_admin/router_admin_donasi";
import { RouterAdminInvestasi } from "@/app/lib/router_admin/router_admin_investasi";
import { RouterAdminDonasi_OLD } from "@/app/lib/router_hipmi/router_admin";
import { MODEL_NOTIFIKASI } from "@/app_modules/notifikasi/model/interface";
import _ from "lodash";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
export default async function adminNotifikasi_findRouterInvestasi({
data,
router,
onChangeNavbar,
onToggleNavbar,
}: {
data: MODEL_NOTIFIKASI;
router: AppRouterInstance;
onChangeNavbar: (val: any) => void;
onToggleNavbar: (val: any) => void;
}) {
if (data.status === "Review") {
const path = RouterAdminInvestasi.table_review;
router.push(path);
onChangeNavbar({
id: 2,
childId: 23,
});
}
// if (
// data.status === "Menunggu" ||
// data.status === "Berhasil" ||
// data.status === "Proses" ||
// data.status === "Gagal"
// ) {
// const path = RouterAdminDonasi_OLD.detail_publish + data.appId;
// router.push(path, { scroll: false });
// onChangeNavbar({
// id: 3,
// childId: 32,
// });
// }
onToggleNavbar(true);
}

View File

@@ -0,0 +1,231 @@
import { MODEL_NOTIFIKASI } from "@/app_modules/notifikasi/model/interface";
import {
Center,
Paper,
Stack,
Card,
Group,
Badge,
Divider,
Text,
} from "@mantine/core";
import { IconChecks, IconCheck } from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import adminNotifikasi_countNotifikasi from "./fun/count/count_is_read";
import adminNotifikasi_getByUserId from "./fun/get/get_notifikasi_by_user_id";
import adminNotifikasi_funUpdateIsReadById from "./fun/update/fun_update_is_read_by_id";
import adminNotifikasi_findRouterDonasi from "./route_setting/donasi";
import { adminNotifikasi_findRouterEvent } from "./route_setting/event";
import adminNotifikasi_findRouterForum from "./route_setting/forum";
import adminNotifikasi_findRouterJob from "./route_setting/job";
import { adminNotifikasi_findRouterVoting } from "./route_setting/voting";
import adminNotifikasi_findRouterInvestasi from "./route_setting/investasi";
export function ComponentAdmin_UIDrawerNotifikasi({
data,
onLoadReadNotif,
onChangeNavbar,
onToggleNavbar,
onLoadCountNotif,
}: {
data: MODEL_NOTIFIKASI[];
onLoadReadNotif: (val: any) => void;
onChangeNavbar: (val: any) => void;
onToggleNavbar: (val: any) => void;
onLoadCountNotif: (val: any) => void;
}) {
const router = useRouter();
if (_.isEmpty(data)) {
return (
<>
<Center>
<Text c={"gray"} fz={"xs"}>
Tidak ada notifikasi
</Text>
</Center>
</>
);
}
return (
<>
<Paper h={"100%"}>
<Stack>
{data.map((e, i) => (
<Card
style={{
transition: "0.5s",
}}
key={e?.id}
// withBorder
bg={e?.isRead ? "gray.1" : "gray.4"}
sx={{
borderColor: "gray",
borderStyle: "solid",
borderWidth: "0.5px",
":hover": {
backgroundColor: "#C1C2C5",
},
}}
onClick={async () => {
// JOB
e?.kategoriApp === "JOB" &&
adminNotifikasi_findRouterJob({
data: e,
router: router,
onChangeNavbar: (val: any) => {
onChangeNavbar(val);
},
onToggleNavbar: onToggleNavbar,
});
// FORUM
e?.kategoriApp === "FORUM" &&
adminNotifikasi_findRouterForum({
data: e,
router: router,
onChangeNavbar(val) {
onChangeNavbar(val);
},
onToggleNavbar(val) {
onToggleNavbar(val);
},
});
// VOTE
e?.kategoriApp === "VOTING" &&
adminNotifikasi_findRouterVoting({
data: e,
router: router,
onChangeNavbar(val) {
onChangeNavbar(val);
},
onToggleNavbar(val) {
onToggleNavbar(val);
},
});
// EVENT
e?.kategoriApp === "EVENT" &&
adminNotifikasi_findRouterEvent({
data: e,
router: router,
onChangeNavbar(val) {
onChangeNavbar(val);
},
onToggleNavbar(val) {
onToggleNavbar(val);
},
});
// DONASI
e.kategoriApp === "DONASI" &&
adminNotifikasi_findRouterDonasi({
data: e,
router: router,
onChangeNavbar(val) {
onChangeNavbar(val);
},
onToggleNavbar(val) {
onToggleNavbar(val);
},
});
// INVESTASI
e.kategoriApp === "INVESTASI" &&
adminNotifikasi_findRouterInvestasi({
data: e,
router: router,
onChangeNavbar(val) {
onChangeNavbar(val);
},
onToggleNavbar(val) {
onToggleNavbar(val);
},
});
const updateIsRead = await adminNotifikasi_funUpdateIsReadById({
notifId: e?.id,
});
if (updateIsRead) {
const loadCountNotif =
await adminNotifikasi_countNotifikasi();
onLoadCountNotif(loadCountNotif);
const loadDataNotif = await adminNotifikasi_getByUserId();
onLoadReadNotif(loadDataNotif);
} else {
return null;
}
// callBackIsNotifikasi(false);
}}
>
<Card.Section p={"sm"}>
<Stack spacing={"xs"}>
<Group position="apart">
<Text fw={"bold"} fz={10}>
# {e?.kategoriApp}
</Text>
{e?.status ? (
<Badge fz={10} size="sm">
{e?.status}
</Badge>
) : (
""
)}
</Group>
<Divider color="gray.3" />
</Stack>
</Card.Section>
<Card.Section px={"sm"} pb={"sm"}>
<Stack spacing={0}>
<Text lineClamp={2} fw={"bold"} fz={"xs"}>
{e?.title}
</Text>
<Text lineClamp={2} fz={"xs"}>
{e?.pesan}
</Text>
</Stack>
</Card.Section>
<Card.Section p={"sm"}>
<Group position="apart">
<Text fz={10} color="gray">
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "long",
}).format(e?.createdAt)}
<Text span inherit fz={10} color="gray">
{", "}
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(e?.createdAt)}
</Text>
</Text>
{e?.isRead ? (
<Group spacing={5}>
<IconChecks color="gray" size={10} />
<Text fz={10} color="gray">
Sudah dilihat
</Text>
</Group>
) : (
<Group spacing={5}>
<IconCheck color="gray" size={10} />
<Text fz={10} color="gray">
Belum dilihat
</Text>
</Group>
)}
</Group>
</Card.Section>
</Card>
))}
</Stack>
</Paper>
</>
);
}