## 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>
</>
);
}

View File

@@ -9,7 +9,7 @@ export async function auth_funLogin(nomor: string) {
try {
const res = await fetch(
`https://wa.wibudev.com/code?nom=${nomor}&text=Masukan Kode OTP:${codeOtp}`
`https://wa.wibudev.com/code?nom=${nomor}&text=HIPMI - Masukan kode OTP sesuai dengan nomor yang anda daftarkan, kode ini bersifat rahasia & jangan di bagikan pada siapapun termasuk anggota ataupun pengurus HIPMI lainnya. Kode OTP anda: ${codeOtp}`
);
const sendWa = await res.json();

View File

@@ -2,7 +2,14 @@
import { MainColor } from "@/app_modules/_global/color/color_pallet";
import UIGlobal_SplashScreen from "@/app_modules/_global/ui/ui_splash";
import { BackgroundImage, Center, Image, Paper, Stack } from "@mantine/core";
import {
Avatar,
BackgroundImage,
Center,
Image,
Paper,
Stack,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useRouter } from "next/navigation";
@@ -31,14 +38,9 @@ export default function SplashScreen({ data }: { data: any }) {
<Center h={"100vh"}>
<Stack align="center" justify="center" p={"md"}>
{/* <Title c={"#002e59"}>Welcome to</Title> */}
<Paper
p={{ base: 20, md: 30, lg: 40 }}
bg={"gray.1"}
radius={"100%"}
shadow="xl"
>
<Image height={200} alt="" src={"/aset/logo/logo-hipmi.png"} />
</Paper>
<Avatar size={300} radius={"100%"} >
<Image height={250} width={250} alt="Logo" src={"/aset/logo/logo-hipmi.png"} />
</Avatar>
</Stack>
</Center>
</BackgroundImage>

View File

@@ -8,17 +8,8 @@ import {
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { gs_donasi_hot_menu } from "@/app_modules/donasi/global_state";
import { gs_investasiFooter } from "@/app_modules/investasi/g_state";
import {
AspectRatio,
Grid,
Image,
Loader,
Paper,
Stack,
Text,
Title,
} from "@mantine/core";
import { gs_investas_menu } from "@/app_modules/investasi/g_state";
import { Grid, Image, Paper, Stack, Text, Title } from "@mantine/core";
import { IconChevronRight } from "@tabler/icons-react";
import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
@@ -26,7 +17,7 @@ import { useState } from "react";
export default function MainCrowd() {
const router = useRouter();
const [changeColor, setChangeColor] = useAtom(gs_investasiFooter);
const [changeColor, setChangeColor] = useAtom(gs_investas_menu);
const [donasiHotMenu, setDonasiHotMenu] = useAtom(gs_donasi_hot_menu);
const [loadingInv, setLoadingInv] = useState(false);
const [loadingDon, setLoadingDon] = useState(false);
@@ -60,17 +51,17 @@ export default function MainCrowd() {
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
backgroundColor: MainColor.darkblue,
// color: "white",
color: "gray",
color: "white",
// color: "gray",
}}
onClick={() => {
// setLoadingInv(true);
// router.push(RouterCrowd.investasi);
// setChangeColor(0);
ComponentGlobal_NotifikasiPeringatan(
"Sedang Perbaikan",
3000
);
setLoadingInv(true);
router.push(RouterCrowd.investasi);
setChangeColor(0);
// ComponentGlobal_NotifikasiPeringatan(
// "Sedang Perbaikan",
// 3000
// );
}}
>
<Grid>

View File

@@ -0,0 +1,57 @@
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { Box, Center } from "@mantine/core";
import _ from "lodash";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { ScrollOnly } from "next-scroll-loader";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { donasi_funGetListPencairanDanaById } from "../../fun/get/get_list_pencairan_dana_by_id";
import { MODEL_DONASI_PENCAIRAN_DANA } from "../../model/interface";
import { ComponentDonasi_CardDonatur } from "./ui_card_donatur";
import { ComponentDonasi_CardPencairanDana } from "./card_pencairan_dana";
export function ComponentDonasi_InformasiPencairanDana({
donasiId,
listPD,
}: {
donasiId: string;
listPD: MODEL_DONASI_PENCAIRAN_DANA[];
}) {
const router = useRouter();
const [data, setData] = useState(listPD);
const [activePage, setActivePage] = useState(1);
return (
<>
{_.isEmpty(listPD) ? (
<ComponentGlobal_IsEmptyData height={20} />
) : (
<Box>
<ScrollOnly
height="62vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await donasi_funGetListPencairanDanaById({
page: activePage + 1,
donasiId: donasiId,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => <ComponentDonasi_CardPencairanDana data={item} />}
</ScrollOnly>
</Box>
)}
</>
);
}

View File

@@ -0,0 +1,44 @@
import { MainColor, AccentColor } from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_BoxInformation from "@/app_modules/_global/component/box_information";
import { Paper, Stack, Grid, Title, Text } from "@mantine/core";
import { MODEL_DONASI } from "../../model/interface";
import TampilanRupiahDonasi from "../tampilan_rupiah";
export function ComponentDonasi_BoxPencariranDana({ akumulasi }: { akumulasi: MODEL_DONASI }) {
return (
<>
<Paper
style={{
backgroundColor: MainColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
padding: "15px",
cursor: "pointer",
borderRadius: "10px",
color: "white",
marginBottom: "10px",
}}
>
<Stack>
<Grid>
<Grid.Col span={6}>
<Title order={5}>
<TampilanRupiahDonasi nominal={akumulasi.totalPencairan} />
</Title>
<Text fz={"xs"}>Dana sudah dicairkan</Text>
</Grid.Col>
<Grid.Col span={6}>
<Title order={5}>{akumulasi.akumulasiPencairan} kali</Title>
<Text fz={"xs"}>Pencairan dana</Text>
</Grid.Col>
</Grid>
<ComponentGlobal_BoxInformation
informasi=" Pencairan dana akan dilakukan oleh Admin HIPMI tanpa campur tangan
pihak manapun, jika berita pencairan dana dibawah tidak sesuai
dengan kabar yang diberikan oleh PENGGALANG DANA. Maka pegguna lain
dapat melaporkannya pada Admin HIPMI !"
/>
</Stack>
</Paper>
</>
);
}

View File

@@ -0,0 +1,113 @@
import {
AspectRatio,
Badge,
Card,
Grid,
Group,
Image,
Paper,
Progress,
Stack,
Text,
} from "@mantine/core";
import { MODEL_DONASI_INVOICE } from "../../model/interface";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import ComponentDonasi_TampilanHitungMundur from "../tampilan_hitung_mundur";
import TampilanRupiahDonasi from "../tampilan_rupiah";
import { useRouter } from "next/navigation";
import { useState } from "react";
import ComponentGlobal_CardLoadingOverlay from "@/app_modules/_global/loading_card";
export function ComponentDonasi_CardInvoice({
data,
}: {
data: MODEL_DONASI_INVOICE;
}) {
const router = useRouter();
const [donasiId, setEventId] = useState("");
const [visible, setVisible] = useState(false);
async function onCekInvoice() {
if (data.donasiMaster_StatusInvoiceId === "1") {
return router.push(RouterDonasi.detail_donasi_saya + `${data?.id}`);
} else {
if (data.donasiMaster_StatusInvoiceId === "2") {
return router.push(RouterDonasi.proses_transaksi + `${data?.id}`);
} else {
if (data.donasiMaster_StatusInvoiceId === "3") {
return router.push(RouterDonasi.invoice + `${data?.id}`);
} else {
ComponentGlobal_NotifikasiGagal("Gagal Melihat Invoice");
}
}
}
}
return (
<>
<Card
style={{
backgroundColor: AccentColor.blue,
border: `2px solid ${AccentColor.darkblue}`,
padding: "15px",
cursor: "pointer",
borderRadius: "10px",
color: "white",
marginBottom: "15px",
}}
onClick={() => onCekInvoice()}
>
<Stack>
<Grid>
<Grid.Col span={5}>
<Stack spacing={5}>
<Stack spacing={0}>
<Text fz={"xs"} fw={"bold"} truncate>
{data.Donasi.title}
</Text>
<ComponentDonasi_TampilanHitungMundur
durasi={data.Donasi.DonasiMaster_Durasi.name}
publishTime={data.Donasi.publishTime}
textSize={10}
/>
</Stack>
<Progress value={+data.Donasi.progres} color="orange" />
<Group position="apart">
<Stack spacing={0}>
<Text fz={10}>Donasi Saya</Text>
<Text fz={10} fw={"bold"} c={"orange"} truncate>
<TampilanRupiahDonasi nominal={+data.nominal} />
</Text>
</Stack>
</Group>
<Badge size="xs" variant="filled" color="yellow">
<Text>{data.DonasiMaster_StatusInvoice.name}</Text>
</Badge>
</Stack>
</Grid.Col>
<Grid.Col span={7}>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image
alt="Foto"
src={RouterDonasi.api_gambar + `${data.Donasi.imagesId}`}
radius={"md"}
/>
</Paper>
</AspectRatio>
</Grid.Col>
</Grid>
{/* {width > 575 ? "" : <Divider />} */}
</Stack>
{visible && donasiId !== "" ? (
<ComponentGlobal_CardLoadingOverlay />
) : (
""
)}
</Card>
</>
);
}

View File

@@ -0,0 +1,71 @@
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import {
Paper,
Stack,
Title,
Spoiler,
Center,
Button,
Text,
} from "@mantine/core";
import { IconImageInPicture } from "@tabler/icons-react";
import moment from "moment";
import { MODEL_DONASI_PENCAIRAN_DANA } from "../../model/interface";
import { useRouter } from "next/navigation";
export function ComponentDonasi_CardPencairanDana({
data,
}: {
data: MODEL_DONASI_PENCAIRAN_DANA;
}) {
const router = useRouter();
return (
<>
<Paper
style={{
padding: "15px",
border: `2px solid ${AccentColor.blue}`,
backgroundColor: AccentColor.darkblue,
borderRadius: "10px",
color: "white",
}}
>
<Text fz={"xs"}>{moment(data.createdAt).format("ll")}</Text>
<Stack spacing={"lg"}>
<Title order={5}>{data.title}</Title>
<Spoiler
maxHeight={50}
hideLabel="Sembunyikan"
showLabel="Baca Selengkapnya"
>
{data.deskripsi}
</Spoiler>
<Center>
<Button
radius={"xl"}
leftIcon={<IconImageInPicture />}
onClick={() => {
// open();
// setIdGambar(e.imagesId);
router.push(RouterDonasi.bukti_transfer + data.imagesId, {
scroll: false,
});
}}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Bukti Transfer
</Button>
</Center>
</Stack>
</Paper>
</>
);
}

View File

@@ -5,16 +5,19 @@ import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import {
AspectRatio,
Box,
Card,
Grid,
Image,
Paper,
Progress,
Stack,
Text
Text,
} from "@mantine/core";
import { useRouter } from "next/navigation";
import ComponentDonasi_TampilanHitungMundur from "../tampilan_hitung_mundur";
import TampilanRupiahDonasi from "../tampilan_rupiah";
import { useState } from "react";
import ComponentGlobal_CardLoadingOverlay from "@/app_modules/_global/loading_card";
export default function ComponentDonasi_CardPublish({
data,
@@ -23,12 +26,13 @@ export default function ComponentDonasi_CardPublish({
data: any;
path: string;
}) {
const router = useRouter();
const [visible, setVisible] = useState(false);
const [donasiId, setDonasiId] = useState("");
return (
<>
<Box
<Card
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
@@ -38,6 +42,8 @@ export default function ComponentDonasi_CardPublish({
marginBottom: "15px",
}}
onClick={() => {
setVisible(true);
setDonasiId(data.id);
router.push(path + `${data.id}`);
}}
>
@@ -78,7 +84,12 @@ export default function ComponentDonasi_CardPublish({
</Grid>
{/* {width > 575 ? "" : <Divider />} */}
</Stack>
</Box>
{visible && donasiId !== "" ? (
<ComponentGlobal_CardLoadingOverlay />
) : (
""
)}
</Card>
</>
);
}

View File

@@ -8,9 +8,12 @@ import {
Paper,
Image,
Text,
Card,
} from "@mantine/core";
import { useRouter } from "next/navigation";
import { MODEL_DONASI } from "../../model/interface";
import { useState } from "react";
import ComponentGlobal_CardLoadingOverlay from "@/app_modules/_global/loading_card";
export function ComponentDonasi_CardStatus({
data,
@@ -20,9 +23,12 @@ export function ComponentDonasi_CardStatus({
path: string;
}) {
const router = useRouter();
const [visible, setVisible] = useState(false);
const [donasiId, setDonasiId] = useState("");
return (
<>
<Box
<Card
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
@@ -31,7 +37,11 @@ export function ComponentDonasi_CardStatus({
color: "white",
marginBottom: "15px",
}}
onClick={() => router.push(path + `${data.id}`)}
onClick={() => {
setVisible(true);
setDonasiId(data.id);
router.push(path + `${data.id}`);
}}
>
<Stack>
<Grid>
@@ -65,7 +75,12 @@ export function ComponentDonasi_CardStatus({
</Grid>
{/* {width > 575 ? "" : <Divider />} */}
</Stack>
</Box>
{visible && donasiId !== "" ? (
<ComponentGlobal_CardLoadingOverlay />
) : (
""
)}
</Card>
</>
);
}

View File

@@ -0,0 +1,48 @@
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import { Paper, Grid, Center, Stack, Title, Group, Text } from "@mantine/core";
import { IconMoodSmileBeam } from "@tabler/icons-react";
import { MODEL_DONASI_INVOICE } from "../../model/interface";
import TampilanRupiahDonasi from "../tampilan_rupiah";
export function ComponentDonasi_CardDonatur({ data }: { data: MODEL_DONASI_INVOICE }){
return (
<>
<Paper
style={{
backgroundColor: AccentColor.blue,
border: `2px solid ${AccentColor.darkblue}`,
padding: "15px",
cursor: "pointer",
borderRadius: "10px",
color: "white",
marginBottom: "10px",
}}
>
<Grid>
<Grid.Col span={3}>
<Center h={"100%"}>
{/* <Avatar variant="filled" radius={"xl"} size={"md"} /> */}
<IconMoodSmileBeam size={50} />
</Center>
</Grid.Col>
<Grid.Col span={9}>
<Stack spacing={0}>
<Title order={5}>{data.Author.username}</Title>
<Group spacing={"xs"}>
<Text fz={"xs"}>Berdonasi sebesar</Text>
<Text truncate fw={"bold"}>
<TampilanRupiahDonasi nominal={+data.nominal} />
</Text>
</Group>
<Text fz={"xs"}>
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(data?.createdAt)}
</Text>
</Stack>
</Grid.Col>
</Grid>
</Paper>
</>
);
}

View File

@@ -26,7 +26,7 @@ export default function ComponentDonasi_ListKabar({
cursor: "pointer",
borderRadius: "10px",
color: "white",
marginBottom: "5px",
marginBottom: "10px",
}}
onClick={() => router.push(route + `${kabar.id}`)}
>

View File

@@ -15,6 +15,7 @@ import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import mqtt_client from "@/util/mqtt_client";
import notifikasiToAdmin_funCreate from "@/app_modules/notifikasi/fun/create/create_notif_to_admin";
import { useState } from "react";
export default function DetailDraftDonasi({
dataDonasi,
@@ -52,6 +53,8 @@ function ButtonAjukanPenggalangan({
const [tabsPostingDonasi, setTabsPostingDonasi] = useAtom(
gs_donasi_tabs_posting
);
const [isLoading, setLoading] = useState(false);
async function onCLick() {
const res = await Donasi_funGantiStatus(dataDonasi.id, "2");
if (res.status === 200) {
@@ -71,6 +74,7 @@ function ButtonAjukanPenggalangan({
if (notif.status === 201) {
mqtt_client.publish("ADMIN", JSON.stringify({ count: 1 }));
setLoading(true);
setTabsPostingDonasi("Review");
ComponentGlobal_NotifikasiBerhasil("Berhasil Diajukan");
router.push(RouterDonasi.main_galang_dana);
@@ -82,6 +86,8 @@ function ButtonAjukanPenggalangan({
return (
<>
<Button
loaderPosition="center"
loading={isLoading ? true : false}
radius={"xl"}
bg={"orange"}
color="orange"

View File

@@ -1,64 +1,55 @@
"use client";
"use dev";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import ComponentDonasi_IsEmptyData from "@/app_modules/donasi/component/is_empty_data";
import TampilanRupiahDonasi from "@/app_modules/donasi/component/tampilan_rupiah";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { ComponentDonasi_CardDonatur } from "@/app_modules/donasi/component/card_view/ui_card_donatur";
import { donasi_funGetListDonaturById } from "@/app_modules/donasi/fun/get/get_list_donatur";
import { MODEL_DONASI_INVOICE } from "@/app_modules/donasi/model/interface";
import { Center, Grid, Group, Paper, Stack, Text, Title } from "@mantine/core";
import { IconMoodSmileBeam } from "@tabler/icons-react";
import { Box, Center } from "@mantine/core";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react";
export default function DonaturDonasi({
listDonatur,
donasiId,
}: {
listDonatur: MODEL_DONASI_INVOICE[];
donasiId: string;
}) {
const [donatur, setDonatur] = useState(listDonatur);
if (_.isEmpty(donatur)) return <ComponentDonasi_IsEmptyData />;
const [data, setData] = useState(listDonatur);
const [activePage, setActivePage] = useState(1);
return (
<>
{donatur.map((e, i) => (
<Paper
key={i}
style={{
backgroundColor: AccentColor.blue,
border: `2px solid ${AccentColor.darkblue}`,
padding: "15px",
cursor: "pointer",
borderRadius: "10px",
color: "white",
marginBottom: "10px",
}}
>
<Grid>
<Grid.Col span={3}>
<Center h={"100%"}>
{/* <Avatar variant="filled" radius={"xl"} size={"md"} /> */}
<IconMoodSmileBeam size={50} />
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
<Box>
<ScrollOnly
height="92vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
</Grid.Col>
<Grid.Col span={9}>
<Stack spacing={0}>
<Title order={5}>{e.Author.username}</Title>
<Group spacing={"xs"}>
<Text fz={"xs"}>Berdonasi sebesar</Text>
<Text truncate fw={"bold"}>
<TampilanRupiahDonasi nominal={+e.nominal} />
</Text>
</Group>
<Text fz={"xs"}>
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "full",
}).format(e?.createdAt)}
</Text>
</Stack>
</Grid.Col>
</Grid>
</Paper>
))}
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await donasi_funGetListDonaturById({
page: activePage + 1,
donasiId: donasiId,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => <ComponentDonasi_CardDonatur data={item} />}
</ScrollOnly>
</Box>
)}
</>
);
}

View File

@@ -2,32 +2,62 @@
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import ComponentDonasi_ListKabar from "@/app_modules/donasi/component/detail_main/list_kabar";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { ComponentDonasi_CardDonatur } from "@/app_modules/donasi/component/card_view/ui_card_donatur";
import ComponentDonasi_ListKabar from "@/app_modules/donasi/component/card_view/ui_card_kabar";
import { donasi_funGetListDonaturById } from "@/app_modules/donasi/fun/get/get_list_donatur";
import { donasi_funGetListKabarById } from "@/app_modules/donasi/fun/get/get_list_kabar";
import { MODEL_DONASI_KABAR } from "@/app_modules/donasi/model/interface";
import { Box } from "@mantine/core";
import { Box, Center } from "@mantine/core";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react";
export default function KabarDonasi({
listKabar,
donasiId,
}: {
listKabar: MODEL_DONASI_KABAR[];
donasiId: string;
}) {
const [kabar, setKabar] = useState(listKabar);
if (_.isEmpty(kabar)) return <ComponentGlobal_IsEmptyData />;
const [data, setData] = useState(listKabar);
const [activePage, setActivePage] = useState(1);
return (
<>
{kabar.map((e, i) => (
<Box key={i}>
<ComponentDonasi_ListKabar
kabar={e}
route={RouterDonasi.detail_kabar}
/>
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
<Box>
<ScrollOnly
height="92vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await donasi_funGetListKabarById({
page: activePage + 1,
donasiId: donasiId,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentDonasi_ListKabar
kabar={item}
route={RouterDonasi.detail_kabar}
/>
)}
</ScrollOnly>
</Box>
))}
)}
</>
);
}

View File

@@ -7,7 +7,8 @@ import {
} from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_BoxInformation from "@/app_modules/_global/component/box_information";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import ComponentDonasi_NotedBox from "@/app_modules/donasi/component/noted_box";
import { ComponentDonasi_InformasiPencairanDana } from "@/app_modules/donasi/component/card_view/box_informasi_pencarian_dana";
import { ComponentDonasi_BoxPencariranDana } from "@/app_modules/donasi/component/card_view/box_pencairan_dana";
import TampilanRupiahDonasi from "@/app_modules/donasi/component/tampilan_rupiah";
import {
MODEL_DONASI,
@@ -15,11 +16,9 @@ import {
} from "@/app_modules/donasi/model/interface";
import {
AspectRatio,
Avatar,
Button,
Center,
Grid,
Group,
Image,
Modal,
Paper,
@@ -29,16 +28,18 @@ import {
Title,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { IconImageInPicture, IconTransferIn } from "@tabler/icons-react";
import { IconImageInPicture } from "@tabler/icons-react";
import _ from "lodash";
import moment from "moment";
import { useRouter } from "next/navigation";
import { useState } from "react";
export default function PencairanDanaDonasi({
donasiId,
totalAkumulasi,
listPencairan,
}: {
donasiId: string;
totalAkumulasi: MODEL_DONASI;
listPencairan: MODEL_DONASI_PENCAIRAN_DANA[];
}) {
@@ -47,119 +48,9 @@ export default function PencairanDanaDonasi({
return (
<>
<Stack>
<BoxDanaDicarikan akumulasi={akumulasi} />
<InformasiPencairanDana listPD={listPD} />
<ComponentDonasi_BoxPencariranDana akumulasi={akumulasi} />
<ComponentDonasi_InformasiPencairanDana donasiId={donasiId} listPD={listPD} />
</Stack>
</>
);
}
function BoxDanaDicarikan({ akumulasi }: { akumulasi: MODEL_DONASI }) {
return (
<>
<Paper
style={{
backgroundColor: MainColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
padding: "15px",
cursor: "pointer",
borderRadius: "10px",
color: "white",
marginBottom: "10px",
}}
>
<Stack>
<Grid>
<Grid.Col span={6}>
<Title order={5}>
<TampilanRupiahDonasi nominal={akumulasi.totalPencairan} />
</Title>
<Text fz={"xs"}>Dana sudah dicairkan</Text>
</Grid.Col>
<Grid.Col span={6}>
<Title order={5}>{akumulasi.akumulasiPencairan} kali</Title>
<Text fz={"xs"}>Pencairan dana</Text>
</Grid.Col>
</Grid>
<ComponentGlobal_BoxInformation
informasi=" Pencairan dana akan dilakukan oleh Admin HIPMI tanpa campur tangan
pihak manapun, jika berita pencairan dana dibawah tidak sesuai
dengan kabar yang diberikan oleh PENGGALANG DANA. Maka pegguna lain
dapat melaporkannya pada Admin HIPMI !"
/>
</Stack>
</Paper>
</>
);
}
function InformasiPencairanDana({
listPD,
}: {
listPD: MODEL_DONASI_PENCAIRAN_DANA[];
}) {
const router = useRouter();
const [opened, { open, close }] = useDisclosure(false);
const [idGambar, setIdGambar] = useState("");
return (
<>
<Modal opened={opened} onClose={close} size={"xl"}>
<AspectRatio ratio={9 / 16}>
<Paper>
<Image
alt="Foto"
src={RouterDonasi.api_gambar_pencairan + `${idGambar}`}
/>
</Paper>
</AspectRatio>
</Modal>
{_.isEmpty(listPD) ? (
<ComponentGlobal_IsEmptyData height={20} />
) : (
listPD.map((e, i) => (
<Paper
key={i}
style={{
padding: "15px",
border: `2px solid ${AccentColor.blue}`,
backgroundColor: AccentColor.darkblue,
borderRadius: "10px",
color: "white",
}}
>
<Text fz={"xs"}>{moment(e.createdAt).format("ll")}</Text>
<Stack spacing={"lg"}>
<Title order={5}>{e.title}</Title>
<Spoiler
maxHeight={50}
hideLabel="Sembunyikan"
showLabel="Baca Selengkapnya"
>
{e.deskripsi}
</Spoiler>
<Center>
<Button
radius={"xl"}
leftIcon={<IconImageInPicture />}
onClick={() => {
// open();
// setIdGambar(e.imagesId);
router.push(`/dev/donasi/bukti-transfer/${e.imagesId}`, {
scroll: false,
});
}}
bg={MainColor.yellow}
color="yellow"
c={"black"}
>
Bukti Transfer
</Button>
</Center>
</Stack>
</Paper>
))
)}
</>
);
}

View File

@@ -3,7 +3,7 @@
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import { AccentColor, MainColor } from "@/app_modules/_global/color/color_pallet";
import ComponentDonasi_CardPublish from "@/app_modules/donasi/component/card_view/box_publish";
import ComponentDonasi_CardPublish from "@/app_modules/donasi/component/card_view/card_publish";
import TampilanRupiahDonasi from "@/app_modules/donasi/component/tampilan_rupiah";
import {
MODEL_DONASI,

View File

@@ -1,30 +1,20 @@
"use client";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import {
ActionIcon,
Avatar,
Box,
Button,
Group,
Paper,
SimpleGrid,
Stack,
Text,
Title,
} from "@mantine/core";
import {
IconCirclePlus,
IconEdit,
IconEditCircle,
IconTrash,
} from "@tabler/icons-react";
import moment from "moment";
import { useRouter } from "next/navigation";
import { MODEL_DONASI_KABAR } from "../../model/interface";
import { useState } from "react";
import ComponentDonasi_ListKabar from "../../component/detail_main/list_kabar";
import { MainColor } from "@/app_modules/_global/color/color_pallet";
import { Box, Button, Center, Stack } from "@mantine/core";
import { IconCirclePlus } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import ComponentDonasi_ListKabar from "../../component/card_view/ui_card_kabar";
import { MODEL_DONASI_KABAR } from "../../model/interface";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader";
import { ComponentDonasi_CardDonatur } from "../../component/card_view/ui_card_donatur";
import { donasi_funGetListDonaturById } from "../../fun/get/get_list_donatur";
import { donasi_funGetListKabarById } from "../../fun/get/get_list_kabar";
export default function ListKabarDonasi({
donasiId,
@@ -34,8 +24,10 @@ export default function ListKabarDonasi({
listKabar: MODEL_DONASI_KABAR[];
}) {
const router = useRouter();
const [kabar, setKabar] = useState(listKabar);
const [data, setData] = useState(listKabar);
const [activePage, setActivePage] = useState(1);
const [isLoading, setIsLoading] = useState(false);
return (
<>
<Stack>
@@ -54,14 +46,40 @@ export default function ListKabarDonasi({
>
Tambah Kabar
</Button>
{kabar.map((e, i) => (
<Box key={i}>
<ComponentDonasi_ListKabar
kabar={e}
route={RouterDonasi.update_kabar}
/>
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
<Box>
<ScrollOnly
height="85vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await donasi_funGetListKabarById({
page: activePage + 1,
donasiId: donasiId,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentDonasi_ListKabar
kabar={item}
route={RouterDonasi.update_kabar}
/>
)}
</ScrollOnly>
</Box>
))}
)}
</Stack>
</>
);

View File

@@ -1,12 +1,22 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export async function donasi_funGetAllInvoiceByAuthorId({
page,
}: {
page: number;
}) {
const authorId = await user_getOneUserId();
const takeData = 5;
const skipData = page * takeData - takeData;
export async function Donasi_getInvoiceByAuthorId(authorId: string) {
// console.log(authorId)
const data = await prisma.donasi_Invoice.findMany({
take: takeData,
skip: skipData,
orderBy: {
createdAt: "desc"
createdAt: "desc",
},
where: {
authorId: authorId,

View File

@@ -3,13 +3,19 @@
import prisma from "@/app/lib/prisma";
import { tree } from "next/dist/build/templates/app-page";
export async function Donasi_getListBeranda() {
export async function donasi_funGetAllPublish({ page }: { page: number }) {
const takeData = 5;
const skipData = page * takeData - takeData;
const data = await prisma.donasi.findMany({
take: takeData,
skip: skipData,
orderBy: {
publishTime: "desc",
},
where: {
donasiMaster_StatusDonasiId: "1",
active: true,
},
select: {
id: true,

View File

@@ -2,8 +2,19 @@
import prisma from "@/app/lib/prisma";
export async function Donasi_getListDonatur(donasiId: string) {
export async function donasi_funGetListDonaturById({
page,
donasiId,
}: {
page: number,
donasiId: string;
}) {
const takeData = 10
const skipData = page * takeData - takeData
const data = await prisma.donasi_Invoice.findMany({
take: takeData,
skip: skipData,
orderBy: {
createdAt: "desc",
},

View File

@@ -2,14 +2,24 @@
import prisma from "@/app/lib/prisma";
export async function Donasi_getListKabar(donasiId: string) {
// console.log(donasiId)
export async function donasi_funGetListKabarById({
page,
donasiId,
}: {
page: number;
donasiId: string;
}) {
const takeData = 10;
const skipData = page * takeData - takeData;
const data = await prisma.donasi_Kabar.findMany({
take: takeData,
skip: skipData,
orderBy: {
createdAt: "desc",
},
where: {
donasiId: donasiId,
active: true,
},
select: {
id: true,

View File

@@ -1,17 +1,26 @@
"use server"
"use server";
import prisma from "@/app/lib/prisma"
import prisma from "@/app/lib/prisma";
export async function Donasi_getListPencairanDanaById(donasiId:string) {
export async function donasi_funGetListPencairanDanaById({
page,
donasiId,
}: {
page: number;
donasiId: string;
}) {
const takeData = 5;
const skipData = page * takeData - takeData;
const data = await prisma.donasi_PencairanDana.findMany({
take: takeData,
skip: skipData,
orderBy: {
createdAt: "desc",
},
where: {
donasiId: donasiId,
},
});
const data = await prisma.donasi_PencairanDana.findMany({
orderBy:{
createdAt: "desc"
},
where: {
donasiId: donasiId
}
})
return data
}
return data;
}

View File

@@ -0,0 +1,24 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export async function donasi_funGetAllStatusDraft({ page }: { page: number }) {
const authorId = await user_getOneUserId();
const takeData = 5;
const skipData = page * takeData - takeData;
const data = await prisma.donasi.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
authorId: authorId,
donasiMaster_StatusDonasiId: "3",
},
});
return data;
}

View File

@@ -0,0 +1,35 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export async function donasi_funGetAllStatusPublish({ page }: { page: number }) {
const authorId = await user_getOneUserId();
const takeData = 5;
const skipData = page * takeData - takeData;
const data = await prisma.donasi.findMany({
take: takeData,
skip: skipData,
orderBy: {
publishTime: "desc",
},
where: {
authorId: authorId,
donasiMaster_StatusDonasiId: "1",
active: true,
},
select: {
id: true,
title: true,
imagesId: true,
target: true,
progres: true,
publishTime: true,
DonasiMaster_Durasi: true,
terkumpul: true,
},
});
return data;
}

View File

@@ -0,0 +1,24 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export async function donasi_funGetAllStatusReject({ page }: { page: number }) {
const authorId = await user_getOneUserId();
const takeData = 5;
const skipData = page * takeData - takeData;
const data = await prisma.donasi.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
authorId: authorId,
donasiMaster_StatusDonasiId: "4",
},
});
return data;
}

View File

@@ -0,0 +1,24 @@
"use server"
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export async function donasi_funGetAllStatusReview({page}: {page: number}) {
const authorId = await user_getOneUserId();
const takeData = 5;
const skipData = page * takeData - takeData;
const data = await prisma.donasi.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
authorId: authorId,
donasiMaster_StatusDonasiId: "2",
},
});
return data;
}

View File

@@ -1,16 +1,19 @@
"use client";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import { ActionIcon, Affix, Box, rem } from "@mantine/core";
import { ActionIcon, Affix, Box, Center, rem } from "@mantine/core";
import { useWindowScroll } from "@mantine/hooks";
import { IconPencilPlus } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import ComponentDonasi_CardPublish from "../component/card_view/box_publish";
import ComponentDonasi_CardPublish from "../component/card_view/card_publish";
import { MODEL_DONASI } from "../model/interface";
import ComponentGlobal_CreateButton from "@/app_modules/_global/component/button_create";
import _ from "lodash";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { ScrollOnly } from "next-scroll-loader";
import { donasi_funGetAllPublish } from "../fun/get/get_list_beranda";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
export default function MainDonasi({
listDonasi,
@@ -18,6 +21,7 @@ export default function MainDonasi({
listDonasi: MODEL_DONASI[];
}) {
const [data, setData] = useState(listDonasi);
const [activePage, setActivePage] = useState(1);
return (
<>
@@ -26,14 +30,32 @@ export default function MainDonasi({
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
data.map((e, i) => (
<Box key={i}>
<ScrollOnly
height="82vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await donasi_funGetAllPublish({
page: activePage + 1,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentDonasi_CardPublish
data={e as any}
data={item as any}
path={RouterDonasi.detail_main}
/>
</Box>
))
)}
</ScrollOnly>
)}
</Box>
</>

View File

@@ -7,6 +7,7 @@ import {
AspectRatio,
Badge,
Box,
Center,
Grid,
Group,
Image,
@@ -25,105 +26,56 @@ import toast from "react-simple-toasts";
import ComponentDonasi_TampilanHitungMundur from "../component/tampilan_hitung_mundur";
import TampilanRupiahDonasi from "../component/tampilan_rupiah";
import { MODEL_DONASI_INVOICE } from "../model/interface";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { ScrollOnly } from "next-scroll-loader";
import ComponentDonasi_CardPublish from "../component/card_view/card_publish";
import { donasi_funGetAllPublish } from "../fun/get/get_list_beranda";
import { donasi_funGetAllInvoiceByAuthorId } from "../fun/get/get_all_invoice_by_author_id";
import { ComponentDonasi_CardInvoice } from "../component/card_view/card_invoice";
export default function DonasiSayaDonasi({
listInvoice,
}: {
listInvoice: MODEL_DONASI_INVOICE[];
}) {
const [invoice, setInvoice] = useState(listInvoice);
const router = useRouter();
const { height, width } = useViewportSize();
if (_.isEmpty(listInvoice))
return <ComponentGlobal_IsEmptyData />;
const [data, setData] = useState(listInvoice);
const [activePage, setActivePage] = useState(1);
return (
<>
{invoice.map((e, i) => (
<Box
style={{
backgroundColor: AccentColor.blue,
border: `2px solid ${AccentColor.darkblue}`,
padding: "15px",
cursor: "pointer",
borderRadius: "10px",
color: "white",
marginBottom: "15px",
}}
key={i}
onClick={() =>
onClick(router, e.donasiMaster_StatusInvoiceId, e.id, e.Donasi.id)
}
>
<Stack>
<Grid>
<Grid.Col span={5}>
<Stack spacing={5}>
<Stack spacing={0}>
<Text fz={"xs"} fw={"bold"} truncate>
{e.Donasi.title}
</Text>
<ComponentDonasi_TampilanHitungMundur
durasi={e.Donasi.DonasiMaster_Durasi.name}
publishTime={e.Donasi.publishTime}
textSize={10}
/>
</Stack>
<Progress value={+e.Donasi.progres} color="orange" />
<Group position="apart">
<Stack spacing={0}>
<Text fz={10}>Donasi Saya</Text>
<Text fz={10} fw={"bold"} c={"orange"} truncate>
<TampilanRupiahDonasi nominal={+e.nominal} />
</Text>
</Stack>
</Group>
<Badge size="xs" variant="filled" color="yellow">
<Text>{e.DonasiMaster_StatusInvoice.name}</Text>
</Badge>
</Stack>
</Grid.Col>
<Grid.Col span={7}>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image
alt="Foto"
src={RouterDonasi.api_gambar + `${e.Donasi.imagesId}`}
radius={"md"}
/>
</Paper>
</AspectRatio>
</Grid.Col>
</Grid>
{/* {width > 575 ? "" : <Divider />} */}
</Stack>
</Box>
))}
</>
);
}
<Box>
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
<ScrollOnly
height="82vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await donasi_funGetAllInvoiceByAuthorId({
page: activePage + 1,
});
function HitungMundur({
durasi,
publishTime,
}: {
durasi: string;
publishTime: Date;
}) {
return (
<>
<Stack spacing={0} align="center">
<Text fz={"xs"}>Sisa hari </Text>
<Text span inherit fw={"bold"} fz={"xs"}>
{Number(durasi) -
moment(new Date()).diff(new Date(publishTime), "days") <=
0
? 0
: Number(durasi) -
moment(new Date()).diff(new Date(publishTime), "days")}
</Text>
</Stack>
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentDonasi_CardInvoice
data={item as any}
/>
)}
</ScrollOnly>
)}
</Box>
</>
);
}
@@ -143,7 +95,7 @@ async function onClick(
if (status === "3") {
return router.push(RouterDonasi.invoice + `${invoiceId}`);
} else {
toast("gagal");
ComponentGlobal_NotifikasiGagal("Gagal Melihat Invoice");
}
}
}

View File

@@ -1,12 +1,14 @@
"use client";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import {
Box
} from "@mantine/core";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { Box, Center } from "@mantine/core";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react";
import { ComponentDonasi_CardStatus } from "../../component/card_view/card_status";
import { donasi_funGetAllStatusDraft } from "../../fun/get/status/get_all_status_draft";
import { MODEL_DONASI } from "../../model/interface";
export default function PostingDraftDonasi({
@@ -14,18 +16,51 @@ export default function PostingDraftDonasi({
}: {
listDraft: MODEL_DONASI[];
}) {
if (_.isEmpty(listDraft)) return <ComponentGlobal_IsEmptyData />;
const [data, setData] = useState(listDraft);
const [activePage, setActivePage] = useState(1);
return (
<>
{listDraft.map((e, i) => (
{/* {listDraft.map((e, i) => (
<Box key={i}>
<ComponentDonasi_CardStatus
data={e}
path={RouterDonasi.detail_draft}
/>
</Box>
))}
))} */}
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
<Box>
<ScrollOnly
height="75vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await donasi_funGetAllStatusDraft({
page: activePage + 1,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentDonasi_CardStatus
data={item}
path={RouterDonasi.detail_draft}
/>
)}
</ScrollOnly>
</Box>
)}
</>
);
}

View File

@@ -1,12 +1,15 @@
"use client";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import ComponentDonasi_CardPublish from "../../component/card_view/box_publish";
import { MODEL_DONASI } from "../../model/interface";
import { useState } from "react";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { Box, Center } from "@mantine/core";
import _ from "lodash";
import { Box } from "@mantine/core";
import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react";
import ComponentDonasi_CardPublish from "../../component/card_view/card_publish";
import { donasi_funGetAllStatusPublish } from "../../fun/get/status/get_all_status_publish";
import { MODEL_DONASI } from "../../model/interface";
export default function PostingPublishDonasi({
listPublish,
@@ -14,27 +17,42 @@ export default function PostingPublishDonasi({
listPublish: MODEL_DONASI[];
}) {
const [data, setData] = useState(listPublish);
const [activePage, setActivePage] = useState(1);
return (
<>
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
data.map((e, i) => (
<Box key={i}>
<ComponentDonasi_CardPublish
data={e}
path={RouterDonasi.detail_publish}
/>
</Box>
))
<Box >
<ScrollOnly
height="75vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await donasi_funGetAllStatusPublish({
page: activePage + 1,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentDonasi_CardPublish
data={item}
path={RouterDonasi.detail_publish}
/>
)}
</ScrollOnly>
</Box>
)}
</>
);
// return (
// <>
// <ComponentDonasi_CardPublish dataDonasi={listPublish} path={RouterDonasi.detail_publish} />
// </>
// );
}

View File

@@ -1,24 +1,15 @@
"use client";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import {
AspectRatio,
Box,
Divider,
Grid,
Image,
Paper,
SimpleGrid,
Stack,
Text,
} from "@mantine/core";
import { useViewportSize } from "@mantine/hooks";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { Box, Center } from "@mantine/core";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react";
import ComponentDonasi_IsEmptyData from "../../component/is_empty_data";
import { MODEL_DONASI } from "../../model/interface";
import { ComponentDonasi_CardStatus } from "../../component/card_view/card_status";
import { donasi_funGetAllStatusReject } from "../../fun/get/status/get_all_status_reject";
import { MODEL_DONASI } from "../../model/interface";
export default function PostingRejectDonasi({
listReject,
@@ -26,73 +17,42 @@ export default function PostingRejectDonasi({
listReject: MODEL_DONASI[];
}) {
const [data, setData] = useState(listReject);
const [activePage, setActivePage] = useState(1);
return (
<>
{data.map((e, i) => (
<Box key={i}>
<ComponentDonasi_CardStatus
data={e}
path={RouterDonasi.detail_reject}
/>
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
<Box>
<ScrollOnly
height="75vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await donasi_funGetAllStatusReject({
page: activePage + 1,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentDonasi_CardStatus
data={item}
path={RouterDonasi.detail_reject}
/>
)}
</ScrollOnly>
</Box>
))}
)}
</>
);
// if (_.isEmpty(listReject))
// return <ComponentDonasi_IsEmptyData text="Tidak ada data" />;
// return (
// <>
// <SimpleGrid
// cols={4}
// spacing="lg"
// breakpoints={[
// { maxWidth: "62rem", cols: 3, spacing: "md" },
// { maxWidth: "48rem", cols: 2, spacing: "sm" },
// { maxWidth: "36rem", cols: 1, spacing: "sm" },
// ]}
// >
// {donasi.map((e, i) => (
// <Box
// key={i}
// onClick={() => router.push(RouterDonasi.detail_reject + `${e.id}`)}
// >
// <Stack>
// <Grid>
// <Grid.Col span={7}>
// <AspectRatio ratio={16 / 9}>
// <Paper radius={"md"}>
// <Image
// alt="Foto"
// src={RouterDonasi.api_gambar + `${e.imagesId}`}
// radius={"md"}
// />
// </Paper>
// </AspectRatio>
// </Grid.Col>
// <Grid.Col span={5}>
// <Stack spacing={"xs"}>
// <Text fz={"sm"} fw={"bold"} lineClamp={2}>
// {e.title}
// </Text>
// <Stack spacing={0}>
// <Text fz={"sm"} fw={"bold"}>
// Alasan ditolak
// </Text>
// <Text fz={"sm"} lineClamp={2}>
// {e.catatan}
// </Text>
// </Stack>
// </Stack>
// </Grid.Col>
// </Grid>
// {width > 575 ? "" : <Divider />}
// </Stack>
// </Box>
// ))}
// </SimpleGrid>
// </>
// );
}

View File

@@ -1,29 +1,58 @@
"use client";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import { Box } from "@mantine/core";
import { Box, Center } from "@mantine/core";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import _ from "lodash";
import { ComponentDonasi_CardStatus } from "../../component/card_view/card_status";
import { MODEL_DONASI } from "../../model/interface";
import { donasi_funGetAllStatusReview } from "../../fun/get/status/get_all_status_review";
import { ScrollOnly } from "next-scroll-loader";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { useState } from "react";
export default function PostingReviewDonasi({
listReview,
}: {
listReview: MODEL_DONASI[];
}) {
if (_.isEmpty(listReview)) return <ComponentGlobal_IsEmptyData />;
const [data, setData] = useState(listReview);
const [activePage, setActivePage] = useState(1);
return (
<>
{listReview.map((e, i) => (
<Box key={i}>
<ComponentDonasi_CardStatus
data={e}
path={RouterDonasi.detail_review}
/>
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
<Box>
<ScrollOnly
height="75vh"
renderLoading={() => (
<Center>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await donasi_funGetAllStatusReview({
page: activePage + 1,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentDonasi_CardStatus
data={item}
path={RouterDonasi.detail_review}
/>
)}
</ScrollOnly>
</Box>
))}
)}
</>
);
}

View File

@@ -75,7 +75,7 @@ export default function GalangDanaDonasi({
},
}}
>
<Stack>
<Stack >
<Tabs.List grow>
{listPosting.map((e, i) => (
<Tabs.Tab
@@ -98,7 +98,7 @@ export default function GalangDanaDonasi({
))}
</Tabs.List>
{listPosting.map((e, i) => (
<Tabs.Panel key={e.id} value={e.value} pt="xs">
<Tabs.Panel key={e.id} value={e.value} >
{e.path}
</Tabs.Panel>
))}

View File

@@ -5,9 +5,14 @@ import { Card, Group, Stack, Text, Title } from "@mantine/core";
import { useRouter } from "next/navigation";
import { MODEL_EVENT } from "../../model/interface";
import { useState } from "react";
import ComponentGlobal_CardLoadingOverlay from "@/app_modules/_global/loading_card";
export function ComponentEvent_CardRiwayat({ data }: { data: MODEL_EVENT }) {
const router = useRouter();
const [eventId, setEventId] = useState("");
const [visible, setVisible] = useState(false);
return (
<>
<Card
@@ -30,7 +35,11 @@ export function ComponentEvent_CardRiwayat({ data }: { data: MODEL_EVENT }) {
</Card.Section>
<Card.Section
p={"sm"}
onClick={() => router.push(RouterEvent.detail_riwayat + data.id)}
onClick={() => {
setVisible(true);
setEventId(data?.id);
router.push(RouterEvent.detail_riwayat + data.id);
}}
>
<Stack>
<Group w={"100%"} position="apart">
@@ -49,6 +58,11 @@ export function ComponentEvent_CardRiwayat({ data }: { data: MODEL_EVENT }) {
</Text>
</Stack>
</Card.Section>
{visible && eventId !== "" ? (
<ComponentGlobal_CardLoadingOverlay />
) : (
""
)}
</Card>
</>
);

View File

@@ -1,20 +1,9 @@
"use client";
import {
Avatar,
Center,
Divider,
Grid,
Paper,
Stack,
Text,
Title,
} from "@mantine/core";
import ComponentEvent_DetailData from "../../component/detail/detail_data";
import { MODEL_EVENT, MODEL_EVENT_PESERTA } from "../../model/interface";
import { useState } from "react";
import { Stack } from "@mantine/core";
import ComponentEvent_DetailMainData from "../../component/detail/detail_main";
import ComponentEvent_ListPeserta from "../../component/detail/list_peserta";
import { MODEL_EVENT, MODEL_EVENT_PESERTA } from "../../model/interface";
export default function Event_DetailKontribusi({
dataEvent,
@@ -27,36 +16,12 @@ export default function Event_DetailKontribusi({
}) {
return (
<>
<Stack spacing={"lg"}>
<Stack spacing={"lg"} mb={"md"}>
<ComponentEvent_DetailMainData data={dataEvent} />
<ComponentEvent_ListPeserta
listPeserta={listKontributor}
total={totalPeserta}
/>
{/* <Paper withBorder mt={"lg"} shadow="lg">
<Stack spacing={"md"} p={"md"}>
<Center>
<Title order={5}>Daftar Peserta</Title>
</Center>
{peserta
.map((e, i) => (
<Stack key={i} spacing={"sm"}>
<Grid>
<Grid.Col span={2}>
<Avatar radius={"xl"} bg={"gray"} size={"md"} />
</Grid.Col>
<Grid.Col span={"auto"}>
<Stack justify="center" h={"100%"}>
<Text>Nama peserta</Text>
</Stack>
</Grid.Col>
</Grid>
<Divider />
</Stack>
))}
</Stack>
</Paper> */}
</Stack>
</>
);

View File

@@ -0,0 +1,34 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export async function event_funGetAllStatusPublish({ page }: { page: number }) {
const authorId = await user_getOneUserId();
const takeData = 10;
const skipData = page * takeData - takeData;
const data = await prisma.event.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
active: true,
eventMaster_StatusId: "1",
authorId: authorId,
tanggal: {
gte: new Date(),
},
},
select: {
id: true,
title: true,
deskripsi: true,
tanggal: true,
},
});
return data;
}

View File

@@ -1,29 +1,19 @@
"use client";
import { RouterEvent } from "@/app/lib/router_hipmi/router_event";
import ComponentGlobal_AuthorNameOnHeader from "@/app_modules/_global/author_name_on_header";
import {
Card,
Stack,
Grid,
Title,
Text,
Center,
Box,
Loader,
Center,
Loader
} from "@mantine/core";
import moment from "moment";
import { MODEL_EVENT } from "../../model/interface";
import { useRouter } from "next/navigation";
import _ from "lodash";
import { useState } from "react";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader";
import ComponentEvent_BoxListStatus from "../../component/box_list_status";
import { event_getAllDraft } from "../../fun/get/status/get_all_draft";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { ComponentEvent_CardRiwayat } from "../../component/card_view/card_riwayat";
import { event_getListSemuaRiwayat } from "../../fun/get/riwayat/get_list_semua_riwayat";
import { MODEL_EVENT } from "../../model/interface";
export default function Event_SemuaRiwayat({
listData,

View File

@@ -15,49 +15,43 @@ export default function Event_StatusDraft({
}: {
listDraft: MODEL_EVENT[];
}) {
const [data, setData] = useState(listDraft);
const [activePage, setActivePage] = useState(1);
const [data, setData] = useState(listDraft);
const [activePage, setActivePage] = useState(1);
return (
<>
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
<Box>
<ScrollOnly
height="75vh"
renderLoading={() => (
<Center mt={"lg"}>
<Loader color={"yellow"} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await event_getAllDraft({
page: activePage + 1,
});
setActivePage((val) => val + 1);
return (
<>
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
<Box>
<ScrollOnly
height="75vh"
renderLoading={() => (
<Center mt={"lg"}>
<Loader color={"yellow"} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await event_getAllDraft({
page: activePage + 1,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentEvent_BoxListStatus
data={item}
path={RouterEvent.detail_draft}
/>
)}
</ScrollOnly>
</Box>
)}
</>
);
return loadData;
}}
>
{(item) => (
<ComponentEvent_BoxListStatus
data={item}
path={RouterEvent.detail_draft}
/>
)}
</ScrollOnly>
</Box>
)}
</>
);
}

View File

@@ -1,45 +1,58 @@
"use client";
import { RouterEvent } from "@/app/lib/router_hipmi/router_event";
import { Box, Center, Group, Paper, Stack, Text, Title } from "@mantine/core";
import moment from "moment";
import { useRouter } from "next/navigation";
import { MODEL_EVENT } from "../../model/interface";
import ComponentEvent_BoxListStatus from "../../component/box_list_status";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { Box, Center } from "@mantine/core";
import _ from "lodash";
import ComponentEvent_IsEmptyData from "../../component/is_empty_data";
import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react";
import ComponentGlobal_CardLoadingOverlay from "@/app_modules/_global/loading_card";
import ComponentEvent_BoxListStatus from "../../component/box_list_status";
import { event_funGetAllStatusPublish } from "../../fun/get/status/get_all_status_publish";
import { MODEL_EVENT } from "../../model/interface";
export default function Event_StatusPublish({
listPublish,
}: {
listPublish: MODEL_EVENT[];
}) {
const router = useRouter();
if (_.isEmpty(listPublish))
return <ComponentEvent_IsEmptyData text="Tidak ada data" />;
const [data, setData] = useState(listPublish);
const [activePage, setActivePage] = useState(1);
return (
<>
{listPublish.map((e, i) => (
<Box key={e.id}>
<Box>
<ComponentEvent_BoxListStatus
data={e}
path={RouterEvent.detail_publish}
/>
{/* {visible && e?.id === eventId ? (
<ComponentGlobal_CardLoadingOverlay />
) : (
""
)} */}
</Box>
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
<Box>
<ScrollOnly
height="75vh"
renderLoading={() => (
<Center mt={"lg"}>
<ComponentGlobal_Loader size={25} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await event_funGetAllStatusPublish({
page: activePage + 1,
});
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentEvent_BoxListStatus
data={item}
path={RouterEvent.detail_publish}
/>
)}
</ScrollOnly>
</Box>
))}
)}
</>
);
}

View File

@@ -19,6 +19,8 @@ import { useRouter } from "next/navigation";
import { MODEL_Investasi } from "../model/model_investasi";
import { useState } from "react";
import _ from "lodash";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
export default function BeritaInvestasi({
dataInvestasi,
@@ -34,17 +36,23 @@ export default function BeritaInvestasi({
berita.BeritaInvestasi.map((e) => (
<Paper
key={e.id}
mb={"md"}
w={"100%"}
bg={"gray"}
p={"sm"}
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
color: "white",
marginBottom: "15px",
}}
onClick={() =>
router.push(RouterInvestasi.detail_berita + `${e.id}`)
}
>
<Stack>
<Group position="apart">
<Title order={6}>{e.title}</Title>
<Title order={6} w={"70%"} lineClamp={1}>
{e.title}
</Title>
<Text fz={"xs"}>{moment(e.createdAt).format("LL")}</Text>
</Group>
@@ -56,7 +64,10 @@ export default function BeritaInvestasi({
</Grid.Col>
<Grid.Col span={4}>
<AspectRatio ratio={16 / 9} h={50} w={100}>
<Image alt="" src={RouterInvestasi.api_gambar + `${e.imagesId}`} />
<Image
alt=""
src={RouterInvestasi.api_gambar + `${e.imagesId}`}
/>
</AspectRatio>
</Grid.Col>
</Grid>
@@ -64,9 +75,7 @@ export default function BeritaInvestasi({
</Paper>
))
) : (
<Center>
<Title order={6}>Tidak Ada Berita</Title>
</Center>
<ComponentGlobal_IsEmptyData />
)}
</>
);

View File

@@ -64,7 +64,7 @@ export function ComponentInvestasi_DetailDataNonPublish({
{/* Title dan Persentase */}
<Center>
<Title order={4} align="center">
<Title order={3} align="center">
{_.startCase(data.title)}
</Title>
</Center>
@@ -129,8 +129,8 @@ export function ComponentInvestasi_DetailDataNonPublish({
{listBox.map((e) => (
<Center key={e.id}>
<Paper
w={100}
style={{
width: 100,
padding: "15px",
backgroundColor: AccentColor.blue,
border: `2px solid ${AccentColor.softblue}`,

View File

@@ -30,13 +30,15 @@ import { useRouter } from "next/navigation";
import { useState } from "react";
import toast from "react-simple-toasts";
import { funCreateInvestasi } from "../fun/fun_create_investasi";
import { gs_StatusPortoInvestasi, gs_investasiFooter } from "../g_state";
import { gs_investasi_status, gs_investas_menu } from "../g_state";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import mqtt_client from "@/util/mqtt_client";
import notifikasiToAdmin_funCreate from "@/app_modules/notifikasi/fun/create/create_notif_to_admin";
export default function InvestasiCreate({
id,
@@ -55,8 +57,8 @@ export default function InvestasiCreate({
const [pdf, setPdf] = useState<File | null>(null);
const [filePdf, setFilePdf] = useState<any | null>(null);
const [changeColor, setChangeColor] = useAtom(gs_investasiFooter);
const [activeTab, setActiveTab] = useAtom(gs_StatusPortoInvestasi);
const [changeColor, setChangeColor] = useAtom(gs_investas_menu);
const [activeTab, setActiveTab] = useAtom(gs_investasi_status);
const [totalLembar, setTotalLembar] = useState(0);
const [isLoading, setLoading] = useState(false);
@@ -93,19 +95,39 @@ export default function InvestasiCreate({
gmbr.append("file", fl as any);
const flPdf = new FormData();
flPdf.append("file", fl as any);
flPdf.append("file", pdf as any);
await funCreateInvestasi(gmbr, flPdf, body as any).then((res) => {
if (res.status === 201) {
const res = await funCreateInvestasi(gmbr, flPdf, body as any);
if (res.status === 201) {
const dataNotif = {
appId: res.data?.id,
status: res.data?.MasterStatusInvestasi?.name,
userId: res.data?.authorId,
pesan: res.data?.title,
kategoriApp: "INVESTASI",
title: "Investasi baru",
};
const notif = await notifikasiToAdmin_funCreate({
data: dataNotif as any,
});
if (notif.status === 201) {
mqtt_client.publish(
"ADMIN",
JSON.stringify({
count: 1,
})
);
setChangeColor(1);
setActiveTab("Review");
setLoading(true);
ComponentGlobal_NotifikasiBerhasil(res.message)
ComponentGlobal_NotifikasiBerhasil(res.message);
router.push(RouterInvestasi.portofolio);
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
});
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
}
async function onTotalLembar({
@@ -115,11 +137,6 @@ export default function InvestasiCreate({
target: number;
harga: number;
}) {
// console.log(target, "ini target");
// console.log(harga, "ini harga");
// if (harga === +"Nan") setTotalLembar(0);
const hasil: any = target / harga;
setTotalLembar(_.floor(hasil === Infinity ? 0 : hasil));
}
@@ -206,7 +223,7 @@ export default function InvestasiCreate({
backgroundColor: "gray.1",
padding: "10px",
borderRadius: "10px",
color: "gray"
color: "gray",
}}
>
<Text>Upload File Prospektus</Text>
@@ -227,7 +244,7 @@ export default function InvestasiCreate({
)}
{/* {JSON.stringify(filePdf)} */}
<FileButton
accept="application/pdf"
accept={"application/pdf"}
onChange={async (files: any) => {
try {
const buffer = URL.createObjectURL(

View File

@@ -8,7 +8,9 @@ import {
FileButton,
Group,
Image,
Paper,
Stack,
Text,
TextInput,
Textarea,
Title,
@@ -19,10 +21,11 @@ import { useRouter } from "next/navigation";
import { useState } from "react";
import toast from "react-simple-toasts";
import funCreateBeritaInvestasi from "../fun/fun_create_berita";
import { MainColor } from "@/app_modules/_global/color/color_pallet";
import { AccentColor, MainColor } from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
export default function CreateBeritaInvestasi({
idInves,
@@ -61,19 +64,35 @@ export default function CreateBeritaInvestasi({
return (
<>
<Stack px={"xl"}>
<AspectRatio ratio={1 / 1} mx={"sm"} mah={300}>
{img ? (
<Image alt="" src={img} radius={"sm"} height={300} width={"100%"} />
) : (
<Image
alt=""
src={"/aset/no-img.png"}
radius={"sm"}
height={300}
width={"100%"}
/>
)}
</AspectRatio>
{img ? (
<AspectRatio ratio={1 / 1} mah={300}>
<Paper
style={{
border: `2px solid ${AccentColor.softblue}`,
backgroundColor: AccentColor.blue,
padding: "10px",
borderRadius: "10px",
}}
>
<Image
alt="Foto"
src={img ? img : "/aset/no-img.png"}
maw={200}
/>
</Paper>
</AspectRatio>
) : (
<Center>
<Paper h={300} w={200} withBorder shadow="lg" bg={"gray.1"}>
<Stack justify="center" align="center" h={"100%"}>
<IconUpload color="gray" />
<Text fz={10} fs={"italic"} c={"gray"} fw={"bold"}>
Upload Gambar
</Text>
</Stack>
</Paper>
</Center>
)}
<Group position="center" mt={"md"}>
<FileButton
onChange={async (files: any) => {
@@ -101,6 +120,7 @@ export default function CreateBeritaInvestasi({
</Group>
<TextInput
withAsterisk
placeholder="Masukan judul berita"
styles={{
label: {
color: "white",
@@ -115,24 +135,33 @@ export default function CreateBeritaInvestasi({
}}
/>
<Textarea
withAsterisk
styles={{
label: {
color: "white",
},
}}
label="Deskripsi"
autosize
minRows={2}
maxRows={6}
onChange={(val) => {
setValue({
...value,
deskripsi: val.target.value,
});
}}
/>
<Stack spacing={5}>
<Textarea
withAsterisk
placeholder="Masukan deskripsi berita"
styles={{
label: {
color: "white",
},
}}
label="Deskripsi"
autosize
maxLength={300}
minRows={2}
maxRows={6}
onChange={(val) => {
setValue({
...value,
deskripsi: val.target.value,
});
}}
/>
<ComponentGlobal_InputCountDown
lengthInput={value.deskripsi.length}
maxInput={300}
/>
</Stack>
<Button
radius={50}
bg={MainColor.yellow}
@@ -145,7 +174,6 @@ export default function CreateBeritaInvestasi({
Simpan
</Button>
</Stack>
</>
);
}

View File

@@ -16,9 +16,10 @@ import {
Image,
Paper,
Progress,
SimpleGrid,
Stack,
Text,
Title
Title,
} from "@mantine/core";
import {
IconBookDownload,
@@ -33,7 +34,10 @@ import { useRouter } from "next/navigation";
import { useState } from "react";
import { gs_TransferValue } from "../g_state";
import { MODEL_Investasi } from "../model/model_investasi";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
export default function DetailInvestasi({
dataInvestasi,
@@ -54,24 +58,25 @@ export default function DetailInvestasi({
const [transaksiValue, setTransaksiValue] = useAtom(gs_TransferValue);
const [boxId, setBoxId] = useState(0);
const [isLoadingBox, setLoadingBox] = useState(false);
const [isLoadingButton, setLoadingButton] = useState(false);
const listBox = [
{
id: 1,
name: "Prospektus",
icon: <IconBookDownload size={70} />,
icon: <IconBookDownload size={70} color="white" />,
route: RouterInvestasi.detail_prospektus,
},
{
id: 2,
name: "Dokumen",
icon: <IconFileDescription size={70} />,
icon: <IconFileDescription size={70} color="white" />,
route: RouterInvestasi.detail_dokumen,
},
{
id: 3,
name: "Berita",
icon: <IconSpeakerphone size={70} />,
icon: <IconSpeakerphone size={70} color="white" />,
route: RouterInvestasi.berita,
},
];
@@ -85,6 +90,7 @@ export default function DetailInvestasi({
nomorRekening: "",
totalTransfer: "",
});
setLoadingButton(true);
}
return (
@@ -161,12 +167,12 @@ export default function DetailInvestasi({
)}
</Group>
<AspectRatio ratio={1 / 1} mx={"sm"} mah={300}>
<AspectRatio ratio={1 / 1} mx={"sm"} mah={250}>
<Image
alt=""
src={RouterInvestasi.api_gambar + `${investasi.imagesId}`}
radius={"sm"}
height={300}
height={250}
width={"100%"}
/>
</AspectRatio>
@@ -268,67 +274,73 @@ export default function DetailInvestasi({
</Grid>
{/* List Box */}
<Grid mb={"md"}>
<Group position="apart" px={"lg"}>
{listBox.map((e, i) => (
<Grid.Col
span={"auto"}
key={e?.id}
onClick={() => {
setBoxId(e?.id);
setLoadingBox(true);
router.push(e.route + `${investasi.id}`);
<Paper
key={i}
style={{
padding: "15px",
backgroundColor: AccentColor.blue,
border: `2px solid ${AccentColor.softblue}`,
borderRadius: "10px",
color: "white",
}}
>
<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
radius={"xl"}
loading={isLoadingBox && e?.id === boxId ? true : false}
variant="transparent"
size={60}
>
{e.icon}
</ActionIcon>
</Flex>
</Paper>
</Grid.Col>
))}
</Grid>
{investasi.sisaLembar === "0" ||
Number(investasi.MasterPencarianInvestor.name) -
moment(new Date()).diff(new Date(investasi.countDown), "days") <=
0 ? (
<Center mb={"md"}>
<Button disabled radius={50} w={350} variant="transparent">
Investasi Telah Ditutup
</Button>
</Center>
) : (
<Box>
{loginUserId === investasi.authorId ? (
<Center mb={"md"}>
<Button disabled radius={50} w={350}>
Investasi Ini Milik Anda
</Button>
</Center>
) : (
<Center mb={"md"}>
<Button
radius={50}
w={350}
bg={Warna.biru}
onClick={() => {
onSubmit();
}}
<Flex direction={"column"} align={"center"} justify={"center"}>
<Text fz={12}>{e.name}</Text>
<ActionIcon
radius={"xl"}
loading={isLoadingBox && e?.id === boxId ? true : false}
variant="transparent"
size={60}
onClick={() => router.push(e.route + `${investasi.id}`)}
>
Beli Saham
</Button>
</Center>
)}
</Box>
)}
{e.icon}
</ActionIcon>
</Flex>
</Paper>
))}
</Group>
<Box my={"md"}>
{investasi.sisaLembar === "0" ||
Number(investasi.MasterPencarianInvestor.name) -
moment(new Date()).diff(new Date(investasi.countDown), "days") <=
0 ? (
<Center mb={"md"}>
<Button disabled radius={50} variant="transparent">
Investasi Telah Ditutup
</Button>
</Center>
) : (
<Box>
{loginUserId === investasi.authorId ? (
<Center mb={"md"}>
<Button disabled radius={50}>
Investasi Ini Milik Anda
</Button>
</Center>
) : (
<Center mb={"md"}>
<Button
loaderPosition="center"
loading={isLoadingButton}
w={"100%"}
radius={50}
bg={MainColor.yellow}
color="yellow"
c={"black"}
onClick={() => {
onSubmit();
}}
>
Beli Saham
</Button>
</Center>
)}
</Box>
)}
</Box>
</Stack>
</>
);

View File

@@ -2,6 +2,8 @@
import AppComponentGlobal_LayoutTamplate from "@/app_modules/_global/component_layout_tamplate";
import ComponentGlobal_HeaderTamplate from "@/app_modules/_global/header_tamplate";
import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_tamplate";
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate";
import { AppShell } from "@mantine/core";
import React from "react";
@@ -12,9 +14,9 @@ export default function LayoutDetailBeritaInvestasi({
}) {
return (
<>
<AppComponentGlobal_LayoutTamplate header={<ComponentGlobal_HeaderTamplate title="Detail Berita" />}>
<UIGlobal_LayoutTamplate header={<UIGlobal_LayoutHeaderTamplate title="Detail Berita" />}>
{children}
</AppComponentGlobal_LayoutTamplate>
</UIGlobal_LayoutTamplate>
</>
);
}

View File

@@ -5,6 +5,7 @@ import { Model_Berita_Investasi } from "../model/model_investasi";
import { useState } from "react";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import moment from "moment";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
export default function DetailBeritaInvestasi({
dataBerita,
@@ -14,17 +15,42 @@ export default function DetailBeritaInvestasi({
const [berita, setBerita] = useState(dataBerita);
return (
<>
<Stack spacing={"lg"}>
<Stack
spacing={"lg"}
style={{
border: `2px solid ${AccentColor.blue}`,
backgroundColor: AccentColor.darkblue,
padding: "15px",
borderRadius: "10px",
color: "white",
}}
>
<Stack spacing={0}>
<Title>{berita.title}</Title>
<Text fz={12}>{moment(berita.createdAt).format("lll")}</Text>
<Title order={4} align="center">
{berita.title}
</Title>
<Text align="center" fz={12}>
{moment(berita.createdAt).format("lll")}
</Text>
</Stack>
<AspectRatio ratio={16 / 9}>
<AspectRatio ratio={1 / 1} mx={"sm"} mah={250}>
<Image
alt=""
src={RouterInvestasi.api_gambar + `${berita.imagesId}`}
radius={"sm"}
height={250}
width={"100%"}
/>
</AspectRatio>
{/* <AspectRatio ratio={16 / 9}>
<Image
radius={"sm"}
src={RouterInvestasi.api_gambar + `${berita.imagesId}`}
alt=""
/>
</AspectRatio>
</AspectRatio> */}
<Text>{berita.deskripsi}</Text>
</Stack>
</>

View File

@@ -7,6 +7,7 @@ import { MODEL_Investasi } from "../model/model_investasi";
import { useState } from "react";
import _ from "lodash";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
export default function DetailDokumenInvestasi({
dataInvestasi,
@@ -17,35 +18,44 @@ export default function DetailDokumenInvestasi({
return (
<>
{!_.isEmpty(dokumen.DokumenInvestasi) ? (
dokumen.DokumenInvestasi.map((e) => (
<Link
key={e.id}
href={`/file/${e.url}`}
target="_blank"
style={{ textDecorationLine: "none" }}
>
<Paper w={"100%"} h={50} bg={"gray"} mb={"md"}>
<Grid
align="center"
justify="center"
h={50}
px={"sm"}
onClick={() => ""}
dokumen.DokumenInvestasi.map((e) => (
<Link
key={e.id}
href={`/file/${e.url}`}
target="_blank"
style={{ textDecorationLine: "none" }}
>
<Grid.Col span={10}>
<Text>{e.title}</Text>
</Grid.Col>
<Grid.Col span={2}>
<Center>
<IconChevronRight />
</Center>
</Grid.Col>
</Grid>
</Paper>
</Link>
))
<Paper
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
color: "white",
marginBottom: "15px",
}}
>
<Grid
align="center"
justify="center"
h={50}
px={"sm"}
onClick={() => ""}
>
<Grid.Col span={10}>
<Text>{e.title}</Text>
</Grid.Col>
<Grid.Col span={2}>
<Center>
<IconChevronRight />
</Center>
</Grid.Col>
</Grid>
</Paper>
</Link>
))
) : (
<ComponentGlobal_IsEmptyData/>
<ComponentGlobal_IsEmptyData />
)}
</>
);

View File

@@ -1,156 +1,79 @@
"use client";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import { Warna } from "@/app/lib/warna";
import { MainColor } from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_BoxInformation from "@/app_modules/_global/component/box_information";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import notifikasiToAdmin_funCreate from "@/app_modules/notifikasi/fun/create/create_notif_to_admin";
import mqtt_client from "@/util/mqtt_client";
import {
ActionIcon,
AspectRatio,
Avatar,
Box,
Button,
Center,
Flex,
Grid,
Group,
Image,
Paper,
Slider,
Stack,
Text,
Title,
Stack
} from "@mantine/core";
import {
IconBookDownload,
IconFileDescription,
IconSpeakerphone,
} from "@tabler/icons-react";
import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import { gs_StatusPortoInvestasi } 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";
import { ComponentInvestasi_DetailDataNonPublish } from "../../component/detail/detai_data_non_publish";
import { MainColor } from "@/app_modules/_global/color/color_pallet";
import { investasi_funEditStatusById } from "../../fun/edit/fun_edit_status_by_id";
import { gs_investasi_status } from "../../g_state";
import { MODEL_Investasi } from "../../model/model_investasi";
export default function DetailDraftInvestasi({
dataInvestasi,
}: {
dataInvestasi: any;
dataInvestasi: MODEL_Investasi;
}) {
const router = useRouter();
const [activeTab, setActiveTab] = useAtom(gs_StatusPortoInvestasi);
// const [investasi, setInvestasi] = useState<MODEL_Investasi>(dataInvestasi);
const [isLoading, setIsLoading] = useState(false);
const [activeTab, setActiveTab] = useAtom(gs_investasi_status);
const listBox = [
{
id: 1,
name: "Prospektus",
icon: <IconBookDownload size={70} />,
route: RouterInvestasi.edit_prospektus,
},
{
id: 2,
name: "Dokumen",
icon: <IconFileDescription size={70} />,
route: RouterInvestasi.edit_dokumen,
},
{
id: 3,
name: "Berita",
icon: <IconSpeakerphone size={70} />,
route: RouterInvestasi.edit_berita,
},
];
async function onAjukanReview() {
const res = await investasi_funEditStatusById({
investasiId: dataInvestasi.id,
statusId: "2",
});
async function onsubmit() {
await funGantiStatusInvestasi(dataInvestasi.id, "2")
.then((res) => res)
.then((val) => {
if (val.status === 200) {
toast("Review Berhasil Diajukan");
router.push(RouterInvestasi.portofolio);
setActiveTab("Review");
} else {
toast("Error");
}
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: "Mengajukan review",
};
const notif = await notifikasiToAdmin_funCreate({
data: dataNotif as any,
});
if (notif.status === 201) {
mqtt_client.publish("ADMIN", JSON.stringify({ count: 1 }));
setIsLoading(true);
ComponentGlobal_NotifikasiBerhasil("Review Berhasil Diajukan");
router.push(RouterInvestasi.portofolio);
setActiveTab("Review");
}
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
}
return (
<>
{/* <Paper withBorder mb={"md"}>
<AspectRatio ratio={16 / 9}>
<Image
alt=""
src={RouterInvestasi.api_gambar + `${investasi.imagesId}`}
/>
</AspectRatio>
</Paper>
<Center>
<Title order={4} mb={"xs"}>
{_.capitalize(investasi.title)}
</Title>
</Center>
<Grid p={"md"} mb={"md"}>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>Dana Dibutuhkan</Text>
<Text>Rp. {new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.targetDana)}</Text>
</Box>
<Box>
<Text>Harga Per Lembar</Text>
<Text>Rp. {new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.hargaLembar)}</Text>
</Box>
<Box>
<Text>Jadwal Pembagian</Text>
<Text>{investasi.MasterPembagianDeviden.name} bulan </Text>
</Box>
<Box>
<Text>Pencarian Investor</Text>
<Text>{investasi.MasterPencarianInvestor.name} Hari </Text>
</Box>
</Stack>
</Grid.Col>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>ROI</Text>
<Text>{investasi.roi} %</Text>
</Box>
<Box>
<Text>Total Lembar</Text>
<Text>{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.totalLembar)} lembar</Text>
</Box>
<Box>
<Text>Pembagian Deviden</Text>
<Text>{investasi.MasterPeriodeDeviden.name}</Text>
</Box>
</Stack>
</Grid.Col>
</Grid> */}
<Stack mb={"lg"}>
{dataInvestasi.catatan && <ComponentGlobal_BoxInformation informasi={dataInvestasi.catatan} isReport/>}
<ComponentInvestasi_DetailDataNonPublish data={dataInvestasi} />
<Stack>
<Button
loaderPosition="center"
loading={isLoading}
radius={50}
bg={MainColor.yellow}
color="yellow"
c={"black"}
onClick={() => onsubmit()}
onClick={() => onAjukanReview()}
>
Ajukan Review
</Button>

View File

@@ -1,24 +1,20 @@
"use client";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import { Warna } from "@/app/lib/warna";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import {
ActionIcon,
AspectRatio,
Avatar,
Box,
Button,
Center,
Flex,
Grid,
Group,
Image,
Paper,
Progress,
Slider,
Stack,
Text,
Title,
Title
} from "@mantine/core";
import {
IconBookDownload,
@@ -26,14 +22,10 @@ import {
IconFileDescription,
IconSpeakerphone,
} from "@tabler/icons-react";
import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import toast from "react-simple-toasts";
import { MODEL_Investasi } from "../../model/model_investasi";
import { useState } from "react";
import moment from "moment";
import _ from "lodash";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { MODEL_Investasi } from "../../model/model_investasi";
export default function DetailPublishInvestasi({
dataInvestasi,
@@ -47,19 +39,19 @@ export default function DetailPublishInvestasi({
{
id: 1,
name: "Prospektus",
icon: <IconBookDownload size={70} />,
icon: <IconBookDownload size={70} color="white" />,
route: RouterInvestasi.detail_prospektus,
},
{
id: 2,
name: "Dokumen",
icon: <IconFileDescription size={70} />,
icon: <IconFileDescription size={70} color="white" />,
route: RouterInvestasi.edit_dokumen,
},
{
id: 3,
name: "Berita",
icon: <IconSpeakerphone size={70} />,
icon: <IconSpeakerphone size={70} color="white" />,
route: RouterInvestasi.list_edit_berita,
},
];
@@ -109,19 +101,19 @@ export default function DetailPublishInvestasi({
</Group>
)}
<AspectRatio ratio={1 / 1} mx={"sm"} mah={300}>
<AspectRatio ratio={1 / 1} mx={"sm"} mah={250}>
<Image
alt=""
src={RouterInvestasi.api_gambar + `${investasi.imagesId}`}
radius={"sm"}
height={300}
height={250}
width={"100%"}
/>
</AspectRatio>
{/* Title dan Persentase */}
<Box mb={"md"}>
<Title order={4} mb={"xs"}>
<Title align="center" order={3} mb={"xs"}>
{investasi.title}
</Title>
<Progress
@@ -208,24 +200,33 @@ export default function DetailPublishInvestasi({
</Grid>
{/* List Box */}
<Grid mb={"md"}>
{listBox.map((e) => (
<Grid.Col
span={"auto"}
key={e.id}
onClick={() => router.push(e.route + `${investasi.id}`)}
<Group position="apart" px={"lg"}>
{listBox.map((e, i) => (
<Paper
key={i}
style={{
padding: "15px",
backgroundColor: AccentColor.blue,
border: `2px solid ${AccentColor.softblue}`,
borderRadius: "10px",
color: "white",
}}
>
<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>
<Flex direction={"column"} align={"center"} justify={"center"}>
<Text fz={12}>{e.name}</Text>
<ActionIcon
radius={"xl"}
// loading={isLoadingBox && e?.id === boxId ? true : false}
variant="transparent"
size={60}
onClick={() => router.push(e.route + `${investasi.id}`)}
>
{e.icon}
</ActionIcon>
</Flex>
</Paper>
))}
</Grid>
</Group>
</Stack>
);
}

View File

@@ -13,8 +13,9 @@ import { useState } from "react";
import { ComponentInvestasi_DetailDataNonPublish } from "../../component/detail/detai_data_non_publish";
import funDeleteInvestasi from "../../fun/fun_delete_investasi";
import funGantiStatusInvestasi from "../../fun/fun_ganti_status";
import { gs_StatusPortoInvestasi } from "../../g_state";
import { gs_investasi_status } from "../../g_state";
import { MODEL_Investasi } from "../../model/model_investasi";
import { investasi_funEditStatusById } from "../../fun/edit/fun_edit_status_by_id";
export default function DetailRejectInvestasi({
dataInvestasi,
@@ -23,40 +24,22 @@ export default function DetailRejectInvestasi({
}) {
const router = useRouter();
const [investasi, setInvestasi] = useState(dataInvestasi);
const [activeTab, setActiveTab] = useAtom(gs_StatusPortoInvestasi);
const [activeTab, setActiveTab] = useAtom(gs_investasi_status);
const [openModal, setOpenModal] = useState(false);
const listBox = [
{
id: 1,
name: "Prospektus",
icon: <IconBookDownload size={70} />,
route: RouterInvestasi.edit_prospektus,
},
{
id: 2,
name: "Dokumen",
icon: <IconFileDescription size={70} />,
route: RouterInvestasi.edit_dokumen,
},
// {
// id: 3,
// name: "Berita",
// icon: <IconSpeakerphone size={70} />,
// route: RouterInvestasi.edit_berita,
// },
];
async function onAjukan() {
await funGantiStatusInvestasi(investasi.id, "1").then((res) => {
if (res.status === 200) {
ComponentGlobal_NotifikasiBerhasil("Project Diajukan Kembali");
setActiveTab("Draft");
router.push(RouterInvestasi.portofolio);
} else {
ComponentGlobal_NotifikasiGagal("Gagal Pengajuan");
}
const res = await investasi_funEditStatusById({
investasiId: dataInvestasi.id,
statusId: "3",
});
if (res.status === 200) {
ComponentGlobal_NotifikasiBerhasil("Project Diajukan Kembali");
setActiveTab("Draft");
router.push(RouterInvestasi.portofolio);
} else {
ComponentGlobal_NotifikasiGagal("Gagal Pengajuan");
}
}
async function onDelete() {

View File

@@ -26,7 +26,7 @@ import {
} from "@tabler/icons-react";
import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import { gs_StatusPortoInvestasi } from "../../g_state";
import { gs_investasi_status } from "../../g_state";
import toast from "react-simple-toasts";
import { MODEL_Investasi } from "../../model/model_investasi";
import funGantiStatusInvestasi from "../../fun/fun_ganti_status";
@@ -36,6 +36,9 @@ import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/noti
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import { ComponentInvestasi_DetailDataNonPublish } from "../../component/detail/detai_data_non_publish";
import { investasi_funEditStatusById } from "../../fun/edit/fun_edit_status_by_id";
import notifikasiToAdmin_funCreate from "@/app_modules/notifikasi/fun/create/create_notif_to_admin";
import mqtt_client from "@/util/mqtt_client";
export default function DetailReviewInvestasi({
dataInvestasi,
@@ -45,40 +48,39 @@ export default function DetailReviewInvestasi({
const router = useRouter();
const [isLoading, setLoading] = useState(false);
const [activeTab, setActiveTab] = useAtom(gs_StatusPortoInvestasi);
const [activeTab, setActiveTab] = useAtom(gs_investasi_status);
const [data, setData] = useState<MODEL_Investasi>(dataInvestasi);
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,
// },
];
async function onsubmit() {
await funGantiStatusInvestasi(data.id, "1").then((val) => {
if (val.status === 200) {
ComponentGlobal_NotifikasiBerhasil("Review Dibatalkan");
router.push(RouterInvestasi.portofolio);
setActiveTab("Draft");
} else {
ComponentGlobal_NotifikasiPeringatan("Error");
}
async function onCancleReview() {
const res = await investasi_funEditStatusById({
investasiId: data.id,
statusId: "3",
});
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: "Membatalkan review",
};
const notif = await notifikasiToAdmin_funCreate({
data: dataNotif as any,
});
if (notif.status === 201) {
mqtt_client.publish("ADMIN", JSON.stringify({ count: 1 }));
setLoading(true);
ComponentGlobal_NotifikasiBerhasil("Review Dibatalkan");
setActiveTab("Draft");
router.push(RouterInvestasi.portofolio);
}
} else {
ComponentGlobal_NotifikasiPeringatan(res.message);
}
}
return (
@@ -96,7 +98,7 @@ export default function DetailReviewInvestasi({
radius={50}
bg={"orange"}
color="yellow"
onClick={() => onsubmit()}
onClick={() => onCancleReview()}
>
Batalkan Review
</Button>

View File

@@ -25,7 +25,7 @@ export default function DetailPropektus({
RouterInvestasi.api_file_prospektus +
`${prospek.ProspektusInvestasi.id}`
}
target="_blank"
// target="_blank"
style={{ textDecorationLine: "none" }}
>
<Paper

View File

@@ -1,8 +1,7 @@
"use client";
import AppComponentGlobal_LayoutTamplate from "@/app_modules/_global/component_layout_tamplate";
import ComponentGlobal_HeaderTamplate from "@/app_modules/_global/header_tamplate";
import { AppShell } from "@mantine/core";
import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_tamplate";
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate";
import React from "react";
export default function LayoutDetailSahamTerbeli({
@@ -12,9 +11,9 @@ export default function LayoutDetailSahamTerbeli({
}) {
return (
<>
<AppComponentGlobal_LayoutTamplate header={<ComponentGlobal_HeaderTamplate title="Saham Terbeli" />}>
<UIGlobal_LayoutTamplate header={<UIGlobal_LayoutHeaderTamplate title="Saham Terbeli" />}>
{children}
</AppComponentGlobal_LayoutTamplate>
</UIGlobal_LayoutTamplate>
</>
);
}

View File

@@ -32,6 +32,8 @@ import { MODEL_Transaksi_Investasi } from "../model/model_investasi";
import { useState } from "react";
import moment from "moment";
import _ from "lodash";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_AuthorNameOnHeader from "@/app_modules/_global/author_name_on_header";
export default function DetailSahamTerbeli({
dataTransaksi,
@@ -46,278 +48,332 @@ export default function DetailSahamTerbeli({
{
id: 1,
name: "Prospektus",
icon: <IconBookDownload size={70} />,
icon: <IconBookDownload size={70} color="white" />,
route: RouterInvestasi.detail_prospektus,
},
{
id: 2,
name: "Dokumen",
icon: <IconFileDescription size={70} />,
icon: <IconFileDescription size={70} color="white" />,
route: RouterInvestasi.detail_dokumen,
},
{
id: 3,
name: "Berita",
icon: <IconSpeakerphone size={70} />,
icon: <IconSpeakerphone size={70} color="white" />,
route: RouterInvestasi.berita,
},
];
return (
<>
<Group position="apart" mb={"md"}>
<Flex align={"center"} gap={"xs"}>
<Avatar radius={"xl"} bg={"gray"}>
{(() => {
const usr = investasi.Investasi.author.username;
const splt = usr.split("");
const Up = _.upperCase(splt[0]);
<Stack>
{/* Saham Terbeli */}
<Stack
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
color: "white",
}}
>
return Up;
})()}
</Avatar>
<Text>{investasi.Investasi.author.username}</Text>
</Flex>
{(() => {
if (
Number(investasi.Investasi.MasterPencarianInvestor.name) -
moment(new Date()).diff(new Date(investasi.createdAt), "days") <=
0
) {
return (
<>
<Group position="right">
<IconCircleCheck color="green" />
<Text c={"green"}>Selesai</Text>
</Group>
</>
);
} else {
return (
<>
<Group position="right" spacing={"xs"}>
{(() => {
if (
Number(investasi.Investasi.MasterPencarianInvestor.name) -
moment(new Date()).diff(
new Date(investasi.Investasi.countDown),
"days"
) <=
0
) {
return (
<>
<Group position="right" spacing={"xs"}>
<IconCircleCheck color="green" />
<Text
truncate
variant="text"
c={Warna.hijau_tua}
sx={{ fontFamily: "Greycliff CF, sans-serif" }}
ta="center"
fz="md"
fw={700}
>
Waktu Habis
</Text>
</Group>
</>
);
} else {
return (
<>
<Group position="right" spacing={"xs"}>
<Text>Sisa waktu:</Text>
<Text truncate>
{Number(
investasi.Investasi.MasterPencarianInvestor.name
) -
moment(new Date()).diff(
new Date(investasi.Investasi.countDown),
"days"
)}
</Text>
<Text truncate>Hari</Text>
</Group>
</>
);
}
})()}
</Group>
</>
);
}
})()}
</Group>
{/* Gambar Investasi */}
<Paper withBorder mb={"md"}>
<AspectRatio ratio={16 / 9}>
<Image
alt=""
src={RouterInvestasi.api_gambar + `${investasi.Investasi.imagesId}`}
/>
</AspectRatio>
</Paper>
{/* Title dan Persentase */}
<Box mb={"md"}>
<Title order={4} mb={"xs"}>
{investasi.Investasi.title}
</Title>
<Progress
label={
"" +
(
((+investasi.Investasi.totalLembar -
+investasi.Investasi.sisaLembar) /
+investasi.Investasi.totalLembar) *
100
).toFixed(1) +
"%"
}
value={
+(
((+investasi.Investasi.totalLembar -
+investasi.Investasi.sisaLembar) /
+investasi.Investasi.totalLembar) *
100
).toFixed(2)
}
color="teal"
size="xl"
radius="xl"
/>
</Box>
{/* Rincian Data */}
<Grid p={"md"}>
<Grid.Col span={6}>
<Stack>
{/* <Box>
<Text>Terkumpul</Text>
<Text>Rp. </Text>
</Box> */}
<Box>
<Text>Dana Dibutuhkan</Text>
<Text>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.Investasi.targetDana)}
</Text>
</Box>
<Box>
<Text>Harga Per Lembar</Text>
<Text>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.Investasi.hargaLembar)}
</Text>
</Box>
<Box>
<Text>Jadwal Pembagian</Text>
<Text>
{investasi.Investasi.MasterPembagianDeviden.name} bulan{" "}
</Text>
</Box>
<Box>
<Text>Pembagian Deviden</Text>
<Text>{investasi.Investasi.MasterPeriodeDeviden.name}</Text>
</Box>
</Stack>
</Grid.Col>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>Investor</Text>
<Text>{new Intl.NumberFormat("id-ID", {maximumSignificantDigits: 10}).format(investor)} </Text>
</Box>
<Box>
<Text>ROI</Text>
<Text>{investasi.Investasi.roi}%</Text>
</Box>
<Box>
<Text>Total Lembar</Text>
<Text>
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.Investasi.totalLembar)}{" "}
lembar
</Text>
</Box>
<Box>
<Text>Sisa Lembar</Text>
<Text>
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.Investasi.sisaLembar)}{" "}
lembar
</Text>
</Box>
</Stack>
</Grid.Col>
</Grid>
<Divider my={"md"} />
{/* Saham Terbeli */}
<Box>
<Center>
<Title order={5}>Saham Anda</Title>
</Center>
<Grid p={"md"}>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>Total Pembelian</Text>
<Group position="apart">
<Group w={"40%"} position="center">
<Stack spacing={5} align="center">
<Text fw={'bold'}>Total Pembelian</Text>
<Text>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.gross_amount)}
</Text>
</Box>
</Stack>
</Grid.Col>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>Lembar Dibeli</Text>
</Stack>
</Group>
<Group w={"40%"} position="center">
<Stack spacing={5} align="center">
<Text fw={"bold"}>Lembar Dibeli</Text>
<Text>
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.quantity)}{" "}
lembar
</Text>
</Box>
</Stack>
</Grid.Col>
</Grid>
</Box>
</Stack>
</Group>
</Group>
</Stack>
{/* List Box */}
<Grid mb={"sm"} justify="center">
{listBox.map((e) => (
<Grid.Col
span={"auto"}
key={e.id}
onClick={() => router.push(e.route + `${investasi.Investasi.id}`)}
>
<Center>
<Paper h={100} w={100} bg={"gray.4"} withBorder py={"xs"}>
<Stack
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
color: "white",
marginBottom: "15px",
}}
>
<Group position="apart" mb={"md"}>
<ComponentGlobal_AuthorNameOnHeader
authorName={investasi?.Investasi?.author?.username}
imagesId={investasi?.Investasi?.author?.Profile?.imagesId}
profileId={investasi?.Investasi?.author?.Profile?.id}
/>
{(() => {
if (
Number(investasi.Investasi.MasterPencarianInvestor.name) -
moment(new Date()).diff(
new Date(investasi.createdAt),
"days"
) <=
0
) {
return (
<>
<Group position="right">
<IconCircleCheck color="green" />
<Text c={"green"}>Selesai</Text>
</Group>
</>
);
} else {
return (
<>
<Group position="right" spacing={"xs"}>
{(() => {
if (
Number(
investasi.Investasi.MasterPencarianInvestor.name
) -
moment(new Date()).diff(
new Date(investasi.Investasi.countDown),
"days"
) <=
0
) {
return (
<>
<Group position="right" spacing={"xs"}>
<IconCircleCheck color="green" />
<Text
truncate
variant="text"
c={Warna.hijau_tua}
sx={{
fontFamily: "Greycliff CF, sans-serif",
}}
ta="center"
fz="md"
fw={700}
>
Waktu Habis
</Text>
</Group>
</>
);
} else {
return (
<>
<Group position="right" spacing={"xs"}>
<Text>Sisa waktu:</Text>
<Text truncate>
{Number(
investasi.Investasi.MasterPencarianInvestor
.name
) -
moment(new Date()).diff(
new Date(investasi.Investasi.countDown),
"days"
)}
</Text>
<Text truncate>Hari</Text>
</Group>
</>
);
}
})()}
</Group>
</>
);
}
})()}
</Group>
{/* Gambar Investasi */}
<AspectRatio ratio={1 / 1} mah={250} mx={"sm"}>
<Image
radius={"sm"}
height={250}
width={"100%"}
alt=""
src={
RouterInvestasi.api_gambar + `${investasi.Investasi.imagesId}`
}
/>
</AspectRatio>
{/* Title dan Persentase */}
<Box mb={"md"}>
<Title align="center" order={3} mb={"xs"}>
{investasi.Investasi.title}
</Title>
<Progress
label={
"" +
(
((+investasi.Investasi.totalLembar -
+investasi.Investasi.sisaLembar) /
+investasi.Investasi.totalLembar) *
100
).toFixed(1) +
"%"
}
value={
+(
((+investasi.Investasi.totalLembar -
+investasi.Investasi.sisaLembar) /
+investasi.Investasi.totalLembar) *
100
).toFixed(2)
}
color="teal"
size="xl"
radius="xl"
/>
</Box>
{/* Rincian Data */}
<Grid p={"md"}>
<Grid.Col span={6}>
<Stack>
{/* <Box>
<Text>Terkumpul</Text>
<Text>Rp. </Text>
</Box> */}
<Box>
<Text>Dana Dibutuhkan</Text>
<Text>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.Investasi.targetDana)}
</Text>
</Box>
<Box>
<Text>Harga Per Lembar</Text>
<Text>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.Investasi.hargaLembar)}
</Text>
</Box>
<Box>
<Text>Jadwal Pembagian</Text>
<Text>
{investasi.Investasi.MasterPembagianDeviden.name} bulan{" "}
</Text>
</Box>
<Box>
<Text>Pembagian Deviden</Text>
<Text>{investasi.Investasi.MasterPeriodeDeviden.name}</Text>
</Box>
</Stack>
</Grid.Col>
<Grid.Col span={6}>
<Stack>
<Box>
<Text>Investor</Text>
<Text>
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(investor)}{" "}
</Text>
</Box>
<Box>
<Text>ROI</Text>
<Text>{investasi.Investasi.roi}%</Text>
</Box>
<Box>
<Text>Total Lembar</Text>
<Text>
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.Investasi.totalLembar)}{" "}
lembar
</Text>
</Box>
<Box>
<Text>Sisa Lembar</Text>
<Text>
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+investasi.Investasi.sisaLembar)}{" "}
lembar
</Text>
</Box>
</Stack>
</Grid.Col>
</Grid>
{/* List Box */}
<Group position="apart" px={"lg"}>
{listBox.map((e, i) => (
<Paper
key={i}
style={{
padding: "15px",
backgroundColor: AccentColor.blue,
border: `2px solid ${AccentColor.softblue}`,
borderRadius: "10px",
color: "white",
}}
>
<Flex direction={"column"} align={"center"} justify={"center"}>
<Text fz={12}>{e.name}</Text>
<ActionIcon variant="transparent" size={60}>
<ActionIcon
radius={"xl"}
variant="transparent"
size={60}
onClick={() => router.push(e.route + `${investasi.Investasi.id}`)}
>
{e.icon}
</ActionIcon>
</Flex>
</Paper>
</Center>
</Grid.Col>
))}
</Grid>
))}
</Group>
{/*
<Grid mb={"sm"} justify="center">
{listBox.map((e) => (
<Grid.Col
span={"auto"}
key={e.id}
onClick={() => router.push(e.route + `${investasi.Investasi.id}`)}
>
<Center>
<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>
</Center>
</Grid.Col>
))}
</Grid> */}
</Stack>
</Stack>
</>
);
}

View File

@@ -5,7 +5,7 @@ import { AppShell, CloseButton, Group, Header, Text } from "@mantine/core";
import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import React from "react";
import { gs_investasiFooter } from "../../g_state";
import { gs_investas_menu } from "../../g_state";
import AppComponentGlobal_LayoutTamplate from "@/app_modules/_global/component_layout_tamplate";
export default function LayoutCountDownTransaksiInvestasi({
@@ -14,7 +14,7 @@ export default function LayoutCountDownTransaksiInvestasi({
children: React.ReactNode;
}) {
const router = useRouter();
const [hotMenu, setHotMenu] = useAtom(gs_investasiFooter);
const [hotMenu, setHotMenu] = useAtom(gs_investas_menu);
return (
<>
<AppComponentGlobal_LayoutTamplate

View File

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

View File

@@ -1,25 +1,21 @@
"use client";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import {
ActionIcon,
Group,
Paper,
Text
} from "@mantine/core";
import {
IconTrash,
IconWorldShare
} from "@tabler/icons-react";
import { ActionIcon, Group, Paper, Text } from "@mantine/core";
import { IconFolderOpen, IconTrash, IconWorldShare } from "@tabler/icons-react";
import _ from "lodash";
import Link from "next/link";
import { useState } from "react";
import funDeleteDokumenInvestasi from "../fun/fun_delete_dokumen";
import funLoadDataInvestasi from "../fun/fun_load_data";
import { MODEL_Investasi } from "../model/model_investasi";
import { IconFile } from "@tabler/icons-react";
export default function EditDokumenInvestasi({
dataInvestasi,
@@ -61,7 +57,11 @@ export default function EditDokumenInvestasi({
<Group position="center">
<Link href={`/file/${e.url}`} target="_blank">
<ActionIcon variant="transparent">
<IconWorldShare color="green" />
<IconFolderOpen
style={{
color: MainColor.yellow,
}}
/>
</ActionIcon>
</Link>
<ActionIcon

View File

@@ -0,0 +1,40 @@
"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 investasi_funEditStatusById({
investasiId,
statusId,
}: {
investasiId: string;
statusId: string;
}) {
const res = await prisma.investasi.update({
where: {
id: investasiId,
},
data: {
masterStatusInvestasiId: statusId,
},
select: {
id: true,
title: true,
authorId: true,
MasterStatusInvestasi: {
select: {
name: true
}
}
}
});
if (!res) return { status: 400, message: "Gagal Update" };
revalidatePath(RouterInvestasi.main_porto);
return {
data: res,
status: 200,
message: "Update Berhasil",
};
}

View File

@@ -10,19 +10,20 @@ import { MODEL_Investasi } from "../model/model_investasi";
import funUploadProspektusInvestasi from "./fun_upload_prospek";
export async function funCreateInvestasi(
gamabar: FormData,
fileGambar: FormData,
filePdf: FormData,
data: MODEL_Investasi
) {
// Function upload gambar
const file: any = gamabar.get("file");
const fName = file.name;
const fExt = _.lowerCase(file.name.split(".").pop());
const fRandomName = v4(fName) + "." + fExt;
const gambar: any = fileGambar.get("file");
const gambarName = gambar.name;
const gambarExtention = _.lowerCase(gambar.name.split(".").pop());
const gambarRandomName = v4(gambarName) + "." + gambarExtention;
const uploadImage = await prisma.images.create({
data: {
url: fRandomName,
url: gambarRandomName,
label: "INVESTASI",
},
select: {
id: true,
@@ -36,13 +37,13 @@ export async function funCreateInvestasi(
message: "Gambar Kosong",
};
const upFolder = Buffer.from(await file.arrayBuffer());
const upFolder = Buffer.from(await gambar.arrayBuffer());
fs.writeFileSync(`./public/investasi/${uploadImage.url}`, upFolder);
const createInvest = await prisma.investasi.create({
data: {
authorId: data.authorId,
title: data.title,
title: _.startCase(data.title),
targetDana: data.targetDana.toString(),
hargaLembar: data.hargaLembar.toString(),
totalLembar: data.totalLembar.toString(),
@@ -54,6 +55,16 @@ export async function funCreateInvestasi(
imagesId: uploadImage.id,
masterStatusInvestasiId: "2",
},
select: {
id: true,
title: true,
authorId: true,
MasterStatusInvestasi: {
select: {
name: true,
},
},
},
});
if (!createInvest)
@@ -62,32 +73,27 @@ export async function funCreateInvestasi(
message: "Gagal Disimpan",
};
// File upload function
// const dataPdf: any = filePdf.get("file");
// const pdfName = dataPdf.name;
// const pdfExt = _.lowerCase(dataPdf.name.split(".").pop());
// const pdfRandomName = v4(pdfName) + "." + pdfExt;
// await funUploadProspektusInvestasi(filePdf, createInvest.id);
// const uploadFile = await prisma.prospektusInvestasi.create({
// data: {
// investasiId: createInvest.id,
// url: pdfRandomName,
// },
// select: {
// id: true,
// url: true,
// },
// });
const file: any = filePdf.get("file");
const fName = file.name;
const fExt = _.lowerCase(file.name.split(".").pop());
const fRandomName = v4(fName) + "." + fExt;
// if (!uploadFile) return { status: 400, message: "File Kosong" };
// const upPdfFolder = Buffer.from(await file.arrayBuffer());
// fs.writeFileSync(`./public/file/${uploadFile.url}`, upPdfFolder);
const createFile = await prisma.prospektusInvestasi.create({
data: {
investasiId: createInvest.id,
url: fRandomName,
},
});
await funUploadProspektusInvestasi(filePdf, createInvest.id);
if (!createFile) return { status: 400, message: "Gagal Upload" };
const uploadFile = Buffer.from(await file.arrayBuffer());
fs.writeFileSync(`./public/file/${createFile.url}`, uploadFile);
revalidatePath(RouterInvestasi.main_porto);
return {
data: createInvest,
status: 201,
message: "Berhasil Disimpan",
};

View File

@@ -14,10 +14,7 @@ export default async function funDeleteInvestasi(id: string) {
if (!res) return { status: 400, message: "Gagal Hapus Data" };
revalidatePath(RouterInvestasi.portofolio)
revalidatePath(RouterAdminInvestasi_OLD.main_investasi)
revalidatePath(RouterInvestasi.portofolio);
return {
status: 200,

View File

@@ -3,7 +3,7 @@
import prisma from "@/app/lib/prisma";
import _ from "lodash";
import { v4 } from "uuid";
import fs from "fs"
import fs from "fs";
import { revalidatePath } from "next/cache";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
@@ -11,12 +11,9 @@ export default async function funUploadProspektusInvestasi(
formData: FormData,
idInves: string
) {
const file: any = formData.get("file");
const fName = file.name;
const fExt = _.lowerCase(file.name.split(".").pop());
// console.log(fName)
// console.log(fExt)
const fRandomName = v4(fName) + "." + fExt;
const uploadFile = await prisma.prospektusInvestasi.upsert({
@@ -32,13 +29,13 @@ export default async function funUploadProspektusInvestasi(
},
});
if(!uploadFile) return {status: 400, message: "Gagal Upload"}
const upFolder = Buffer.from(await file.arrayBuffer())
fs.writeFileSync(`./public/file/${uploadFile.url}`, upFolder)
if (!uploadFile) return { status: 400, message: "Gagal Upload" };
const upFolder = Buffer.from(await file.arrayBuffer());
fs.writeFileSync(`./public/file/${uploadFile.url}`, upFolder);
revalidatePath(RouterInvestasi.edit_prospektus)
revalidatePath(RouterInvestasi.edit_prospektus);
return {
status: 201,
message: "File tersimpan "
}
message: "File tersimpan ",
};
}

View File

@@ -0,0 +1,86 @@
"use server";
import prisma from "@/app/lib/prisma";
import moment from "moment";
export async function investasi_funGetAllPublish() {
const data = await prisma.investasi.findMany({
where: {
masterStatusInvestasiId: "1",
masterProgresInvestasiId: "1",
},
select: {
id: true,
MasterPencarianInvestor: true,
countDown: true,
progress: true,
},
});
for (let a of data) {
if (
(a.MasterPencarianInvestor?.name as any) -
moment(new Date()).diff(new Date(a.countDown as any), "days") <=
0
) {
// console.log(a.MasterPencarianInvestor?.name);
await prisma.investasi.update({
where: {
id: a.id,
},
data: {
masterProgresInvestasiId: "3",
},
});
}
if (a.progress === "100") {
await prisma.investasi.update({
where: {
id: a.id,
},
data: {
masterProgresInvestasiId: "2",
},
});
}
}
// cek data yang lewat
// klo ada, update status
const dataFix = await prisma.investasi.findMany({
orderBy: [
{
masterProgresInvestasiId: "asc",
},
],
where: {
masterStatusInvestasiId: "1",
},
select: {
id: true,
title: true,
authorId: true,
hargaLembar: true,
targetDana: true,
totalLembar: true,
sisaLembar: true,
progress: true,
roi: true,
active: true,
createdAt: true,
updatedAt: true,
imagesId: true,
ProspektusInvestasi: true,
MasterPembagianDeviden: true,
MasterPencarianInvestor: true,
MasterPeriodeDeviden: true,
MasterProgresInvestasi: true,
countDown: true,
},
});
return dataFix;
}

View File

@@ -1,45 +0,0 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function getAllDataPublishInvestasi() {
const data = await prisma.investasi.findMany({
orderBy: [
{
masterProgresInvestasiId: "asc",
},
{
countDown: "desc",
},
],
where: {
MasterStatusInvestasi: {
name: {
equals: "Publish",
},
},
},
select: {
id: true,
title: true,
authorId: true,
hargaLembar: true,
targetDana: true,
totalLembar: true,
sisaLembar: true,
progress: true,
roi: true,
active: true,
createdAt: true,
updatedAt: true,
imagesId: true,
ProspektusInvestasi: true,
MasterPembagianDeviden: true,
MasterPencarianInvestor: true,
MasterPeriodeDeviden: true,
MasterProgresInvestasi: true,
countDown: true,
},
});
return data;
}

View File

@@ -17,12 +17,21 @@ export default async function getListTransaksiBerhasilInvestasi(
id: true,
Investasi: {
select: {
author: true,
author: {
select: {
username: true,
Profile: {
select: {
userId: true,
imagesId: true
},
},
},
},
imagesId: true,
title: true,
totalLembar: true,
sisaLembar: true,
},
},
Author: true,

View File

@@ -6,11 +6,17 @@ export default async function getOneInvestasiById(id: string) {
const data = await prisma.investasi.findUnique({
where: {
id: id,
},
select: {
id: true,
author: {
select: {
id: true,
username: true,
nomor: true,
Profile: true,
},
},
title: true,
authorId: true,
hargaLembar: true,
@@ -33,8 +39,8 @@ export default async function getOneInvestasiById(id: string) {
MasterPencarianInvestor: true,
MasterPeriodeDeviden: true,
MasterProgresInvestasi: true,
author: true,
countDown: true
masterStatusInvestasiId: true,
countDown: true,
},
});

View File

@@ -16,7 +16,13 @@ export default async function getOneTransaksiBerhasilByIdInvestasi(
select: {
nomor: true,
username: true,
}
Profile: {
select: {
id: true,
imagesId: true,
},
},
},
},
BeritaInvestasi: true,
DokumenInvestasi: true,

View File

@@ -1,10 +1,10 @@
import { atom } from "jotai";
import { atomWithStorage } from "jotai/utils";
export const gs_investasiFooter = atomWithStorage<number>("changeColor", 0);
export const gs_StatusPortoInvestasi = atomWithStorage<any | string>(
export const gs_investas_menu = atomWithStorage<number>("changeColor", 0);
export const gs_investasi_status = atomWithStorage<any | string>(
"gs_TabPortoInvestasi",
"Draft"
"Publish"
);
export const gs_TransferValue = atomWithStorage("gs_TransferValue", {

View File

@@ -2,34 +2,61 @@
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import ComponentGlobal_HeaderTamplate from "@/app_modules/_global/header_tamplate";
import { AppShell } from "@mantine/core";
import { IconPencilPlus } from "@tabler/icons-react";
import { ActionIcon, AppShell } from "@mantine/core";
import { IconDotsVertical, IconPencilPlus } from "@tabler/icons-react";
import React from "react";
import getOneInvestasiById from "../fun/get_one_investasi_by_id";
import AppComponentGlobal_LayoutTamplate from "@/app_modules/_global/component_layout_tamplate";
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate";
import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_tamplate";
import { useRouter } from "next/navigation";
import UIGlobal_Drawer from "@/app_modules/_global/ui/ui_drawer";
export default function LayoutListEditBeritaInvestasi({
children,
idInves
idInves,
}: {
children: React.ReactNode;
idInves: string
idInves: string;
}) {
const router = useRouter();
const [isOpenDrawer, setIsOpenDrawer] = React.useState(false);
const listPage = [
{
id: "1",
name: "Tambah Berita",
icon: <IconPencilPlus />,
path: RouterInvestasi.create_berita + `${idInves}`,
},
];
return (
<>
<UIGlobal_LayoutTamplate
header={
<UIGlobal_LayoutHeaderTamplate
title="List Berita"
iconRight={<IconPencilPlus />}
routerRight={RouterInvestasi.create_berita + `${idInves}`}
title="Daftar Berita"
// iconRight={<IconPencilPlus />}
// routerRight={RouterInvestasi.create_berita + `${idInves}`}
customButtonRight={
<ActionIcon
variant="transparent"
onClick={() => setIsOpenDrawer(true)}
>
<IconDotsVertical color="white" />
</ActionIcon>
}
/>
}
>
{children}
</UIGlobal_LayoutTamplate>
<UIGlobal_Drawer
opened={isOpenDrawer}
close={() => setIsOpenDrawer(false)}
component={listPage}
/>
</>
);
}

View File

@@ -17,18 +17,20 @@ import {
Text,
Title,
} from "@mantine/core";
import { IconDots } from "@tabler/icons-react";
import { IconDots, IconEdit } 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 React, { useState } from "react";
import _ from "lodash";
import getOneInvestasiById from "../fun/get_one_investasi_by_id";
import funLoadDataInvestasi from "../fun/fun_load_data";
import funDeleteBeritaInvestasi from "../fun/fun_delete_berita";
import { useShallowEffect } from "@mantine/hooks";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import UIGlobal_Drawer from "@/app_modules/_global/ui/ui_drawer";
export default function ListEditBeritaInvestasi({
dataInvestasi,
@@ -37,6 +39,8 @@ export default function ListEditBeritaInvestasi({
}) {
const router = useRouter();
const [investasi, setInvestasi] = useState(dataInvestasi);
const [beritaId, setBeritaId] = React.useState("");
const [isOpenDrawer, setIsOpenDrawer] = React.useState(false);
async function onDelete(idBerita: string) {
await funDeleteBeritaInvestasi(idBerita).then(async (res) => {
@@ -50,22 +54,54 @@ export default function ListEditBeritaInvestasi({
});
}
const listPage = [
{
id: "1",
name: "Edit Berita",
icon: <IconEdit />,
// path: RouterInvestasi.edit_berita + `${v.id}`,
},
];
return (
<>
{_.isEmpty(investasi.BeritaInvestasi) ? (
<ComponentGlobal_IsEmptyData />
) : (
investasi.BeritaInvestasi.map((v, k) => (
<Paper key={k} w={"100%"} bg={"gray"} p={"sm"} mb={"md"}>
<Paper
key={k}
style={{
padding: "15px",
backgroundColor: AccentColor.darkblue,
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px",
color: "white",
marginBottom: "15px",
}}
onClick={() => router.push(RouterInvestasi.detail_berita + v.id)}
>
<Stack spacing={"xs"}>
<Group position="apart">
<Box>
<Title order={6}>{v.title}</Title>
<Text fz={10}>
<Title lineClamp={1} w={"70%"} order={6}>
{v.title}
</Title>
<Text lineClamp={1} fz={10}>
{moment(v.createdAt).local().format("lll")}
</Text>
</Box>
<Menu position="left">
{/* <ActionIcon
variant="transparent"
onClick={() => {
setIsOpenDrawer(true);
}}
>
<IconDots color="white" />
</ActionIcon> */}
{/* <Menu position="left">
<Menu.Target>
<ActionIcon variant="transparent">
<IconDots color="black" />
@@ -87,7 +123,7 @@ export default function ListEditBeritaInvestasi({
Hapus
</Menu.Item>
</Menu.Dropdown>
</Menu>
</Menu> */}
</Group>
<Grid pt={5}>
<Grid.Col span={8}>
@@ -115,6 +151,12 @@ export default function ListEditBeritaInvestasi({
</Paper>
))
)}
<UIGlobal_Drawer
opened={isOpenDrawer}
close={() => setIsOpenDrawer(false)}
component={listPage}
/>
</>
);
}

View File

@@ -1,17 +1,15 @@
"use client";
import { RouterCrowd } from "@/app/lib/router_hipmi/router_crowd";
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import AppComponentGlobal_LayoutTamplate from "@/app_modules/_global/component_layout_tamplate";
import ComponentGlobal_HeaderTamplate from "@/app_modules/_global/header_tamplate";
import { MainColor } from "@/app_modules/_global/color/color_pallet";
import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_tamplate";
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate";
import {
ActionIcon,
Center,
Flex,
Footer,
Grid,
SimpleGrid,
Stack,
Text,
Text
} from "@mantine/core";
import {
IconCash,
@@ -22,13 +20,7 @@ import {
import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import React from "react";
import { gs_investasiFooter } from "../g_state";
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate";
import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_tamplate";
import { RouterHome } from "@/app/lib/router_hipmi/router_home";
import { MainColor } from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { RouterCrowd } from "@/app/lib/router_hipmi/router_crowd";
import { gs_investas_menu } from "../g_state";
export default function LayoutMainInvestasi({
children,
@@ -36,7 +28,7 @@ export default function LayoutMainInvestasi({
children: React.ReactNode;
}) {
const router = useRouter();
const [active, setActive] = useAtom(gs_investasiFooter);
const [active, setActive] = useAtom(gs_investas_menu);
const listFooter = [
{

View File

@@ -2,91 +2,75 @@
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import { Warna } from "@/app/lib/warna";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_CreateButton from "@/app_modules/_global/component/button_create";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import {
ActionIcon,
Affix,
AspectRatio,
Box,
Button,
Card,
CardSection,
Center,
Divider,
Grid,
Group,
Image,
Paper,
Progress,
rem,
Stack,
Text,
Title,
rem,
} from "@mantine/core";
import { useWindowScroll } from "@mantine/hooks";
import {
IconCircleCheck,
IconPencilPlus,
IconXboxX,
} from "@tabler/icons-react";
import { useShallowEffect, useWindowScroll } from "@mantine/hooks";
import { IconCircleCheck, IconXboxX } from "@tabler/icons-react";
import _ from "lodash";
import moment from "moment";
import { useRouter } from "next/navigation";
import { useState } from "react";
import ComponentInvestasi_IsEmptyData from "../component/is_empty_data";
import { MODEL_Investasi } from "../model/model_investasi";
import ComponentGlobal_CreateButton from "@/app_modules/_global/component/button_create";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import mqtt_client from "@/util/mqtt_client";
import { investasi_funGetAllPublish } from "../fun/get_all_investasi";
export default function MainInvestasi({
listData,
dataSelesai,
dataWaktuHabis,
}: {
listData: MODEL_Investasi[];
dataSelesai: MODEL_Investasi[];
dataWaktuHabis: MODEL_Investasi[];
}) {
// console.log(listData)
const router = useRouter();
const [investasi, setInvestasi] = useState(listData);
const [invesDone, setInvesDone] = useState(dataSelesai);
const [invesFail, setInvesFail] = useState(dataWaktuHabis);
const [statusPublish, setStatusPublish] = useState(false);
const [isLoading, setLoading] = useState(false);
const [data, setData] = useState(listData);
const [isLoadingDetail, setLoadingDetail] = useState(false);
const [scroll, scrollTo] = useWindowScroll();
const [isNewPost, setIsNewPost] = useState(false);
// console.log(dataWaktuHabis)
useShallowEffect(() => {
mqtt_client.subscribe("Beranda_Investasi");
mqtt_client.on("message", (topic, message) => {
const newPost = JSON.parse(message.toString());
setIsNewPost(newPost);
});
}, []);
return (
<>
{/* <Affix position={{ bottom: rem(150), right: rem(30) }}>
<ActionIcon
loading={isLoading ? true : false}
opacity={scroll.y > 0 ? 0.5 : ""}
style={{
transition: "0.5s",
}}
size={"xl"}
radius={"xl"}
variant="transparent"
bg={"blue"}
onClick={() => {
setLoading(true);
router.push(RouterInvestasi.create);
}}
>
<IconPencilPlus color="white" />
</ActionIcon>
</Affix> */}
{isNewPost && (
<Affix position={{ top: rem(100) }} w={"100%"}>
<ButtonUpdateBeranda
onLoadData={(val) => {
setData(val.data);
setIsNewPost(val.isNewPost);
}}
/>
</Affix>
)}
<ComponentGlobal_CreateButton path={RouterInvestasi.create} />
{_.isEmpty(investasi) && _.isEmpty(invesDone) && _.isEmpty(invesFail) ? (
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
investasi.map((e) => (
data.map((e) => (
<Card
key={e.id}
style={{
@@ -103,99 +87,59 @@ export default function MainInvestasi({
router.push(RouterInvestasi.detail + `${e.id}`);
}}
>
<CardSection>
<AspectRatio ratio={16 / 9}>
<Paper radius={"sm"} withBorder>
<CardSection py={"md"} px={"sm"}>
<AspectRatio ratio={1 / 1} mah={250}>
<Box style={{ borderRadius: "7px" }}>
{e.imagesId ? (
<Image
alt=""
radius={"sm"}
alt="Foto"
src={RouterInvestasi.api_gambar + `${e.imagesId}`}
w={200}
/>
) : (
<Image alt="" src={"/aset/no-img.png"} />
)}
</Paper>
</Box>
</AspectRatio>
</CardSection>
<CardSection p={"sm"}>
<CardSection p={"md"}>
<Stack>
<Title order={4}>{e.title}</Title>
<Progress
<Title align="center" order={3}>
{e.title}
</Title>
{/* <Progress
label={(+e.progress).toFixed(2) + " %"}
value={+e.progress}
color="teal"
size="xl"
radius="xl"
/> */}
<Progress
label={
"" +
(
((+e.totalLembar - +e.sisaLembar) / +e.totalLembar) *
100
).toFixed(1) +
"%"
}
value={
+(
((+e.totalLembar - +e.sisaLembar) / +e.totalLembar) *
100
).toFixed(1)
}
color="teal"
size="xl"
radius="xl"
/>
</Stack>
</CardSection>
<CardSection p={"sm"}>
<Box>
<Grid>
<Grid.Col span={6}>
<Center>
<Stack>
<Box>
<Text truncate>Dana Dibutuhkan</Text>
<Text truncate>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+e.targetDana)}
</Text>
</Box>
<Box>
<Text truncate>Harga Per Lembar</Text>
<Text truncate>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumSignificantDigits: 10,
}).format(+e.hargaLembar)}
</Text>
</Box>
</Stack>
</Center>
</Grid.Col>
<Grid.Col span={6}>
<Center>
<Stack>
<Box>
<Text truncate>ROI</Text>
<Text truncate>{e.roi}%</Text>
</Box>
<Box>
<Text truncate>Sisa Lembar</Text>
<Text truncate>
{new Intl.NumberFormat("id-ID").format(
+e.sisaLembar
)}
</Text>
</Box>
</Stack>
</Center>
</Grid.Col>
</Grid>
</Box>
</CardSection>
<Divider color="gray.4" />
<CardSection p={"md"}>
<Group position="right">
{/* <Button
loaderPosition="center"
loading={isLoadingDetail ? true : false}
radius={"xl"}
compact
bg={Warna.hijau_muda}
color="green"
onClick={() => {
setLoadingDetail(true);
router.push(RouterInvestasi.detail + `${e.id}`);
}}
>
Detail
</Button> */}
{e.progress === "100" ? (
<Group position="right" spacing={"xs"}>
<IconCircleCheck color="green" />
@@ -253,3 +197,41 @@ export default function MainInvestasi({
</>
);
}
function ButtonUpdateBeranda({
onLoadData,
}: {
onLoadData: (val: any) => void;
}) {
const [isLoading, setIsLoading] = useState(false);
async function onLoaded() {
const loadData = await investasi_funGetAllPublish();
onLoadData({
data: loadData,
isNewPost: false,
});
setIsLoading(true);
}
return (
<>
<center>
<Button
style={{
transition: "0.5s",
border: `1px solid ${AccentColor.skyblue}`,
}}
bg={AccentColor.blue}
loaderPosition="center"
loading={isLoading ? true : false}
radius={"xl"}
onClick={() => onLoaded()}
>
Update beranda
</Button>
</center>
</>
);
}

View File

@@ -23,21 +23,22 @@ export interface MODEL_Investasi {
MasterPembagianDeviden: Model_All_Master;
MasterPencarianInvestor: Model_All_Master;
MasterPeriodeDeviden: Model_All_Master;
MasterProgresInvestasi: Model_All_Master,
MasterProgresInvestasi: Model_All_Master;
masterPeriodeDevidenId: string;
masterPembagianDevidenId: string;
masterPencarianInvestorId: string;
masterStatusInvestasiId: string;
author: MODEL_PROFILE_OLD;
countDown: Date
countDown: Date;
}
export interface MODEL_Transaksi_Investasi {
id: string;
namaBank: string;
nomorRekening: string;
transaction_id: string,
status_message: string
payment_type: string,
transaction_id: string;
status_message: string;
payment_type: string;
active: boolean;
createdAt: Date;
updatedAt: Date;

View File

@@ -1,52 +1,27 @@
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import {
Card,
CardSection,
AspectRatio,
Box,
Title,
Divider,
Group,
Badge,
Image,
Text,
Center,
Paper,
Grid,
Flex,
Stack,
} from "@mantine/core";
import { useRouter } from "next/navigation";
import { MODEL_Investasi } from "../model/model_investasi";
import _ from "lodash";
import ComponentInvestasi_IsEmptyData from "../component/is_empty_data";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import { Box } from "@mantine/core";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { ComponentInvestasi_CardStatus } from "../component/detail/card_status";
import { MODEL_Investasi } from "../model/model_investasi";
export default function Draft({ data }: { data: MODEL_Investasi[] }) {
const router = useRouter();
// console.log(data)
if (_.isEmpty(data))
return (
<>
<ComponentGlobal_IsEmptyData />
</>
);
if (_.isEmpty(data)) return <ComponentGlobal_IsEmptyData />;
return (
<>
{/* <pre> {JSON.stringify(data,null, 2)}</pre> */}
{data.map((e) => (
<Box key={e.id}>
<Box key={e.id}>
<ComponentInvestasi_CardStatus
data={e}
path={RouterInvestasi.detail_draft}
/>
</Box>
))}
</>
);

View File

@@ -1,30 +1,17 @@
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import {
AspectRatio,
Box,
Grid,
Image,
Paper,
Stack,
Text,
} from "@mantine/core";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { Box } from "@mantine/core";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useState } from "react";
import ComponentInvestasi_IsEmptyData from "../component/is_empty_data";
import { MODEL_Investasi } from "../model/model_investasi";
import { ComponentInvestasi_CardStatus } from "../component/detail/card_status";
import { MODEL_Investasi } from "../model/model_investasi";
export default function Reject({ data }: { data: MODEL_Investasi[] }) {
const [investasi, setInvestasi] = useState(data);
const router = useRouter();
if (_.isEmpty(data))
return (
<>
<ComponentInvestasi_IsEmptyData text="Tidak ada data" />
</>
);
if (_.isEmpty(data)) return <ComponentGlobal_IsEmptyData />;
return (
<>

View File

@@ -1,38 +1,16 @@
import { RouterInvestasi } from "@/app/lib/router_hipmi/router_investasi";
import {
Card,
CardSection,
AspectRatio,
Box,
Title,
Divider,
Group,
Badge,
Image,
Center,
Text,
Paper,
Grid,
Stack,
} from "@mantine/core";
import { useRouter } from "next/navigation";
import {
MODEL_Status_investasi,
MODEL_Investasi,
} from "../model/model_investasi";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { Box } from "@mantine/core";
import _ from "lodash";
import ComponentInvestasi_IsEmptyData from "../component/is_empty_data";
import { useRouter } from "next/navigation";
import { ComponentInvestasi_CardStatus } from "../component/detail/card_status";
import { MODEL_Investasi } from "../model/model_investasi";
export default function Review({ data }: { data: MODEL_Investasi[] }) {
const router = useRouter();
if (_.isEmpty(data))
return (
<>
<ComponentInvestasi_IsEmptyData text="Tidak ada data" />
</>
);
if (_.isEmpty(data)) return <ComponentGlobal_IsEmptyData />;
return (
<>
{data.map((e) => (

Some files were not shown because too many files have changed in this diff Show More