Fix voting

Deksripsi:
- Fix user server to API di tampilan utama voting
This commit is contained in:
2024-12-27 11:04:55 +08:00
parent 5f8a1c38d0
commit 924e994236
34 changed files with 1039 additions and 468 deletions

View File

@@ -1,56 +1,36 @@
"use server";
import { prisma } from "@/app/lib";
import { ServerEnv } from "@/app/lib/server_env";
import { unsealData } from "iron-session";
import { jwtVerify } from "jose";
import { cookies } from "next/headers";
import { decrypt } from "../../../../app/auth/_lib/decrypt";
export async function funGetUserIdByToken() {
const SESSION_KEY = process.env.NEXT_PUBLIC_BASE_SESSION_KEY!;
// console.log("SESSION_KEY", SESSION_KEY);
const c = cookies().get("hipmi-key");
const c = cookies().get(SESSION_KEY);
const cekUser = await decrypt({
token: c?.value as string,
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;
}
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;
}
}
// 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

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

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

View File

@@ -1,12 +1,17 @@
"use client";
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 { 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 { MODEL_VOTING } from "../model/interface";
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({
path,
@@ -17,13 +22,13 @@ export default function ComponentVote_CardViewStatus({
}) {
const router = useRouter();
const [visible, setVisible] = useState(false);
return (
<>
<ComponentGlobal_CardStyles
onClickHandler={() => {
if (data?.id === undefined) {
ComponentGlobal_NotifikasiPeringatan("Path tidak ditemukan");
ComponentGlobal_NotifikasiPeringatan("Halaman tidak ditemukan");
} else {
setVisible(true);
router.push((path as string) + data?.id);
@@ -42,23 +47,14 @@ export default function ComponentVote_CardViewStatus({
backgroundColor: AccentColor.blue,
border: `1px solid ${AccentColor.skyblue}`,
color: "white",
width: "80%",
width: "70%",
},
}}
>
<Group>
<Text>
{data?.awalVote.toLocaleDateString(["id-ID"], {
dateStyle: "medium",
})}
</Text>
<Text>-</Text>
<Text>
{data?.akhirVote.toLocaleDateString(["id-ID"], {
dateStyle: "medium",
})}
</Text>
</Group>
<Text>
{data ? moment(data.awalVote).format("ll") : "tgl awal voting"} -{" "}
{data ? moment(data.akhirVote).format("ll") : "tgl akhir voting"}
</Text>
</Badge>
</Stack>
{visible && <ComponentGlobal_CardLoadingOverlay />}

View File

@@ -1,3 +1,9 @@
import { Voting_ComponentLayoutHeaderDetailPublish } from "./detail/comp_layout_header_detail_publish";
import {
Voting_ComponentSkeletonViewPublish,
Voting_ComponentSkeletonViewStatus,
} from "./skeleton_view";
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,
LayoutVote_DetailRiwayatSaya,
};

View File

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

View File

@@ -1,64 +1,80 @@
"use client";
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 { 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 { vote_getAllListPublish } from "../fun/get/get_all_list_publish";
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({
dataKontribusi,
}: {
dataKontribusi: MODEL_VOTE_KONTRIBUTOR[];
}) {
const [data, setData] = useState(dataKontribusi);
export default function Vote_Kontribusi() {
const [data, setData] = useState<MODEL_VOTE_KONTRIBUTOR[] | null>(null);
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 (
<>
{_.isEmpty(dataKontribusi) ? (
<ComponentGlobal_IsEmptyData />
) : (
<Box >
<ScrollOnly
height="82vh"
renderLoading={() => (
<Center mt={"lg"}>
<Loader color={"yellow"} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await vote_getAllListKontribusiByAuthorId({
page: activePage + 1,
});
<Stack>
{_.isNull(data) ? (
<Voting_ComponentSkeletonViewKontribusi />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
<Box>
<ScrollOnly
height="82vh"
renderLoading={() => (
<Center mt={"lg"}>
<Loader color={"yellow"} />
</Center>
)}
data={data}
setData={setData as any}
moreData={async () => {
const loadData = await apiGetAllVoting({
kategori: "kontribusi",
page: `${activePage + 1}`,
});
setActivePage((val) => val + 1);
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentVote_CardViewPublish
path={RouterVote.detail_kontribusi}
pilihanSaya={true}
data={item.Voting}
authorName={true}
namaPilihan={item.Voting_DaftarNamaVote.value}
/>
)}
</ScrollOnly>
</Box>
)}
{/* <pre>{JSON.stringify(dataKontribusi, null, 2)}</pre> */}
return loadData.data;
}}
>
{(item) => (
<ComponentVote_CardViewPublish
path={RouterVote.detail_kontribusi}
pilihanSaya={true}
data={item.Voting}
authorName={true}
namaPilihan={item.Voting_DaftarNamaVote.value}
/>
)}
</ScrollOnly>
</Box>
)}
</Stack>
</>
);
}

View File

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

View File

@@ -1,28 +1,47 @@
"use client";
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 { 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 { 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({
listRiwayatSaya,
}: {
listRiwayatSaya: MODEL_VOTING[];
}) {
const [data, setData] = useState(listRiwayatSaya);
export default function Vote_RiwayatSaya() {
const [data, setData] = useState<MODEL_VOTING[] | null>(null);
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 (
<>
{_.isEmpty(data) ? (
{_.isNull(data) ? (
<Voting_ComponentSkeletonViewPublish />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
@@ -35,14 +54,17 @@ export default function Vote_RiwayatSaya({
</Center>
)}
data={data}
setData={setData}
setData={setData as any}
moreData={async () => {
const loadData = await Vote_getAllListRiwayatSaya({
page: activePage + 1,
const respone = await apiGetAllVoting({
kategori: "riwayat",
page: `${activePage + 1}`,
status: "2",
});
setActivePage((val) => val + 1);
return loadData;
return respone.data;
}}
>
{(item) => (

View File

@@ -2,25 +2,46 @@
import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
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 { useState } from "react";
import { apiGetAllVoting } from "../../_lib/api_voting";
import { Voting_ComponentSkeletonViewPublish } from "../../component";
import ComponentVote_CardViewPublish from "../../component/card_view_publish";
import { vote_getAllListRiwayat } from "../../fun/get/get_all_list_riwayat";
import { MODEL_VOTING } from "../../model/interface";
export default function Vote_SemuaRiwayat({
listRiwayat,
}: {
listRiwayat: MODEL_VOTING[];
}) {
const [data, setData] = useState(listRiwayat);
export default function Vote_SemuaRiwayat() {
const [data, setData] = useState<MODEL_VOTING[] | null>(null);
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 (
<>
{_.isEmpty(data) ? (
{_.isNull(data) ? (
<Voting_ComponentSkeletonViewPublish />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
@@ -33,14 +54,17 @@ export default function Vote_SemuaRiwayat({
</Center>
)}
data={data}
setData={setData}
setData={setData as any}
moreData={async () => {
const loadData = await vote_getAllListRiwayat({
page: activePage + 1,
const respone = await apiGetAllVoting({
kategori: "riwayat",
page: `${activePage + 1}`,
status: "1",
});
setActivePage((val) => val + 1);
return loadData;
return respone.data;
}}
>
{(item) => (

View File

@@ -1,28 +1,47 @@
"use client";
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 { 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 { vote_getAllReview } from "../../fun/get/status/get_all_review";
import { vote_getAllDraft } from "../../fun/get/status/get_all_draft";
import { useState } from "react";
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({
listDraft,
}: {
listDraft: MODEL_VOTING[];
}) {
const [data, setData] = useState(listDraft);
export default function Vote_StatusDraft() {
const [data, setData] = useState<MODEL_VOTING[] | null>(null);
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 (
<>
{_.isEmpty(data) ? (
{_.isNull(data) ? (
<Voting_ComponentSkeletonViewStatus />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
@@ -35,20 +54,22 @@ export default function Vote_StatusDraft({
</Center>
)}
data={data}
setData={setData}
setData={setData as any}
moreData={async () => {
const loadData = await vote_getAllDraft({
page: activePage + 1,
const respone = await apiGetAllVoting({
kategori: "status",
page: `${activePage + 1}`,
status: "3",
});
setActivePage((val) => val + 1);
return loadData;
return respone.data;
}}
>
{(item) => (
<ComponentVote_CardViewStatus
data={item}
path={RouterVote.detail_draft}
path={RouterVote.detail_review}
/>
)}
</ScrollOnly>

View File

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

View File

@@ -2,56 +2,82 @@
import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
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 { Center, Loader } from "@mantine/core";
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 { useState } from "react";
import { apiGetAllVoting } from "../../_lib/api_voting";
import ComponentVote_CardViewPublish from "../../component/card_view_publish";
import { MODEL_VOTING } from "../../model/interface";
import { Voting_ComponentSkeletonViewPublish } from "../../component";
export default function Vote_StatusPublish({
listPublish,
}: {
listPublish: MODEL_VOTING[];
}) {
const [data, setData] = useState(listPublish);
export default function Vote_StatusPublish() {
const [data, setData] = useState<MODEL_VOTING[] | null>(null);
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 (
<>
{_.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
<ScrollOnly
height="75vh"
renderLoading={() => (
<Center mt={"lg"}>
<Loader color={"yellow"} />
</Center>
)}
data={data}
setData={setData}
moreData={async () => {
const loadData = await job_getAllStatusPublish({
page: activePage + 1,
});
<Stack>
{_.isNull(data) ? (
<Voting_ComponentSkeletonViewPublish />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
<Box>
<ScrollOnly
height="75vh"
renderLoading={() => (
<Center mt={"lg"}>
<Loader color={"yellow"} />
</Center>
)}
data={data}
setData={setData as any}
moreData={async () => {
const respone = await apiGetAllVoting({
kategori: "status",
page: `${activePage + 1}`,
status: "1",
});
setActivePage((val) => val + 1);
setActivePage((val) => val + 1);
return loadData;
}}
>
{(item) => (
<ComponentVote_CardViewPublish
data={item}
path={RouterVote.detail_publish}
statusArsip
/>
)}
</ScrollOnly>
)}
return respone.data;
}}
>
{(item) => (
<ComponentVote_CardViewPublish
data={item}
path={RouterVote.detail_publish}
statusArsip
/>
)}
</ScrollOnly>
</Box>
)}
</Stack>
</>
);
}

View File

@@ -2,25 +2,46 @@
import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
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 { useState } from "react";
import { apiGetAllVoting } from "../../_lib/api_voting";
import { Voting_ComponentSkeletonViewStatus } from "../../component";
import ComponentVote_CardViewStatus from "../../component/card_view_status";
import { vote_getAllReject } from "../../fun/get/status/get_all_reject";
import { MODEL_VOTING } from "../../model/interface";
export default function Vote_StatusReject({
listReject,
}: {
listReject: MODEL_VOTING[];
}) {
const [data, setData] = useState(listReject);
export default function Vote_StatusReject() {
const [data, setData] = useState<MODEL_VOTING[] | null>(null);
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 (
<>
{_.isEmpty(data) ? (
{_.isNull(data) ? (
<Voting_ComponentSkeletonViewStatus />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
@@ -33,20 +54,22 @@ export default function Vote_StatusReject({
</Center>
)}
data={data}
setData={setData}
setData={setData as any}
moreData={async () => {
const loadData = await vote_getAllReject({
page: activePage + 1,
const respone = await apiGetAllVoting({
kategori: "status",
page: `${activePage + 1}`,
status: "4",
});
setActivePage((val) => val + 1);
return loadData;
return respone.data;
}}
>
{(item) => (
<ComponentVote_CardViewStatus
data={item}
path={RouterVote.detail_reject}
path={RouterVote.detail_review}
/>
)}
</ScrollOnly>

View File

@@ -2,29 +2,50 @@
import { RouterVote } from "@/app/lib/router_hipmi/router_vote";
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 { useState } from "react";
import { apiGetAllVoting } from "../../_lib/api_voting";
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 { Voting_ComponentSkeletonViewStatus } from "../../component";
export default function Vote_StatusReview({
listReview,
}: {
listReview: MODEL_VOTING[];
}) {
const [data, setData] = useState(listReview);
export default function Vote_StatusReview() {
const [data, setData] = useState<MODEL_VOTING[] | null>(null);
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 (
<>
{_.isEmpty(data) ? (
{_.isNull(data) ? (
<Voting_ComponentSkeletonViewStatus />
) : _.isEmpty(data) ? (
<ComponentGlobal_IsEmptyData />
) : (
// --- Main component --- //
<Box >
<Box>
<ScrollOnly
height="75vh"
renderLoading={() => (
@@ -33,14 +54,16 @@ export default function Vote_StatusReview({
</Center>
)}
data={data}
setData={setData}
setData={setData as any}
moreData={async () => {
const loadData = await vote_getAllReview({
page: activePage + 1,
const respone = await apiGetAllVoting({
kategori: "status",
page: `${activePage + 1}`,
status: "2",
});
setActivePage((val) => val + 1);
return loadData;
return respone.data;
}}
>
{(item) => (