Merge pull request #216 from bipproduction/fix/bug/voting

Fix/bug/voting
This commit is contained in:
Bagasbanuna02
2024-12-27 11:08:28 +08:00
committed by GitHub
38 changed files with 1082 additions and 490 deletions

View File

@@ -2,6 +2,8 @@
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
## [1.2.35](https://github.com/bipproduction/hipmi/compare/v1.2.34...v1.2.35) (2024-12-27)
## [1.2.34](https://github.com/bipproduction/hipmi/compare/v1.2.33...v1.2.34) (2024-12-24) ## [1.2.34](https://github.com/bipproduction/hipmi/compare/v1.2.33...v1.2.34) (2024-12-24)
## [1.2.33](https://github.com/bipproduction/hipmi/compare/v1.2.32...v1.2.33) (2024-12-22) ## [1.2.33](https://github.com/bipproduction/hipmi/compare/v1.2.32...v1.2.33) (2024-12-22)

View File

@@ -1,6 +1,6 @@
{ {
"name": "hipmi", "name": "hipmi",
"version": "1.2.34", "version": "1.2.35",
"private": true, "private": true,
"prisma": { "prisma": {
"seed": "npx tsx prisma/seed.ts --yes" "seed": "npx tsx prisma/seed.ts --yes"

View File

@@ -1,5 +1,5 @@
import { prisma } from "@/app/lib"; import { prisma } from "@/app/lib";
import { newFunGetUserId } from "@/app/lib/new_fun_user_id"; import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import backendLogger from "@/util/backendLogger"; import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
@@ -7,7 +7,7 @@ export const dynamic = "force-dynamic";
export async function GET(request: Request) { export async function GET(request: Request) {
try { try {
const userLoginId = await newFunGetUserId(); const userLoginId = await funGetUserIdByToken();
const count = await prisma.notifikasi.findMany({ const count = await prisma.notifikasi.findMany({
where: { where: {

View File

@@ -1,5 +1,5 @@
import { prisma } from "@/app/lib"; import { prisma } from "@/app/lib";
import { newFunGetUserId } from "@/app/lib/new_fun_user_id"; import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { ICategoryapp } from "@/app_modules/notifikasi/model/interface"; import { ICategoryapp } from "@/app_modules/notifikasi/model/interface";
import backendLogger from "@/util/backendLogger"; import backendLogger from "@/util/backendLogger";
import _ from "lodash"; import _ from "lodash";
@@ -13,7 +13,7 @@ export async function GET(request: Request) {
const category = searchParams.get("category") as ICategoryapp; const category = searchParams.get("category") as ICategoryapp;
const page = searchParams.get("page"); const page = searchParams.get("page");
const userLoginId = await newFunGetUserId(); const userLoginId = await funGetUserIdByToken();
const fixPage = _.toNumber(page); const fixPage = _.toNumber(page);
const takeData = 10; const takeData = 10;
const skipData = fixPage * takeData - takeData; const skipData = fixPage * takeData - takeData;

View File

@@ -1,4 +1,4 @@
import { jwtVerify } from "jose"; import { decrypt } from "@/app/auth/_lib/decrypt";
import _ from "lodash"; import _ from "lodash";
import { cookies } from "next/headers"; import { cookies } from "next/headers";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
@@ -20,22 +20,3 @@ export async function GET() {
return NextResponse.json({ status: 200, message: "OK", data: dataUser }); return NextResponse.json({ status: 200, message: "OK", data: dataUser });
} }
async function decrypt({
token,
encodedKey,
}: {
token: string;
encodedKey: string;
}): Promise<Record<string, any> | null> {
try {
const enc = new TextEncoder().encode(encodedKey);
const { payload } = await jwtVerify(token, enc, {
algorithms: ["HS256"],
});
return (payload.user as Record<string, any>) || null;
} catch (error) {
console.error("Gagal verifikasi session", error);
return null;
}
}

View File

@@ -0,0 +1,312 @@
import { prisma } from "@/app/lib";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(request: Request) {
try {
let fixData;
const { searchParams } = new URL(request.url);
const search = searchParams.get("search");
const kategori = searchParams.get("kategori");
const status = searchParams.get("status");
const page = searchParams.get("page");
const takeData = 5;
const skipData = Number(page) * 5 - 5;
const userLoginId = await funGetUserIdByToken();
if (userLoginId == null) {
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan data, user id tidak ada",
},
{ status: 500 }
);
}
if (kategori == "beranda" && search != null && search != "") {
fixData = await prisma.voting.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
voting_StatusId: "1",
isArsip: false,
isActive: true,
akhirVote: {
gte: new Date(),
},
title: {
contains: search,
mode: "insensitive",
},
},
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: {
orderBy: {
createdAt: "asc",
},
include: {
Voting_Kontributor: {
include: {
Author: true,
},
},
},
},
Author: {
select: {
id: true,
username: true,
nomor: true,
Profile: true,
},
},
},
});
} else if (kategori == "beranda") {
fixData = await prisma.voting.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
voting_StatusId: "1",
isArsip: false,
isActive: true,
akhirVote: {
gte: new Date(),
},
title: {
// contains: search,
mode: "insensitive",
},
},
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: {
orderBy: {
createdAt: "asc",
},
include: {
Voting_Kontributor: {
include: {
Author: true,
},
},
},
},
Author: {
select: {
id: true,
username: true,
nomor: true,
Profile: true,
},
},
},
});
} else if (kategori == "status" && status == "1") {
fixData = await prisma.voting.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
voting_StatusId: status,
authorId: userLoginId as string,
isActive: true,
akhirVote: {
gte: new Date(),
},
},
include: {
Voting_DaftarNamaVote: {
orderBy: {
createdAt: "asc",
},
},
},
});
} else if (kategori == "status" && status != "1") {
fixData = await prisma.voting.findMany({
take: takeData,
skip: skipData,
orderBy: {
updatedAt: "desc",
},
where: {
voting_StatusId: status,
authorId: userLoginId as string,
isActive: true,
},
});
} else if (kategori == "kontribusi") {
fixData = await prisma.voting_Kontributor.findMany({
take: takeData,
skip: skipData,
orderBy: {
createdAt: "desc",
},
where: {
authorId: userLoginId,
},
select: {
id: true,
Voting: {
select: {
id: true,
title: true,
isActive: true,
awalVote: true,
akhirVote: true,
Voting_DaftarNamaVote: {
orderBy: {
createdAt: "asc",
},
},
Author: {
select: {
Profile: true,
},
},
},
},
Voting_DaftarNamaVote: true,
Author: true,
},
});
} else if (kategori == "riwayat" && status == "1") {
fixData = await prisma.voting.findMany({
take: takeData,
skip: skipData,
orderBy: {
createdAt: "asc",
},
where: {
voting_StatusId: "1",
isActive: true,
akhirVote: {
lte: new Date(),
},
},
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: {
orderBy: {
createdAt: "asc",
},
},
Author: {
select: {
id: true,
username: true,
nomor: true,
Profile: true,
},
},
},
});
} else if (kategori == "riwayat" && status == "2") {
fixData = await prisma.voting.findMany({
take: takeData,
skip: skipData,
orderBy: {
createdAt: "asc",
},
where: {
voting_StatusId: "1",
authorId: userLoginId as string,
isActive: true,
akhirVote: {
lte: new Date(),
},
},
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: {
orderBy: {
createdAt: "asc",
},
},
Author: {
select: {
id: true,
username: true,
nomor: true,
Profile: true,
},
},
},
});
}
return NextResponse.json(
{ success: true, message: "Berhasil mendapatkan data", data: fixData },
{ status: 200 }
);
} catch (error) {
backendLogger.error("Error get voting: ", error);
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan data",
reason: (error as Error).message,
},
{ status: 500 }
);
}
}

