# Voting
## feat - Create function - Get list by status id - Get one vote by id ### No issuue
This commit is contained in:
@@ -28,6 +28,7 @@ model User {
|
|||||||
Donasi_Notif Donasi_Notif[]
|
Donasi_Notif Donasi_Notif[]
|
||||||
Event Event[]
|
Event Event[]
|
||||||
Event_Peserta Event_Peserta[]
|
Event_Peserta Event_Peserta[]
|
||||||
|
Voting Voting[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model MasterUserRole {
|
model MasterUserRole {
|
||||||
@@ -532,3 +533,44 @@ model Event_Peserta {
|
|||||||
User User? @relation(fields: [userId], references: [id])
|
User User? @relation(fields: [userId], references: [id])
|
||||||
userId String?
|
userId String?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========================================= VOTING ========================================= //
|
||||||
|
|
||||||
|
model Voting {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
title String
|
||||||
|
deskripsi String
|
||||||
|
awalVote DateTime
|
||||||
|
akhirVote DateTime
|
||||||
|
catatan String?
|
||||||
|
|
||||||
|
Author User @relation(fields: [authorId], references: [id])
|
||||||
|
authorId String
|
||||||
|
Voting_Status Voting_Status? @relation(fields: [voting_StatusId], references: [id])
|
||||||
|
voting_StatusId String? @default("2")
|
||||||
|
Voting_DaftarNamaVote Voting_DaftarNamaVote[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model Voting_Status {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
name String
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
Voting Voting[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model Voting_DaftarNamaVote {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
value String
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
Voting Voting? @relation(fields: [votingId], references: [id])
|
||||||
|
votingId String?
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import donasi_namaBank from "../../../bin/seeder/donasi/master_bank.json";
|
|||||||
import donasi_status_invoice from "../../../bin/seeder/donasi/master_status_invoice.json";
|
import donasi_status_invoice from "../../../bin/seeder/donasi/master_status_invoice.json";
|
||||||
import event_status from "../../../bin/seeder/event/master_status.json";
|
import event_status from "../../../bin/seeder/event/master_status.json";
|
||||||
import event_tipe_acara from "../../../bin/seeder/event/master_tipe_acara.json";
|
import event_tipe_acara from "../../../bin/seeder/event/master_tipe_acara.json";
|
||||||
|
import voting_status from "../../../bin/seeder/voting/master_status.json";
|
||||||
|
|
||||||
export async function GET(req: Request) {
|
export async function GET(req: Request) {
|
||||||
const dev = new URL(req.url).searchParams.get("dev");
|
const dev = new URL(req.url).searchParams.get("dev");
|
||||||
@@ -296,6 +297,21 @@ export async function GET(req: Request) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let v of voting_status) {
|
||||||
|
await prisma.voting_Status.upsert({
|
||||||
|
where: {
|
||||||
|
id: v.id,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
id: v.id,
|
||||||
|
name: v.name,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
name: v.name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return NextResponse.json({ success: true });
|
return NextResponse.json({ success: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
src/app/dev/admin/vote/child/riwayat/page.tsx
Normal file
9
src/app/dev/admin/vote/child/riwayat/page.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { AdminVote_Riwayat } from "@/app_modules/admin/voting";
|
||||||
|
|
||||||
|
export default async function Page() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AdminVote_Riwayat />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
7
src/app/dev/admin/vote/child/table_publish/page.tsx
Normal file
7
src/app/dev/admin/vote/child/table_publish/page.tsx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { AdminVote_TablePublish } from "@/app_modules/admin/voting";
|
||||||
|
|
||||||
|
export default async function Page() {
|
||||||
|
return<>
|
||||||
|
<AdminVote_TablePublish/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
8
src/app/dev/admin/vote/child/table_reject/page.tsx
Normal file
8
src/app/dev/admin/vote/child/table_reject/page.tsx
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { AdminVote_TableReject } from "@/app_modules/admin/voting";
|
||||||
|
|
||||||
|
|
||||||
|
export default async function Page() {
|
||||||
|
return<>
|
||||||
|
<AdminVote_TableReject/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
9
src/app/dev/admin/vote/child/table_review/page.tsx
Normal file
9
src/app/dev/admin/vote/child/table_review/page.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { AdminVote_TableReview } from "@/app_modules/admin/voting";
|
||||||
|
|
||||||
|
export default async function Page() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AdminVote_TableReview />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
9
src/app/dev/admin/vote/main/page.tsx
Normal file
9
src/app/dev/admin/vote/main/page.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { AdminVote_Main } from "@/app_modules/admin/voting";
|
||||||
|
|
||||||
|
export default async function Page() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AdminVote_Main />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_Create } from "@/app_modules/vote";
|
import { LayoutVote_Create } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_Create } from "@/app_modules/vote";
|
import { Vote_Create } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_DetailDraft } from "@/app_modules/vote";
|
import { LayoutVote_DetailDraft } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_DetailDraft } from "@/app_modules/vote";
|
import { Vote_DetailDraft } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_DetailKontribusi } from "@/app_modules/vote";
|
import { LayoutVote_DetailKontribusi } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_DetailKontribusi } from "@/app_modules/vote";
|
import { Vote_DetailKontribusi } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_MainDetail } from "@/app_modules/vote";
|
import { LayoutVote_MainDetail } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_MainDetail } from "@/app_modules/vote";
|
import { Vote_MainDetail } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default async function Page(){
|
export default async function Page(){
|
||||||
return<>
|
return<>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_DetailPublish } from "@/app_modules/vote";
|
import { LayoutVote_DetailPublish } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_DetailPublish } from "@/app_modules/vote";
|
import { Vote_DetailPublish } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default function Page(){
|
export default function Page(){
|
||||||
return <>
|
return <>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_DetailReject } from "@/app_modules/vote";
|
import { LayoutVote_DetailReject } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default async function Layout({children}: {children: React.ReactNode}) {
|
export default async function Layout({children}: {children: React.ReactNode}) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_DetailReject } from "@/app_modules/vote";
|
import { Vote_DetailReject } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
return <>
|
return <>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_DetailReview } from "@/app_modules/vote";
|
import { LayoutVote_DetailReview } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
13
src/app/dev/vote/detail/review/[id]/page.tsx
Normal file
13
src/app/dev/vote/detail/review/[id]/page.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Vote_DetailReview } from "@/app_modules/voting";
|
||||||
|
import { Vote_getOnebyId } from "@/app_modules/voting/fun/get/get_one_by_id";
|
||||||
|
|
||||||
|
export default async function Page({ params }: { params: { id: string } }) {
|
||||||
|
let voteId = params.id;
|
||||||
|
const dataVote = await Vote_getOnebyId(voteId);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Vote_DetailReview dataVote={dataVote as any} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { Vote_DetailReview } from "@/app_modules/vote";
|
|
||||||
|
|
||||||
export default function Page() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Vote_DetailReview />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_DetailRiwayatSaya } from "@/app_modules/vote";
|
import { LayoutVote_DetailRiwayatSaya } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_DetailRiwayatSaya } from "@/app_modules/vote";
|
import { Vote_DetailRiwayatSaya } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_DetailSemuaRiwayat } from "@/app_modules/vote";
|
import { LayoutVote_DetailSemuaRiwayat } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_DetailSemuaRiwayat } from "@/app_modules/vote";
|
import { Vote_DetailSemuaRiwayat } from "@/app_modules/voting";
|
||||||
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_Edit } from "@/app_modules/vote";
|
import { LayoutVote_Edit } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_Edit } from "@/app_modules/vote";
|
import { Vote_Edit } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_Beranda } from "@/app_modules/vote";
|
import { Vote_Beranda } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
return<>
|
return<>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_Kontribusi } from "@/app_modules/vote";
|
import { Vote_Kontribusi } from "@/app_modules/voting";
|
||||||
|
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LayoutVote_Main } from "@/app_modules/vote";
|
import { LayoutVote_Main } from "@/app_modules/voting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_Riwayat } from "@/app_modules/vote";
|
import { Vote_Riwayat } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
import { Vote_Status } from "@/app_modules/vote";
|
import { Vote_Status } from "@/app_modules/voting";
|
||||||
|
import { Vote_getListByStatusId } from "@/app_modules/voting/fun/get/get_list_status_by_status_id";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
|
const listPublish = await Vote_getListByStatusId("1");
|
||||||
|
const listReview = await Vote_getListByStatusId("2");
|
||||||
|
const listDraft = await Vote_getListByStatusId("3");
|
||||||
|
const listReject = await Vote_getListByStatusId("4");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Vote_Status />
|
<Vote_Status
|
||||||
|
listPublish={listPublish as any}
|
||||||
|
listReview={listReview as any}
|
||||||
|
listDraft={listDraft as any}
|
||||||
|
listReject={listReject as any}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Vote_Splash } from "@/app_modules/vote";
|
import { Vote_Splash } from "@/app_modules/voting";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
8
src/app/lib/router_admin/router_admin_vote.ts
Normal file
8
src/app/lib/router_admin/router_admin_vote.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const RouterAdminVote = {
|
||||||
|
// main
|
||||||
|
main: "/dev/admin/vote/main",
|
||||||
|
table_publish: "/dev/admin/vote/child/table_publish",
|
||||||
|
table_review: "/dev/admin/vote/child/table_review",
|
||||||
|
table_reject: "/dev/admin/vote/child/table_reject",
|
||||||
|
riwayat: "/dev/admin/vote/child/riwayat",
|
||||||
|
};
|
||||||
@@ -15,7 +15,7 @@ export const RouterVote = {
|
|||||||
//detail
|
//detail
|
||||||
main_detail: "/dev/vote/detail/main",
|
main_detail: "/dev/vote/detail/main",
|
||||||
detail_publish: "/dev/vote/detail/publish",
|
detail_publish: "/dev/vote/detail/publish",
|
||||||
detail_review: "/dev/vote/detail/review",
|
detail_review: "/dev/vote/detail/review/",
|
||||||
detail_draft: "/dev/vote/detail/draft",
|
detail_draft: "/dev/vote/detail/draft",
|
||||||
detail_reject: "/dev/vote/detail/reject",
|
detail_reject: "/dev/vote/detail/reject",
|
||||||
detail_kontribusi: "/dev/vote/detail/kontribusi",
|
detail_kontribusi: "/dev/vote/detail/kontribusi",
|
||||||
|
|||||||
@@ -1,13 +1,54 @@
|
|||||||
'use client'
|
"use client";
|
||||||
|
|
||||||
import { Button } from "@mantine/core";
|
import { Box, Button, Stack, TextInput } from "@mantine/core";
|
||||||
import makuro_test from "./makuro_test";
|
import makuro_test from "./makuro_test";
|
||||||
|
import { useState } from "react";
|
||||||
|
import _, { forIn } from "lodash";
|
||||||
|
|
||||||
export default function ViewMakuro() {
|
export default function ViewMakuro() {
|
||||||
|
const [listnya, setListnya] = useState<any[]>([
|
||||||
|
{
|
||||||
|
name: "Voting",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
{ name: "Voting", value: "" },
|
||||||
|
]);
|
||||||
|
|
||||||
return <>
|
return (
|
||||||
|
<>
|
||||||
|
<Stack p={24}>
|
||||||
|
{listnya.map((e, k) => (
|
||||||
|
<Box key={k}>
|
||||||
|
<TextInput
|
||||||
|
onChange={(v) => {
|
||||||
|
const val = _.clone(listnya);
|
||||||
|
val[k].value = v.currentTarget.value;
|
||||||
|
setListnya([...val]);
|
||||||
|
}}
|
||||||
|
label={e.name}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
<Button
|
<Button
|
||||||
onClick={() => makuro_test()}
|
onClick={() => {
|
||||||
>Tekan Aja</Button>
|
// const cek = listnya[listnya.length - 1]
|
||||||
|
// console.log(cek.id + 1);
|
||||||
|
|
||||||
|
if (listnya.length > 4) return console.log("ga bisa lebih");
|
||||||
|
setListnya([...listnya, { name: "Voting", value: "" }]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
Tambah
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
console.log(JSON.stringify(listnya, null, 4));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Hasilnya
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
</>
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
useMantineTheme,
|
useMantineTheme,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import ComponentGlobal_HeaderTamplate from "../../../component_global/header_tamplate";
|
import ComponentGlobal_HeaderTamplate from "../component_global/header_tamplate";
|
||||||
import { useDisclosure } from "@mantine/hooks";
|
import { useDisclosure } from "@mantine/hooks";
|
||||||
import { IconLetterH, IconLogout } from "@tabler/icons-react";
|
import { IconLetterH, IconLogout } from "@tabler/icons-react";
|
||||||
import {
|
import {
|
||||||
@@ -33,8 +33,8 @@ import { useRouter } from "next/navigation";
|
|||||||
import { RouterHome } from "@/app/lib/router_hipmi/router_home";
|
import { RouterHome } from "@/app/lib/router_hipmi/router_home";
|
||||||
import { Logout } from "@/app_modules/auth";
|
import { Logout } from "@/app_modules/auth";
|
||||||
import { useAtom } from "jotai";
|
import { useAtom } from "jotai";
|
||||||
import { gs_admin_hotMenu, gs_admin_subMenu } from "../../global_state";
|
import { gs_admin_hotMenu, gs_admin_subMenu } from "./global_state";
|
||||||
import Admin_Logout from "../../component/logout";
|
import Admin_Logout from "./component/logout";
|
||||||
import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event";
|
import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { listAdminPage } from "./list_page";
|
import { listAdminPage } from "./list_page";
|
||||||
@@ -48,24 +48,23 @@ export default function AdminLayout({
|
|||||||
const [opened, setOpened] = useState(false);
|
const [opened, setOpened] = useState(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [active, setActive] = useAtom(gs_admin_hotMenu);
|
const [active, setActive] = useAtom(gs_admin_hotMenu);
|
||||||
const [activeChild, setActiveChild] = useAtom(gs_admin_subMenu)
|
const [activeChild, setActiveChild] = useAtom(gs_admin_subMenu);
|
||||||
|
|
||||||
const navbarItems = listAdminPage.map((e, i) => (
|
const navbarItems = listAdminPage.map((e, i) => (
|
||||||
<Box key={i}>
|
<Box key={e.id}>
|
||||||
<NavLink
|
<NavLink
|
||||||
sx={{
|
sx={{
|
||||||
":hover": {
|
":hover": {
|
||||||
backgroundColor: "transparent",
|
backgroundColor: "transparent",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
fw={active === e.id ? "bold" : "normal"}
|
||||||
fw={active === i ? "bold" : "normal"}
|
|
||||||
label={<Text size={"md"}>{e.name}</Text>}
|
label={<Text size={"md"}>{e.name}</Text>}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActive(i);
|
setActive(e.id);
|
||||||
setActiveChild(null);
|
setActiveChild(null);
|
||||||
e.path === "" ? router.push(e.child[0].path) : router.push(e.path);
|
e.path === "" ? router.push(e.child[0].path) : router.push(e.path);
|
||||||
e.path === "" ? setActiveChild(0) : ""
|
e.path === "" ? setActiveChild(e.child[0].id) : "";
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{_.isEmpty(e.child) ? (
|
{_.isEmpty(e.child) ? (
|
||||||
@@ -73,18 +72,18 @@ export default function AdminLayout({
|
|||||||
) : (
|
) : (
|
||||||
<Box>
|
<Box>
|
||||||
{e.child.map((v, ii) => (
|
{e.child.map((v, ii) => (
|
||||||
<Box key={ii}>
|
<Box key={v.id}>
|
||||||
<NavLink
|
<NavLink
|
||||||
sx={{
|
sx={{
|
||||||
":hover": {
|
":hover": {
|
||||||
backgroundColor: "transparent",
|
backgroundColor: "transparent",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
fw={activeChild === ii ? "bold" : "normal"}
|
fw={activeChild === v.id ? "bold" : "normal"}
|
||||||
label={<Text>{v.name}</Text>}
|
label={<Text>{v.name}</Text>}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActive(i);
|
setActive(e.id);
|
||||||
setActiveChild(ii)
|
setActiveChild(v.id);
|
||||||
router.push(v.path);
|
router.push(v.path);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event";
|
import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event";
|
||||||
|
import { RouterAdminVote } from "@/app/lib/router_admin/router_admin_vote";
|
||||||
import {
|
import {
|
||||||
RouterAdminDashboard,
|
RouterAdminDashboard,
|
||||||
RouterAdminDonasi,
|
RouterAdminDonasi,
|
||||||
@@ -30,27 +31,27 @@ export const listAdminPage = [
|
|||||||
path: "",
|
path: "",
|
||||||
child: [
|
child: [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 41,
|
||||||
name: "Dashboard",
|
name: "Dashboard",
|
||||||
path: RouterAdminEvent.main_event,
|
path: RouterAdminEvent.main_event,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 42,
|
||||||
name: "Table Publish",
|
name: "Table Publish",
|
||||||
path: RouterAdminEvent.table_publish,
|
path: RouterAdminEvent.table_publish,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 43,
|
||||||
name: "Table Review",
|
name: "Table Review",
|
||||||
path: RouterAdminEvent.table_review,
|
path: RouterAdminEvent.table_review,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 44,
|
||||||
name: "Table Reject",
|
name: "Table Reject",
|
||||||
path: RouterAdminEvent.table_reject,
|
path: RouterAdminEvent.table_reject,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 45,
|
||||||
name: "Tipe Acara",
|
name: "Tipe Acara",
|
||||||
path: RouterAdminEvent.detail_tipe_acara,
|
path: RouterAdminEvent.detail_tipe_acara,
|
||||||
},
|
},
|
||||||
@@ -61,4 +62,36 @@ export const listAdminPage = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "Voting",
|
||||||
|
path: "",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
id: 51,
|
||||||
|
name: "Dashboard",
|
||||||
|
path: RouterAdminVote.main,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 52,
|
||||||
|
name: "Table Publish",
|
||||||
|
path: RouterAdminVote.table_publish,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 53,
|
||||||
|
name: "Table Review",
|
||||||
|
path: RouterAdminVote.table_review,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 54,
|
||||||
|
name: "Table Reject",
|
||||||
|
path: RouterAdminVote.table_reject,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 55,
|
||||||
|
name: "Riwayat",
|
||||||
|
path: RouterAdminVote.riwayat,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import AdminMain from "./main/view";
|
import AdminMain from "./main/view";
|
||||||
import AdminLayout from "./main/layout";
|
import AdminLayout from "../layout";
|
||||||
import SplashDashboardAdmin from "../splash/splash";
|
import SplashDashboardAdmin from "../splash/splash";
|
||||||
|
|
||||||
export { AdminMain, AdminLayout, SplashDashboardAdmin };
|
export { AdminMain, AdminLayout, SplashDashboardAdmin };
|
||||||
|
|||||||
177
src/app_modules/admin/voting/child/riwayat/index.tsx
Normal file
177
src/app_modules/admin/voting/child/riwayat/index.tsx
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||||
|
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/component/header_tamplate";
|
||||||
|
import { AdminEvent_getListPesertaById } from "@/app_modules/admin/event/fun/get/get_list_peserta_by_id";
|
||||||
|
import {
|
||||||
|
Stack,
|
||||||
|
Center,
|
||||||
|
Spoiler,
|
||||||
|
Button,
|
||||||
|
Modal,
|
||||||
|
Paper,
|
||||||
|
Title,
|
||||||
|
Grid,
|
||||||
|
Avatar,
|
||||||
|
Group,
|
||||||
|
Divider,
|
||||||
|
Box,
|
||||||
|
Table,
|
||||||
|
Text,
|
||||||
|
} from "@mantine/core";
|
||||||
|
import { useDisclosure } from "@mantine/hooks";
|
||||||
|
import { IconEyeShare } from "@tabler/icons-react";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function AdminVote_Riwayat() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack>
|
||||||
|
<ComponentAdminGlobal_HeaderTamplate name="Voting: Table Riwayat" />
|
||||||
|
<TableStatus listPublish={[]} />
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableStatus({ listPublish }: { listPublish: any[] }) {
|
||||||
|
const router = useRouter();
|
||||||
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
|
const [data, setData] = useState(listPublish);
|
||||||
|
const [peserta, setPeserta] = useState<any[]>();
|
||||||
|
const [eventId, setEventId] = useState("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const TableRows = data.map((e, i) => (
|
||||||
|
<tr key={i}>
|
||||||
|
<td>
|
||||||
|
<Center>{e.title}</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>
|
||||||
|
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan">
|
||||||
|
{e.deskripsi}
|
||||||
|
</Spoiler>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>Mulai vote</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>Selesai vote</Center>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<Center>
|
||||||
|
<Button
|
||||||
|
loading={
|
||||||
|
e.id === eventId ? (loading === true ? true : false) : false
|
||||||
|
}
|
||||||
|
color={"green"}
|
||||||
|
leftIcon={<IconEyeShare />}
|
||||||
|
radius={"xl"}
|
||||||
|
onClick={async () => {
|
||||||
|
setEventId(e.id);
|
||||||
|
setLoading(true);
|
||||||
|
await new Promise((v) => setTimeout(v, 500));
|
||||||
|
await AdminEvent_getListPesertaById(e.id).then((res: any) => {
|
||||||
|
setPeserta(res);
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
open();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Hasil Voting
|
||||||
|
</Button>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Modal opened={opened} onClose={close}>
|
||||||
|
<Paper>
|
||||||
|
<Stack>
|
||||||
|
<Center>
|
||||||
|
<Title order={3}>Daftar Peserta</Title>
|
||||||
|
</Center>
|
||||||
|
<Stack>
|
||||||
|
{peserta?.map((e) => (
|
||||||
|
<Stack key={e.id} spacing={"xs"}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={"content"}>
|
||||||
|
<Avatar
|
||||||
|
sx={{ borderStyle: "solid", borderWidth: "0.5px" }}
|
||||||
|
radius={"xl"}
|
||||||
|
src={
|
||||||
|
RouterProfile.api_foto_profile +
|
||||||
|
e.User.Profile.imagesId
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={"auto"}>
|
||||||
|
<Group align="center" h={"100%"}>
|
||||||
|
<Text>{e.User.Profile.name}</Text>
|
||||||
|
</Group>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
<Divider />
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Modal>
|
||||||
|
<Box>
|
||||||
|
<Box bg={"gray.1"} p={"xs"}>
|
||||||
|
<Title order={6} c={"gray"}>
|
||||||
|
RIWAYAT
|
||||||
|
</Title>
|
||||||
|
</Box>
|
||||||
|
<Table
|
||||||
|
withBorder
|
||||||
|
verticalSpacing={"md"}
|
||||||
|
horizontalSpacing={"xl"}
|
||||||
|
p={"md"}
|
||||||
|
striped
|
||||||
|
highlightOnHover
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<Center>Judul</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Deskripsi</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Mulai Vote</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Selesai Vote</Center>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
<th>
|
||||||
|
<Center>Aksi</Center>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>{TableRows}</tbody>
|
||||||
|
</Table>
|
||||||
|
<Center>
|
||||||
|
{_.isEmpty(TableRows) ? (
|
||||||
|
<Center h={"50vh"}>
|
||||||
|
<Title order={6}>Tidak Ada Data</Title>
|
||||||
|
</Center>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</Center>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
180
src/app_modules/admin/voting/child/table_publish/index.tsx
Normal file
180
src/app_modules/admin/voting/child/table_publish/index.tsx
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||||
|
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/component/header_tamplate";
|
||||||
|
import { AdminEvent_getListPesertaById } from "@/app_modules/admin/event/fun/get/get_list_peserta_by_id";
|
||||||
|
import {
|
||||||
|
MODEL_EVENT,
|
||||||
|
MODEL_EVENT_PESERTA,
|
||||||
|
} from "@/app_modules/event/model/interface";
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Divider,
|
||||||
|
Grid,
|
||||||
|
Group,
|
||||||
|
Modal,
|
||||||
|
Paper,
|
||||||
|
Spoiler,
|
||||||
|
Stack,
|
||||||
|
Table,
|
||||||
|
Text,
|
||||||
|
Title,
|
||||||
|
} from "@mantine/core";
|
||||||
|
import { useDisclosure } from "@mantine/hooks";
|
||||||
|
import { IconEyeShare } from "@tabler/icons-react";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function AdminVote_TablePublish() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack>
|
||||||
|
<ComponentAdminGlobal_HeaderTamplate name="Voting: Table Publish" />
|
||||||
|
<TableStatus listPublish={[]} />
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableStatus({ listPublish }: { listPublish: any[] }) {
|
||||||
|
const router = useRouter();
|
||||||
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
|
const [data, setData] = useState(listPublish);
|
||||||
|
const [peserta, setPeserta] = useState<any[]>();
|
||||||
|
const [eventId, setEventId] = useState("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const TableRows = data.map((e, i) => (
|
||||||
|
<tr key={i}>
|
||||||
|
<td>
|
||||||
|
<Center>{e.title}</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>
|
||||||
|
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan">
|
||||||
|
{e.deskripsi}
|
||||||
|
</Spoiler>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>Mulai vote</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>Selesai vote</Center>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<Center>
|
||||||
|
<Button
|
||||||
|
loading={
|
||||||
|
e.id === eventId ? (loading === true ? true : false) : false
|
||||||
|
}
|
||||||
|
color={"green"}
|
||||||
|
leftIcon={<IconEyeShare />}
|
||||||
|
radius={"xl"}
|
||||||
|
onClick={async () => {
|
||||||
|
setEventId(e.id);
|
||||||
|
setLoading(true);
|
||||||
|
await new Promise((v) => setTimeout(v, 500));
|
||||||
|
await AdminEvent_getListPesertaById(e.id).then((res: any) => {
|
||||||
|
setPeserta(res);
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
open();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Hasil Voting
|
||||||
|
</Button>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Modal opened={opened} onClose={close}>
|
||||||
|
<Paper>
|
||||||
|
<Stack>
|
||||||
|
<Center>
|
||||||
|
<Title order={3}>Daftar Peserta</Title>
|
||||||
|
</Center>
|
||||||
|
<Stack>
|
||||||
|
{peserta?.map((e) => (
|
||||||
|
<Stack key={e.id} spacing={"xs"}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={"content"}>
|
||||||
|
<Avatar
|
||||||
|
sx={{ borderStyle: "solid", borderWidth: "0.5px" }}
|
||||||
|
radius={"xl"}
|
||||||
|
src={
|
||||||
|
RouterProfile.api_foto_profile +
|
||||||
|
e.User.Profile.imagesId
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={"auto"}>
|
||||||
|
<Group align="center" h={"100%"}>
|
||||||
|
<Text>{e.User.Profile.name}</Text>
|
||||||
|
</Group>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
<Divider />
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Modal>
|
||||||
|
<Box>
|
||||||
|
<Box bg={"green.1"} p={"xs"}>
|
||||||
|
<Title order={6} c={"green"}>
|
||||||
|
PUBLISH
|
||||||
|
</Title>
|
||||||
|
</Box>
|
||||||
|
<Table
|
||||||
|
withBorder
|
||||||
|
verticalSpacing={"md"}
|
||||||
|
horizontalSpacing={"xl"}
|
||||||
|
p={"md"}
|
||||||
|
striped
|
||||||
|
highlightOnHover
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<Center>Judul</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Deskripsi</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Mulai Vote</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Selesai Vote</Center>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
<th>
|
||||||
|
<Center>Aksi</Center>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>{TableRows}</tbody>
|
||||||
|
</Table>
|
||||||
|
<Center>
|
||||||
|
{_.isEmpty(TableRows) ? (
|
||||||
|
<Center h={"50vh"}>
|
||||||
|
<Title order={6}>Tidak Ada Data</Title>
|
||||||
|
</Center>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</Center>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
176
src/app_modules/admin/voting/child/table_reject/index.tsx
Normal file
176
src/app_modules/admin/voting/child/table_reject/index.tsx
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||||
|
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/component/header_tamplate";
|
||||||
|
import { AdminEvent_getListPesertaById } from "@/app_modules/admin/event/fun/get/get_list_peserta_by_id";
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Divider,
|
||||||
|
Grid,
|
||||||
|
Group,
|
||||||
|
Modal,
|
||||||
|
Paper,
|
||||||
|
Spoiler,
|
||||||
|
Stack,
|
||||||
|
Table,
|
||||||
|
Text,
|
||||||
|
Title,
|
||||||
|
} from "@mantine/core";
|
||||||
|
import { useDisclosure } from "@mantine/hooks";
|
||||||
|
import { IconEyeShare } from "@tabler/icons-react";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function AdminVote_TableReject() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack>
|
||||||
|
<ComponentAdminGlobal_HeaderTamplate name="Voting: Table Reject" />
|
||||||
|
<TableStatus listData={[]} />
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableStatus({ listData }: { listData: any[] }) {
|
||||||
|
const router = useRouter();
|
||||||
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
|
const [data, setData] = useState(listData);
|
||||||
|
const [peserta, setPeserta] = useState<any[]>();
|
||||||
|
const [eventId, setEventId] = useState("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const TableRows = data.map((e, i) => (
|
||||||
|
<tr key={i}>
|
||||||
|
<td>
|
||||||
|
<Center>{e.title}</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>
|
||||||
|
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan">
|
||||||
|
{e.deskripsi}
|
||||||
|
</Spoiler>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>Mulai vote</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>Selesai vote</Center>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<Center>
|
||||||
|
<Button
|
||||||
|
loading={
|
||||||
|
e.id === eventId ? (loading === true ? true : false) : false
|
||||||
|
}
|
||||||
|
color={"green"}
|
||||||
|
leftIcon={<IconEyeShare />}
|
||||||
|
radius={"xl"}
|
||||||
|
onClick={async () => {
|
||||||
|
setEventId(e.id);
|
||||||
|
setLoading(true);
|
||||||
|
await new Promise((v) => setTimeout(v, 500));
|
||||||
|
await AdminEvent_getListPesertaById(e.id).then((res: any) => {
|
||||||
|
setPeserta(res);
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
open();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Hasil Voting
|
||||||
|
</Button>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Modal opened={opened} onClose={close}>
|
||||||
|
<Paper>
|
||||||
|
<Stack>
|
||||||
|
<Center>
|
||||||
|
<Title order={3}>Daftar Peserta</Title>
|
||||||
|
</Center>
|
||||||
|
<Stack>
|
||||||
|
{peserta?.map((e) => (
|
||||||
|
<Stack key={e.id} spacing={"xs"}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={"content"}>
|
||||||
|
<Avatar
|
||||||
|
sx={{ borderStyle: "solid", borderWidth: "0.5px" }}
|
||||||
|
radius={"xl"}
|
||||||
|
src={
|
||||||
|
RouterProfile.api_foto_profile +
|
||||||
|
e.User.Profile.imagesId
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={"auto"}>
|
||||||
|
<Group align="center" h={"100%"}>
|
||||||
|
<Text>{e.User.Profile.name}</Text>
|
||||||
|
</Group>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
<Divider />
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Modal>
|
||||||
|
<Box>
|
||||||
|
<Box bg={"red.1"} p={"xs"}>
|
||||||
|
<Title order={6} c={"red"}>
|
||||||
|
REJECT
|
||||||
|
</Title>
|
||||||
|
</Box>
|
||||||
|
<Table
|
||||||
|
withBorder
|
||||||
|
verticalSpacing={"md"}
|
||||||
|
horizontalSpacing={"xl"}
|
||||||
|
p={"md"}
|
||||||
|
striped
|
||||||
|
highlightOnHover
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<Center>Judul</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Deskripsi</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Mulai Vote</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Selesai Vote</Center>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
<th>
|
||||||
|
<Center>Aksi</Center>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>{TableRows}</tbody>
|
||||||
|
</Table>
|
||||||
|
<Center>
|
||||||
|
{_.isEmpty(TableRows) ? (
|
||||||
|
<Center h={"50vh"}>
|
||||||
|
<Title order={6}>Tidak Ada Data</Title>
|
||||||
|
</Center>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</Center>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
164
src/app_modules/admin/voting/child/table_review/index.tsx
Normal file
164
src/app_modules/admin/voting/child/table_review/index.tsx
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||||
|
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/component/header_tamplate";
|
||||||
|
import { AdminEvent_getListPesertaById } from "@/app_modules/admin/event/fun/get/get_list_peserta_by_id";
|
||||||
|
import { Avatar, Box, Button, Center, Divider, Grid, Group, Modal, Paper, Spoiler, Stack, Table, Text, Title } from "@mantine/core";
|
||||||
|
import { useDisclosure } from "@mantine/hooks";
|
||||||
|
import { IconBan } from "@tabler/icons-react";
|
||||||
|
import { IconEyeShare } from "@tabler/icons-react";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function AdminVote_TableReview() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack>
|
||||||
|
<ComponentAdminGlobal_HeaderTamplate name="Voting: Table Review" />
|
||||||
|
<TableStatus listData={[]}/>
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableStatus({ listData }: { listData: any[] }) {
|
||||||
|
const router = useRouter();
|
||||||
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
|
const [data, setData] = useState(listData);
|
||||||
|
const [peserta, setPeserta] = useState<any[]>();
|
||||||
|
const [eventId, setEventId] = useState("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const TableRows = data.map((e, i) => (
|
||||||
|
<tr key={i}>
|
||||||
|
<td>
|
||||||
|
<Center>{e.title}</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>
|
||||||
|
<Spoiler hideLabel="sembunyikan" maxHeight={50} showLabel="tampilkan">
|
||||||
|
{e.deskripsi}
|
||||||
|
</Spoiler>
|
||||||
|
</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>Mulai vote</Center>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Center>Selesai vote</Center>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<Stack align="center">
|
||||||
|
<Button
|
||||||
|
w={150}
|
||||||
|
color={"green"}
|
||||||
|
leftIcon={<IconEyeShare />}
|
||||||
|
radius={"xl"}
|
||||||
|
// onClick={() => onPublish(e.id, setData)}
|
||||||
|
>
|
||||||
|
Publish
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
w={150}
|
||||||
|
color={"red"}
|
||||||
|
leftIcon={<IconBan />}
|
||||||
|
radius={"xl"}
|
||||||
|
// onClick={() => {
|
||||||
|
// open();
|
||||||
|
// setEventId(e.id);
|
||||||
|
// }}
|
||||||
|
>
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Modal opened={opened} onClose={close}>
|
||||||
|
<Paper>
|
||||||
|
<Stack>
|
||||||
|
<Center>
|
||||||
|
<Title order={3}>Daftar Peserta</Title>
|
||||||
|
</Center>
|
||||||
|
<Stack>
|
||||||
|
{peserta?.map((e) => (
|
||||||
|
<Stack key={e.id} spacing={"xs"}>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={"content"}>
|
||||||
|
<Avatar
|
||||||
|
sx={{ borderStyle: "solid", borderWidth: "0.5px" }}
|
||||||
|
radius={"xl"}
|
||||||
|
src={
|
||||||
|
RouterProfile.api_foto_profile +
|
||||||
|
e.User.Profile.imagesId
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={"auto"}>
|
||||||
|
<Group align="center" h={"100%"}>
|
||||||
|
<Text>{e.User.Profile.name}</Text>
|
||||||
|
</Group>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
<Divider />
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Modal>
|
||||||
|
<Box>
|
||||||
|
<Box bg={"orange.1"} p={"xs"}>
|
||||||
|
<Title order={6} c={"orange"}>
|
||||||
|
REVIEW
|
||||||
|
</Title>
|
||||||
|
</Box>
|
||||||
|
<Table
|
||||||
|
withBorder
|
||||||
|
verticalSpacing={"md"}
|
||||||
|
horizontalSpacing={"xl"}
|
||||||
|
p={"md"}
|
||||||
|
striped
|
||||||
|
highlightOnHover
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<Center>Judul</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Deskripsi</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Mulai Vote</Center>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Center>Selesai Vote</Center>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
<th>
|
||||||
|
<Center>Aksi</Center>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>{TableRows}</tbody>
|
||||||
|
</Table>
|
||||||
|
<Center>
|
||||||
|
{_.isEmpty(TableRows) ? (
|
||||||
|
<Center h={"50vh"}>
|
||||||
|
<Title order={6}>Tidak Ada Data</Title>
|
||||||
|
</Center>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</Center>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
13
src/app_modules/admin/voting/index.ts
Normal file
13
src/app_modules/admin/voting/index.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import AdminVote_Main from "./main";
|
||||||
|
import AdminVote_TablePublish from "./child/table_publish";
|
||||||
|
import AdminVote_TableReview from "./child/table_review";
|
||||||
|
import AdminVote_TableReject from "./child/table_reject";
|
||||||
|
import AdminVote_Riwayat from "./child/riwayat";
|
||||||
|
|
||||||
|
export {
|
||||||
|
AdminVote_Main,
|
||||||
|
AdminVote_TablePublish,
|
||||||
|
AdminVote_TableReview,
|
||||||
|
AdminVote_TableReject,
|
||||||
|
AdminVote_Riwayat,
|
||||||
|
};
|
||||||
96
src/app_modules/admin/voting/main/index.tsx
Normal file
96
src/app_modules/admin/voting/main/index.tsx
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Stack, SimpleGrid, Paper, Group, Title, Text } from "@mantine/core";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import ComponentAdminGlobal_HeaderTamplate from "../../component/header_tamplate";
|
||||||
|
|
||||||
|
export default function AdminVote_Main({
|
||||||
|
countPublish,
|
||||||
|
countReview,
|
||||||
|
countDraft,
|
||||||
|
countReject,
|
||||||
|
countTipeAcara,
|
||||||
|
countRiwayat,
|
||||||
|
}: {
|
||||||
|
countPublish?: number;
|
||||||
|
countReview?: number;
|
||||||
|
countDraft?: number;
|
||||||
|
countReject?: number;
|
||||||
|
countTipeAcara?: number;
|
||||||
|
countRiwayat?: number;
|
||||||
|
}) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const listStatus = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Publish",
|
||||||
|
jumlah: countPublish,
|
||||||
|
color: "green",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Review",
|
||||||
|
jumlah: countReview,
|
||||||
|
color: "orange",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Draft",
|
||||||
|
jumlah: countDraft,
|
||||||
|
path: "",
|
||||||
|
color: "yellow",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Reject",
|
||||||
|
jumlah: countReject,
|
||||||
|
color: "red",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack spacing={"xl"}>
|
||||||
|
<ComponentAdminGlobal_HeaderTamplate name="Voting" />
|
||||||
|
|
||||||
|
<SimpleGrid
|
||||||
|
cols={4}
|
||||||
|
spacing="lg"
|
||||||
|
breakpoints={[
|
||||||
|
{ maxWidth: "62rem", cols: 4, spacing: "lg" },
|
||||||
|
{ maxWidth: "48rem", cols: 2, spacing: "sm" },
|
||||||
|
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{listStatus.map((e, i) => (
|
||||||
|
<Paper
|
||||||
|
key={i}
|
||||||
|
bg={`${e.color}.2`}
|
||||||
|
shadow="md"
|
||||||
|
radius="md"
|
||||||
|
p="md"
|
||||||
|
// sx={{ borderColor: e.color, borderStyle: "solid" }}
|
||||||
|
>
|
||||||
|
<Group position="center">
|
||||||
|
<Stack align="center" spacing={0}>
|
||||||
|
<Text>{e.name}</Text>
|
||||||
|
<Title>{e.jumlah ? e.jumlah : 0}</Title>
|
||||||
|
</Stack>
|
||||||
|
</Group>
|
||||||
|
</Paper>
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
<SimpleGrid
|
||||||
|
cols={4}
|
||||||
|
spacing="lg"
|
||||||
|
breakpoints={[
|
||||||
|
{ maxWidth: "62rem", cols: 4, spacing: "lg" },
|
||||||
|
{ maxWidth: "48rem", cols: 2, spacing: "sm" },
|
||||||
|
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
|
||||||
|
]}
|
||||||
|
></SimpleGrid>
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Center,
|
|
||||||
Grid,
|
|
||||||
Group,
|
|
||||||
Stack,
|
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
Title,
|
|
||||||
} from "@mantine/core";
|
|
||||||
import { DatePickerInput } from "@mantine/dates";
|
|
||||||
import { useCounter } from "@mantine/hooks";
|
|
||||||
import { IconHome } from "@tabler/icons-react";
|
|
||||||
import { useAtom } from "jotai";
|
|
||||||
import moment from "moment";
|
|
||||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { gs_vote_hotMenu, gs_vote_status } from "../global_state";
|
|
||||||
import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
|
|
||||||
|
|
||||||
export default function Vote_Create() {
|
|
||||||
const router = useRouter();
|
|
||||||
const [hotMenu, setHotMenu] = useAtom(gs_vote_hotMenu);
|
|
||||||
const [tabsStatus, setTabsStatus] = useAtom(gs_vote_status);
|
|
||||||
|
|
||||||
const [data, setData] = useState({
|
|
||||||
title: "",
|
|
||||||
deskripsi: "",
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Stack px={"sm"}>
|
|
||||||
<TextInput
|
|
||||||
label="Judul"
|
|
||||||
withAsterisk
|
|
||||||
placeholder="Masukan judul"
|
|
||||||
onChange={() => {}}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
label="Deskripsi"
|
|
||||||
withAsterisk
|
|
||||||
placeholder="Masukan deskripsi"
|
|
||||||
onChange={() => {}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<DatePickerInput
|
|
||||||
label="Jangka Waktu"
|
|
||||||
placeholder="Masukan jangka waktu voting"
|
|
||||||
withAsterisk
|
|
||||||
dropdownType="modal"
|
|
||||||
type="range"
|
|
||||||
excludeDate={(date) => {
|
|
||||||
return moment(date).diff(Date.now(), "days") < 0;
|
|
||||||
}}
|
|
||||||
onChange={(val) => console.log(val)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Stack>
|
|
||||||
<Text fw={"bold"} fz={"sm"}>
|
|
||||||
Daftar Voting
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Stack>
|
|
||||||
<Grid>
|
|
||||||
<Grid.Col span={"content"}>
|
|
||||||
<Stack h={"100%"} justify="center">
|
|
||||||
<Title order={3}>-</Title>
|
|
||||||
</Stack>
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={"auto"}>
|
|
||||||
<TextInput
|
|
||||||
label="Pilihan 1"
|
|
||||||
placeholder="Masukan pilihan 1"
|
|
||||||
withAsterisk
|
|
||||||
onChange={() => {}}
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
<Grid>
|
|
||||||
<Grid.Col span={"content"}>
|
|
||||||
<Stack h={"100%"} justify="center">
|
|
||||||
<Title order={3}>-</Title>
|
|
||||||
</Stack>
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={"auto"}>
|
|
||||||
<TextInput
|
|
||||||
label="Pilihan 2"
|
|
||||||
placeholder="Masukan pilihan 2"
|
|
||||||
withAsterisk
|
|
||||||
onChange={() => {}}
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
mt={"lg"}
|
|
||||||
radius={"xl"}
|
|
||||||
onClick={() => onSave(router, setHotMenu, setTabsStatus)}
|
|
||||||
>
|
|
||||||
Simpan
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onSave(
|
|
||||||
router: AppRouterInstance,
|
|
||||||
setHotMenu: any,
|
|
||||||
setTabsStatus: any
|
|
||||||
) {
|
|
||||||
ComponentGlobal_NotifikasiBerhasil("Berhasil Disimpan");
|
|
||||||
setHotMenu(1);
|
|
||||||
setTabsStatus("Review")
|
|
||||||
|
|
||||||
router.replace(RouterVote.status);
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
|
|
||||||
import ComponentVote_CardViewStatus from "../../component/card_view_status";
|
|
||||||
|
|
||||||
export default function Vote_StatusReview() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ComponentVote_CardViewStatus path={RouterVote.detail_review}/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -13,11 +13,15 @@ import {
|
|||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
import { MODEL_VOTING } from "../model/interface";
|
||||||
|
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/component_global/notif_global/notifikasi_peringatan";
|
||||||
|
|
||||||
export default function ComponentVote_CardViewStatus({
|
export default function ComponentVote_CardViewStatus({
|
||||||
path,
|
path,
|
||||||
|
data,
|
||||||
}: {
|
}: {
|
||||||
path: string;
|
path?: string;
|
||||||
|
data?: MODEL_VOTING;
|
||||||
}) {
|
}) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
return (
|
return (
|
||||||
@@ -27,24 +31,30 @@ export default function ComponentVote_CardViewStatus({
|
|||||||
withBorder
|
withBorder
|
||||||
p={30}
|
p={30}
|
||||||
radius={"md"}
|
radius={"md"}
|
||||||
onClick={() => router.push(path)}
|
onClick={() => {
|
||||||
|
if (data?.id === undefined) {
|
||||||
|
ComponentGlobal_NotifikasiPeringatan("Path tidak ditemukan");
|
||||||
|
} else {
|
||||||
|
router.push((path as string) + data?.id);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{/* Isi deskripsi */}
|
{/* Isi deskripsi */}
|
||||||
<Card.Section >
|
<Card.Section>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text fw={"bold"} truncate>Judul Voting : Pemilihan tempat wisata</Text>
|
<Text fw={"bold"} truncate>
|
||||||
|
{data?.title}
|
||||||
|
</Text>
|
||||||
<Badge>
|
<Badge>
|
||||||
<Group>
|
<Group>
|
||||||
<Text>
|
<Text>
|
||||||
{new Date().toLocaleDateString(["id-ID"], {
|
{data?.awalVote.toLocaleDateString(["id-ID"], {
|
||||||
dateStyle: "medium",
|
dateStyle: "medium",
|
||||||
})}
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
<Text>-</Text>
|
<Text>-</Text>
|
||||||
<Text>
|
<Text>
|
||||||
{new Date(
|
{data?.akhirVote.toLocaleDateString(["id-ID"], {
|
||||||
moment(Date.now()).add(10, "days").calendar()
|
|
||||||
).toLocaleDateString(["id-ID"], {
|
|
||||||
dateStyle: "medium",
|
dateStyle: "medium",
|
||||||
})}
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -11,8 +11,13 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import { MODEL_VOTING } from "../../model/interface";
|
||||||
|
|
||||||
export default function ComponentVote_DetailData() {
|
export default function ComponentVote_DetailData({
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
data?: MODEL_VOTING;
|
||||||
|
}) {
|
||||||
const listVote = [
|
const listVote = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@@ -31,14 +36,9 @@ export default function ComponentVote_DetailData() {
|
|||||||
<Card.Section px={"xs"}>
|
<Card.Section px={"xs"}>
|
||||||
<Stack spacing={"lg"}>
|
<Stack spacing={"lg"}>
|
||||||
<Center>
|
<Center>
|
||||||
<Title order={5}>Judul voting</Title>
|
<Title order={5}>{data?.title}</Title>
|
||||||
</Center>
|
</Center>
|
||||||
<Text>
|
<Text>{data?.deskripsi}</Text>
|
||||||
Deskripsi: Lorem, ipsum dolor sit amet consectetur adipisicing
|
|
||||||
elit. Mollitia possimus repellendus in, iste voluptatibus sit
|
|
||||||
laborum voluptates aliquam nisi? Earum quas ea quaerat veniam
|
|
||||||
porro, magni nulla consequuntur distinctio at.
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Stack spacing={0}>
|
<Stack spacing={0}>
|
||||||
<Center>
|
<Center>
|
||||||
@@ -49,15 +49,13 @@ export default function ComponentVote_DetailData() {
|
|||||||
<Badge>
|
<Badge>
|
||||||
<Group>
|
<Group>
|
||||||
<Text>
|
<Text>
|
||||||
{new Date().toLocaleDateString(["id-ID"], {
|
{data?.awalVote.toLocaleDateString(["id-ID"], {
|
||||||
dateStyle: "medium",
|
dateStyle: "medium",
|
||||||
})}
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
<Text>-</Text>
|
<Text>-</Text>
|
||||||
<Text>
|
<Text>
|
||||||
{new Date(
|
{data?.akhirVote.toLocaleDateString(["id-ID"], {
|
||||||
moment(Date.now()).add(10, "days").calendar()
|
|
||||||
).toLocaleDateString(["id-ID"], {
|
|
||||||
dateStyle: "medium",
|
dateStyle: "medium",
|
||||||
})}
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -70,14 +68,12 @@ export default function ComponentVote_DetailData() {
|
|||||||
<Stack>
|
<Stack>
|
||||||
<Radio.Group>
|
<Radio.Group>
|
||||||
<Grid>
|
<Grid>
|
||||||
{listVote.map((e) => (
|
{data?.Voting_DaftarNamaVote.map((e) => (
|
||||||
<Grid.Col key={e.id} span={"auto"}>
|
<Grid.Col key={e.id} span={"auto"}>
|
||||||
<Center>
|
<Center>
|
||||||
<Radio
|
<Radio
|
||||||
value={e.value}
|
value={e.value}
|
||||||
label={
|
label={<Text fw={"bold"}>{e.value}</Text>}
|
||||||
<Text fw={"bold"}>{`Nama Voting ${e.label}`}</Text>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
224
src/app_modules/voting/create/index.tsx
Normal file
224
src/app_modules/voting/create/index.tsx
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Grid,
|
||||||
|
Group,
|
||||||
|
Stack,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
Title,
|
||||||
|
} from "@mantine/core";
|
||||||
|
import { DatePickerInput } from "@mantine/dates";
|
||||||
|
import { useCounter } from "@mantine/hooks";
|
||||||
|
import { IconHome, IconMinus, IconPlus } from "@tabler/icons-react";
|
||||||
|
import { useAtom } from "jotai";
|
||||||
|
import moment from "moment";
|
||||||
|
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { gs_vote_hotMenu, gs_vote_status } from "../global_state";
|
||||||
|
import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/component_global/notif_global/notifikasi_peringatan";
|
||||||
|
import { data } from "autoprefixer";
|
||||||
|
import { Vote_funCreate } from "../fun/create/create_vote";
|
||||||
|
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
|
||||||
|
import { MODEL_VOTING } from "../model/interface";
|
||||||
|
|
||||||
|
export default function Vote_Create() {
|
||||||
|
const router = useRouter();
|
||||||
|
const [hotMenu, setHotMenu] = useAtom(gs_vote_hotMenu);
|
||||||
|
const [tabsStatus, setTabsStatus] = useAtom(gs_vote_status);
|
||||||
|
|
||||||
|
const [data, setData] = useState({
|
||||||
|
title: "",
|
||||||
|
deskripsi: "",
|
||||||
|
awalVote: Date,
|
||||||
|
akhirVote: Date,
|
||||||
|
});
|
||||||
|
|
||||||
|
// const [range, setRange] = useState({
|
||||||
|
// });
|
||||||
|
|
||||||
|
const [listVote, setListVote] = useState([
|
||||||
|
{
|
||||||
|
name: "Nama Voting",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Nama Voting",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack px={"sm"} spacing={"xl"}>
|
||||||
|
<Stack>
|
||||||
|
<TextInput
|
||||||
|
label="Judul"
|
||||||
|
withAsterisk
|
||||||
|
placeholder="Masukan judul"
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
title: val.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Deskripsi"
|
||||||
|
withAsterisk
|
||||||
|
placeholder="Masukan deskripsi"
|
||||||
|
onChange={(val) => {
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
deskripsi: val.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DatePickerInput
|
||||||
|
label="Jangka Waktu"
|
||||||
|
placeholder="Masukan jangka waktu voting"
|
||||||
|
withAsterisk
|
||||||
|
dropdownType="modal"
|
||||||
|
type="range"
|
||||||
|
excludeDate={(date) => {
|
||||||
|
return moment(date).diff(Date.now(), "days") < 0;
|
||||||
|
}}
|
||||||
|
onChange={(val: any) => {
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
awalVote: val[0],
|
||||||
|
akhirVote: val[1],
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<Center>
|
||||||
|
<Text fw={"bold"} fz={"sm"}>
|
||||||
|
Daftar Voting
|
||||||
|
</Text>
|
||||||
|
</Center>
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
<Stack>
|
||||||
|
{listVote.map((e, index) => (
|
||||||
|
<Box key={index}>
|
||||||
|
<TextInput
|
||||||
|
label={e.name}
|
||||||
|
withAsterisk
|
||||||
|
placeholder="Nama pilihan voting"
|
||||||
|
onChange={(v) => {
|
||||||
|
const val = _.clone(listVote);
|
||||||
|
val[index].value = v.currentTarget.value;
|
||||||
|
setListVote([...val]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Group position="center">
|
||||||
|
{listVote.length >= 4 ? (
|
||||||
|
""
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
compact
|
||||||
|
w={100}
|
||||||
|
radius={"xl"}
|
||||||
|
leftIcon={<IconPlus size={15} />}
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => {
|
||||||
|
// if (listVote.length >= 4)
|
||||||
|
// return ComponentGlobal_NotifikasiPeringatan(
|
||||||
|
// "Daftar Voting Maksimal 4"
|
||||||
|
// );
|
||||||
|
setListVote([
|
||||||
|
...listVote,
|
||||||
|
{ name: "Nama Voting", value: "" },
|
||||||
|
]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text fz={8}>Tambah List</Text>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{listVote.length <= 2 ? (
|
||||||
|
""
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
compact
|
||||||
|
w={100}
|
||||||
|
radius={"xl"}
|
||||||
|
leftIcon={<IconMinus size={15} />}
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => {
|
||||||
|
if (listVote.length <= 2)
|
||||||
|
return ComponentGlobal_NotifikasiPeringatan(
|
||||||
|
"Daftar Voting Minimal 2"
|
||||||
|
);
|
||||||
|
setListVote([...listVote.slice(0, -1)]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text fz={8}>Kurangi List</Text>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
// disabled
|
||||||
|
mt={"lg"}
|
||||||
|
radius={"xl"}
|
||||||
|
onClick={() => {
|
||||||
|
onSave(router, setHotMenu, setTabsStatus, data as any, listVote);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Simpan
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onSave(
|
||||||
|
router: AppRouterInstance,
|
||||||
|
setHotMenu: any,
|
||||||
|
setTabsStatus: any,
|
||||||
|
data: MODEL_VOTING,
|
||||||
|
listVote: any[]
|
||||||
|
) {
|
||||||
|
if (_.values(data).includes(""))
|
||||||
|
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Data");
|
||||||
|
|
||||||
|
const cekAwalVote = moment(data.awalVote).format();
|
||||||
|
if (cekAwalVote === "Invalid date")
|
||||||
|
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Tanggal");
|
||||||
|
|
||||||
|
const cekAkhirVote = moment(data.akhirVote).format();
|
||||||
|
if (cekAkhirVote === "Invalid date")
|
||||||
|
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Tanggal");
|
||||||
|
|
||||||
|
if (_.values(listVote.map((e) => e.value)).includes(""))
|
||||||
|
return ComponentGlobal_NotifikasiPeringatan("Isi Semua Nama Voting");
|
||||||
|
|
||||||
|
await Vote_funCreate(data, listVote).then((res) => {
|
||||||
|
if (res.status === 201) {
|
||||||
|
setHotMenu(1);
|
||||||
|
setTabsStatus("Review");
|
||||||
|
router.replace(RouterVote.status);
|
||||||
|
ComponentGlobal_NotifikasiBerhasil(res.message);
|
||||||
|
} else {
|
||||||
|
ComponentGlobal_NotifikasiGagal(res.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -20,11 +20,11 @@ import { useRouter } from "next/navigation";
|
|||||||
import { gs_vote_status } from "../../global_state";
|
import { gs_vote_status } from "../../global_state";
|
||||||
import ComponentVote_DetailData from "../../component/detail/detail_data";
|
import ComponentVote_DetailData from "../../component/detail/detail_data";
|
||||||
|
|
||||||
export default function Vote_DetailReview() {
|
export default function Vote_DetailReview({ dataVote }: { dataVote : any[]}) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack spacing={"xl"}>
|
<Stack spacing={"xl"}>
|
||||||
<ComponentVote_DetailData />
|
<ComponentVote_DetailData data={dataVote as any} />
|
||||||
<ButtonAction />
|
<ButtonAction />
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
41
src/app_modules/voting/fun/create/create_vote.ts
Normal file
41
src/app_modules/voting/fun/create/create_vote.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import { User_getUserId } from "@/app_modules/fun_global/get_user_token";
|
||||||
|
import { MODEL_VOTING } from "../../model/interface";
|
||||||
|
import prisma from "@/app/lib/prisma";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
export async function Vote_funCreate(req: MODEL_VOTING, listVote: any[]) {
|
||||||
|
const authorId = await User_getUserId();
|
||||||
|
|
||||||
|
const create = await prisma.voting.create({
|
||||||
|
data: {
|
||||||
|
title: req.title,
|
||||||
|
deskripsi: req.deskripsi,
|
||||||
|
awalVote: req.awalVote,
|
||||||
|
akhirVote: req.akhirVote,
|
||||||
|
authorId: authorId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!create) return { status: 400, message: "Gagal Membuat Vote" };
|
||||||
|
|
||||||
|
for (let v of listVote) {
|
||||||
|
const val = v.value;
|
||||||
|
|
||||||
|
const namaVote = await prisma.voting_DaftarNamaVote.createMany({
|
||||||
|
data: {
|
||||||
|
value: val,
|
||||||
|
votingId: create.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!namaVote) return { status: 400, message: "Gagal Membuat List" };
|
||||||
|
}
|
||||||
|
revalidatePath("/dev/vote/main/status");
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 201,
|
||||||
|
message: "Berhasil Membuat Vote",
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import prisma from "@/app/lib/prisma";
|
||||||
|
import { User_getUserId } from "@/app_modules/fun_global/get_user_token";
|
||||||
|
|
||||||
|
export async function Vote_getListByStatusId(statusId: string) {
|
||||||
|
const authorId = await User_getUserId();
|
||||||
|
|
||||||
|
if (statusId === "1") {
|
||||||
|
const data = await prisma.voting.findMany({
|
||||||
|
where: {
|
||||||
|
voting_StatusId: "1",
|
||||||
|
authorId: authorId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusId === "2") {
|
||||||
|
const data = await prisma.voting.findMany({
|
||||||
|
where: {
|
||||||
|
voting_StatusId: "2",
|
||||||
|
authorId: authorId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusId === "3") {
|
||||||
|
const data = await prisma.voting.findMany({
|
||||||
|
where: {
|
||||||
|
voting_StatusId: "3",
|
||||||
|
authorId: authorId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusId === "4") {
|
||||||
|
const data = await prisma.voting.findMany({
|
||||||
|
where: {
|
||||||
|
voting_StatusId: "4",
|
||||||
|
authorId: authorId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/app_modules/voting/fun/get/get_one_by_id.ts
Normal file
27
src/app_modules/voting/fun/get/get_one_by_id.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import prisma from "@/app/lib/prisma";
|
||||||
|
|
||||||
|
export async function Vote_getOnebyId(voteId: string) {
|
||||||
|
const data = await prisma.voting.findFirst({
|
||||||
|
where: {
|
||||||
|
id: voteId,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
title: true,
|
||||||
|
isActive: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true,
|
||||||
|
deskripsi: true,
|
||||||
|
awalVote: true,
|
||||||
|
akhirVote: true,
|
||||||
|
catatan: true,
|
||||||
|
authorId: true,
|
||||||
|
voting_StatusId: true,
|
||||||
|
Voting_DaftarNamaVote: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
@@ -10,7 +10,17 @@ import Vote_StatusReview from "./review";
|
|||||||
import Vote_StatusDraft from "./draft";
|
import Vote_StatusDraft from "./draft";
|
||||||
import Vote_StatusReject from "./reject";
|
import Vote_StatusReject from "./reject";
|
||||||
|
|
||||||
export default function Vote_Status() {
|
export default function Vote_Status({
|
||||||
|
listPublish,
|
||||||
|
listReview,
|
||||||
|
listDraft,
|
||||||
|
listReject,
|
||||||
|
}: {
|
||||||
|
listPublish: any[];
|
||||||
|
listReview: any[];
|
||||||
|
listDraft: any[];
|
||||||
|
listReject: any[];
|
||||||
|
}) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [tabsStatus, setTabsStatus] = useAtom(gs_vote_status);
|
const [tabsStatus, setTabsStatus] = useAtom(gs_vote_status);
|
||||||
const listTabs = [
|
const listTabs = [
|
||||||
@@ -21,7 +31,7 @@ export default function Vote_Status() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
path: <Vote_StatusReview />,
|
path: <Vote_StatusReview listReview={listReview} />,
|
||||||
value: "Review",
|
value: "Review",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
import { MODEL_VOTING } from "../../model/interface";
|
||||||
|
|
||||||
export default function Vote_StatusPublish() {
|
export default function Vote_StatusPublish() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
27
src/app_modules/voting/main/status/review.tsx
Normal file
27
src/app_modules/voting/main/status/review.tsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
|
||||||
|
import ComponentVote_CardViewStatus from "../../component/card_view_status";
|
||||||
|
import { MODEL_VOTING } from "../../model/interface";
|
||||||
|
import { Box, Stack } from "@mantine/core";
|
||||||
|
|
||||||
|
export default function Vote_StatusReview({
|
||||||
|
listReview,
|
||||||
|
}: {
|
||||||
|
listReview: MODEL_VOTING[];
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack>
|
||||||
|
{listReview.map((e) => (
|
||||||
|
<Box key={e.id}>
|
||||||
|
<ComponentVote_CardViewStatus
|
||||||
|
path={RouterVote.detail_review}
|
||||||
|
data={e}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
25
src/app_modules/voting/model/interface.ts
Normal file
25
src/app_modules/voting/model/interface.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { MODEL_USER } from "@/app_modules/home/model/interface";
|
||||||
|
|
||||||
|
export interface MODEL_VOTING {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
deskripsi: string;
|
||||||
|
awalVote: Date;
|
||||||
|
akhirVote: Date;
|
||||||
|
isActive: boolean;
|
||||||
|
createdAt: Date;
|
||||||
|
updateAt: Date;
|
||||||
|
catatan: string;
|
||||||
|
authorId: string,
|
||||||
|
Author: MODEL_USER
|
||||||
|
Voting_DaftarNamaVote: MODEL_VOTING_DAFTAR_NAMA_VOTE[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MODEL_VOTING_DAFTAR_NAMA_VOTE {
|
||||||
|
id: string;
|
||||||
|
value: string;
|
||||||
|
isActive: boolean;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
votingId: string;
|
||||||
|
}
|
||||||
18
src/bin/seeder/voting/master_status.json
Normal file
18
src/bin/seeder/voting/master_status.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"name": "Publish"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"name": "Review"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3",
|
||||||
|
"name": "Draft"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4",
|
||||||
|
"name": "Reject"
|
||||||
|
}
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user