Create dan Update

# feat
- tampilan user
- tampilan admin
## No Issue
This commit is contained in:
2024-01-02 16:35:55 +08:00
parent f02e907bc5
commit 4fc158bdc5
92 changed files with 2357 additions and 851 deletions

View File

@@ -1,17 +1,205 @@
"use client";
import { Button, Stack, Text } from "@mantine/core";
import {
AspectRatio,
Button,
Divider,
Group,
Image,
Modal,
Paper,
Progress,
SimpleGrid,
Stack,
Text,
TextInput,
Textarea,
Title,
} from "@mantine/core";
import AdminDonasi_TombolKembali from "../component/tombol_kembali";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import TampilanRupiahDonasi from "@/app_modules/donasi/component/tampilan_rupiah";
import {
MODEL_CERITA_DONASI,
MODEL_DONASI,
} from "@/app_modules/donasi/model/interface";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { useDisclosure } from "@mantine/hooks";
import { AdminDonasi_funUpdateStatusPublish } from "../fun/update/fun_status_publish";
import { NotifBerhasil } from "@/app_modules/donasi/component/notifikasi/notif_berhasil";
import { NotifPeringatan } from "@/app_modules/donasi/component/notifikasi/notif_peringatan";
import toast from "react-simple-toasts";
import { AdminDonasi_funUpdateStatusReject } from "../fun/update/fun_status_reject";
import _ from "lodash";
import { NotifGagal } from "@/app_modules/donasi/component/notifikasi/notif_gagal";
export default function AdminDonasi_DetailReview({
closeModal,
dataReview,
}: {
closeModal: any;
dataReview: MODEL_DONASI;
}) {
const [donasi, setDonasi] = useState(dataReview);
return (
<>
<Stack>
<Text>Cooming Soon</Text>
<Button onClick={() => closeModal()}>close</Button>
<ButtonOnHeader donasi={donasi} />
<SimpleGrid
cols={2}
spacing="lg"
breakpoints={[
{ maxWidth: "md", cols: 2, spacing: "md" },
{ maxWidth: "sm", cols: 1, spacing: "sm" },
{ maxWidth: "xs", cols: 1, spacing: "xs" },
]}
>
<TampilanDetailDonasi donasi={donasi} />
<CeritaPenggalangDana cerita={donasi.CeritaDonasi} />
</SimpleGrid>
</Stack>
</>
);
}
function ButtonOnHeader({ donasi }: { donasi: MODEL_DONASI }) {
const router = useRouter();
const [opened, { open, close }] = useDisclosure(false);
const [catatan, setCatatan] = useState("");
async function onPulish() {
await AdminDonasi_funUpdateStatusPublish(donasi.id, "1").then((res) => {
if (res.status === 200) {
NotifBerhasil("Berhasil Mengubah Status Donasi");
router.back();
} else {
NotifPeringatan("Gagal Mengubah Status Donasi");
}
});
}
async function onReject() {
if (catatan === "") return NotifPeringatan("Lengkapi Alasan Penolakan");
await AdminDonasi_funUpdateStatusReject(donasi.id, "4", catatan).then(
(res) => {
if (res.status === 200) {
NotifBerhasil(res.message);
router.back()
} else {
NotifGagal(res.message);
}
}
);
}
return (
<>
<Group position="apart">
<AdminDonasi_TombolKembali />
<Group>
<Button
radius={"xl"}
bg={"green"}
color="green"
onClick={() => onPulish()}
>
Publish
</Button>
<Button radius={"xl"} bg={"red"} color="red" onClick={open}>
Reject
</Button>
</Group>
</Group>
<Divider />
<Modal
opened={opened}
onClose={close}
centered
size={"lg"}
withCloseButton={false}
>
<Stack>
<Textarea
autosize
minRows={3}
maxRows={5}
label="Masukan alasan penolakan"
onChange={(val) => setCatatan(val.target.value)}
/>
<Group position="right">
<Button
radius={"xl"}
onClick={() => {
onReject();
}}
>
Simpan
</Button>
</Group>
</Stack>
</Modal>
</>
);
}
function TampilanDetailDonasi({ donasi }: { donasi: MODEL_DONASI }) {
return (
<>
<Paper radius={"md"} p={"md"}>
<Stack>
<Stack>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image
alt="Foto"
src={RouterDonasi.api_gambar + `${donasi.imagesId}`}
/>
</Paper>
</AspectRatio>
<Stack spacing={0}>
<Title order={4}>{donasi.title}</Title>
<Text fz={"xs"}>
Durasi: {donasi.DonasiMaster_Durasi.name} hari
</Text>
</Stack>
<Stack spacing={0}>
<Group>
<Text fz={12}>Dana dibutuhkan</Text>
<Title order={4} c="blue">
<TampilanRupiahDonasi nominal={+donasi.target} />
</Title>
</Group>
<Group>
<Text fz={12}>Kategori</Text>
<Title order={4} c="blue">
{donasi.DonasiMaster_Ketegori.name}
</Title>
</Group>
</Stack>
</Stack>
</Stack>
</Paper>
</>
);
}
function CeritaPenggalangDana({ cerita }: { cerita: MODEL_CERITA_DONASI }) {
return (
<>
<Stack>
<Title order={5}>Cerita Penggalang Dana</Title>
<Text>{cerita.pembukaan}</Text>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image
alt="Foto"
src={RouterDonasi.api_gambar_cerita + `${cerita.imagesId}`}
/>
</Paper>
</AspectRatio>
<Text>{cerita.cerita}</Text>
</Stack>
</>
);

View File

@@ -0,0 +1,50 @@
"use server";
import prisma from "@/app/lib/prisma";
/**
*
* @param status | string > 1 - 4
* @returns jumlah dari donasi per status
*/
export default async function AdminDonasi_funCountByStatus(status: string) {
if (status === "1") {
const count = await prisma.donasi.count({
where: {
donasiMaster_StatusDonasiId: "1",
},
});
return count;
}
if (status === "2") {
const count = await prisma.donasi.count({
where: {
donasiMaster_StatusDonasiId: "2",
},
});
return count;
}
if (status === "3") {
const count = await prisma.donasi.count({
where: {
donasiMaster_StatusDonasiId: "3",
},
});
return count;
}
if (status === "4") {
const count = await prisma.donasi.count({
where: {
donasiMaster_StatusDonasiId: "4",
},
});
return count;
}
if (status === undefined || status === null) {
return {
status: 400,
message: "Parameter tidak sesuai"
}
}
}

View File

@@ -0,0 +1,109 @@
"use server";
import prisma from "@/app/lib/prisma";
export async function AdminDonasi_getByStatus(status: string) {
if (status === "1") {
const getReview = await prisma.donasi.findMany({
where: {
donasiMaster_StatusDonasiId: "1",
},
select: {
id: true,
title: true,
target: true,
active: true,
createdAt: true,
updatedAt: true,
publishTime: true,
authorId: true,
imagesId: true,
donasiMaster_KategoriId: true,
donasiMaster_DurasiId: true,
donasiMaster_StatusDonasiId: true,
Author: true,
imageDonasi: true,
CeritaDonasi: true,
DonasiMaster_Ketegori: true,
DonasiMaster_Durasi: true,
DonasiMaster_Status: true,
},
});
return getReview;
}
if (status === "2") {
const getReview = await prisma.donasi.findMany({
where: {
donasiMaster_StatusDonasiId: "2",
},
select: {
id: true,
title: true,
target: true,
active: true,
createdAt: true,
updatedAt: true,
publishTime: true,
authorId: true,
imagesId: true,
donasiMaster_KategoriId: true,
donasiMaster_DurasiId: true,
donasiMaster_StatusDonasiId: true,
Author: true,
imageDonasi: true,
CeritaDonasi: true,
DonasiMaster_Ketegori: true,
DonasiMaster_Durasi: true,
DonasiMaster_Status: true,
},
});
return getReview;
}
if (status === "3") {
const getReview = await prisma.donasi.findMany({
where: {
donasiMaster_StatusDonasiId: "3",
},
});
return getReview;
}
if (status === "4") {
const getReview = await prisma.donasi.findMany({
where: {
donasiMaster_StatusDonasiId: "4",
},
select: {
id: true,
title: true,
target: true,
active: true,
createdAt: true,
updatedAt: true,
publishTime: true,
catatan: true,
authorId: true,
imagesId: true,
donasiMaster_KategoriId: true,
donasiMaster_DurasiId: true,
donasiMaster_StatusDonasiId: true,
Author: true,
imageDonasi: true,
CeritaDonasi: true,
DonasiMaster_Ketegori: true,
DonasiMaster_Durasi: true,
DonasiMaster_Status: true,
},
});
return getReview;
}
if (status === undefined) {
return {
status: 400,
message: "Not Found",
};
}
}

View File

@@ -0,0 +1,32 @@
"use server";
import prisma from "@/app/lib/prisma";
export async function AdminDonasi_getById(id: string) {
const res = await prisma.donasi.findFirst({
where: {
id: id,
},
select: {
id: true,
title: true,
target: true,
active: true,
createdAt: true,
updatedAt: true,
publishTime: true,
authorId: true,
imagesId: true,
donasiMaster_KategoriId: true,
donasiMaster_DurasiId: true,
donasiMaster_StatusDonasiId: true,
Author: true,
imageDonasi: true,
CeritaDonasi: true,
DonasiMaster_Ketegori: true,
DonasiMaster_Durasi: true,
DonasiMaster_Status: true,
},
});
return res;
}

View File

@@ -0,0 +1,30 @@
"use server";
import prisma from "@/app/lib/prisma";
import { RouterAdminDonasi } from "@/app/lib/router_hipmi/router_admin";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import { revalidatePath } from "next/cache";
export async function AdminDonasi_funUpdateStatusPublish(
donasiId: string,
statusId: string
) {
const publishTime = Date.now();
const data = await prisma.donasi.update({
where: {
id: donasiId,
},
data: {
donasiMaster_StatusDonasiId: statusId,
publishTime: new Date(publishTime),
},
});
if (!data) return { status: 400, message: "Data tidak ditemukan" };
revalidatePath(RouterAdminDonasi.table_review);
return {
status: 200,
message: "Status berhasil diganti",
};
}

View File

@@ -0,0 +1,30 @@
"use server";
import prisma from "@/app/lib/prisma";
import { RouterAdminDonasi } from "@/app/lib/router_hipmi/router_admin";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import { revalidatePath } from "next/cache";
export async function AdminDonasi_funUpdateStatusReject(
donasiId: string,
statusId: string,
catatan: string
) {
const data = await prisma.donasi.update({
where: {
id: donasiId,
},
data: {
donasiMaster_StatusDonasiId: statusId,
catatan: catatan
},
});
if (!data) return { status: 400, message: "Data tidak ditemukan" };
revalidatePath(RouterAdminDonasi.table_review);
return {
status: 200,
message: "Status berhasil diganti",
};
}

View File

@@ -2,12 +2,16 @@ import AdminDonasi_Main from "./main";
import AdminDonasi_TablePublish from "./table_status/table_publish";
import AdminDonasi_DetailPublish from "./detail_table/detail_publish";
import AdminDonasi_TableReview from "./table_status/table_review";
import AdminDonasi_DetailReview from "./detail_table/detail_review";
import AdminDonasi_TableReject from "./table_status/table_reject";
import AdminDonasi_DetailReject from "./detail_table/detail_reject";
export {
AdminDonasi_Main,
AdminDonasi_TablePublish,
AdminDonasi_DetailPublish,
AdminDonasi_TableReview,
AdminDonasi_TableReject
AdminDonasi_TableReject,
AdminDonasi_DetailReview,
AdminDonasi_DetailReject,
};

View File

@@ -16,34 +16,44 @@ import {
import { IconChevronsRight } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
export default function AdminDonasi_Main() {
export default function AdminDonasi_Main({
countPublish,
countReview,
countDraft,
countReject,
}: {
countPublish: number;
countReview: number;
countDraft: number;
countReject: number;
}) {
const router = useRouter();
const listBox = [
{
id: 1,
name: "Publish",
// jumlah: countDraft,
jumlah: countPublish,
link: RouterAdminDonasi.table_publish,
color: "green",
},
{
id: 2,
name: "Review",
// jumlah: countReview,
jumlah: countReview,
link: RouterAdminDonasi.table_review,
color: "orange",
},
{
id: 3,
name: "Draft",
// jumlah: countPublish,
jumlah: countDraft,
link: "",
color: "yellow",
},
{
id: 4,
name: "Reject",
// jumlah: countReject,
jumlah: countReject,
link: RouterAdminDonasi.table_reject,
color: "red",
},
@@ -75,7 +85,7 @@ export default function AdminDonasi_Main() {
<IconChevronsRight color={`${e.color}.2`} />
<Stack align="center" spacing={0}>
<Text>{e.name}</Text>
<Title>10</Title>
<Title>{e.jumlah}</Title>
</Stack>
{e.link !== "" ? (
<ActionIcon radius={"xl"} onClick={() => router.push(e.link)}>

View File

@@ -5,6 +5,7 @@ import {
ActionIcon,
Box,
Button,
Center,
Group,
Stack,
Table,
@@ -14,44 +15,56 @@ import {
import { IconChevronLeft, IconEyeCheck } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import AdminDonasi_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";
export default function AdminDonasi_TablePublish() {
export default function AdminDonasi_TablePublish({
listPublish,
}: {
listPublish: MODEL_DONASI;
}) {
return (
<>
<Stack>
<AdminDonasi_TombolKembali />
<TableStatus />
<TableStatus listPublish={listPublish as any} />
</Stack>
</>
);
}
function TableStatus() {
function TableStatus({ listPublish }: { listPublish: MODEL_DONASI[] }) {
const router = useRouter();
const [donasi, setDonasi] = useState(listPublish);
async function onClick() {
router.push(RouterAdminDonasi.detail_publish);
}
const TableRows = Array(5)
.fill(0)
.map((e, i) => (
<tr key={i}>
<td>{`User ${i + 1}`}</td>
<td>{`Judul ${i + 1}`}</td>
<td>
<Button
compact
color={"green"}
leftIcon={<IconEyeCheck />}
radius={"xl"}
variant="outline"
onClick={onClick}
>
Tampilkan
</Button>
</td>
</tr>
));
const TableRows = donasi.map((e, i) => (
<tr key={i}>
<td>{e.title}</td>
<td>
<TampilanRupiahDonasi nominal={+e.target} />
</td>
<td>{e.DonasiMaster_Ketegori.name}</td>
<td>{e.DonasiMaster_Durasi.name} hari</td>
<td>
<Center>
<Button
compact
color={"green"}
leftIcon={<IconEyeCheck />}
radius={"xl"}
variant="outline"
onClick={onClick}
>
Tampilkan
</Button>
</Center>
</td>
</tr>
));
return (
<>
@@ -71,9 +84,11 @@ function TableStatus() {
>
<thead>
<tr>
<th>Name</th>
<th>Judul</th>
<th>Aksi</th>
<th>Target</th>
<th>Ketegori</th>
<th>Durasi</th>
<th><Center>Aksi</Center></th>
</tr>
</thead>
<tbody>{TableRows}</tbody>

View File

@@ -5,6 +5,7 @@ import {
ActionIcon,
Box,
Button,
Center,
Group,
Modal,
Stack,
@@ -17,46 +18,69 @@ import { useRouter } from "next/navigation";
import AdminDonasi_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";
import { useState } from "react";
import TampilanRupiahDonasi from "@/app_modules/donasi/component/tampilan_rupiah";
export default function AdminDonasi_TableReject() {
export default function AdminDonasi_TableReject({
dataReject,
}: {
dataReject: MODEL_DONASI[];
}) {
return (
<>
<Stack>
<AdminDonasi_TombolKembali />
<TableStatus />
<TableStatus dataReject={dataReject} />
</Stack>
</>
);
}
function TableStatus() {
function TableStatus({ dataReject }: { dataReject: MODEL_DONASI[] }) {
const router = useRouter();
const [opened, { open, close }] = useDisclosure(false);
const [donasi, setDonasi] = useState(dataReject);
async function onClick() {
// router.push(RouterAdminDonasi.detail_publish);
function onClick() {
return (
<Modal opened={opened} onClose={close} centered withCloseButton={false}>
<Stack>
<Title order={6}>Alasan penolakan</Title>
<Text>{"test"}</Text>
</Stack>
</Modal>
);
}
const TableRows = Array(5)
.fill(0)
.map((e, i) => (
<tr key={i}>
<td>{`User ${i + 1}`}</td>
<td>{`Judul ${i + 1}`}</td>
<td>
const TableRows = donasi.map((e, i) => (
<tr key={i}>
<td>{e.title}</td>
<td>
<TampilanRupiahDonasi nominal={+e.target} />
</td>
<td>{e.DonasiMaster_Ketegori.name}</td>
<td>{e.DonasiMaster_Durasi.name} hari</td>
<td>{e.catatan}</td>
<td>
<Center>
<Button
compact
color={"red"}
leftIcon={<IconEyeCheck />}
radius={"xl"}
variant="outline"
onClick={open}
onClick={() => {
onClick()
// onClick(e.catatan);
}}
>
Tampilkan
</Button>
</td>
</tr>
));
</Center>
</td>
</tr>
));
return (
<>
@@ -76,18 +100,19 @@ function TableStatus() {
>
<thead>
<tr>
<th>Name</th>
<th>Judul</th>
<th>Aksi</th>
<th>Target</th>
<th>Ketegori</th>
<th>Durasi</th>
<th>Catatan</th>
<th>
<Center>Lihat alasan</Center>
</th>
</tr>
</thead>
<tbody>{TableRows}</tbody>
</Table>
</Box>
<Modal opened={opened} onClose={close}>
<AdminDonasi_DetailReview closeModal={close}/>
</Modal>
</>
);
}

View File

@@ -5,6 +5,7 @@ import {
ActionIcon,
Box,
Button,
Center,
Group,
Modal,
Stack,
@@ -17,46 +18,58 @@ import { useRouter } from "next/navigation";
import AdminDonasi_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";
import { useState } from "react";
import TampilanRupiahDonasi from "@/app_modules/donasi/component/tampilan_rupiah";
export default function AdminDonasi_TableReview() {
export default function AdminDonasi_TableReview({
listReview,
}: {
listReview: MODEL_DONASI[];
}) {
return (
<>
<Stack>
<AdminDonasi_TombolKembali />
<TableStatus />
<TableStatus listReview={listReview} />
</Stack>
</>
);
}
function TableStatus() {
function TableStatus({ listReview }: { listReview: MODEL_DONASI[] }) {
const router = useRouter();
const [opened, { open, close }] = useDisclosure(false);
const [donasi, setDonasi] = useState(listReview);
async function onClick() {
// router.push(RouterAdminDonasi.detail_publish);
}
const TableRows = Array(5)
.fill(0)
.map((e, i) => (
<tr key={i}>
<td>{`User ${i + 1}`}</td>
<td>{`Judul ${i + 1}`}</td>
<td>
<Button
compact
color={"orange"}
leftIcon={<IconEyeCheck />}
radius={"xl"}
variant="outline"
onClick={open}
>
Tampilkan
</Button>
</td>
</tr>
));
const TableRows = donasi.map((e, i) => (
<tr key={i}>
<td>{e.title}</td>
<td>
<TampilanRupiahDonasi nominal={+e.target} />
</td>
<td>{e.DonasiMaster_Ketegori.name}</td>
<td>{e.DonasiMaster_Durasi.name} hari</td>
<td>
<Center>
<Button
compact
color={"orange"}
leftIcon={<IconEyeCheck />}
radius={"xl"}
variant="outline"
onClick={() => router.push(RouterAdminDonasi.detail_review + `${e.id}`)}
>
Tampilkan
</Button>
</Center>
</td>
</tr>
));
return (
<>
@@ -76,18 +89,20 @@ function TableStatus() {
>
<thead>
<tr>
<th>Name</th>
<th>Judul</th>
<th>Aksi</th>
<th>Target</th>
<th>Ketegori</th>
<th>Durasi</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{TableRows}</tbody>
</Table>
</Box>
<Modal opened={opened} onClose={close}>
<AdminDonasi_DetailReview closeModal={close}/>
</Modal>
</>
);
}