View File

@@ -0,0 +1,22 @@
import { prisma } from "@/app/lib";
import { NextResponse } from "next/server";
export async function GET(request: Request) {
try {
const data = await prisma.voting_Status.findMany();
return NextResponse.json({
success: true,
message: "Berhasil mendapatkan data",
data: data,
});
} catch (error) {
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan data",
reason: (error as Error).message,
},
{ status: 500 }
);
}
}

View File

@@ -1,9 +1,9 @@
import { newFunGetUserId } from "@/app/lib/new_fun_user_id"; import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { Event_Create } from "@/app_modules/event"; import { Event_Create } from "@/app_modules/event";
import { Event_getMasterTipeAcara } from "@/app_modules/event/fun/master/get_tipe_acara"; import { Event_getMasterTipeAcara } from "@/app_modules/event/fun/master/get_tipe_acara";
export default async function Page() { export default async function Page() {
const userLoginId = await newFunGetUserId(); const userLoginId = await funGetUserIdByToken();
const listTipeAcara = await Event_getMasterTipeAcara(); const listTipeAcara = await Event_getMasterTipeAcara();
return ( return (

View File

@@ -1,10 +1,10 @@
import { newFunGetUserId } from "@/app/lib/new_fun_user_id"; import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { Event_DetailMain } from "@/app_modules/event"; import { Event_DetailMain } from "@/app_modules/event";
import { Event_countTotalPesertaById } from "@/app_modules/event/fun/count/count_total_peserta_by_id"; import { Event_countTotalPesertaById } from "@/app_modules/event/fun/count/count_total_peserta_by_id";
export default async function Page({ params }: { params: { id: string } }) { export default async function Page({ params }: { params: { id: string } }) {
let eventId = params.id; let eventId = params.id;
const userLoginId = await newFunGetUserId(); const userLoginId = await funGetUserIdByToken();
const totalPeserta = await Event_countTotalPesertaById(eventId); const totalPeserta = await Event_countTotalPesertaById(eventId);
return ( return (

View File

@@ -1,4 +1,4 @@
import { newFunGetUserId } from "@/app/lib/new_fun_user_id"; import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import Ui_Konfirmasi from "@/app_modules/event/_ui/konfirmasi"; import Ui_Konfirmasi from "@/app_modules/event/_ui/konfirmasi";
export default async function Page({ export default async function Page({
@@ -7,7 +7,7 @@ export default async function Page({
params: Promise<{ id: string }>; params: Promise<{ id: string }>;
}) { }) {
const eventId = (await params).id; const eventId = (await params).id;
const userLoginId = await newFunGetUserId(); const userLoginId = await funGetUserIdByToken();
return ( return (
<> <>

View File

@@ -1,5 +1,5 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { RealtimeProvider } from "../lib"; import { RealtimeProvider } from "../lib";
import { newFunGetUserId } from "../lib/new_fun_user_id";
import { ServerEnv } from "../lib/server_env"; import { ServerEnv } from "../lib/server_env";
export default async function Layout({ export default async function Layout({
@@ -8,7 +8,7 @@ export default async function Layout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
const userId = await newFunGetUserId(); const userId = await funGetUserIdByToken();
return ( return (
<> <>

View File

@@ -1,12 +1,10 @@
import { Vote_Beranda } from "@/app_modules/vote"; import { Vote_Beranda } from "@/app_modules/vote";
import { vote_getAllListPublish } from "@/app_modules/vote/fun/get/get_all_list_publish";
export default async function Page() { export default async function Page() {
const dataVote = await vote_getAllListPublish({ page: 1 });
return ( return (
<> <>
<Vote_Beranda dataVote={dataVote as any} /> <Vote_Beranda />
</> </>
); );
} }

View File

@@ -1,11 +1,9 @@
import { Vote_Kontribusi } from "@/app_modules/vote"; import { Vote_Kontribusi } from "@/app_modules/vote";
import { vote_getAllListKontribusiByAuthorId } from "@/app_modules/vote/fun/get/get_list_kontribusi_by_author_id";
export default async function Page() { export default async function Page() {
const dataKontribusi = await vote_getAllListKontribusiByAuthorId({ page: 1 });
return ( return (
<> <>
<Vote_Kontribusi dataKontribusi={dataKontribusi as any} /> <Vote_Kontribusi />
</> </>
); );
} }

View File

@@ -1,41 +1,9 @@
import { Vote_Riwayat } from "@/app_modules/vote"; import { Vote_Riwayat } from "@/app_modules/vote";
import { vote_getAllListRiwayat } from "@/app_modules/vote/fun/get/get_all_list_riwayat";
import { Vote_getAllListRiwayatSaya as vote_getAllListRiwayatSaya } from "@/app_modules/vote/fun/get/get_all_list_riwayat_saya";
export default async function Page({ params }: { params: { id: string } }) { export default async function Page({ params }: { params: { id: string } }) {
let statusRiwayatId = params.id;
const listRiwayat = await vote_getAllListRiwayat({ page: 1 });
const listRiwayatSaya = await vote_getAllListRiwayatSaya({ page: 1 });
if (statusRiwayatId == "1") {
return ( return (
<> <>
<Vote_Riwayat <Vote_Riwayat />
riwayatId={statusRiwayatId}
listRiwayat={listRiwayat as any}
/>
</> </>
); );
} }
if (statusRiwayatId == "2") {
return (
<>
<Vote_Riwayat
riwayatId={statusRiwayatId}
listRiwayatSaya={listRiwayatSaya as any}
/>
</>
);
}
// return (
// <>
// <Vote_Riwayat
// riwayatId={statusRiwayatId}
// listRiwayat={listRiwayat as any}
// listRiwayatSaya={listRiwayatSaya as any}
// />
// </>
// );
}

View File

@@ -1,25 +1,9 @@
import { Vote_Status } from "@/app_modules/vote"; import { Vote_Status } from "@/app_modules/vote";
import {
vote_funGetAllByStatusId,
voting_getMasterStatus,
} from "@/app_modules/vote/fun";
export default async function Page({ params }: { params: { id: string } }) {
const statusId = params.id;
const listStatus = await voting_getMasterStatus();
const dataVoting = await vote_funGetAllByStatusId({
page: 1,
statusId: statusId,
});
export default async function Page() {
return ( return (
<> <>
<Vote_Status <Vote_Status />
statusId={statusId}
dataVoting={dataVoting as any}
listStatus={listStatus as any}
/>
</> </>
); );
} }

View File

@@ -1,11 +1,14 @@
"use server" "use server";
import _ from "lodash"; import _ from "lodash";
import { cookies } from "next/headers"; import { cookies } from "next/headers";
import { decrypt } from "../auth/_lib/decrypt"; import { decrypt } from "../auth/_lib/decrypt";
import backendLogger from "@/util/backendLogger";
export async function newFunGetUserId() { export async function newFunGetUserId() {
const c = cookies().get(process.env.NEXT_PUBLIC_BASE_SESSION_KEY!); try {
const key = process.env.NEXT_PUBLIC_BASE_SESSION_KEY;
const c = cookies().get("hipmi-key");
if (!c || !c?.value || _.isEmpty(c?.value) || _.isUndefined(c?.value)) { if (!c || !c?.value || _.isEmpty(c?.value) || _.isUndefined(c?.value)) {
return null; return null;
@@ -18,4 +21,8 @@ export async function newFunGetUserId() {
}); });
return dataUser?.id; return dataUser?.id;
} catch (error) {
backendLogger.log("Gagal mendapatkan user id", error);
return null;
}
} }

View File

@@ -0,0 +1,51 @@
"use client";
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import {
UIGlobal_LayoutHeaderTamplate,
UIGlobal_LayoutTamplate,
} from "@/app_modules/_global/ui";
import { Center, Grid, Group, Skeleton, Stack } from "@mantine/core";
export default function Voting_ComponentSkeletonViewPuh() {
return (
<>
<UIGlobal_LayoutTamplate
header={<UIGlobal_LayoutHeaderTamplate title="Detail Publish" />}
>
<ComponentGlobal_CardStyles marginBottom={"0"}>
<Stack spacing={"lg"}>
<Grid align="center">
<Grid.Col span={"content"}>
<Skeleton circle height={40} />
</Grid.Col>
<Grid.Col span={4}>
<Skeleton height={20} w={150} />
</Grid.Col>
</Grid>
<Stack align="center">
<Skeleton height={20} w={150} />
<Skeleton height={20} w={300} />
</Stack>
<Group position="center" spacing={100}>
<Stack align="center">
<Skeleton circle height={70} />
<Skeleton height={20} w={50} />
</Stack>
<Stack align="center">
<Skeleton circle height={70} />
<Skeleton height={20} w={50} />
</Stack>
</Group>
<Stack align="center">
<Skeleton height={15} w={50} /> <Skeleton height={20} w={50} />
</Stack>
</Stack>
</ComponentGlobal_CardStyles>
</UIGlobal_LayoutTamplate>
</>
);
}

View File

@@ -1,56 +1,36 @@
"use server"; "use server";
import { prisma } from "@/app/lib";
import { ServerEnv } from "@/app/lib/server_env";
import { unsealData } from "iron-session";
import { jwtVerify } from "jose"; import { jwtVerify } from "jose";
import { cookies } from "next/headers"; import { cookies } from "next/headers";
import { decrypt } from "../../../../app/auth/_lib/decrypt";
export async function funGetUserIdByToken() { export async function funGetUserIdByToken() {
const SESSION_KEY = process.env.NEXT_PUBLIC_BASE_SESSION_KEY!; const SESSION_KEY = process.env.NEXT_PUBLIC_BASE_SESSION_KEY!;
// console.log("SESSION_KEY", SESSION_KEY); const c = cookies().get(SESSION_KEY);
const c = cookies().get("hipmi-key");
const cekUser = await decrypt({ const cekUser = await decrypt({
token: c?.value as string, token: c?.value as string,
encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!, encodedKey: process.env.NEXT_PUBLIC_BASE_TOKEN_KEY!,
}); });
// console.log("userid" , cekUser?.id)
// const token = JSON.parse(
// await unsealData(c?.value as string, {
// password: process.env.WIBU_PWD as string,
// })
// );
// return token.id;
// const token = c?.value;
// const cekToken = await prisma.userSession.findFirst({
// where: {
// token: token,
// },
// });
// if (cekToken === null) return null
return cekUser?.id; return cekUser?.id;
} }
async function decrypt({ // async function decrypt({
token, // token,
encodedKey, // encodedKey,
}: { // }: {
token: string; // token: string;
encodedKey: string; // encodedKey: string;
}): Promise<Record<string, any> | null> { // }): Promise<Record<string, any> | null> {
try { // try {
const enc = new TextEncoder().encode(encodedKey); // const enc = new TextEncoder().encode(encodedKey);
const { payload } = await jwtVerify(token, enc, { // const { payload } = await jwtVerify(token, enc, {
algorithms: ["HS256"], // algorithms: ["HS256"],
}); // });
return (payload.user as Record<string, any>) || null; // return (payload.user as Record<string, any>) || null;
} catch (error) { // } catch (error) {
console.error("Gagal verifikasi session", error); // console.error("Gagal verifikasi session", error);
return null; // return null;
} // }
} // }

View File

@@ -15,7 +15,7 @@ export default function LayoutMainCrowd({
<UIGlobal_LayoutTamplate <UIGlobal_LayoutTamplate
header={ header={
<UIGlobal_LayoutHeaderTamplate <UIGlobal_LayoutHeaderTamplate
title="Crowd Funding" title="Crowdfunding"
routerLeft={RouterHome.main_home} routerLeft={RouterHome.main_home}
/> />
} }

View File

@@ -5,8 +5,6 @@ import {
AccentColor, AccentColor,
MainColor, MainColor,
} from "@/app_modules/_global/color/color_pallet"; } from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { gs_donasi_hot_menu } from "@/app_modules/donasi/global_state"; import { gs_donasi_hot_menu } from "@/app_modules/donasi/global_state";
import { gs_investas_menu } from "@/app_modules/investasi/g_state"; import { gs_investas_menu } from "@/app_modules/investasi/g_state";
import { Grid, Image, Paper, Stack, Text, Title } from "@mantine/core"; import { Grid, Image, Paper, Stack, Text, Title } from "@mantine/core";
@@ -21,26 +19,27 @@ export default function MainCrowd() {
const [donasiHotMenu, setDonasiHotMenu] = useAtom(gs_donasi_hot_menu); const [donasiHotMenu, setDonasiHotMenu] = useAtom(gs_donasi_hot_menu);
const [loadingInv, setLoadingInv] = useState(false); const [loadingInv, setLoadingInv] = useState(false);
const [loadingDon, setLoadingDon] = useState(false); const [loadingDon, setLoadingDon] = useState(false);
const [isLoading, setLoading] = useState(true);
return ( return (
<> <>
<Stack> <Stack>
<Paper>
{/* <AspectRatio ratio={16 / 9}>
<Paper radius={"md"}>
</Paper>
</AspectRatio> */}
<Image <Image
alt="Logo" height={200}
fit={"cover"}
alt="logo"
src={"/aset/investasi/logo-crowd-panjang-new.png"} src={"/aset/investasi/logo-crowd-panjang-new.png"}
mah={"100%"} onLoad={() => setLoading(false)}
styles={{ styles={{
imageWrapper: {
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px 10px 10px 10px",
},
image: { image: {
borderRadius: "20px", borderRadius: "8px 8px 8px 8px",
}, },
}} }}
/> />
</Paper>
<Stack> <Stack>
{/* INVESTASI */} {/* INVESTASI */}

View File

@@ -26,6 +26,7 @@ export default function BodyHome() {
const [dataUser, setDataUser] = useState<any>({}); const [dataUser, setDataUser] = useState<any>({});
const [dataJob, setDataJob] = useState<any[]>([]); const [dataJob, setDataJob] = useState<any[]>([]);
const [loadingJob, setLoadingJob] = useState(true); const [loadingJob, setLoadingJob] = useState(true);
const [loading, setLoading] = useState(true);
useShallowEffect(() => { useShallowEffect(() => {
cekUserLogin(); cekUserLogin();
@@ -59,16 +60,35 @@ export default function BodyHome() {
return ( return (
<Box> <Box>
<Paper {/* <Paper
radius={"xl"} radius={"xl"}
h={150}
mb={"xs"} mb={"xs"}
style={{ style={{
borderRadius: "10px 10px 10px 10px", borderRadius: "10px 10px 10px 10px",
border: `2px solid ${AccentColor.blue}`, border: `2px solid ${AccentColor.blue}`,
position: "relative",
}} }}
> >
<Image radius={"lg"} alt="logo" src={"/aset/home/home-hipmi-new.png"} />
</Paper> </Paper> */}
<Image
height={140}
fit={"cover"}
alt="logo"
src={"/aset/home/home-hipmi-new.png"}
onLoad={() => setLoading(false)}
styles={{
imageWrapper: {
border: `2px solid ${AccentColor.blue}`,
borderRadius: "10px 10px 10px 10px",
},
image: {
borderRadius: "8px 8px 8px 8px",
},
}}
/>
<Stack my={"sm"}> <Stack my={"sm"}>
<SimpleGrid cols={2} spacing="md"> <SimpleGrid cols={2} spacing="md">

View File

@@ -0,0 +1,42 @@
/**
* Mengambil daftar semua voting dari API berdasarkan filter yang diberikan.
*
* @param {Object} params - Parameter untuk permintaan data voting.
* @param {"beranda"|"status"} params.kategori - Kategori voting yang diminta, hanya dapat berupa "beranda" atau "status".
* @param {string} params.page - Nomor halaman untuk pagination.
* @param {string|null|undefined} [params.search] - Kata kunci pencarian untuk memfilter voting (opsional).
* @param {"1"|"2"|"3"|"4"|undefined} [params.status] - Status voting, di mana:
* - "1": Publish,
* - "2": Review,
* - "3": Draft,
* - "4": Reject.
* Parameter ini bersifat opsional.
* @returns {Promise<Object|null>} Mengembalikan objek hasil permintaan dalam bentuk JSON jika berhasil,
* atau `null` jika terjadi kesalahan dalam parsing respons.
*
* @example
* // Contoh penggunaan:
* apiGetAllVoting({
* kategori: "beranda",
* page: "1",
* search: "pemilu",
* status: "1",
* }).then(data => console.log(data));
*/
export const apiGetAllVoting = async ({
kategori,
page,
search,
status,
}: {
kategori: "beranda" | "status" | "kontribusi" | "riwayat";
page: string;
search?: string | null;
status?: "1" | "2" | "3" | "4";
}) => {
const respone = await fetch(
`/api/voting/get?kategori=${kategori}&page=${page}&search=${search || ""}&status=${status || ""}`
);
return await respone.json().catch(() => null);
};

View File

@@ -7,17 +7,9 @@ import {
ComponentGlobal_CardStyles, ComponentGlobal_CardStyles,
} from "@/app_modules/_global/component"; } from "@/app_modules/_global/component";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { import { Avatar, Badge, Box, Center, Grid, Stack, Text } from "@mantine/core";
Avatar, import moment from "moment";
Badge, import "moment/locale/id";
Box,
Center,
Grid,
Group,
Stack,
Text,
Title
} from "@mantine/core";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
import { MODEL_VOTING } from "../model/interface"; import { MODEL_VOTING } from "../model/interface";
@@ -75,35 +67,23 @@ export default function ComponentVote_CardViewPublish({
backgroundColor: AccentColor.blue, backgroundColor: AccentColor.blue,
border: `1px solid ${AccentColor.skyblue}`, border: `1px solid ${AccentColor.skyblue}`,
color: "white", color: "white",
width: "80%", width: "70%",
}, },
}} }}
> >
<Group>
<Text> <Text>
{data {data
? data?.awalVote.toLocaleDateString(["id-ID"], { ? moment(data.awalVote).format("ll")
dateStyle: "medium", : "tgl awal voting"}{" "}
}) -{" "}
: "tgl awal voting"}
</Text>
<Text>-</Text>
<Text>
{data {data
? data?.akhirVote.toLocaleDateString(["id-ID"], { ? moment(data.akhirVote).format("ll")
dateStyle: "medium",
})
: "tgl akhir voting"} : "tgl akhir voting"}
</Text> </Text>
</Group>
</Badge> </Badge>
</Stack> </Stack>
{data ? ( {data ? (
<Stack> <Stack>
<Center>
<Title order={5}>Hasil Voting</Title>
</Center>
<Grid justify="center"> <Grid justify="center">
{data?.Voting_DaftarNamaVote.map((e) => ( {data?.Voting_DaftarNamaVote.map((e) => (
<Grid.Col <Grid.Col

View File

@@ -1,12 +1,17 @@
"use client"; "use client";
import { AccentColor } from "@/app_modules/_global/color/color_pallet"; import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import {
ComponentGlobal_CardLoadingOverlay,
ComponentGlobal_CardStyles,
} from "@/app_modules/_global/component";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { Badge, Card, Group, Stack, Text } from "@mantine/core"; import { Badge, Stack, Text } from "@mantine/core";
import moment from "moment";
import "moment/locale/id";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { MODEL_VOTING } from "../model/interface";
import { useState } from "react"; import { useState } from "react";
import { ComponentGlobal_CardLoadingOverlay, ComponentGlobal_CardStyles } from "@/app_modules/_global/component"; import { MODEL_VOTING } from "../model/interface";
export default function ComponentVote_CardViewStatus({ export default function ComponentVote_CardViewStatus({
path, path,
@@ -23,7 +28,7 @@ export default function ComponentVote_CardViewStatus({
<ComponentGlobal_CardStyles <ComponentGlobal_CardStyles
onClickHandler={() => { onClickHandler={() => {
if (data?.id === undefined) { if (data?.id === undefined) {
ComponentGlobal_NotifikasiPeringatan("Path tidak ditemukan"); ComponentGlobal_NotifikasiPeringatan("Halaman tidak ditemukan");
} else { } else {
setVisible(true); setVisible(true);
router.push((path as string) + data?.id); router.push((path as string) + data?.id);
@@ -42,23 +47,14 @@ export default function ComponentVote_CardViewStatus({
backgroundColor: AccentColor.blue, backgroundColor: AccentColor.blue,
border: `1px solid ${AccentColor.skyblue}`, border: `1px solid ${AccentColor.skyblue}`,
color: "white", color: "white",
width: "80%", width: "70%",
}, },
}} }}
> >
<Group>
<Text> <Text>
{data?.awalVote.toLocaleDateString(["id-ID"], { {data ? moment(data.awalVote).format("ll") : "tgl awal voting"} -{" "}
dateStyle: "medium", {data ? moment(data.akhirVote).format("ll") : "tgl akhir voting"}
})}
</Text> </Text>
<Text>-</Text>
<Text>
{data?.akhirVote.toLocaleDateString(["id-ID"], {
dateStyle: "medium",
})}
</Text>
</Group>
</Badge> </Badge>
</Stack> </Stack>
{visible && <ComponentGlobal_CardLoadingOverlay />} {visible && <ComponentGlobal_CardLoadingOverlay />}

View File

@@ -1,3 +1,9 @@
import { Voting_ComponentLayoutHeaderDetailPublish } from "./detail/comp_layout_header_detail_publish"; import { Voting_ComponentLayoutHeaderDetailPublish } from "./detail/comp_layout_header_detail_publish";
import {
Voting_ComponentSkeletonViewPublish,
Voting_ComponentSkeletonViewStatus,
} from "./skeleton_view";
export { Voting_ComponentLayoutHeaderDetailPublish }; export { Voting_ComponentLayoutHeaderDetailPublish };
export { Voting_ComponentSkeletonViewPublish };
export { Voting_ComponentSkeletonViewStatus };

View File

@@ -0,0 +1,97 @@
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import { Grid, Group, Skeleton, Stack } from "@mantine/core";
export function Voting_ComponentSkeletonViewPublish() {
return (
<>
{Array.from({ length: 2 }).map((e, i) => (
<ComponentGlobal_CardStyles key={i} marginBottom={"0"}>
<Stack spacing={"lg"}>
<Grid align="center">
<Grid.Col span={"content"}>
<Skeleton circle height={40} />
</Grid.Col>
<Grid.Col span={4}>
<Skeleton height={20} w={150} />
</Grid.Col>
</Grid>
<Stack align="center">
<Skeleton height={20} w={150} />
<Skeleton height={20} w={300} />
{/* <Skeleton height={20} w={70} /> */}
</Stack>
<Grid grow>
{Array.from({ length: 2 }).map((e, i) => (
<Grid.Col span={4} key={i}>
<Stack align="center">
<Skeleton circle height={70} />
<Skeleton height={20} w={50} />
</Stack>
</Grid.Col>
))}
</Grid>
</Stack>
</ComponentGlobal_CardStyles>
))}
</>
);
}
export function Voting_ComponentSkeletonViewStatus() {
return (
<>
{Array.from({ length: 2 }).map((e, i) => (
<ComponentGlobal_CardStyles key={i}>
<Stack align="center" spacing="lg">
<Skeleton height={20} w={150} />
<Skeleton height={20} w={300} />
</Stack>
</ComponentGlobal_CardStyles>
))}
</>
);
}
export function Voting_ComponentSkeletonViewKontribusi() {
return (
<>
{Array.from({ length: 2 }).map((e, i) => (
<ComponentGlobal_CardStyles key={i} marginBottom={"0"}>
<Stack spacing={"lg"}>
<Grid align="center">
<Grid.Col span={"content"}>
<Skeleton circle height={40} />
</Grid.Col>
<Grid.Col span={4}>
<Skeleton height={20} w={150} />
</Grid.Col>
</Grid>
<Stack align="center">
<Skeleton height={20} w={150} />
<Skeleton height={20} w={300} />
</Stack>
<Group position="center" spacing={100}>
<Stack align="center">
<Skeleton circle height={70} />
<Skeleton height={20} w={50} />
</Stack>
<Stack align="center">
<Skeleton circle height={70} />
<Skeleton height={20} w={50} />
</Stack>
</Group>
<Stack align="center">
<Skeleton height={15} w={50} /> <Skeleton height={20} w={50} />
</Stack>
</Stack>
</ComponentGlobal_CardStyles>
))}
</>
);
}

View File

@@ -53,3 +53,4 @@ export {
Vote_DetailRiwayatSaya, Vote_DetailRiwayatSaya,
LayoutVote_DetailRiwayatSaya, LayoutVote_DetailRiwayatSaya,
}; };

View File

@@ -1,8 +1,11 @@
"use client"; "use client";
import { gs_votingTiggerBeranda } from "@/app/lib/global_state";
import { RouterVote } from "@/app/lib/router_hipmi/router_vote"; import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
import { AccentColor } from "@/app_modules/_global/color";
import ComponentGlobal_CreateButton from "@/app_modules/_global/component/button_create"; import ComponentGlobal_CreateButton from "@/app_modules/_global/component/button_create";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { clientLogger } from "@/util/clientLogger";
import { import {
Affix, Affix,
Box, Box,
@@ -14,22 +17,17 @@ import {
TextInput, TextInput,
} from "@mantine/core"; } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks"; import { useShallowEffect } from "@mantine/hooks";
import { useAtom } from "jotai";
import _ from "lodash"; import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader"; import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react"; import { useState } from "react";
import { apiGetAllVoting } from "../_lib/api_voting";
import { Voting_ComponentSkeletonViewPublish } from "../component";
import ComponentVote_CardViewPublish from "../component/card_view_publish"; import ComponentVote_CardViewPublish from "../component/card_view_publish";
import { vote_getAllListPublish } from "../fun/get/get_all_list_publish";
import { MODEL_VOTING } from "../model/interface"; import { MODEL_VOTING } from "../model/interface";
import { gs_votingTiggerBeranda } from "@/app/lib/global_state";
import { useAtom } from "jotai";
import { AccentColor } from "@/app_modules/_global/color";
export default function Vote_Beranda({ export default function Vote_Beranda() {
dataVote, const [data, setData] = useState<MODEL_VOTING[] | null>(null);
}: {
dataVote: MODEL_VOTING[];
}) {
const [data, setData] = useState(dataVote);
const [activePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
// Realtime // Realtime
@@ -46,33 +44,51 @@ export default function Vote_Beranda({
}, [isTriggerVotingBeranda, setIsShowUpdate]); }, [isTriggerVotingBeranda, setIsShowUpdate]);
useShallowEffect(() => { useShallowEffect(() => {
onLoad({ onLoad();
newData(val) { }, []);
setData(val);
},
});
setIsTriggerVotingBeranda(false);
}, [setData, setIsTriggerVotingBeranda]);
async function onLoad({ newData }: { newData: (val: any) => void }) { async function onLoad() {
const loadData = await vote_getAllListPublish({ page: 1 }); try {
newData(loadData); const loadData = await apiGetAllVoting({
kategori: "beranda",
page: "1",
});
setData(loadData.data as any);
setIsTriggerVotingBeranda(false);
} catch (error) {
clientLogger.error("Error get data beranda", error);
}
} }
async function onSearch(s: string) { async function onSearch(s: string) {
const loadSearch = await vote_getAllListPublish({ page: 1, search: s }); try {
setData(loadSearch as any); const loadData = await apiGetAllVoting({
kategori: "beranda",
page: "1",
search: s,
});
setData(loadData.data as any);
} catch (error) {
clientLogger.error("Error get data beranda", error);
}
} }
async function onLoadData({ onPublish }: { onPublish: (val: any) => void }) { async function onLoadData() {
try {
setIsLoading(true); setIsLoading(true);
const loadData = await vote_getAllListPublish({ page: 1 }); const loadData = await apiGetAllVoting({
onPublish(loadData); kategori: "beranda",
page: "1",
});
setData(loadData.data as any);
setIsShowUpdate(false); setIsShowUpdate(false);
setIsTriggerVotingBeranda(false); setIsTriggerVotingBeranda(false);
} catch (error) {
clientLogger.error("Error get data beranda", error);
} finally {
setIsLoading(false); setIsLoading(false);
} }
}
return ( return (
<Stack mt={"1vh"}> <Stack mt={"1vh"}>
@@ -90,11 +106,7 @@ export default function Vote_Beranda({
radius={"xl"} radius={"xl"}
opacity={0.8} opacity={0.8}
onClick={() => { onClick={() => {
onLoadData({ onLoadData();
onPublish(val) {
setData(val);
},
});
}} }}
> >
Update beranda Update beranda
@@ -111,7 +123,9 @@ export default function Vote_Beranda({
<ComponentGlobal_CreateButton path={RouterVote.create} /> <ComponentGlobal_CreateButton path={RouterVote.create} />
{_.isEmpty(data) ? ( {_.isNull(data) ? (
<Voting_ComponentSkeletonViewPublish />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData /> <ComponentGlobal_IsEmptyData />
) : ( ) : (
<Box> <Box>
@@ -123,15 +137,16 @@ export default function Vote_Beranda({
</Center> </Center>
)} )}
data={data} data={data}
setData={setData} setData={setData as any}
moreData={async () => { moreData={async () => {
const loadData = await vote_getAllListPublish({ const loadData = await apiGetAllVoting({
page: activePage + 1, kategori: "beranda",
page: `${activePage + 1}`,
}); });
setActivePage((val) => val + 1); setActivePage((val) => val + 1);
return loadData; return loadData.data;
}} }}
> >
{(item) => ( {(item) => (

View File

@@ -1,29 +1,44 @@
"use client"; "use client";
import { RouterVote } from "@/app/lib/router_hipmi/router_vote"; import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
import { Box, Center, Loader, Stack } from "@mantine/core";
import _ from "lodash";
import ComponentVote_CardViewPublish from "../component/card_view_publish";
import ComponentVote_IsEmptyData from "../component/is_empty_data";
import { MODEL_VOTE_KONTRIBUTOR } from "../model/interface";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { data } from "autoprefixer"; import { clientLogger } from "@/util/clientLogger";
import { Box, Center, Loader, Stack } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader"; import { ScrollOnly } from "next-scroll-loader";
import { vote_getAllListPublish } from "../fun/get/get_all_list_publish";
import { useState } from "react"; import { useState } from "react";
import { vote_getAllListKontribusiByAuthorId } from "../fun/get/get_list_kontribusi_by_author_id"; import { apiGetAllVoting } from "../_lib/api_voting";
import ComponentVote_CardViewPublish from "../component/card_view_publish";
import { MODEL_VOTE_KONTRIBUTOR } from "../model/interface";
import { Voting_ComponentSkeletonViewKontribusi } from "../component/skeleton_view";
export default function Vote_Kontribusi({ export default function Vote_Kontribusi() {
dataKontribusi, const [data, setData] = useState<MODEL_VOTE_KONTRIBUTOR[] | null>(null);
}: {
dataKontribusi: MODEL_VOTE_KONTRIBUTOR[];
}) {
const [data, setData] = useState(dataKontribusi);
const [activePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
useShallowEffect(() => {
onLoad();
}, []);
async function onLoad() {
try {
const loadData = await apiGetAllVoting({
kategori: "kontribusi",
page: "1",
});
setData(loadData.data as any);
} catch (error) {
clientLogger.error("Error get data beranda", error);
}
}
return ( return (
<> <>
{_.isEmpty(dataKontribusi) ? ( <Stack>
{_.isNull(data) ? (
<Voting_ComponentSkeletonViewKontribusi />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData /> <ComponentGlobal_IsEmptyData />
) : ( ) : (
<Box> <Box>
@@ -35,15 +50,16 @@ export default function Vote_Kontribusi({
</Center> </Center>
)} )}
data={data} data={data}
setData={setData} setData={setData as any}
moreData={async () => { moreData={async () => {
const loadData = await vote_getAllListKontribusiByAuthorId({ const loadData = await apiGetAllVoting({
page: activePage + 1, kategori: "kontribusi",
page: `${activePage + 1}`,
}); });
setActivePage((val) => val + 1); setActivePage((val) => val + 1);
return loadData; return loadData.data;
}} }}
> >
{(item) => ( {(item) => (
@@ -58,7 +74,7 @@ export default function Vote_Kontribusi({
</ScrollOnly> </ScrollOnly>
</Box> </Box>
)} )}
{/* <pre>{JSON.stringify(dataKontribusi, null, 2)}</pre> */} </Stack>
</> </>
); );
} }

View File

@@ -1,30 +1,18 @@
"use client"; "use client";
import { Stack, Tabs } from "@mantine/core"; import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
import { useState } from "react";
import Vote_SemuaRiwayat from "./semua";
import Vote_RiwayatSaya from "./saya";
import { useAtom } from "jotai";
import { gs_vote_riwayat } from "../../global_state";
import { MODEL_VOTING } from "../../model/interface";
import { import {
AccentColor, AccentColor,
MainColor, MainColor,
} from "@/app_modules/_global/color/color_pallet"; } from "@/app_modules/_global/color/color_pallet";
import { useRouter } from "next/navigation"; import { Stack, Tabs } from "@mantine/core";
import { RouterVote } from "@/app/lib/router_hipmi/router_vote"; import { useParams, useRouter } from "next/navigation";
import Vote_RiwayatSaya from "./saya";
import Vote_SemuaRiwayat from "./semua";
export default function Vote_Riwayat({ export default function Vote_Riwayat() {
riwayatId,
listRiwayat,
listRiwayatSaya,
}: {
riwayatId: string;
listRiwayat?: MODEL_VOTING[];
listRiwayatSaya?: MODEL_VOTING[];
}) {
const router = useRouter(); const router = useRouter();
const [changeStatus, setChangeStatus] = useState(riwayatId); const params = useParams<{ id: string }>();
const listTabs = [ const listTabs = [
{ {
@@ -39,20 +27,15 @@ export default function Vote_Riwayat({
}, },
]; ];
async function onChangeStatus({ statusId }: { statusId: string }) {
router.push(RouterVote.riwayat({ id: statusId }));
}
return ( return (
<> <>
<Tabs <Tabs
mt={1} mt={1}
variant="pills" variant="pills"
radius={"xl"} radius={"xl"}
value={changeStatus} value={params.id}
onTabChange={(val: any) => { onTabChange={(val: any) => {
setChangeStatus(val); router.replace(RouterVote.riwayat({ id: val }));
onChangeStatus({ statusId: val });
}} }}
styles={{ styles={{
tabsList: { tabsList: {
@@ -77,9 +60,9 @@ export default function Vote_Riwayat({
style={{ style={{
transition: "0.5s", transition: "0.5s",
backgroundColor: backgroundColor:
changeStatus === e.id ? MainColor.yellow : "white", params.id === e.id ? MainColor.yellow : "white",
border: border:
changeStatus === e.id params.id === e.id
? `1px solid ${AccentColor.yellow}` ? `1px solid ${AccentColor.yellow}`
: `1px solid white`, : `1px solid white`,
}} }}
@@ -89,13 +72,8 @@ export default function Vote_Riwayat({
))} ))}
</Tabs.List> </Tabs.List>
{riwayatId === "1" && ( {params.id === "1" && <Vote_SemuaRiwayat />}
<Vote_SemuaRiwayat listRiwayat={listRiwayat as any} /> {params.id === "2" && <Vote_RiwayatSaya />}
)}
{riwayatId === "2" && (
<Vote_RiwayatSaya listRiwayatSaya={listRiwayatSaya as any} />
)}
</Stack> </Stack>
</Tabs> </Tabs>
</> </>

View File

@@ -1,28 +1,47 @@
"use client"; "use client";
import { RouterVote } from "@/app/lib/router_hipmi/router_vote"; import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
import { Box, Center, Loader, Stack } from "@mantine/core";
import _ from "lodash";
import { useRouter } from "next/navigation";
import ComponentVote_CardViewPublish from "../../component/card_view_publish";
import ComponentVote_IsEmptyData from "../../component/is_empty_data";
import { MODEL_VOTING } from "../../model/interface";
import { useState } from "react";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { clientLogger } from "@/util/clientLogger";
import { Box, Center, Loader } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader"; import { ScrollOnly } from "next-scroll-loader";
import { Vote_getAllListRiwayatSaya } from "../../fun/get/get_all_list_riwayat_saya"; import { useState } from "react";
import { apiGetAllVoting } from "../../_lib/api_voting";
import { Voting_ComponentSkeletonViewPublish } from "../../component";
import ComponentVote_CardViewPublish from "../../component/card_view_publish";
import { MODEL_VOTING } from "../../model/interface";
export default function Vote_RiwayatSaya({ export default function Vote_RiwayatSaya() {
listRiwayatSaya, const [data, setData] = useState<MODEL_VOTING[] | null>(null);
}: {
listRiwayatSaya: MODEL_VOTING[];
}) {
const [data, setData] = useState(listRiwayatSaya);
const [activePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
useShallowEffect(() => {
onLoad();
}, []);
async function onLoad() {
try {
const respone = await apiGetAllVoting({
kategori: "riwayat",
page: "1",
status: "2",
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get data review", error);
}
}
return ( return (
<> <>
{_.isEmpty(data) ? ( {_.isNull(data) ? (
<Voting_ComponentSkeletonViewPublish />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData /> <ComponentGlobal_IsEmptyData />
) : ( ) : (
// --- Main component --- // // --- Main component --- //
@@ -35,14 +54,17 @@ export default function Vote_RiwayatSaya({
</Center> </Center>
)} )}
data={data} data={data}
setData={setData} setData={setData as any}
moreData={async () => { moreData={async () => {
const loadData = await Vote_getAllListRiwayatSaya({ const respone = await apiGetAllVoting({
page: activePage + 1, kategori: "riwayat",
page: `${activePage + 1}`,
status: "2",
}); });
setActivePage((val) => val + 1); setActivePage((val) => val + 1);
return loadData; return respone.data;
}} }}
> >
{(item) => ( {(item) => (

View File

@@ -2,25 +2,46 @@
import { RouterVote } from "@/app/lib/router_hipmi/router_vote"; import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { clientLogger } from "@/util/clientLogger";
import { Box, Center, Loader } from "@mantine/core"; import { Box, Center, Loader } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash"; import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader"; import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react"; import { useState } from "react";
import { apiGetAllVoting } from "../../_lib/api_voting";
import { Voting_ComponentSkeletonViewPublish } from "../../component";
import ComponentVote_CardViewPublish from "../../component/card_view_publish"; import ComponentVote_CardViewPublish from "../../component/card_view_publish";
import { vote_getAllListRiwayat } from "../../fun/get/get_all_list_riwayat";
import { MODEL_VOTING } from "../../model/interface"; import { MODEL_VOTING } from "../../model/interface";
export default function Vote_SemuaRiwayat({ export default function Vote_SemuaRiwayat() {
listRiwayat, const [data, setData] = useState<MODEL_VOTING[] | null>(null);
}: {
listRiwayat: MODEL_VOTING[];
}) {
const [data, setData] = useState(listRiwayat);
const [activePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
useShallowEffect(() => {
onLoad();
}, []);
async function onLoad() {
try {
const respone = await apiGetAllVoting({
kategori: "riwayat",
page: "1",
status: "1",
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get data review", error);
}
}
return ( return (
<> <>
{_.isEmpty(data) ? ( {_.isNull(data) ? (
<Voting_ComponentSkeletonViewPublish />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData /> <ComponentGlobal_IsEmptyData />
) : ( ) : (
// --- Main component --- // // --- Main component --- //
@@ -33,14 +54,17 @@ export default function Vote_SemuaRiwayat({
</Center> </Center>
)} )}
data={data} data={data}
setData={setData} setData={setData as any}
moreData={async () => { moreData={async () => {
const loadData = await vote_getAllListRiwayat({ const respone = await apiGetAllVoting({
page: activePage + 1, kategori: "riwayat",
page: `${activePage + 1}`,
status: "1",
}); });
setActivePage((val) => val + 1); setActivePage((val) => val + 1);
return loadData; return respone.data;
}} }}
> >
{(item) => ( {(item) => (

View File

@@ -1,28 +1,47 @@
"use client"; "use client";
import { RouterVote } from "@/app/lib/router_hipmi/router_vote"; import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
import { Box, Center, Loader, Stack } from "@mantine/core";
import _ from "lodash";
import ComponentVote_CardViewStatus from "../../component/card_view_status";
import ComponentVote_IsEmptyData from "../../component/is_empty_data";
import { MODEL_VOTING } from "../../model/interface";
import { useState } from "react";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { clientLogger } from "@/util/clientLogger";
import { Box, Center, Loader } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader"; import { ScrollOnly } from "next-scroll-loader";
import { vote_getAllReview } from "../../fun/get/status/get_all_review"; import { useState } from "react";
import { vote_getAllDraft } from "../../fun/get/status/get_all_draft"; import { apiGetAllVoting } from "../../_lib/api_voting";
import { Voting_ComponentSkeletonViewStatus } from "../../component";
import ComponentVote_CardViewStatus from "../../component/card_view_status";
import { MODEL_VOTING } from "../../model/interface";
export default function Vote_StatusDraft({ export default function Vote_StatusDraft() {
listDraft, const [data, setData] = useState<MODEL_VOTING[] | null>(null);
}: {
listDraft: MODEL_VOTING[];
}) {
const [data, setData] = useState(listDraft);
const [activePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
useShallowEffect(() => {
onLoad();
}, []);
async function onLoad() {
try {
const respone = await apiGetAllVoting({
kategori: "status",
page: "1",
status: "3",
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get data review", error);
}
}
return ( return (
<> <>
{_.isEmpty(data) ? ( {_.isNull(data) ? (
<Voting_ComponentSkeletonViewStatus />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData /> <ComponentGlobal_IsEmptyData />
) : ( ) : (
// --- Main component --- // // --- Main component --- //
@@ -35,20 +54,22 @@ export default function Vote_StatusDraft({
</Center> </Center>
)} )}
data={data} data={data}
setData={setData} setData={setData as any}
moreData={async () => { moreData={async () => {
const loadData = await vote_getAllDraft({ const respone = await apiGetAllVoting({
page: activePage + 1, kategori: "status",
page: `${activePage + 1}`,
status: "3",
}); });
setActivePage((val) => val + 1); setActivePage((val) => val + 1);
return loadData; return respone.data;
}} }}
> >
{(item) => ( {(item) => (
<ComponentVote_CardViewStatus <ComponentVote_CardViewStatus
data={item} data={item}
path={RouterVote.detail_draft} path={RouterVote.detail_review}
/> />
)} )}
</ScrollOnly> </ScrollOnly>

View File

@@ -5,32 +5,34 @@ import {
AccentColor, AccentColor,
MainColor, MainColor,
} from "@/app_modules/_global/color/color_pallet"; } from "@/app_modules/_global/color/color_pallet";
import { MODEL_NEW_DEFAULT_MASTER } from "@/app_modules/model_global/interface";
import { Box, Stack, Tabs } from "@mantine/core"; import { Box, Stack, Tabs } from "@mantine/core";
import { useRouter } from "next/navigation"; import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { MODEL_VOTING } from "../../model/interface";
import Vote_StatusDraft from "./draft"; import Vote_StatusDraft from "./draft";
import Vote_StatusPublish from "./publish"; import Vote_StatusPublish from "./publish";
import Vote_StatusReject from "./reject"; import Vote_StatusReject from "./reject";
import Vote_StatusReview from "./review"; import Vote_StatusReview from "./review";
export default function Vote_Status({ export default function Vote_Status() {
statusId,
dataVoting,
listStatus,
}: {
statusId: string;
dataVoting: MODEL_VOTING[];
listStatus: MODEL_NEW_DEFAULT_MASTER[];
}) {
const router = useRouter(); const router = useRouter();
const [changeStatus, setChangeStatus] = useState(statusId); const params = useParams<{ id: string }>();
const status = [
async function onChangeStatus({ statusId }: { statusId: string }) { {
router.replace(RouterVote.status({ id: statusId })); id: "1",
} name: "Publish",
},
{
id: "2",
name: "Review",
},
{
id: "3",
name: "Draft",
},
{
id: "4",
name: "Reject",
},
];
return ( return (
<> <>
@@ -38,10 +40,9 @@ export default function Vote_Status({
mt={1} mt={1}
variant="pills" variant="pills"
radius={"xl"} radius={"xl"}
value={changeStatus} value={params.id}
onTabChange={(val: any) => { onTabChange={(val: any) => {
setChangeStatus(val); router.replace(RouterVote.status({ id: val }));
onChangeStatus({ statusId: val });
}} }}
styles={{ styles={{
tabsList: { tabsList: {
@@ -57,7 +58,7 @@ export default function Vote_Status({
> >
<Stack> <Stack>
<Tabs.List grow> <Tabs.List grow>
{listStatus.map((e) => ( {status.map((e) => (
<Tabs.Tab <Tabs.Tab
w={"20%"} w={"20%"}
key={e.id} key={e.id}
@@ -67,9 +68,9 @@ export default function Vote_Status({
style={{ style={{
transition: "0.5s", transition: "0.5s",
backgroundColor: backgroundColor:
changeStatus === e.id ? MainColor.yellow : "white", params.id === e.id ? MainColor.yellow : "white",
border: border:
changeStatus === e.id params.id === e.id
? `1px solid ${AccentColor.yellow}` ? `1px solid ${AccentColor.yellow}`
: `1px solid white`, : `1px solid white`,
}} }}
@@ -80,12 +81,10 @@ export default function Vote_Status({
</Tabs.List> </Tabs.List>
<Box> <Box>
{statusId === "1" && ( {params.id === "1" && <Vote_StatusPublish />}
<Vote_StatusPublish listPublish={dataVoting} /> {params.id === "2" && <Vote_StatusReview />}
)} {params.id === "3" && <Vote_StatusDraft />}
{statusId === "2" && <Vote_StatusReview listReview={dataVoting} />} {params.id === "4" && <Vote_StatusReject />}
{statusId === "3" && <Vote_StatusDraft listDraft={dataVoting} />}
{statusId === "4" && <Vote_StatusReject listReject={dataVoting} />}
</Box> </Box>
</Stack> </Stack>
</Tabs> </Tabs>

View File

@@ -2,28 +2,51 @@
import { RouterVote } from "@/app/lib/router_hipmi/router_vote"; import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import job_getAllStatusPublish from "@/app_modules/job/fun/get/status/get_list_publish"; import { clientLogger } from "@/util/clientLogger";
import { Center, Loader } from "@mantine/core"; import { Box, Center, Loader, Stack } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash"; import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader"; import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react"; import { useState } from "react";
import { apiGetAllVoting } from "../../_lib/api_voting";
import ComponentVote_CardViewPublish from "../../component/card_view_publish"; import ComponentVote_CardViewPublish from "../../component/card_view_publish";
import { MODEL_VOTING } from "../../model/interface"; import { MODEL_VOTING } from "../../model/interface";
import { Voting_ComponentSkeletonViewPublish } from "../../component";
export default function Vote_StatusPublish({ export default function Vote_StatusPublish() {
listPublish, const [data, setData] = useState<MODEL_VOTING[] | null>(null);
}: {
listPublish: MODEL_VOTING[];
}) {
const [data, setData] = useState(listPublish);
const [activePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
useShallowEffect(() => {
onLoad();
}, []);
async function onLoad() {
try {
const respone = await apiGetAllVoting({
kategori: "status",
page: "1",
status: "1",
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get data review", error);
}
}
return ( return (
<> <>
{_.isEmpty(data) ? ( <Stack>
{_.isNull(data) ? (
<Voting_ComponentSkeletonViewPublish />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData /> <ComponentGlobal_IsEmptyData />
) : ( ) : (
// --- Main component --- // // --- Main component --- //
<Box>
<ScrollOnly <ScrollOnly
height="75vh" height="75vh"
renderLoading={() => ( renderLoading={() => (
@@ -32,15 +55,16 @@ export default function Vote_StatusPublish({
</Center> </Center>
)} )}
data={data} data={data}
setData={setData} setData={setData as any}
moreData={async () => { moreData={async () => {
const loadData = await job_getAllStatusPublish({ const respone = await apiGetAllVoting({
page: activePage + 1, kategori: "status",
page: `${activePage + 1}`,
status: "1",
}); });
setActivePage((val) => val + 1); setActivePage((val) => val + 1);
return loadData; return respone.data;
}} }}
> >
{(item) => ( {(item) => (
@@ -51,7 +75,9 @@ export default function Vote_StatusPublish({
/> />
)} )}
</ScrollOnly> </ScrollOnly>
</Box>
)} )}
</Stack>
</> </>
); );
} }

View File

@@ -2,25 +2,46 @@
import { RouterVote } from "@/app/lib/router_hipmi/router_vote"; import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { clientLogger } from "@/util/clientLogger";
import { Box, Center, Loader } from "@mantine/core"; import { Box, Center, Loader } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash"; import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader"; import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react"; import { useState } from "react";
import { apiGetAllVoting } from "../../_lib/api_voting";
import { Voting_ComponentSkeletonViewStatus } from "../../component";
import ComponentVote_CardViewStatus from "../../component/card_view_status"; import ComponentVote_CardViewStatus from "../../component/card_view_status";
import { vote_getAllReject } from "../../fun/get/status/get_all_reject";
import { MODEL_VOTING } from "../../model/interface"; import { MODEL_VOTING } from "../../model/interface";
export default function Vote_StatusReject({ export default function Vote_StatusReject() {
listReject, const [data, setData] = useState<MODEL_VOTING[] | null>(null);
}: {
listReject: MODEL_VOTING[];
}) {
const [data, setData] = useState(listReject);
const [activePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
useShallowEffect(() => {
onLoad();
}, []);
async function onLoad() {
try {
const respone = await apiGetAllVoting({
kategori: "status",
page: "1",
status: "4",
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get data review", error);
}
}
return ( return (
<> <>
{_.isEmpty(data) ? ( {_.isNull(data) ? (
<Voting_ComponentSkeletonViewStatus />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData /> <ComponentGlobal_IsEmptyData />
) : ( ) : (
// --- Main component --- // // --- Main component --- //
@@ -33,20 +54,22 @@ export default function Vote_StatusReject({
</Center> </Center>
)} )}
data={data} data={data}
setData={setData} setData={setData as any}
moreData={async () => { moreData={async () => {
const loadData = await vote_getAllReject({ const respone = await apiGetAllVoting({
page: activePage + 1, kategori: "status",
page: `${activePage + 1}`,
status: "4",
}); });
setActivePage((val) => val + 1); setActivePage((val) => val + 1);
return loadData; return respone.data;
}} }}
> >
{(item) => ( {(item) => (
<ComponentVote_CardViewStatus <ComponentVote_CardViewStatus
data={item} data={item}
path={RouterVote.detail_reject} path={RouterVote.detail_review}
/> />
)} )}
</ScrollOnly> </ScrollOnly>

View File

@@ -2,25 +2,46 @@
import { RouterVote } from "@/app/lib/router_hipmi/router_vote"; import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data"; import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { clientLogger } from "@/util/clientLogger";
import { Box, Center, Loader } from "@mantine/core"; import { Box, Center, Loader } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash"; import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader"; import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react"; import { useState } from "react";
import { apiGetAllVoting } from "../../_lib/api_voting";
import ComponentVote_CardViewStatus from "../../component/card_view_status"; import ComponentVote_CardViewStatus from "../../component/card_view_status";
import { vote_getAllReview } from "../../fun/get/status/get_all_review";
import { MODEL_VOTING } from "../../model/interface"; import { MODEL_VOTING } from "../../model/interface";
import { Voting_ComponentSkeletonViewStatus } from "../../component";
export default function Vote_StatusReview({ export default function Vote_StatusReview() {
listReview, const [data, setData] = useState<MODEL_VOTING[] | null>(null);
}: {
listReview: MODEL_VOTING[];
}) {
const [data, setData] = useState(listReview);
const [activePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
useShallowEffect(() => {
onLoad();
}, []);
async function onLoad() {
try {
const respone = await apiGetAllVoting({
kategori: "status",
page: "1",
status: "2",
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get data review", error);
}
}
return ( return (
<> <>
{_.isEmpty(data) ? ( {_.isNull(data) ? (
<Voting_ComponentSkeletonViewStatus />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData /> <ComponentGlobal_IsEmptyData />
) : ( ) : (
// --- Main component --- // // --- Main component --- //
@@ -33,14 +54,16 @@ export default function Vote_StatusReview({
</Center> </Center>
)} )}
data={data} data={data}
setData={setData} setData={setData as any}
moreData={async () => { moreData={async () => {
const loadData = await vote_getAllReview({ const respone = await apiGetAllVoting({
page: activePage + 1, kategori: "status",
page: `${activePage + 1}`,
status: "2",
}); });
setActivePage((val) => val + 1); setActivePage((val) => val + 1);
return loadData; return respone.data;
}} }}
> >
{(item) => ( {(item) => (

View File

@@ -19,6 +19,7 @@ const middlewareConfig: MiddlewareConfig = {
userPath: "/dev/home", userPath: "/dev/home",
publicRoutes: [ publicRoutes: [
"/", "/",
"/api/voting/*",
"/api/collaboration/*", "/api/collaboration/*",
"/api/notifikasi/*", "/api/notifikasi/*",
"/api/logs/*", "/api/logs/*",