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

@@ -16,6 +16,7 @@
"@mantine/dropzone": "^7.1.3",
"@mantine/hooks": "^6.0.17",
"@mantine/next": "^6.0.17",
"@mantine/notifications": "^6.0.17",
"@prisma/client": "^5.0.0",
"@tabler/icons-react": "^2.38.0",
"@types/lodash": "^4.14.199",

View File

@@ -281,9 +281,10 @@ model Donasi {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
publishTime DateTime?
catatan String?
Author User? @relation(fields: [authorId], references: [id])
authorId String? @unique
authorId String?
imageDonasi Images? @relation(fields: [imagesId], references: [id])
imagesId String? @unique
CeritaDonasi Donasi_Cerita?

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,32 @@
import prisma from "@/app/lib/prisma";
import fs from "fs";
import { NextRequest, NextResponse } from "next/server";
export async function GET(
req: NextRequest,
{ params }: { params: { id: string } }
) {
const get = await prisma.images.findUnique({
where: {
id: params.id,
},
select: {
url: true,
},
});
if (!fs.existsSync(`./public/donasi/image/${get?.url}`)) {
const notFile = fs.readFileSync("./public/aset/global/no_img.png");
return new NextResponse(notFile, {
headers: {
"Content-Type": "image/png",
},
});
}
const file = fs.readFileSync(`./public/donasi/image/${get?.url}`);
return new NextResponse(file, {
headers: {
"Content-Type": "image/png",
},
});
}

View File

@@ -0,0 +1,34 @@
import prisma from "@/app/lib/prisma";
import fs from "fs";
import { NextRequest, NextResponse } from "next/server";
export async function GET(
req: NextRequest,
{ params }: { params: { id: string } }
) {
const get = await prisma.images.findUnique({
where: {
id: params.id,
},
select: {
url: true,
},
});
if (!fs.existsSync(`./public/donasi/image_cerita/${get?.url}`)) {
const notFile = fs.readFileSync("./public/aset/global/no_img.png");
return new NextResponse(notFile, {
headers: {
"Content-Type": "image/png",
},
});
}
const file = fs.readFileSync(`./public/donasi/image_cerita/${get?.url}`);
return new NextResponse(file, {
headers: {
"Content-Type": "image/png",
},
});
}

View File

@@ -0,0 +1,23 @@
import fs from "fs";
import { NextRequest, NextResponse } from "next/server";
export async function GET(
req: NextRequest,
{ params }: { params: { url: string } }
) {
if (!fs.existsSync(`./public/donasi/image/${params.url}`)) {
const notFile = fs.readFileSync("./public/aset/global/no_img.png");
return new NextResponse(notFile, {
headers: {
"Content-Type": "image/png",
},
});
}
const file = fs.readFileSync(`./public/donasi/image/${params.url}`);
return new NextResponse(file, {
headers: {
"Content-Type": "image/png",
},
});
}

View File

@@ -0,0 +1,25 @@
import { NextRequest, NextResponse } from "next/server";
import fs from "fs"
export async function GET(
req: NextRequest,
{ params }: { params: { url: string } }
) {
if (!fs.existsSync(`./public/donasi/image_cerita/${params.url}`)) {
const notFile = fs.readFileSync("./public/aset/global/no_img.png");
return new NextResponse(notFile, {
headers: {
"Content-Type": "image/png",
},
});
}
const file = fs.readFileSync(`./public/donasi/image_cerita/${params.url}`);
return new NextResponse(file, {
headers: {
"Content-Type": "image/png",
},
});
}

View File

@@ -0,0 +1 @@
# Test

View File

@@ -0,0 +1,9 @@
import { AdminDonasi_DetailReview } from "@/app_modules/admin/donasi";
import { AdminDonasi_getById } from "@/app_modules/admin/donasi/fun/get/get_one_by_id";
export default async function Page({params}: {params: {id: string}}) {
// console.log(params.id)
const dataReview = await AdminDonasi_getById(params.id)
// console.log(dataReview)
return <AdminDonasi_DetailReview dataReview={dataReview as any}/>
}

View File

@@ -1,10 +1,20 @@
import { AdminDonasi_Main } from "@/app_modules/admin/donasi";
import AdminDonasi_funCountByStatus from "@/app_modules/admin/donasi/fun/count/fun_count_donasi_by_status";
export default async function Page() {
const countPublish = await AdminDonasi_funCountByStatus("1");
const countReview = await AdminDonasi_funCountByStatus("2");
const countDraft = await AdminDonasi_funCountByStatus("3");
const countReject = await AdminDonasi_funCountByStatus("4");
return (
<>
<AdminDonasi_Main />
<AdminDonasi_Main
countPublish={countPublish as number}
countReview={countReview as number}
countDraft={countDraft as number}
countReject={countReject as number}
/>
</>
);
}

View File

@@ -1,7 +1,10 @@
import { AdminDonasi_TablePublish } from "@/app_modules/admin/donasi";
import { AdminDonasi_getByStatus } from "@/app_modules/admin/donasi/fun/get/get_donasi_by_status";
export default async function Page() {
const listPublish = await AdminDonasi_getByStatus("1")
// console.log(listPublish)
return<>
<AdminDonasi_TablePublish/>
<AdminDonasi_TablePublish listPublish={listPublish as any}/>
</>
}

View File

@@ -1,7 +1,10 @@
import { AdminDonasi_TableReject } from "@/app_modules/admin/donasi";
import { AdminDonasi_getByStatus } from "@/app_modules/admin/donasi/fun/get/get_donasi_by_status";
export default async function Page() {
const dataReject = await AdminDonasi_getByStatus("4")
// console.log(dataReject)
return<>
<AdminDonasi_TableReject/>
<AdminDonasi_TableReject dataReject={dataReject as any}/>
</>
}

View File

@@ -1,5 +1,9 @@
import { AdminDonasi_TableReview } from "@/app_modules/admin/donasi";
import { AdminDonasi_getByStatus } from "@/app_modules/admin/donasi/fun/get/get_donasi_by_status";
import { getToken_UserId } from "@/app_modules/fun/get_user_token";
export default async function Page() {
return <AdminDonasi_TableReview />;
const listReview = await AdminDonasi_getByStatus("2");
// console.log(listReview);
return <AdminDonasi_TableReview listReview={listReview as any} />;
}

View File

@@ -0,0 +1,21 @@
import { LayoutCeritaPenggalangDonasi } from "@/app_modules/donasi";
import { Donasi_getOneById } from "@/app_modules/donasi/fun/get/get_one_donasi_by_id";
import React from "react";
export default async function Layout({
children,
params,
}: {
children: React.ReactNode;
params: { id: string };
}) {
const dataDonasi = await Donasi_getOneById(params.id);
const statusDonasiId = dataDonasi?.donasiMaster_StatusDonasiId;
return (
<>
<LayoutCeritaPenggalangDonasi statusDonasiId={statusDonasiId as string}>
{children}
</LayoutCeritaPenggalangDonasi>
</>
);
}

View File

@@ -0,0 +1,12 @@
import { CeritaPenggalangDonasi } from "@/app_modules/donasi";
import Donasi_getCeritaByDonasiId from "@/app_modules/donasi/fun/get/get_cerita_penggalang";
export default async function Page({ params }: { params: { id: string } }) {
const dataCerita = await Donasi_getCeritaByDonasiId(params.id);
// console.log(dataCerita)
return (
<>
<CeritaPenggalangDonasi dataCerita={dataCerita as any}/>
</>
);
}

View File

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

View File

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

View File

@@ -1,13 +1,12 @@
import { CreateCeritaPenggalangDonasi } from "@/app_modules/donasi";
import { Donasi_getTemporaryCreate } from "@/app_modules/donasi/fun/get/get_temporary_create";
import { funGetUserToken } from "@/app_modules/fun/fun_get_user_token";
import { getToken_UserId } from "@/app_modules/fun/get_user_token";
export default async function Page({ params }: { params: { id: string } }) {
const getTemporaryCreate = await Donasi_getTemporaryCreate(params.id);
const getToken = await funGetUserToken()
const userId = getToken.id
const userId = await getToken_UserId()
return (
<>

View File

@@ -3,13 +3,11 @@ import {
Donasi_getMasterDurasi,
Donasi_getMasterKategori,
} from "@/app_modules/donasi/fun";
import { funGetUserToken } from "@/app_modules/fun/fun_get_user_token";
import { getToken_UserId } from "@/app_modules/fun/get_user_token";
export default async function Page() {
const masterKategori = await Donasi_getMasterKategori();
const masterDurasi = await Donasi_getMasterDurasi();
const getToken = await funGetUserToken()
const userId = getToken.id
return (
<CreateDonasi masterKategori={masterKategori} masterDurasi={masterDurasi} />

View File

@@ -3,12 +3,14 @@ import React from "react";
export default async function Layout({
children,
params
}: {
children: React.ReactNode;
params: {id: string}
}) {
return (
<>
<LayoutDetailDraftDonasi>{children}</LayoutDetailDraftDonasi>
<LayoutDetailDraftDonasi donasiId={params.id} >{children}</LayoutDetailDraftDonasi>
</>
);
}

View File

@@ -0,0 +1,12 @@
import { DetailDraftDonasi } from "@/app_modules/donasi";
import { Donasi_getOneById } from "@/app_modules/donasi/fun/get/get_one_donasi_by_id";
export default async function Page({ params }: { params: { id: string } }) {
const dataDonasi = await Donasi_getOneById(params.id);
return (
<>
<DetailDraftDonasi dataDonasi={dataDonasi as any} />
</>
);
}

View File

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

View File

@@ -0,0 +1,12 @@
import { DetailReviewDonasi } from "@/app_modules/donasi";
import { Donasi_getOneById } from "@/app_modules/donasi/fun/get/get_one_donasi_by_id";
export default async function Page({ params }: { params: { id: string } }) {
const dataDonasi = await Donasi_getOneById(params.id);
return (
<>
<DetailReviewDonasi dataDonasi={dataDonasi as any} />
</>
);
}

View File

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

View File

@@ -0,0 +1,12 @@
import { EditCeritaPenggalangDonasi } from "@/app_modules/donasi";
import Donasi_getCeritaByDonasiId from "@/app_modules/donasi/fun/get/get_cerita_penggalang";
export default async function Page({ params }: { params: { id: string } }) {
const dataCerita = await Donasi_getCeritaByDonasiId(params.id)
// console.log(dataCerita);
return (
<>
<EditCeritaPenggalangDonasi dataCerita={dataCerita as any} />
</>
);
}

View File

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

View File

@@ -0,0 +1,15 @@
import { EditDonasi } from "@/app_modules/donasi";
import { Donasi_getMasterDurasi, Donasi_getMasterKategori } from "@/app_modules/donasi/fun";
import { Donasi_getOneById } from "@/app_modules/donasi/fun/get/get_one_donasi_by_id";
export default async function Page({params}: {params: {id: string}}) {
const dataDonasi = await Donasi_getOneById(params.id)
const masterKategori = await Donasi_getMasterKategori()
const masterDurasi = await Donasi_getMasterDurasi()
return (
<>
<EditDonasi dataDonasi={dataDonasi as any} masterKategori={masterKategori} masterDurasi={masterDurasi} />
</>
);
}

View File

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

View File

@@ -1,7 +1,17 @@
import { PostingDonasi } from "@/app_modules/donasi";
import Donasi_getByStatus from "@/app_modules/donasi/fun/get/get_donasi_by_status";
import { getToken_UserId } from "@/app_modules/fun/get_user_token";
export default async function Page() {
return<>
<PostingDonasi/>
const authorId = await getToken_UserId();
const listReview = await Donasi_getByStatus(authorId, "2");
const listDraft = await Donasi_getByStatus(authorId, "3");
// console.log(listReview)
return (
<>
<PostingDonasi listReview={listReview} listDraft={listDraft} />
</>
}
);
}

View File

@@ -3,6 +3,7 @@ import AppNotif from "@/app_modules/notif";
// import './globals.css'
import { CacheProvider } from "@emotion/react";
import { MantineProvider, useEmotionCache } from "@mantine/core";
import { Notifications } from "@mantine/notifications";
import { useServerInsertedHTML } from "next/navigation";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
@@ -29,9 +30,10 @@ export default function RootStyleRegistry({
<body suppressHydrationWarning={true}>
<CacheProvider value={cache}>
<MantineProvider withGlobalStyles withNormalizeCSS>
<Notifications position="top-center" containerWidth="250px" />
{children}
<ToastContainer position="bottom-center" />
<AppNotif />
{/* <ToastContainer position="bottom-center" />
<AppNotif /> */}
</MantineProvider>
</CacheProvider>
</body>

View File

@@ -24,6 +24,9 @@ export const RouterAdminDonasi = {
// detail
detail_publish: "/dev/admin/donasi/detail/publish",
detail_review: "/dev/admin/donasi/detail/review/",
};
export const RouterAdminAward = {

View File

@@ -1,4 +1,10 @@
export const RouterDonasi = {
//api
api_gambar: "/api/donasi/gambar/",
api_gambar_cerita: "/api/donasi/gambar_cerita/",
api_image: "/api/donasi/image/",
api_image_cerita: "/api/donasi/image_cerita/",
//main
main_beranda: "/dev/donasi/main/beranda",
main_galang_dana: "/dev/donasi/main/galang_dana",
@@ -10,9 +16,8 @@ export const RouterDonasi = {
// edit
update_kabar: "/dev/donasi/edit/update_kabar",
edit_donasi: "/dev/donasi/edit/edit_donasi",
edit_cerita_penggalang: "/dev/donasi/edit/edit_cerita",
edit_donasi: "/dev/donasi/edit/edit_donasi/",
edit_cerita_penggalang: "/dev/donasi/edit/edit_cerita/",
//pop up
page_pop_up_create: "/dev/donasi/page_pop_up/create",
@@ -21,8 +26,8 @@ export const RouterDonasi = {
detail_main: "/dev/donasi/detail/detail_main",
detail_kabar: "/dev/donasi/detail/detail_kabar",
detail_publish: "/dev/donasi/detail/detail_publish",
detail_review: "/dev/donasi/detail/detail_review",
detail_draft: "/dev/donasi/detail/detail_draft",
detail_review: "/dev/donasi/detail/detail_review/",
detail_draft: "/dev/donasi/detail/detail_draft/",
detail_reject: "/dev/donasi/detail/detail_reject",
detail_donasi_saya: "/dev/donasi/detail/detail_donasi_saya",
@@ -32,6 +37,6 @@ export const RouterDonasi = {
kabar: "/dev/donasi/kabar",
pencairan_dana: "/dev/donasi/pencairan_dana",
penggalang_dana: "/dev/donasi/penggalang_dana",
cerita_penggalang: "/dev/donasi/cerita_penggalang",
list_kabar: "/dev/donasi/list_kabar"
cerita_penggalang: "/dev/donasi/cerita_penggalang/",
list_kabar: "/dev/donasi/list_kabar",
};

19
src/app/zCoba/page.tsx Normal file
View File

@@ -0,0 +1,19 @@
"use client";
import { NotifPeringatan } from "@/app_modules/donasi/component/notifikasi/notif_peringatan";
import { Box, Button, Group } from "@mantine/core";
import { notifications } from "@mantine/notifications";
export default function Coba() {
return (
<>
<Box p={"lg"}>
<Group position="center">
<Button variant="outline" onClick={() => NotifPeringatan("Coba")}>
Show notification
</Button>
</Group>
</Box>
</>
);
}

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

View File

@@ -0,0 +1,40 @@
"use client";
import { useRouter } from "next/navigation";
import { MODEL_DONASI } from "../../model/interface";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import { Stack, Title, Paper, Group, ActionIcon, Text } from "@mantine/core";
import { IconCircleChevronRight } from "@tabler/icons-react";
import moment from "moment";
export default function ComponentCeritaPenggalangDanaDonasi({
donasi,
}: {
donasi: MODEL_DONASI;
}) {
const router = useRouter();
return (
<>
<Stack spacing={"xs"}>
<Title order={4}>Cerita Penggalang Dana</Title>
<Paper p={"sm"} withBorder>
<Stack>
<Group position="apart">
<Text>{moment(donasi.createdAt).format("ll")}</Text>
<ActionIcon
variant="transparent"
onClick={() => router.push(RouterDonasi.cerita_penggalang + `${donasi.id}`)}
>
<IconCircleChevronRight />
</ActionIcon>
</Group>
<Text lineClamp={4}>
{donasi.CeritaDonasi.cerita}
</Text>
{/* <Text c={"blue"}>Baca selengkapnya</Text> */}
</Stack>
</Paper>
</Stack>
</>
);
}

View File

@@ -0,0 +1,31 @@
import { Center, Text } from "@mantine/core";
import { notifications } from "@mantine/notifications";
import { IconAlertTriangle, IconChecklist, IconCircleCheck } from "@tabler/icons-react";
/**
*
* @param text | masukan text untuk peringatan
* @type string
* @returns notifikasi peringatan
*/
export async function NotifBerhasil(text: string) {
return notifications.show({
message: (
<Center>
<Text fw={"bold"}>{text}</Text>
</Center>
),
color: "green",
radius: "md",
autoClose: 1000,
icon: <IconCircleCheck color="white" />,
withCloseButton: false,
styles: (theme) => ({
description: { color: theme.white },
root: {
backgroundColor: theme.colors.green[7],
},
}),
});
}

View File

@@ -0,0 +1,31 @@
import { Center, Text } from "@mantine/core";
import { notifications } from "@mantine/notifications";
import { IconAlertTriangle } from "@tabler/icons-react";
/**
*
* @param text | masukan text untuk peringatan
* @type string
* @returns notifikasi peringatan
*/
export async function NotifGagal(text: string) {
return notifications.show({
message: (
<Center>
<Text fw={"bold"}>{text}</Text>
</Center>
),
color: "red",
radius: "md",
autoClose: 1000,
icon: <IconAlertTriangle color="white" />,
withCloseButton: false,
styles: (theme) => ({
description: { color: theme.white },
root: {
backgroundColor: theme.colors.red[7],
},
}),
});
}

View File

@@ -0,0 +1,31 @@
import { Center, Text } from "@mantine/core";
import { notifications } from "@mantine/notifications";
import { IconAlertTriangle } from "@tabler/icons-react";
/**
*
* @param text | masukan text untuk peringatan
* @type string
* @returns notifikasi peringatan
*/
export async function NotifPeringatan(text: string) {
return notifications.show({
message: (
<Center>
<Text fw={"bold"}>{text}</Text>
</Center>
),
color: "yellow",
radius: "md",
autoClose: 1000,
icon: <IconAlertTriangle color="white" />,
withCloseButton: false,
styles: (theme) => ({
description: { color: theme.white },
root: {
backgroundColor: theme.colors.yellow[7],
},
}),
});
}

View File

@@ -0,0 +1,14 @@
import { Text } from "@mantine/core";
export default function TampilanRupiahDonasi({nominal}: {nominal: number}) {
return (
<>
<Text>
Rp.{" "}
{new Intl.NumberFormat("id-ID", { maximumFractionDigits: 10 }).format(
nominal
)}
</Text>
</>
);
}

View File

@@ -21,13 +21,15 @@ import { MODEL_DONASI_TEMPORARY } from "../model/interface";
import _ from "lodash";
import toast from "react-simple-toasts";
import { Donasi_funCreate } from "../fun/create/fun_create_donasi";
import { notifications } from "@mantine/notifications";
import { NotifPeringatan } from "../component/notifikasi/notif_peringatan";
export default function CreateCeritaPenggalangDonasi({
dataTemporary,
userId
userId,
}: {
dataTemporary: MODEL_DONASI_TEMPORARY;
userId: string
userId: string;
}) {
const router = useRouter();
const [tabsPostingDonasi, setTabsPostingDonasi] = useAtom(
@@ -42,8 +44,8 @@ export default function CreateCeritaPenggalangDonasi({
const [imageCerita, setImageCerita] = useState<any | null>();
async function onCreate() {
if (_.values(create).includes("")) return toast("Lengkapi Data");
if (!file) return toast("Lengkapi Gambar");
if (_.values(create).includes("")) return NotifPeringatan("Lengkapin Data");
if (!file) return NotifPeringatan("Lengkapi Gambar");
const gambar = new FormData();
gambar.append("file", file as any);
@@ -67,7 +69,7 @@ export default function CreateCeritaPenggalangDonasi({
router.push(RouterDonasi.page_pop_up_create);
setTabsPostingDonasi("Review");
} else {
toast(res.message)
toast(res.message);
}
});
}

View File

@@ -27,6 +27,8 @@ import { useShallowEffect } from "@mantine/hooks";
import Donasi_funCreateTemporary from "../fun/create/fun_create_donasi_temporary";
import toast from "react-simple-toasts";
import _ from "lodash";
import { notifications } from "@mantine/notifications";
import { NotifPeringatan } from "../component/notifikasi/notif_peringatan";
export default function CreateDonasi({
masterKategori,
@@ -48,13 +50,20 @@ export default function CreateDonasi({
const [imageDonasi, setImageDonasi] = useState<any | null>();
async function onCreate() {
if (_.values(create).includes("")) return toast("Lengkapi Data");
if (!file) return toast("Lengkapi Gambar");
const body = {
donasiMaster_KategoriId: create.kategoriId,
donasiMaster_DurasiId: create.durasiId,
title: create.title,
target: create.target,
};
if (_.values(body).includes("")) return NotifPeringatan("Lengkapin Data");
if (!file) return NotifPeringatan("Lengkapi Gambar");
const gambar = new FormData();
gambar.append("file", file as any);
await Donasi_funCreateTemporary(create as any, gambar).then((res) => {
await Donasi_funCreateTemporary(body as any, gambar).then((res) => {
if (res.status === 201) {
router.push(RouterDonasi.create_cerita_penggalang + `${res.donasiId}`);
} else {
@@ -146,7 +155,7 @@ export default function CreateDonasi({
withAsterisk
data={durasi.map((e) => ({
value: e.id,
label: e.name + " " + `bulan`,
label: e.name + " " + `hari`,
}))}
onChange={(val: string) => setCreate({ ...create, durasiId: val })}
/>

View File

@@ -27,60 +27,100 @@ import { useRouter } from "next/navigation";
import BoxInformasiDonasi from "../../component/box_informasi";
import { useAtom } from "jotai";
import { gs_donasi_tabs_posting } from "../../global_state";
import { MODEL_DONASI } from "../../model/interface";
import { useState } from "react";
import TampilanRupiahDonasi from "../../component/tampilan_rupiah";
import ComponentCeritaPenggalangDanaDonasi from "../../component/detail_main/cerita_penggalang";
import { Donasi_funGantiStatus } from "../../fun/update/fun_ganti_status";
import { NotifBerhasil } from "../../component/notifikasi/notif_berhasil";
import { NotifPeringatan } from "../../component/notifikasi/notif_peringatan";
import { useShallowEffect } from "@mantine/hooks";
export default function DetailDraftDonasi() {
const router = useRouter()
const [tabsPostingDonasi, setTabsPostingDonasi] = useAtom(
gs_donasi_tabs_posting
);
async function onClick() {
router.push(RouterDonasi.main_galang_dana)
setTabsPostingDonasi("Review")
}
export default function DetailDraftDonasi({
dataDonasi,
}: {
dataDonasi: MODEL_DONASI;
}) {
return (
<>
<Stack spacing={"xl"}>
<DetailDonasi />
{/* <InformasiPenggalangDana /> */}
<CeritaPenggalangDana />
<Button
radius={"xl"}
bg={"orange"}
color="orange"
onClick={() => onClick()}
>
Ajukan Penggalangan Dana
</Button>
<DetailDonasi dataDonasi={dataDonasi} />
<ComponentCeritaPenggalangDanaDonasi donasi={dataDonasi} />
<ButtonAjukanPenggalangan dataDonasi={dataDonasi} />
</Stack>
</>
);
}
function DetailDonasi() {
function ButtonAjukanPenggalangan({
dataDonasi,
}: {
dataDonasi: MODEL_DONASI;
}) {
const router = useRouter();
const [tabsPostingDonasi, setTabsPostingDonasi] = useAtom(
gs_donasi_tabs_posting
);
async function onCLick() {
await Donasi_funGantiStatus(dataDonasi.id, "2").then((res) => {
if (res.status === 200) {
router.push(RouterDonasi.main_galang_dana);
setTabsPostingDonasi("Review");
NotifBerhasil("Berhasil Diajukan");
} else {
NotifPeringatan(res.message);
}
});
}
return (
<>
<Button
radius={"xl"}
bg={"orange"}
color="orange"
onClick={() => onCLick()}
>
Ajukan Penggalangan Dana
</Button>
</>
);
}
function DetailDonasi({ dataDonasi }: { dataDonasi: MODEL_DONASI }) {
const [donasi, setDonasi] = useState(dataDonasi);
useShallowEffect(() => {
setDonasi(dataDonasi);
}, [dataDonasi]);
return (
<>
<Stack>
<Stack>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image alt="Foto" src={"/aset/no-img.png"} />
<Image
alt="Foto"
src={RouterDonasi.api_image + `${donasi.imageDonasi.url}`}
/>
</Paper>
</AspectRatio>
<Title order={4}>Judul Donasi</Title>
<Stack spacing={0}>
<Title order={4}>{donasi.title}</Title>
<Text fz={"xs"}>
Durasi: {donasi.DonasiMaster_Durasi.name} hari
</Text>
</Stack>
<Stack spacing={0}>
<Group position="apart">
<Stack spacing={0}>
<Text fz={12}>Dana dibutuhkan</Text>
<Title order={4} c="blue">
Rp. 50.000.000
<TampilanRupiahDonasi nominal={+donasi.target} />
</Title>
</Stack>
<Stack spacing={0}>
<Text fz={12}>Kategori</Text>
<Title order={4} c="blue">
Kesehatan
{donasi.DonasiMaster_Ketegori.name}
</Title>
</Stack>
</Group>
@@ -90,68 +130,3 @@ function DetailDonasi() {
</>
);
}
function InformasiPenggalangDana() {
const router = useRouter();
return (
<>
<Stack spacing={"xs"}>
<Title order={4}>Informasi Penggalang Dana</Title>
<Paper p={"sm"} withBorder>
<Stack>
<Group position="apart">
<Title order={5}>Penggalang Dana</Title>
<ActionIcon
variant="transparent"
onClick={() => router.push(RouterDonasi.penggalang_dana)}
>
<IconCircleChevronRight />
</ActionIcon>
</Group>
<Group>
<Avatar radius={"xl"} variant="filled" bg={"blue"}>
U
</Avatar>
<Text>Username</Text>
</Group>
<BoxInformasiDonasi
informasi="Semua dana yang terkumpul akan disalurkan ke penggalang dana,
kabar penyaluran dapat dilihat di halaman kabar terbaru."
/>
</Stack>
</Paper>
</Stack>
</>
);
}
function CeritaPenggalangDana() {
const router = useRouter();
return (
<>
<Stack spacing={"xs"}>
<Title order={4}>Cerita Penggalang Dana</Title>
<Paper p={"sm"} withBorder>
<Stack>
<Group position="apart">
<Text>1 Des 2023</Text>
<ActionIcon
variant="transparent"
onClick={() => router.push(RouterDonasi.cerita_penggalang)}
>
<IconCircleChevronRight />
</ActionIcon>
</Group>
<Text lineClamp={4}>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat
doloremque perferendis laborum? Cupiditate sed consequatur quasi
doloremque, consequuntur libero? Vel nam esse fuga, sed et
repellat commodi nemo quia dignissimos?
</Text>
{/* <Text c={"blue"}>Baca selengkapnya</Text> */}
</Stack>
</Paper>
</Stack>
</>
);
}

View File

@@ -23,11 +23,14 @@ import { useDisclosure } from "@mantine/hooks";
import router from "next/router";
import { title } from "process";
import { useRouter } from "next/navigation";
import { data } from "autoprefixer";
export default function LayoutDetailDraftDonasi({
children,
donasiId
}: {
children: React.ReactNode;
donasiId: string
}) {
const [opened, { open, close }] = useDisclosure(false);
const router = useRouter();
@@ -62,7 +65,7 @@ export default function LayoutDetailDraftDonasi({
radius={"xl"}
w={"100%"}
color="blue"
onClick={() => router.push(RouterDonasi.edit_donasi)}
onClick={() => router.push(RouterDonasi.edit_donasi + `${donasiId}`)}
>
Edit Donasi
</Button>
@@ -71,7 +74,7 @@ export default function LayoutDetailDraftDonasi({
radius={"xl"}
w={"100%"}
color="teal"
onClick={() => router.push(RouterDonasi.edit_cerita_penggalang)}
onClick={() => router.push(RouterDonasi.edit_cerita_penggalang + `${donasiId}`)}
>
Edit Cerita
</Button>

View File

@@ -1,28 +1,29 @@
"use client";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import { MODEL_CERITA_DONASI } from "@/app_modules/donasi/model/interface";
import { Box, Image, Stack, Text } from "@mantine/core";
import moment from "moment";
import { useState } from "react";
export default function CeritaPenggalangDonasi() {
export default function CeritaPenggalangDonasi({
dataCerita,
}: {
dataCerita: MODEL_CERITA_DONASI;
}) {
const [data, setData] = useState(dataCerita);
return (
<>
{/* <pre>{JSON.stringify(data.imageCeritaDonasi, null, 2)}</pre> */}
<Stack>
{moment(Date.now()).format("ll")}
<Text> Halo Orang-orang baik</Text>
<Text>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias eos
expedita vitae unde tenetur, veritatis libero doloribus sunt
temporibus, vel cum, quo odio asperiores quos. Suscipit facilis dolore
optio quaerat?
</Text>
<Image alt="Foto" src={"/aset/no-img.png"}/>
<Text>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias eos
expedita vitae unde tenetur, veritatis libero doloribus sunt
temporibus, vel cum, quo odio asperiores quos. Suscipit facilis dolore
optio quaerat?
</Text>
{moment(data.createdAt).format("ll")}
<Text fw={"bold"}> #HaloOrangBaik</Text>
<Text>{data.pembukaan}</Text>
<Image
alt="Foto"
src={RouterDonasi.api_image_cerita + `${data.imageCeritaDonasi.url}`}
/>
<Text>{data.cerita}</Text>
</Stack>
</>
);

View File

@@ -8,17 +8,28 @@ import React from "react";
export default function LayoutCeritaPenggalangDonasi({
children,
statusDonasiId,
}: {
children: React.ReactNode;
statusDonasiId: string;
}) {
if (statusDonasiId !== "1") {
return (
<>
<AppShell
header={<HeaderTamplateDonasi title="Cerita Penggalang Dana" />}
>
{children}
</AppShell>
</>
);
}
return (
<>
<AppShell
header={<HeaderTamplateDonasi title="Cerita Penggalang Dana" />}
footer={<ButtonDonasi />}
>
{children}
</AppShell>
</>
<AppShell
header={<HeaderTamplateDonasi title="Cerita Penggalang Dana" />}
footer={<ButtonDonasi />}
>
{children}
</AppShell>
);
}

View File

@@ -27,38 +27,58 @@ import { useRouter } from "next/navigation";
import BoxInformasiDonasi from "../../component/box_informasi";
import { useAtom } from "jotai";
import { gs_donasi_tabs_posting } from "../../global_state";
import { MODEL_DONASI } from "../../model/interface";
import { useState } from "react";
import TampilanRupiahDonasi from "../../component/tampilan_rupiah";
import ComponentCeritaPenggalangDanaDonasi from "../../component/detail_main/cerita_penggalang";
import { Donasi_funGantiStatus } from "../../fun/update/fun_ganti_status";
import { NotifPeringatan } from "../../component/notifikasi/notif_peringatan";
import { NotifBerhasil } from "../../component/notifikasi/notif_berhasil";
export default function DetailReviewDonasi() {
const [tabsPostingDonasi, setTabsPostingDonasi] = useAtom(
gs_donasi_tabs_posting
);
const router = useRouter()
async function onCLick() {
router.push(RouterDonasi.main_galang_dana)
setTabsPostingDonasi("Draft")
}
export default function DetailReviewDonasi({
dataDonasi,
}: {
dataDonasi: MODEL_DONASI;
}) {
const [donasi, setDonasi] = useState(dataDonasi);
return (
<>
<Stack spacing={"xl"}>
<DetailDonasi />
{/* <InformasiPenggalangDana /> */}
<CeritaPenggalangDana />
<Button
radius={"xl"}
bg={"red"}
color="red"
onClick={() => onCLick()}
>
Batalkan Review
</Button>
<DetailDonasi donasi={donasi} />
<ComponentCeritaPenggalangDanaDonasi donasi={donasi} />
<ButtonBatalReview donasi={donasi} />
</Stack>
</>
);
}
function DetailDonasi() {
function ButtonBatalReview({ donasi }: { donasi: MODEL_DONASI }) {
const router = useRouter();
const [tabsPostingDonasi, setTabsPostingDonasi] = useAtom(
gs_donasi_tabs_posting
);
async function onCLick() {
await Donasi_funGantiStatus(donasi.id, "3").then((res) => {
if (res.status === 200) {
router.push(RouterDonasi.main_galang_dana);
setTabsPostingDonasi("Draft");
NotifBerhasil("Berhasil Dibatalkan");
} else {
NotifPeringatan(res.message);
}
});
}
return (
<>
<Button radius={"xl"} bg={"red"} color="red" onClick={() => onCLick()}>
Batalkan Review
</Button>
</>
);
}
function DetailDonasi({ donasi }: { donasi: MODEL_DONASI }) {
const router = useRouter();
return (
<>
@@ -66,24 +86,31 @@ function DetailDonasi() {
<Stack>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image alt="Foto" src={"/aset/no-img.png"} />
<Image
alt="Foto"
src={RouterDonasi.api_gambar + `${donasi.imagesId}`}
/>
</Paper>
</AspectRatio>
<Title order={4}>Judul Donasi</Title>
<Stack spacing={0}>
<Title order={4}>{donasi.title}</Title>
<Text fz={"xs"}>
Durasi: {donasi.DonasiMaster_Durasi.name} hari
</Text>
</Stack>
<Stack spacing={0}>
<Group position="apart">
<Stack spacing={0}>
<Text fz={12}>Dana dibutuhkan</Text>
<Title order={4} c="blue">
Rp. 50.000.000
<TampilanRupiahDonasi nominal={+donasi.target} />
</Title>
</Stack>
<Stack spacing={0}>
<Text fz={12}>Kategori</Text>
<Text fz={12}>Kategori</Text>
<Title order={4} c="blue">
Kesehatan
{donasi.DonasiMaster_Ketegori.name}
</Title>
</Stack>
</Group>
</Stack>
@@ -92,68 +119,3 @@ function DetailDonasi() {
</>
);
}
function InformasiPenggalangDana() {
const router = useRouter();
return (
<>
<Stack spacing={"xs"}>
<Title order={4}>Informasi Penggalang Dana</Title>
<Paper p={"sm"} withBorder>
<Stack>
<Group position="apart">
<Title order={5}>Penggalang Dana</Title>
<ActionIcon
variant="transparent"
onClick={() => router.push(RouterDonasi.penggalang_dana)}
>
<IconCircleChevronRight />
</ActionIcon>
</Group>
<Group>
<Avatar radius={"xl"} variant="filled" bg={"blue"}>
U
</Avatar>
<Text>Username</Text>
</Group>
<BoxInformasiDonasi
informasi="Semua dana yang terkumpul akan disalurkan ke penggalang dana,
kabar penyaluran dapat dilihat di halaman kabar terbaru."
/>
</Stack>
</Paper>
</Stack>
</>
);
}
function CeritaPenggalangDana() {
const router = useRouter();
return (
<>
<Stack spacing={"xs"}>
<Title order={4}>Cerita Penggalang Dana</Title>
<Paper p={"sm"} withBorder>
<Stack>
<Group position="apart">
<Text>1 Des 2023</Text>
<ActionIcon
variant="transparent"
onClick={() => router.push(RouterDonasi.cerita_penggalang)}
>
<IconCircleChevronRight />
</ActionIcon>
</Group>
<Text lineClamp={4}>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat
doloremque perferendis laborum? Cupiditate sed consequatur quasi
doloremque, consequuntur libero? Vel nam esse fuga, sed et
repellat commodi nemo quia dignissimos?
</Text>
{/* <Text c={"blue"}>Baca selengkapnya</Text> */}
</Stack>
</Paper>
</Stack>
</>
);
}

View File

@@ -5,6 +5,7 @@ import {
AspectRatio,
Button,
Center,
FileButton,
Image,
Paper,
Stack,
@@ -16,31 +17,37 @@ import { useRouter } from "next/navigation";
import { useState } from "react";
import { gs_donasi_tabs_posting } from "../../global_state";
import toast from "react-simple-toasts";
import { MODEL_CERITA_DONASI } from "../../model/interface";
import { NotifPeringatan } from "../../component/notifikasi/notif_peringatan";
import _ from "lodash";
import { Donasi_funUpdateCerita } from "../../fun/update/fun_update_cerita_donasi";
import { NotifBerhasil } from "../../component/notifikasi/notif_berhasil";
export default function EditCeritaPenggalangDonasi() {
export default function EditCeritaPenggalangDonasi({
dataCerita,
}: {
dataCerita: MODEL_CERITA_DONASI;
}) {
const router = useRouter();
const [tabsPostingDonasi, setTabsPostingDonasi] = useAtom(
gs_donasi_tabs_posting
);
const [value, setValue] = useState({
pembukaan: "",
cerita: "",
});
async function onUpdate() {
router.back();
toast("Berhasil update cerita")
const [value, setValue] = useState(dataCerita);
const [file, setFile] = useState<File | null>(null);
const [updateImage, setUpdateImage] = useState<any | null>();
}
return (
<>
{/* <pre>{JSON.stringify(value, null, 2)}</pre> */}
<Stack spacing={"md"} px={"md"}>
<Textarea
autosize
minRows={2}
maxRows={4}
maxRows={7}
withAsterisk
label="Pembukaan"
placeholder="Pembuka dari isi cerita"
value={value.pembukaan}
onChange={(val) =>
setValue({
...value,
@@ -48,13 +55,59 @@ export default function EditCeritaPenggalangDonasi() {
})
}
/>
<Stack spacing={"lg"}>
<Center>
<FileButton
onChange={async (files: any | null) => {
try {
const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())])
);
setUpdateImage(buffer);
setFile(files);
} catch (error) {
console.log(error);
}
}}
accept="image/png,image/jpeg"
>
{(props) => (
<Button
{...props}
radius={"xl"}
variant="outline"
w={150}
leftIcon={<IconCamera />}
>
Upload
</Button>
)}
</FileButton>
</Center>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image
alt="Foto"
src={
updateImage
? updateImage
: RouterDonasi.api_image_cerita +
value.imageCeritaDonasi.url
}
/>
</Paper>
</AspectRatio>
</Stack>
<Textarea
autosize
minRows={2}
maxRows={10}
maxRows={7}
withAsterisk
label="Cerita"
placeholder="Ceritakan alasan mengapa harus membuat Penggalangan Dana"
value={value.cerita}
onChange={(val) =>
setValue({
...value,
@@ -63,24 +116,11 @@ export default function EditCeritaPenggalangDonasi() {
}
/>
<Stack spacing={"xs"}>
<Center>
<Button
radius={"xl"}
variant="outline"
w={150}
leftIcon={<IconCamera />}
>
Upload
</Button>
</Center>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image alt="Foto" src={"/aset/no-img.png"} />
</Paper>
</AspectRatio>
</Stack>
<Button w={"100%"} radius={"xl"} onClick={() => onUpdate()}>
<Button
w={"100%"}
radius={"xl"}
onClick={() => onUpdate(router, value, file as any)}
>
Simpan
</Button>
</Stack>
@@ -88,3 +128,30 @@ export default function EditCeritaPenggalangDonasi() {
</>
);
}
async function onUpdate(
router: any,
value: MODEL_CERITA_DONASI,
file: FormData
) {
// router.back();
const body = {
id: value.id,
pembukaan: value.pembukaan,
cerita: value.cerita,
imagesId: value.imageCeritaDonasi.id
};
const gambar = new FormData();
gambar.append("file", file as any);
if (_.values(body).includes("")) return NotifPeringatan("Lengkapi Data");
await Donasi_funUpdateCerita(body as any,gambar).then((res) => {
if (res.status === 200) {
NotifBerhasil(res.message);
router.back();
} else {
toast(res.message);
}
});
}

View File

@@ -10,53 +10,109 @@ import {
Button,
TextInput,
Image,
FileButton,
Modal,
Group,
Title,
} from "@mantine/core";
import { IconCamera } from "@tabler/icons-react";
import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import { gs_donasi_tabs_posting } from "../../global_state";
import toast from "react-simple-toasts";
import { MODEL_DONASI, MODEL_DONASI_ALL_MASTER } from "../../model/interface";
import { useState } from "react";
import { Donasi_funUpdateDonasi } from "../../fun/update/fun_update_donasi";
import { useDisclosure } from "@mantine/hooks";
import { NotifBerhasil } from "../../component/notifikasi/notif_berhasil";
import { NotifPeringatan } from "../../component/notifikasi/notif_peringatan";
import _ from "lodash";
import { Donasi_getOneById } from "../../fun/get/get_one_donasi_by_id";
export default function EditDonasi() {
export default function EditDonasi({
dataDonasi,
masterKategori,
masterDurasi,
}: {
dataDonasi: MODEL_DONASI;
masterKategori: MODEL_DONASI_ALL_MASTER[];
masterDurasi: MODEL_DONASI_ALL_MASTER[];
}) {
const router = useRouter();
const [tabsPostingDonasi, setTabsPostingDonasi] = useAtom(
gs_donasi_tabs_posting
);
const [value, setValue] = useState(dataDonasi);
const [kategori, setKategori] = useState(masterKategori);
const [durasi, setDurasi] = useState(masterDurasi);
const [file, setFile] = useState<File | null>(null);
const [updateImage, setUpdateImage] = useState<any | null>();
const [opened, { open, close }] = useDisclosure(false);
async function onUpdate() {
router.back();
toast("Berhasil update data")
}
return (
<>
{/* <pre>{JSON.stringify(donasi, null, 2)}</pre> */}
<Stack spacing={"md"} px={"md"}>
<Select
label="Kategori"
placeholder="Pilih kategori penggalangan dana"
value={value.DonasiMaster_Ketegori.id}
withAsterisk
data={[
{ value: "1", label: "Medis" },
{ value: "2", label: "Lingkungan" },
{ value: "3", label: "Kegiatan Sosial" },
{ value: "4", label: "Rumah Ibadah" },
{ value: "5", label: "Bantuan Pendidikan" },
]}
data={kategori.map((e) => ({
value: e.id,
label: e.name,
}))}
onChange={(val) =>
setValue({
...(value as any),
DonasiMaster_Ketegori: {
id: val,
},
})
}
/>
<Stack>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image alt="Foto" src={"/aset/no-img.png"} />
<Image
alt="Foto"
src={
updateImage
? updateImage
: RouterDonasi.api_gambar + `${value.imagesId}`
}
/>
</Paper>
</AspectRatio>
<Center>
<Button
radius={"xl"}
variant="outline"
w={150}
leftIcon={<IconCamera />}
<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");
setUpdateImage(buffer);
setFile(files);
} catch (error) {
console.log(error);
}
}}
accept="image/png,image/jpeg"
>
Upload
</Button>
{(props) => (
<Button
{...props}
radius={"xl"}
variant="outline"
w={150}
leftIcon={<IconCamera />}
>
Upload
</Button>
)}
</FileButton>
</Center>
</Stack>
<Stack>
@@ -64,28 +120,99 @@ export default function EditDonasi() {
withAsterisk
label="Judul Donasi"
placeholder="Contoh: Renovasi Masjid pada kampung, dll"
value={value.title}
onChange={(val) =>
setValue({
...value,
title: val.target.value,
})
}
/>
<TextInput
type="number"
withAsterisk
label="Target Dana"
placeholder="Masukan nominal angka"
value={+value.target ? +value.target : ""}
onChange={(val) =>
setValue({
...value,
target: val.target.value,
})
}
/>
<Select
label="Durasi"
placeholder="Jangka waktu penggalangan dana"
withAsterisk
data={[
{ value: "30", label: "30 Hari" },
{ value: "60", label: "60 Hari" },
{ value: "90", label: "90 Hari" },
]}
value={value.DonasiMaster_Durasi.id}
data={durasi.map((e) => ({
value: e.id,
label: e.name + " " + `hari`,
}))}
onChange={(val) =>
setValue({
...(value as any),
DonasiMaster_Durasi: {
id: val,
},
})
}
/>
</Stack>
<Button my={"lg"} radius={"xl"} onClick={() => onUpdate()}>
<Button
my={"lg"}
radius={"xl"}
onClick={() => {
onUpdate(value, file as any, router);
}}
>
Update
</Button>
{/* <Modal opened={opened} onClose={close} withCloseButton={false} centered >
<ModalEdit />
</Modal> */}
</Stack>
</>
);
}
// function ModalEdit() {
// return (
// <>
// <Stack>
// <Title order={6}>Anda yakin menyimpan data ini ?</Title>
// <Group position="center">
// <Button variant="outline" >Batal</Button>
// <Button>Simpan</Button>
// </Group>
// </Stack>
// </>
// );
// }
async function onUpdate(value: MODEL_DONASI, file: FormData, router: any) {
const body = {
id: value.id,
donasiMaster_KategoriId: value.DonasiMaster_Ketegori.id,
donasiMaster_DurasiId: value.DonasiMaster_Durasi.id,
title: value.title,
target: value.target,
imagesId: value.imagesId,
};
const gambar = new FormData();
gambar.append("file", file as any);
if (_.values(body).includes("")) return NotifPeringatan("Lengkapi Data");
await Donasi_funUpdateDonasi(body as any, gambar).then((res) => {
if (res.status === 200) {
NotifBerhasil(res.message);
router.back();
} else {
NotifPeringatan(res.message);
}
});
}

View File

@@ -6,6 +6,7 @@ import { MODEL_DONASI } from "../../model/interface";
import { Donasi_funDeleteTemporaryCreate } from "../delete/fun_delete_temporary_create";
import { v4 } from "uuid";
import _ from "lodash";
import { revalidatePath } from "next/cache";
export async function Donasi_funCreate(req: MODEL_DONASI, file: FormData) {
const body = req;
@@ -17,7 +18,7 @@ export async function Donasi_funCreate(req: MODEL_DONASI, file: FormData) {
donasiMaster_DurasiId: body.donasiMaster_DurasiId,
donasiMaster_KategoriId: body.donasiMaster_KategoriId,
imagesId: body.imagesId,
authorId: body.authorId
authorId: body.authorId,
},
});
@@ -63,6 +64,7 @@ export async function Donasi_funCreate(req: MODEL_DONASI, file: FormData) {
});
if (!dataCerita) return { status: 400, message: "Gagal simpan data cerita" };
revalidatePath("/dev/donasi/main/galang_dana");
return {
status: 201,
message: "Data donasi tersimpan",

View File

@@ -2,7 +2,7 @@
import fs from "fs";
import prisma from "@/app/lib/prisma";
import { MODEL_DONASI_TEMPORARY } from "../../model/interface";
import { MODEL_DONASI, MODEL_DONASI_TEMPORARY } from "../../model/interface";
import _ from "lodash";
import { v4 } from "uuid";
@@ -14,7 +14,7 @@ interface Model_Temporary {
}
export default async function Donasi_funCreateTemporary(
data: Model_Temporary,
data: MODEL_DONASI,
file: FormData
) {
// console.log(data, "ini data")
@@ -37,16 +37,17 @@ export default async function Donasi_funCreateTemporary(
if (!uploadTemporary) return { status: 400, message: "Gagal upload gambar" };
const uploadFolder = Buffer.from(await dataImage.arrayBuffer());
fs.writeFileSync(`./public/donasi/image/${uploadTemporary.url}`, uploadFolder);
fs.writeFileSync(
`./public/donasi/image/${uploadTemporary.url}`,
uploadFolder
);
const res = await prisma.donasi_TemporaryCreate.create({
data: {
title: data.title,
target: data.target,
donasiMaster_KategoriId: data.kategoriId,
donasiMaster_DurasiId: data.durasiId,
donasiMaster_KategoriId: data.donasiMaster_KategoriId,
donasiMaster_DurasiId: data.donasiMaster_DurasiId,
imagesId: uploadTemporary.id,
},
});
@@ -56,6 +57,6 @@ export default async function Donasi_funCreateTemporary(
return {
status: 201,
message: "Berhasil membuat donasi",
donasiId: res.id
donasiId: res.id,
};
}

View File

@@ -0,0 +1,18 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function Donasi_getCeritaByDonasiId(donasiId: string) {
const data = await prisma.donasi_Cerita.findFirst({
where: {
donasiId: donasiId,
},
select: {
id: true,
pembukaan: true,
cerita: true,
imageCeritaDonasi: true,
},
});
return data;
}

View File

@@ -0,0 +1,61 @@
"use server";
import prisma from "@/app/lib/prisma";
/**
*
* @param authorId string
* @param status string | masukan angka 1 - 4
* @returns List data donasi by status
*/
export default async function Donasi_getByStatus(
authorId: string,
status: string
) {
if (status === "1") {
const getReview = await prisma.donasi.findMany({
where: {
authorId: authorId,
donasiMaster_StatusDonasiId: "1",
},
});
return getReview;
}
if (status === "2") {
const getReview = await prisma.donasi.findMany({
where: {
authorId: authorId,
donasiMaster_StatusDonasiId: "2",
},
});
return getReview;
}
if (status === "3") {
const getReview = await prisma.donasi.findMany({
where: {
authorId: authorId,
donasiMaster_StatusDonasiId: "3",
},
});
return getReview;
}
if (status === "4") {
const getReview = await prisma.donasi.findMany({
where: {
authorId: authorId,
donasiMaster_StatusDonasiId: "4",
},
});
return getReview;
}
if (status === undefined) {
return {
status: 400,
message: "Not Found",
};
}
}

View File

@@ -0,0 +1,33 @@
"use server";
import prisma from "@/app/lib/prisma";
export async function Donasi_getOneById(donasiId: string) {
const data = await prisma.donasi.findFirst({
where: {
id: donasiId,
},
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 data;
}

View File

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

View File

@@ -0,0 +1,59 @@
"use server";
import _ from "lodash";
import { MODEL_CERITA_DONASI } from "../../model/interface";
import { v4 } from "uuid";
import prisma from "@/app/lib/prisma";
import { revalidatePath } from "next/cache";
import fs from "fs";
export async function Donasi_funUpdateCerita(
data: MODEL_CERITA_DONASI,
file: FormData
) {
const gambar: any = file.get("file");
if (gambar !== "null") {
const fileName = gambar.name;
const fileExtension = _.lowerCase(gambar.name.split(".").pop());
const fileRandomName = v4(fileName) + "." + fileExtension;
const updateGambar = await prisma.images.update({
where: {
id: data.imagesId,
},
data: {
url: fileRandomName,
},
});
if (!updateGambar) return { status: 400, message: "Update gambat gagal" };
revalidatePath("/dev/donasi/detail/detail_draft");
const uploadFolder = Buffer.from(await gambar.arrayBuffer());
fs.writeFileSync(
`./public/donasi/image_cerita/${updateGambar.url}`,
uploadFolder
);
}
const update = await prisma.donasi_Cerita.update({
where: {
id: data.id,
},
data: {
pembukaan: data.pembukaan,
cerita: data.cerita,
},
});
if (!update) return { status: 400, message: "Gagal update cerita" };
revalidatePath("/dev/donasi/detail/detail_draft");
return {
status: 200,
message: "Berhasil update cerita",
};
}

View File

@@ -0,0 +1,71 @@
"use server";
import prisma from "@/app/lib/prisma";
import { MODEL_DONASI } from "../../model/interface";
import _ from "lodash";
import { v4 } from "uuid";
import fs from "fs";
import { revalidatePath, revalidateTag } from "next/cache";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
export async function Donasi_funUpdateDonasi(
data: MODEL_DONASI,
file: FormData
) {
// console.log(data);
const gambar: any = file.get("file");
if (gambar !== "null") {
const fileName = gambar.name;
const fileExtension = _.lowerCase(gambar.name.split(".").pop());
const fileRandomName = v4(fileName) + "." + fileExtension;
const cariGambar = await prisma.images.findFirst({
where: {
id: data.imagesId,
},
select: {
url: true,
},
});
if (!cariGambar) return { status: 400, message: "Gambar tidak ditemukan" };
revalidatePath("/dev/donasi/detail/detail_draft");
fs.unlinkSync(`./public/donasi/image/${cariGambar.url}`);
const updateGambar = await prisma.images.update({
where: {
id: data.imagesId,
},
data: {
url: fileRandomName,
},
});
if (!updateGambar) return { status: 400, message: "Update gambat gagal" };
revalidatePath("/dev/donasi/detail/detail_draft");
const uploadFolder = Buffer.from(await gambar.arrayBuffer());
fs.writeFileSync(`./public/donasi/image/${updateGambar.url}`, uploadFolder);
}
const update = await prisma.donasi.update({
where: {
id: data.id,
},
data: {
donasiMaster_KategoriId: data.donasiMaster_KategoriId,
donasiMaster_DurasiId: data.donasiMaster_DurasiId,
title: data.title,
target: data.target,
},
});
if (!update) return { status: 400, message: "Gagal update" };
revalidatePath("/dev/donasi/detail/detail_draft");
return {
status: 200,
message: "Berhasil update",
};
}

View File

@@ -23,7 +23,7 @@ import { Warna } from "@/app/lib/warna";
import { RouterDonasi } from "@/app/lib/router_hipmi/router_donasi";
import PostingDraftDonasi from "./galang_dana/draft";
export default function GalangDanaDonasi() {
export default function GalangDanaDonasi({listReview, listDraft}: {listReview: any, listDraft: any}) {
const router = useRouter();
const [tabsPostingDonasi, setTabsPostingDonasi] = useAtom(
gs_donasi_tabs_posting
@@ -39,13 +39,13 @@ export default function GalangDanaDonasi() {
{
id: 2,
value: "Review",
path: <PostingReviewDonasi data={"2"} />,
path: <PostingReviewDonasi listReview={listReview} />,
color: "yellow",
},
{
id: 3,
value: "Draft",
path: <PostingDraftDonasi data={"3"} />,
path: <PostingDraftDonasi listDraft={listDraft} />,
color: "red",
},
{

View File

@@ -21,8 +21,14 @@ import { useViewportSize } from "@mantine/hooks";
import { useRouter } from "next/navigation";
import toast from "react-simple-toasts";
import { MODEL_DONASI } from "../../model/interface";
import TampilanRupiahDonasi from "../../component/tampilan_rupiah";
export default function PostingDraftDonasi({ data }: { data: any }) {
export default function PostingDraftDonasi({
listDraft,
}: {
listDraft: MODEL_DONASI[];
}) {
const { height, width } = useViewportSize();
const router = useRouter();
return (
@@ -36,44 +42,39 @@ export default function PostingDraftDonasi({ data }: { data: any }) {
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
]}
>
{Array(5)
.fill(0)
.map((e, i) => (
<Box
key={i}
onClick={() => router.push(RouterDonasi.detail_draft)}
>
<Stack>
<Grid>
<Grid.Col span={7}>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image
alt="Foto"
src={"/aset/no-img.png"}
radius={"md"}
/>
</Paper>
</AspectRatio>
</Grid.Col>
<Grid.Col span={5}>
<Stack spacing={"xs"}>
<Text fz={"sm"} fw={"bold"} lineClamp={2}>
Judul Donasi Bisa Dilihat Disini Untuk Contoh
{listDraft.map((e, i) => (
<Box key={i} onClick={() => router.push(RouterDonasi.detail_draft + `${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"}>Terget Dana</Text>
<Text fz={"sm"} fw={"bold"} c={"orange"} truncate>
<TampilanRupiahDonasi nominal={+e.target} />
</Text>
<Stack spacing={0}>
<Text fz={"sm"}>Terget Dana</Text>
<Text fz={"sm"} fw={"bold"} c={"orange"} truncate>
Rp. 100.000.000
</Text>
</Stack>
</Stack>
</Grid.Col>
</Grid>
{width > 575 ? "" : <Divider />}
</Stack>
</Box>
))}
</Stack>
</Grid.Col>
</Grid>
{width > 575 ? "" : <Divider />}
</Stack>
</Box>
))}
</SimpleGrid>
</>
);

View File

@@ -21,8 +21,13 @@ import { useViewportSize } from "@mantine/hooks";
import { useRouter } from "next/navigation";
import toast from "react-simple-toasts";
import { MODEL_DONASI } from "../../model/interface";
export default function PostingReviewDonasi({ data }: { data: any }) {
export default function PostingReviewDonasi({
listReview,
}: {
listReview: MODEL_DONASI[];
}) {
const { height, width } = useViewportSize();
const router = useRouter();
return (
@@ -36,44 +41,42 @@ export default function PostingReviewDonasi({ data }: { data: any }) {
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
]}
>
{Array(5)
.fill(0)
.map((e, i) => (
<Box
key={i}
onClick={() => router.push(RouterDonasi.detail_review)}
>
<Stack>
<Grid>
<Grid.Col span={7}>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
<Image
alt="Foto"
src={"/aset/no-img.png"}
radius={"md"}
/>
</Paper>
</AspectRatio>
</Grid.Col>
<Grid.Col span={5}>
<Stack spacing={"xs"}>
<Text fz={"sm"} fw={"bold"} lineClamp={2}>
Judul Donasi Bisa Dilihat Disini Untuk Contoh
{listReview.map((e, i) => (
<Box key={i} onClick={() => router.push(RouterDonasi.detail_review + `${e.id}`)}>
<Stack>
<Grid>
<Grid.Col span={7}>
<AspectRatio ratio={16 / 9}>
<Paper radius={"md"} bg={"gray.1"}>
<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"}>Terget Dana</Text>
<Text fz={"sm"} fw={"bold"} c={"orange"} truncate>
Rp.{" "}
{new Intl.NumberFormat("id-ID", {
maximumFractionDigits: 10,
}).format(+e.target)}
</Text>
<Stack spacing={0}>
<Text fz={"sm"}>Terget Dana</Text>
<Text fz={"sm"} fw={"bold"} c={"orange"} truncate>
Rp. 100.000.000
</Text>
</Stack>
</Stack>
</Grid.Col>
</Grid>
{width > 575 ? "" : <Divider />}
</Stack>
</Box>
))}
</Stack>
</Grid.Col>
</Grid>
{width > 575 ? "" : <Divider />}
</Stack>
</Box>
))}
</SimpleGrid>
</>
);

View File

@@ -1,3 +1,6 @@
import { MODEL_AUTHOR } from "@/app_modules/home/models/interface";
import { MODEL_IMAGES } from "@/app_modules/models/interface";
export interface MODEL_DONASI {
id: string;
title: string;
@@ -6,23 +9,32 @@ export interface MODEL_DONASI {
createdAt: Date;
updatedAt: Date;
imagesId: string;
authorId: string,
publishTime: Date;
catatan: string,
authorId: string;
donasiMaster_KategoriId: string;
donasiMaster_DurasiId: string;
CeritaDonasi : MODEL_CERITA_DONASI
donasiMaster_StatusDonasiId: string;
CeritaDonasi: MODEL_CERITA_DONASI;
Author: MODEL_AUTHOR;
imageDonasi: MODEL_IMAGES;
DonasiMaster_Ketegori: MODEL_DONASI_ALL_MASTER;
DonasiMaster_Durasi: MODEL_DONASI_ALL_MASTER;
DonasiMaster_Status: MODEL_DONASI_ALL_MASTER;
}
export interface MODEL_CERITA_DONASI {
id: string;
pembukaan: string,
cerita: string,
pembukaan: string;
cerita: string;
active: boolean;
createdAt: Date;
updatedAt: Date;
imagesId: string
imagesId: string;
imageCeritaDonasi: MODEL_IMAGES
donasiId: string
}
export interface MODEL_DONASI_ALL_MASTER {
id: string;
name: string;
@@ -42,5 +54,3 @@ export interface MODEL_DONASI_TEMPORARY {
donasiMaster_KategoriId: string;
donasiMaster_DurasiId: string;
}

View File

@@ -7,7 +7,7 @@ import { unsealData } from "iron-session";
import { redirect } from "next/navigation";
const config = yaml.parse(fs.readFileSync("config.yaml").toString());
export async function funGetUserToken() {
export async function getToken_UserId() {
const c = cookies().get("ssn");
if (!c?.value) return redirect("/dev/auth/login");
@@ -17,5 +17,5 @@ export async function funGetUserToken() {
})
);
return token;
return token.id
}

View File

@@ -0,0 +1,9 @@
export interface MODEL_AUTHOR {
id: string;
username: string;
nomor: string;
active: boolean;
createdAt: Date;
updatedAt: Date;
masterUserRoleId: string;
}

View File

@@ -0,0 +1,7 @@
export interface MODEL_IMAGES {
id: string;
url: string;
active: boolean;
createdAt: Date;
updatedAt: Date;
}

View File

@@ -1,18 +1,18 @@
[
{
"id": "1",
"name": "3"
"name": "30"
},
{
"id": "2",
"name": "6"
"name": "60"
},
{
"id": "3",
"name": "9"
"name": "90"
},
{
"id": "4",
"name": "12"
"name": "120"
}
]

View File

@@ -14,5 +14,9 @@
{
"id": "4",
"name": "Rumah Ibadah"
},
{
"id": "5",
"name": "Bencana Alam"
}
]

798
yarn.lock

File diff suppressed because it is too large Load Diff