Donasi Info Admni
# feat - info admin - hapus admin ## Issue: Loading data belum untuk versi alfa
This commit is contained in:
@@ -4,7 +4,7 @@ import { Group, Button } from "@mantine/core";
|
||||
import { IconChevronLeft } from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export default function AdminDonasi_TombolKembali() {
|
||||
export default function ComponentAdminDonasi_TombolKembali() {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -7,16 +7,23 @@ import {
|
||||
Divider,
|
||||
Group,
|
||||
Image,
|
||||
Modal,
|
||||
Paper,
|
||||
SimpleGrid,
|
||||
Stack,
|
||||
Text,
|
||||
Textarea,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import { useState } from "react";
|
||||
import AdminDonasi_TombolKembali from "../component/tombol_kembali";
|
||||
import ComponentAdminDonasi_TombolKembali from "../component/tombol_kembali";
|
||||
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
|
||||
import TampilanRupiahDonasi from "@/app_modules/donasi/component/tampilan_rupiah";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import { AdminDonasi_funUpdateCatatanReject } from "../fun/update/fun_update_catatan_reject";
|
||||
import { NotifBerhasil } from "@/app_modules/donasi/component/notifikasi/notif_berhasil";
|
||||
import { NotifGagal } from "@/app_modules/donasi/component/notifikasi/notif_gagal";
|
||||
import { AdminDonasi_getOneById } from "../fun/get/get_one_by_id";
|
||||
|
||||
export default function AdminDonasi_DetailReject({
|
||||
dataReject,
|
||||
@@ -28,7 +35,11 @@ export default function AdminDonasi_DetailReject({
|
||||
return (
|
||||
<>
|
||||
<Stack>
|
||||
<ButtonOnHeader />
|
||||
<ButtonOnHeader
|
||||
catatan={donasi.catatan}
|
||||
donasiId={donasi.id}
|
||||
setDonasi={setDonasi}
|
||||
/>
|
||||
<SimpleGrid
|
||||
cols={2}
|
||||
spacing="lg"
|
||||
@@ -46,18 +57,61 @@ export default function AdminDonasi_DetailReject({
|
||||
);
|
||||
}
|
||||
|
||||
function ButtonOnHeader() {
|
||||
function ButtonOnHeader({
|
||||
catatan,
|
||||
donasiId,
|
||||
setDonasi,
|
||||
}: {
|
||||
catatan: string;
|
||||
donasiId: string;
|
||||
setDonasi: any;
|
||||
}) {
|
||||
const [catat, setCatat] = useState(catatan);
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
|
||||
async function onUpdate() {
|
||||
await AdminDonasi_funUpdateCatatanReject(donasiId, catat).then(
|
||||
async (res) => {
|
||||
if (res.status === 200) {
|
||||
NotifBerhasil(res.message);
|
||||
close();
|
||||
await AdminDonasi_getOneById(donasiId).then((res) => setDonasi(res));
|
||||
} else {
|
||||
NotifGagal(res.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack>
|
||||
<Group position="apart">
|
||||
<AdminDonasi_TombolKembali />
|
||||
<Button radius={"xl"} bg={"orange"} color="orange">
|
||||
<ComponentAdminDonasi_TombolKembali />
|
||||
<Button radius={"xl"} bg={"orange"} color="orange" onClick={open}>
|
||||
Tambah catatan
|
||||
</Button>
|
||||
</Group>
|
||||
<Divider />
|
||||
</Stack>
|
||||
<Modal
|
||||
opened={opened}
|
||||
onClose={close}
|
||||
centered
|
||||
title="Tambah catatan penolakan"
|
||||
>
|
||||
<Stack>
|
||||
<Textarea
|
||||
value={catat}
|
||||
onChange={(val) => setCatat(val.target.value)}
|
||||
/>
|
||||
<Group position="right">
|
||||
<Button radius="xl" onClick={() => onUpdate()}>
|
||||
Simpan
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
Textarea,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import AdminDonasi_TombolKembali from "../component/tombol_kembali";
|
||||
import ComponentAdminDonasi_TombolKembali from "../component/tombol_kembali";
|
||||
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
|
||||
import TampilanRupiahDonasi from "@/app_modules/donasi/component/tampilan_rupiah";
|
||||
import {
|
||||
@@ -95,7 +95,7 @@ function ButtonOnHeader({ donasi }: { donasi: MODEL_DONASI }) {
|
||||
return (
|
||||
<>
|
||||
<Group position="apart">
|
||||
<AdminDonasi_TombolKembali />
|
||||
<ComponentAdminDonasi_TombolKembali />
|
||||
<Group>
|
||||
<Button
|
||||
radius={"xl"}
|
||||
|
||||
@@ -10,17 +10,20 @@ import {
|
||||
Grid,
|
||||
Group,
|
||||
Image,
|
||||
Modal,
|
||||
Pagination,
|
||||
Paper,
|
||||
Progress,
|
||||
ScrollArea,
|
||||
SimpleGrid,
|
||||
Spoiler,
|
||||
Stack,
|
||||
Table,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import AdminDonasi_TombolKembali from "../../component/tombol_kembali";
|
||||
import ComponentAdminDonasi_TombolKembali from "../../component/tombol_kembali";
|
||||
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
|
||||
import {
|
||||
IconClover,
|
||||
@@ -32,44 +35,50 @@ import moment from "moment";
|
||||
import {
|
||||
MODEL_DONASI,
|
||||
MODEL_DONASI_INVOICE,
|
||||
MODEL_DONASI_PENCAIRAN_DANA,
|
||||
} from "@/app_modules/donasi/model/interface";
|
||||
import { useState } from "react";
|
||||
import { RouterAdminDonasi } from "@/app/lib/router_hipmi/router_admin";
|
||||
import TampilanRupiahDonasi from "@/app_modules/donasi/component/tampilan_rupiah";
|
||||
import _ from "lodash";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useInterval, useShallowEffect } from "@mantine/hooks";
|
||||
import { useDisclosure, useInterval, useShallowEffect } from "@mantine/hooks";
|
||||
import { Donasi_getOneById } from "@/app_modules/donasi/fun/get/get_one_donasi_by_id";
|
||||
import { AdminDonasi_getOneById } from "../../fun/get/get_one_by_id";
|
||||
|
||||
export default function AdminDonasi_DetailPublish({
|
||||
dataPublish,
|
||||
listDonatur,
|
||||
countDonatur,
|
||||
listPencairan,
|
||||
}: {
|
||||
dataPublish: MODEL_DONASI;
|
||||
listDonatur: any[];
|
||||
countDonatur: number;
|
||||
listPencairan: MODEL_DONASI_PENCAIRAN_DANA[];
|
||||
}) {
|
||||
const [donasi, setDonasi] = useState(dataPublish);
|
||||
const [donatur, setDoanutur] = useState(listDonatur);
|
||||
const interval = useInterval(() => reloadData(donasi.id), 5000);
|
||||
const [pencairan, setPencairan] = useState(listPencairan);
|
||||
|
||||
useShallowEffect(() => {
|
||||
interval.start();
|
||||
}, []);
|
||||
|
||||
async function reloadData(donasiId: string) {
|
||||
const data = await Donasi_getOneById(donasiId);
|
||||
setDonasi(data as any)
|
||||
const data = await AdminDonasi_getOneById(donasiId);
|
||||
setDonasi(data as any);
|
||||
return data;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{/* <pre>{JSON.stringify(donatur.map((e) => e), null, 2)}</pre> */}
|
||||
{/* <pre>{JSON.stringify(pencairan, null, 2)}</pre> */}
|
||||
<Stack>
|
||||
<AdminDonasi_TombolKembali />
|
||||
<ComponentAdminDonasi_TombolKembali />
|
||||
<TampilanDetailDonasi donasi={donasi} countDonatur={countDonatur} />
|
||||
<TampilanListDonatur donatur={donatur} donasi={donasi} />
|
||||
<TampilanListPencairan pencairan={pencairan} />
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
@@ -82,14 +91,16 @@ function TampilanDetailDonasi({
|
||||
donasi: MODEL_DONASI;
|
||||
countDonatur: number;
|
||||
}) {
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
<Paper radius={"md"} p={"md"}>
|
||||
<Stack>
|
||||
<Grid>
|
||||
<Grid.Col span={6}>
|
||||
<Grid.Col md={6} lg={4}>
|
||||
<AspectRatio ratio={16 / 9}>
|
||||
<Paper radius={"md"}>
|
||||
<Paper radius={"md"} h={{ lg: 200, md: 200, sm: 200 }}>
|
||||
<Image
|
||||
alt="Foto"
|
||||
src={RouterDonasi.api_gambar + `${donasi.imagesId}`}
|
||||
@@ -97,52 +108,134 @@ function TampilanDetailDonasi({
|
||||
</Paper>
|
||||
</AspectRatio>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={6}>
|
||||
<Stack spacing={7}>
|
||||
<Title order={4}>{donasi.title}</Title>
|
||||
<Text fz={"xs"}>
|
||||
Durasi: {donasi.DonasiMaster_Durasi.name} hari
|
||||
</Text>
|
||||
<Grid.Col md={6} lg={4}>
|
||||
<Paper withBorder p={"sm"} mah={250} h={250}>
|
||||
<Stack spacing={5}>
|
||||
<Title order={4}>{donasi.title}</Title>
|
||||
<Group>
|
||||
<Text fz={"xs"}>Penggalang Dana</Text>
|
||||
<Title order={5} c="blue">
|
||||
{donasi.Author.username}
|
||||
</Title>
|
||||
</Group>
|
||||
<Group>
|
||||
<Text fz={12}>Durasi</Text>
|
||||
<Title order={5} c="blue">
|
||||
{donasi.DonasiMaster_Durasi.name} hari
|
||||
</Title>
|
||||
</Group>
|
||||
|
||||
<Group>
|
||||
<Text fz={12}>Dana dibutuhkan</Text>
|
||||
<Title order={5} c="blue">
|
||||
<TampilanRupiahDonasi nominal={+donasi.target} />
|
||||
</Title>
|
||||
</Group>
|
||||
<Group>
|
||||
<Text fz={12}>Kategori</Text>
|
||||
<Title order={5} c="blue">
|
||||
{donasi.DonasiMaster_Ketegori.name}
|
||||
</Title>
|
||||
</Group>
|
||||
<Group>
|
||||
<Text fz={12}>Total donatur</Text>
|
||||
<Title order={5} c="blue">
|
||||
{countDonatur}
|
||||
</Title>
|
||||
</Group>
|
||||
<Group>
|
||||
<Text fz={12}>Progres</Text>
|
||||
<Title order={5} c="blue">
|
||||
{donasi.progres} %
|
||||
</Title>
|
||||
</Group>
|
||||
<Group>
|
||||
<Text fz={12}>Dana terkumpul</Text>
|
||||
<Title order={5} c="blue">
|
||||
<TampilanRupiahDonasi nominal={+donasi.terkumpul} />
|
||||
</Title>
|
||||
</Group>
|
||||
</Stack>
|
||||
<Group>
|
||||
<Text fz={12}>Dana dibutuhkan</Text>
|
||||
<Title order={5} c="blue">
|
||||
<TampilanRupiahDonasi nominal={+donasi.target} />
|
||||
</Title>
|
||||
</Group>
|
||||
<Group>
|
||||
<Text fz={12}>Kategori</Text>
|
||||
<Title order={5} c="blue">
|
||||
{donasi.DonasiMaster_Ketegori.name}
|
||||
</Title>
|
||||
</Group>
|
||||
<Group>
|
||||
<Text fz={12}>Total donatur</Text>
|
||||
<Title order={5} c="blue">
|
||||
{countDonatur}
|
||||
</Title>
|
||||
</Group>
|
||||
<Group>
|
||||
<Text fz={12}>Progres</Text>
|
||||
<Title order={5} c="blue">
|
||||
{donasi.progres} %
|
||||
</Title>
|
||||
</Group>
|
||||
<Group>
|
||||
<Text fz={12}>Dana terkumpul</Text>
|
||||
<Title order={5} c="blue">
|
||||
<TampilanRupiahDonasi nominal={+donasi.terkumpul} />
|
||||
</Title>
|
||||
</Group>
|
||||
{/* <Button w={200} bg={"green.5"} color="green">Pencairan Dana</Button> */}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col md={6} lg={4}>
|
||||
<Paper withBorder p={"sm"} mah={250} h={250}>
|
||||
<Stack spacing={"xl"}>
|
||||
<Center>
|
||||
<Title order={4}>Pencairan Dana</Title>
|
||||
</Center>
|
||||
<Grid>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Stack spacing={0}>
|
||||
<Text fz={"xs"}>Total Dana Dicairkan</Text>
|
||||
<Title>
|
||||
<TampilanRupiahDonasi
|
||||
nominal={donasi.totalPencairan}
|
||||
fontSize={14}
|
||||
/>
|
||||
</Title>
|
||||
</Stack>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Stack spacing={0}>
|
||||
<Text fz={"xs"}>Bank Tujuan</Text>
|
||||
<Title order={6}>{donasi.namaBank}</Title>
|
||||
</Stack>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Stack spacing={0}>
|
||||
<Text fz={"xs"}>Akumulasi Pencairan</Text>
|
||||
<Title order={6}>
|
||||
{donasi.akumulasiPencairan} Kali
|
||||
</Title>
|
||||
</Stack>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={"auto"}>
|
||||
<Stack spacing={0}>
|
||||
<Text fz={"xs"}>Nomor Rekening</Text>
|
||||
<Title order={6}>{donasi.rekening}</Title>
|
||||
</Stack>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
<Button
|
||||
radius={"xl"}
|
||||
onClick={() =>
|
||||
router.push(
|
||||
RouterAdminDonasi.pencairan_dana + `${donasi.id}`
|
||||
)
|
||||
}
|
||||
>
|
||||
Cairkan Dana
|
||||
</Button>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Stack>
|
||||
</Paper>
|
||||
<Modal opened={opened} onClose={close} centered>
|
||||
<PencairanDana />
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function PencairanDana() {
|
||||
return (
|
||||
<>
|
||||
<Stack>
|
||||
<TextInput label="Masukan nominal" />
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
//######################## LIST DONATUR #####################//
|
||||
function TampilanListDonatur({
|
||||
donatur,
|
||||
donasi,
|
||||
@@ -220,3 +313,94 @@ function TampilanListDonatur({
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
//######################## LIST PENCAIRAN #####################//
|
||||
function TampilanListPencairan({
|
||||
pencairan,
|
||||
}: {
|
||||
pencairan: MODEL_DONASI_PENCAIRAN_DANA[];
|
||||
}) {
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
const [gambarId, setGambarId] = useState("");
|
||||
|
||||
const rowTable = pencairan.map((e) => (
|
||||
<tr key={e.id}>
|
||||
<td>
|
||||
<TampilanRupiahDonasi nominal={e.nominalCair} />
|
||||
</td>
|
||||
<td>{moment(e.createdAt).format("ll")}</td>
|
||||
<td>
|
||||
<Text>{e.title}</Text>
|
||||
</td>
|
||||
<td width={500}>
|
||||
<Box w={"100%"}>
|
||||
<Spoiler hideLabel="Sembunyikan" maxHeight={70} showLabel="Lihat">
|
||||
{e.deskripsi}
|
||||
</Spoiler>
|
||||
</Box>
|
||||
</td>
|
||||
<td>
|
||||
{
|
||||
<Box>
|
||||
<Center>
|
||||
<Button
|
||||
radius={"xl"}
|
||||
compact
|
||||
bg={"green"}
|
||||
color="green"
|
||||
onClick={() => {
|
||||
open();
|
||||
setGambarId(e.imagesId);
|
||||
}}
|
||||
>
|
||||
Detail
|
||||
</Button>
|
||||
</Center>
|
||||
</Box>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
));
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal opened={opened} onClose={close} centered>
|
||||
<AspectRatio ratio={9 / 16}>
|
||||
<Image
|
||||
src={RouterDonasi.api_gambar_pencairan + `${gambarId}`}
|
||||
alt="Foto"
|
||||
/>
|
||||
</AspectRatio>
|
||||
</Modal>
|
||||
|
||||
<Stack p={"md"}>
|
||||
<Title order={3}>Rincian Pencairan Dana</Title>
|
||||
{/* <pre>{JSON.stringify(pencairan, null, 2)}</pre> */}
|
||||
{_.isEmpty(pencairan) ? (
|
||||
<Paper bg={"gray.1"} p={"xs"}>
|
||||
<Center>BELUM ADA PENCAIRAN DANA</Center>
|
||||
</Paper>
|
||||
) : (
|
||||
<Paper withBorder p={"xs"}>
|
||||
<Table horizontalSpacing={"md"} verticalSpacing={"md"}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nominal</th>
|
||||
<th>Tanggal</th>
|
||||
<th>Judul</th>
|
||||
<th>
|
||||
<Center>Deskripsi</Center>
|
||||
</th>
|
||||
<th>
|
||||
<Center>Bukti Transfer</Center>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{rowTable}</tbody>
|
||||
</Table>
|
||||
</Paper>
|
||||
)}
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
AspectRatio,
|
||||
Button,
|
||||
Center,
|
||||
FileButton,
|
||||
Image,
|
||||
NumberInput,
|
||||
Paper,
|
||||
Stack,
|
||||
TextInput,
|
||||
Textarea,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import ComponentAdminDonasi_TombolKembali from "../../component/tombol_kembali";
|
||||
import { useState } from "react";
|
||||
import { IconCamera } from "@tabler/icons-react";
|
||||
import ComponentDonasi_NotedBox from "@/app_modules/donasi/component/noted_box";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import { MODEL_DONASI_PENCAIRAN_DANA } from "@/app_modules/donasi/model/interface";
|
||||
import _ from "lodash";
|
||||
import { NotifPeringatan } from "@/app_modules/donasi/component/notifikasi/notif_peringatan";
|
||||
import { AdminDonasi_funCreatePencairanDana } from "../../fun/create/fun_create_pencairan_dana";
|
||||
import { NotifBerhasil } from "@/app_modules/donasi/component/notifikasi/notif_berhasil";
|
||||
import { NotifGagal } from "@/app_modules/donasi/component/notifikasi/notif_gagal";
|
||||
import { AdminDonasi_AkumulasiPencairanById } from "../../fun/update/fun_update_akumulasi_pencairan";
|
||||
|
||||
export default function AdminDonasi_PencairanDana({
|
||||
donasiId,
|
||||
}: {
|
||||
donasiId: string;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [images, setImages] = useState<any | null>();
|
||||
const [value, setValue] = useState({
|
||||
title: "",
|
||||
deskripsi: "",
|
||||
nilai: "",
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<Stack>
|
||||
<ComponentAdminDonasi_TombolKembali />
|
||||
<Center>
|
||||
<Paper
|
||||
p={"md"}
|
||||
w={{ base: 200, sm: 200, md: 300, lg: 400 }}
|
||||
withBorder
|
||||
>
|
||||
<Center mb={"lg"}>
|
||||
<Title order={5}>Form Pencairan Dana</Title>
|
||||
</Center>
|
||||
<Stack>
|
||||
<TextInput
|
||||
withAsterisk
|
||||
type="number"
|
||||
placeholder="Masukan jumlah nominal"
|
||||
label="Nominal"
|
||||
onChange={(val) => {
|
||||
setValue({
|
||||
...value,
|
||||
nilai: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
withAsterisk
|
||||
placeholder="Masukan judul"
|
||||
label="Judul"
|
||||
onChange={(val: any) => {
|
||||
setValue({
|
||||
...value,
|
||||
title: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Textarea
|
||||
withAsterisk
|
||||
placeholder="Masukan deskripsi"
|
||||
label="Deskripsi"
|
||||
onChange={(val: any) => {
|
||||
setValue({
|
||||
...value,
|
||||
deskripsi: val.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
<ComponentDonasi_NotedBox informasi="Wajib menyertakan bukti transfer" />
|
||||
<Stack>
|
||||
<Center>
|
||||
<FileButton
|
||||
onChange={async (files: any | null) => {
|
||||
try {
|
||||
const buffer = URL.createObjectURL(
|
||||
new Blob([new Uint8Array(await files.arrayBuffer())])
|
||||
);
|
||||
// console.log(buffer, "ini buffer");
|
||||
// console.log(files, " ini file");
|
||||
setImages(buffer);
|
||||
setFile(files);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}}
|
||||
accept="image/png,image/jpeg"
|
||||
>
|
||||
{(props) => (
|
||||
<Button
|
||||
{...props}
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
w={150}
|
||||
leftIcon={<IconCamera />}
|
||||
compact
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
)}
|
||||
</FileButton>
|
||||
</Center>
|
||||
{images ? (
|
||||
<AspectRatio ratio={9 / 16}>
|
||||
<Paper radius={"md"} withBorder>
|
||||
<Image
|
||||
alt="Foto"
|
||||
src={images}
|
||||
/>
|
||||
</Paper>
|
||||
</AspectRatio>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</Stack>
|
||||
<Button
|
||||
radius={"xl"}
|
||||
mt={"lg"}
|
||||
onClick={
|
||||
() => onSave(router, value, donasiId, file as any)
|
||||
// console.log(value)
|
||||
}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Center>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function onSave(
|
||||
router: AppRouterInstance,
|
||||
value: any,
|
||||
donasiId: string,
|
||||
file: FormData
|
||||
) {
|
||||
const body = {
|
||||
donasiId: donasiId,
|
||||
nominalCair: value.nilai,
|
||||
title: value.title,
|
||||
deskripsi: value.deskripsi,
|
||||
};
|
||||
|
||||
// console.log(body);
|
||||
|
||||
if (_.values(body).includes("")) return NotifPeringatan("Lengkapi Data");
|
||||
if (!file) return NotifPeringatan("Lampirkan Bukti Transfer");
|
||||
|
||||
const gambar = new FormData();
|
||||
gambar.append("file", file as any);
|
||||
|
||||
await AdminDonasi_funCreatePencairanDana(body as any, gambar).then(
|
||||
async (res) => {
|
||||
if (res.status === 200) {
|
||||
await AdminDonasi_AkumulasiPencairanById(
|
||||
body.donasiId as any,
|
||||
body.nominalCair as any
|
||||
).then((res) => {
|
||||
if (res.status === 200) {
|
||||
NotifBerhasil(res.message);
|
||||
router.back();
|
||||
} else {
|
||||
NotifGagal(res.message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
NotifGagal(res.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -2,18 +2,21 @@
|
||||
|
||||
import {
|
||||
ActionIcon,
|
||||
AspectRatio,
|
||||
Box,
|
||||
Button,
|
||||
Center,
|
||||
Group,
|
||||
HoverCard,
|
||||
Image,
|
||||
Modal,
|
||||
Paper,
|
||||
Stack,
|
||||
Table,
|
||||
Text,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import AdminDonasi_TombolKembali from "../../component/tombol_kembali";
|
||||
import ComponentAdminDonasi_TombolKembali from "../../component/tombol_kembali";
|
||||
import { MODEL_DONASI_INVOICE } from "@/app_modules/donasi/model/interface";
|
||||
import { useState } from "react";
|
||||
import moment from "moment";
|
||||
@@ -24,15 +27,17 @@ import { NotifBerhasil } from "@/app_modules/donasi/component/notifikasi/notif_b
|
||||
import { NotifGagal } from "@/app_modules/donasi/component/notifikasi/notif_gagal";
|
||||
import { AdminDonasi_getListStatusInvoiceProses } from "../../fun/get/get_list_status_invoice_proses";
|
||||
import { AdminDonasi_funUpdateProgresDanTerkumpul } from "../../fun/update/fun_update_progres_dan_terkumpul";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import { RouterAdminDonasi } from "@/app/lib/router_hipmi/router_admin";
|
||||
|
||||
export default function AdminDonasi_ProsesTransaksi({
|
||||
listProses,
|
||||
}: {
|
||||
listProses: MODEL_DONASI_INVOICE[];
|
||||
}) {
|
||||
const [invoice, setInvoice] = useState<MODEL_DONASI_INVOICE[] | any[]>(
|
||||
listProses
|
||||
);
|
||||
const [invoice, setInvoice] = useState<MODEL_DONASI_INVOICE[]>(listProses);
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
const [imageId, setImageId] = useState("");
|
||||
|
||||
async function onClick(invoice: MODEL_DONASI_INVOICE) {
|
||||
let nominal: number = +invoice.nominal;
|
||||
@@ -50,7 +55,7 @@ export default function AdminDonasi_ProsesTransaksi({
|
||||
if (res.status === 200) {
|
||||
await AdminDonasi_getListStatusInvoiceProses(
|
||||
invoice.Donasi.id
|
||||
).then((res) => {
|
||||
).then((res: any) => {
|
||||
setInvoice(res);
|
||||
});
|
||||
} else {
|
||||
@@ -79,6 +84,20 @@ export default function AdminDonasi_ProsesTransaksi({
|
||||
<Button
|
||||
radius={"xl"}
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
open();
|
||||
setImageId(e.imagesId);
|
||||
}}
|
||||
>
|
||||
Lihat
|
||||
</Button>
|
||||
</Center>
|
||||
</td>
|
||||
<td>
|
||||
<Center>
|
||||
<Button
|
||||
radius={"xl"}
|
||||
variant="filled"
|
||||
color="green"
|
||||
onClick={() => onClick(e)}
|
||||
>
|
||||
@@ -91,9 +110,12 @@ export default function AdminDonasi_ProsesTransaksi({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal opened={opened} onClose={close} centered>
|
||||
<ModalBuktiTransfer imageId={imageId} />
|
||||
</Modal>
|
||||
{/* <pre>{JSON.stringify(invoice, null, 2)}</pre> */}
|
||||
<Stack>
|
||||
<AdminDonasi_TombolKembali />
|
||||
<ComponentAdminDonasi_TombolKembali />
|
||||
<Stack>
|
||||
<HeaderPage />
|
||||
|
||||
@@ -107,6 +129,9 @@ export default function AdminDonasi_ProsesTransaksi({
|
||||
<Center>Metode Pembayaran</Center>
|
||||
</th>
|
||||
<th>Tanggal</th>
|
||||
<th>
|
||||
<Center>Bukti Transfer</Center>
|
||||
</th>
|
||||
<th>
|
||||
<Center>Aksi</Center>
|
||||
</th>
|
||||
@@ -151,3 +176,16 @@ function HeaderPage() {
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ModalBuktiTransfer({ imageId }: { imageId: string }) {
|
||||
return (
|
||||
<>
|
||||
<AspectRatio ratio={9 / 16}>
|
||||
<Image
|
||||
alt="Foto"
|
||||
src={RouterAdminDonasi.api_gambar_bukti_transfer + `${imageId}`}
|
||||
/>
|
||||
</AspectRatio>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { MODEL_DONASI_PENCAIRAN_DANA } from "@/app_modules/donasi/model/interface";
|
||||
import _ from "lodash";
|
||||
import { v4 } from "uuid";
|
||||
import fs from "fs";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export async function AdminDonasi_funCreatePencairanDana(
|
||||
req: MODEL_DONASI_PENCAIRAN_DANA,
|
||||
gambar: FormData
|
||||
) {
|
||||
const dataImage: any = gambar.get("file");
|
||||
const fileName = dataImage.name;
|
||||
const fileExtension = _.lowerCase(dataImage.name.split(".").pop());
|
||||
const fRandomName = v4(fileName) + "." + fileExtension;
|
||||
|
||||
const uploadBukti = await prisma.images.create({
|
||||
data: {
|
||||
url: fRandomName,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
url: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!uploadBukti) return { status: 400, message: "Gagal upload gambar" };
|
||||
const uploadFolder = Buffer.from(await dataImage.arrayBuffer());
|
||||
fs.writeFileSync(
|
||||
`./public/donasi/pencairan/${uploadBukti.url}`,
|
||||
uploadFolder
|
||||
);
|
||||
|
||||
const createPencairan = await prisma.donasi_PencairanDana.create({
|
||||
data: {
|
||||
nominalCair: +req.nominalCair,
|
||||
deskripsi: req.deskripsi,
|
||||
title: req.title,
|
||||
donasiId: req.donasiId,
|
||||
imagesId: uploadBukti.id
|
||||
},
|
||||
});
|
||||
|
||||
if (!createPencairan) return { status: 400, message: "Gagal membuat data" };
|
||||
revalidatePath("/dev/admin/donasi/detail/publish");
|
||||
return {
|
||||
status: 200,
|
||||
message: "Berhasil",
|
||||
};
|
||||
}
|
||||
@@ -4,7 +4,10 @@ import prisma from "@/app/lib/prisma";
|
||||
|
||||
export async function AdminDonasi_getByStatus(status: string) {
|
||||
if (status === "1") {
|
||||
const getReview = await prisma.donasi.findMany({
|
||||
const getPublish = await prisma.donasi.findMany({
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
},
|
||||
where: {
|
||||
donasiMaster_StatusDonasiId: "1",
|
||||
},
|
||||
@@ -12,24 +15,25 @@ export async function AdminDonasi_getByStatus(status: string) {
|
||||
id: true,
|
||||
title: true,
|
||||
target: true,
|
||||
active: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
publishTime: true,
|
||||
// active: true,
|
||||
// createdAt: true,
|
||||
// updatedAt: true,
|
||||
// publishTime: true,
|
||||
authorId: true,
|
||||
imagesId: true,
|
||||
donasiMaster_KategoriId: true,
|
||||
donasiMaster_DurasiId: true,
|
||||
donasiMaster_StatusDonasiId: true,
|
||||
Author: true,
|
||||
// imagesId: true,
|
||||
terkumpul: true,
|
||||
// donasiMaster_KategoriId: true,
|
||||
// donasiMaster_DurasiId: true,
|
||||
// donasiMaster_StatusDonasiId: true,
|
||||
// Author: true,
|
||||
imageDonasi: true,
|
||||
CeritaDonasi: true,
|
||||
// CeritaDonasi: true,
|
||||
DonasiMaster_Ketegori: true,
|
||||
DonasiMaster_Durasi: true,
|
||||
DonasiMaster_Status: true,
|
||||
// DonasiMaster_Status: true,
|
||||
},
|
||||
});
|
||||
return getReview;
|
||||
return getPublish;
|
||||
}
|
||||
|
||||
if (status === "2") {
|
||||
@@ -0,0 +1,13 @@
|
||||
"use server"
|
||||
|
||||
import prisma from "@/app/lib/prisma"
|
||||
|
||||
export async function AdminDonasi_getListPencairanDana(donasiId:string) {
|
||||
const data = await prisma.donasi_PencairanDana.findMany({
|
||||
where: {
|
||||
donasiId: donasiId
|
||||
}
|
||||
})
|
||||
|
||||
return data
|
||||
}
|
||||
@@ -15,6 +15,7 @@ export async function AdminDonasi_getListStatusInvoiceProses(donasiId: string) {
|
||||
nominal: true,
|
||||
createdAt: true,
|
||||
Author: true,
|
||||
imagesId: true,
|
||||
Donasi: {
|
||||
select: {
|
||||
id: true,
|
||||
@@ -26,8 +27,6 @@ export async function AdminDonasi_getListStatusInvoiceProses(donasiId: string) {
|
||||
publishTime: true,
|
||||
catatan: true,
|
||||
terkumpul: true,
|
||||
authorId: true,
|
||||
imagesId: true,
|
||||
donasiMaster_KategoriId: true,
|
||||
donasiMaster_DurasiId: true,
|
||||
donasiMaster_StatusDonasiId: true,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
|
||||
export async function AdminDonasi_getById(id: string) {
|
||||
export async function AdminDonasi_getOneById(id: string) {
|
||||
const res = await prisma.donasi.findFirst({
|
||||
where: {
|
||||
id: id,
|
||||
@@ -19,6 +19,10 @@ export async function AdminDonasi_getById(id: string) {
|
||||
progres: true,
|
||||
terkumpul: true,
|
||||
authorId: true,
|
||||
namaBank: true,
|
||||
rekening: true,
|
||||
totalPencairan: true,
|
||||
akumulasiPencairan: true,
|
||||
imagesId: true,
|
||||
donasiMaster_KategoriId: true,
|
||||
donasiMaster_DurasiId: true,
|
||||
@@ -31,5 +35,6 @@ export async function AdminDonasi_getById(id: string) {
|
||||
DonasiMaster_Status: true,
|
||||
},
|
||||
});
|
||||
// console.log(res)
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { MODEL_DONASI } from "@/app_modules/donasi/model/interface";
|
||||
|
||||
export async function AdminDonasi_AkumulasiPencairanById(
|
||||
donasiId: string,
|
||||
nominalPencairan: number
|
||||
) {
|
||||
const cariDonasi = await prisma.donasi.findFirst({
|
||||
where: {
|
||||
id: donasiId,
|
||||
},
|
||||
select: {
|
||||
akumulasiPencairan: true,
|
||||
totalPencairan: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!cariDonasi) return { status: 400, message: "Donasi tidak ditemukan" };
|
||||
|
||||
let akumulasiSementara: number | any = cariDonasi.akumulasiPencairan;
|
||||
let totalSementara: number | any = cariDonasi.totalPencairan;
|
||||
|
||||
// console.log(akumulasiSementara, "akumulasi");
|
||||
// console.log(totalSementara, "total");
|
||||
|
||||
const hasilTotal = totalSementara + Number(nominalPencairan)
|
||||
const hasilAkumulasi = akumulasiSementara + 1;
|
||||
|
||||
const update = await prisma.donasi.update({
|
||||
where: {
|
||||
id: donasiId,
|
||||
},
|
||||
data: {
|
||||
akumulasiPencairan: hasilAkumulasi,
|
||||
totalPencairan: hasilTotal,
|
||||
},
|
||||
});
|
||||
|
||||
if (!update) return { status: 400, message: "Update akumulasi gagal" };
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
message: "Berhasil di simpan",
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
"use server"
|
||||
|
||||
import prisma from "@/app/lib/prisma"
|
||||
|
||||
export async function AdminDonasi_funUpdateCatatanReject(doansiId: string, catatan: string) {
|
||||
const updt = await prisma.donasi.update({
|
||||
where: {
|
||||
id: doansiId
|
||||
},
|
||||
data: {
|
||||
catatan: catatan
|
||||
}
|
||||
})
|
||||
|
||||
if(!updt) return {status: 400, message: "Gagal update"}
|
||||
return {
|
||||
status: 200,
|
||||
message: "Berhasil update"
|
||||
}
|
||||
}
|
||||
3
src/app_modules/admin/donasi/global_state/index.ts
Normal file
3
src/app_modules/admin/donasi/global_state/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { atomWithStorage } from "jotai/utils";
|
||||
|
||||
export const gs_adminDonasi_hotMenu = atomWithStorage("gs_adminDonasi_hotMenu", 0)
|
||||
@@ -6,6 +6,7 @@ import AdminDonasi_DetailReview from "./detail_table/detail_review";
|
||||
import AdminDonasi_TableReject from "./table_status/table_reject";
|
||||
import AdminDonasi_DetailReject from "./detail_table/detail_reject";
|
||||
import AdminDonasi_ProsesTransaksi from "./detail_table/publish/proses_transaksi";
|
||||
import AdminDonasi_PencairanDana from "./detail_table/publish/pencairan_dana";
|
||||
|
||||
export {
|
||||
AdminDonasi_Main,
|
||||
@@ -15,4 +16,6 @@ export {
|
||||
AdminDonasi_TableReject,
|
||||
AdminDonasi_DetailReview,
|
||||
AdminDonasi_DetailReject,
|
||||
AdminDonasi_ProsesTransaksi,
|
||||
AdminDonasi_PencairanDana,
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from "@mantine/core";
|
||||
import { IconChevronLeft, IconEyeCheck } from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import AdminDonasi_TombolKembali from "../component/tombol_kembali";
|
||||
import ComponentAdminDonasi_TombolKembali from "../component/tombol_kembali";
|
||||
import { MODEL_DONASI } from "@/app_modules/donasi/model/interface";
|
||||
import { useState } from "react";
|
||||
import TampilanRupiahDonasi from "@/app_modules/donasi/component/tampilan_rupiah";
|
||||
@@ -27,7 +27,7 @@ export default function AdminDonasi_TablePublish({
|
||||
return (
|
||||
<>
|
||||
<Stack>
|
||||
<AdminDonasi_TombolKembali />
|
||||
<ComponentAdminDonasi_TombolKembali />
|
||||
<TableStatus listPublish={listPublish as any} />
|
||||
</Stack>
|
||||
</>
|
||||
@@ -45,6 +45,9 @@ function TableStatus({ listPublish }: { listPublish: MODEL_DONASI[] }) {
|
||||
<td>
|
||||
<TampilanRupiahDonasi nominal={+e.target} />
|
||||
</td>
|
||||
<td>
|
||||
<TampilanRupiahDonasi nominal={+e.terkumpul}/>
|
||||
</td>
|
||||
<td>{e.DonasiMaster_Ketegori.name}</td>
|
||||
<td>{e.DonasiMaster_Durasi.name} hari</td>
|
||||
<td>
|
||||
@@ -84,6 +87,7 @@ function TableStatus({ listPublish }: { listPublish: MODEL_DONASI[] }) {
|
||||
<tr>
|
||||
<th>Judul</th>
|
||||
<th>Target</th>
|
||||
<th>Terkumpul</th>
|
||||
<th>Ketegori</th>
|
||||
<th>Durasi</th>
|
||||
<th><Center>Aksi</Center></th>
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
} from "@mantine/core";
|
||||
import { IconChevronLeft, IconEyeCheck } from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import AdminDonasi_TombolKembali from "../component/tombol_kembali";
|
||||
import ComponentAdminDonasi_TombolKembali from "../component/tombol_kembali";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import AdminDonasi_DetailReview from "../detail_table/detail_review";
|
||||
import { MODEL_DONASI } from "@/app_modules/donasi/model/interface";
|
||||
@@ -30,7 +30,7 @@ export default function AdminDonasi_TableReject({
|
||||
return (
|
||||
<>
|
||||
<Stack>
|
||||
<AdminDonasi_TombolKembali />
|
||||
<ComponentAdminDonasi_TombolKembali />
|
||||
<TableStatus dataReject={dataReject} />
|
||||
</Stack>
|
||||
</>
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
} from "@mantine/core";
|
||||
import { IconChevronLeft, IconEyeCheck } from "@tabler/icons-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import AdminDonasi_TombolKembali from "../component/tombol_kembali";
|
||||
import ComponentAdminDonasi_TombolKembali from "../component/tombol_kembali";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import AdminDonasi_DetailReview from "../detail_table/detail_review";
|
||||
import { MODEL_DONASI } from "@/app_modules/donasi/model/interface";
|
||||
@@ -30,7 +30,7 @@ export default function AdminDonasi_TableReview({
|
||||
return (
|
||||
<>
|
||||
<Stack>
|
||||
<AdminDonasi_TombolKembali />
|
||||
<ComponentAdminDonasi_TombolKembali />
|
||||
<TableStatus listReview={listReview} />
|
||||
</Stack>
|
||||
</>
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Avatar,
|
||||
Box,
|
||||
Burger,
|
||||
Divider,
|
||||
Drawer,
|
||||
Footer,
|
||||
Group,
|
||||
@@ -31,6 +32,8 @@ import {
|
||||
import { useRouter } from "next/navigation";
|
||||
import { RouterHome } from "@/app/lib/router_hipmi/router_home";
|
||||
import { Logout } from "@/app_modules/auth";
|
||||
import { useAtom } from "jotai";
|
||||
import { gs_adminDonasi_hotMenu } from "../donasi/global_state";
|
||||
|
||||
export default function AdminLayout({
|
||||
children,
|
||||
@@ -40,7 +43,7 @@ export default function AdminLayout({
|
||||
const theme = useMantineTheme();
|
||||
const [opened, setOpened] = useState(false);
|
||||
const router = useRouter();
|
||||
const [active, setActive] = useState(1);
|
||||
const [active, setActive] = useAtom(gs_adminDonasi_hotMenu);
|
||||
|
||||
const listAdminPage = [
|
||||
{
|
||||
@@ -75,15 +78,24 @@ export default function AdminLayout({
|
||||
p="xs"
|
||||
bg={"gray.2"}
|
||||
>
|
||||
{listAdminPage.map((e) => (
|
||||
<NavLink
|
||||
key={e.id}
|
||||
label={e.name}
|
||||
onClick={() => {
|
||||
// setActive(e.id);
|
||||
router.push(e.route);
|
||||
}}
|
||||
/>
|
||||
{listAdminPage.map((e, i) => (
|
||||
<Box key={i}>
|
||||
<NavLink
|
||||
sx={{
|
||||
":hover": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
}}
|
||||
fw={active === i ? "bold" : "normal"}
|
||||
// key={e.id}
|
||||
label={e.name}
|
||||
onClick={() => {
|
||||
setActive(i);
|
||||
router.push(e.route);
|
||||
}}
|
||||
/>
|
||||
{active === i ? <Divider size={"lg"} color="gray" /> : ""}
|
||||
</Box>
|
||||
))}
|
||||
</Navbar>
|
||||
</MediaQuery>
|
||||
|
||||
Reference in New Issue
Block a user