fix header dashboard

This commit is contained in:
2025-04-14 12:03:14 +08:00
parent 94e202db8d
commit 8e8789aa2d
14 changed files with 977 additions and 149 deletions

1
run.env.local.dev Normal file
View File

@@ -0,0 +1 @@
bun --env-file=.env.local run --bun dev -p 3005

1
run.env.start.local Normal file
View File

@@ -0,0 +1 @@
bun --env-file=.env-local run --bun start -p 3000

View File

View File

@@ -0,0 +1,106 @@
import { NextResponse } from "next/server";
import prisma from "@/lib/prisma";
export { GET, POST };
async function GET(request: Request, { params }: { params: { id: string } }) {
try {
let fixData;
const { id } = params;
const userLoginId = id;
if (!id) {
return NextResponse.json(
{ success: false, message: "ID not provided" },
{ status: 400 }
);
}
const { searchParams } = new URL(request.url);
const page = searchParams.get("page");
const takeData = 10;
const skipData = Number(page) * takeData - takeData;
if (!page) {
fixData = await prisma.notifikasi.findMany({
orderBy: [
{
isRead: "asc",
},
{
createdAt: "desc",
},
],
where: {
adminId: userLoginId,
userRoleId: "2",
},
});
} else {
fixData = await prisma.notifikasi.findMany({
take: takeData,
skip: skipData,
orderBy: [
{
isRead: "asc",
},
{
createdAt: "desc",
},
],
where: {
adminId: id,
userRoleId: "2",
},
});
}
return NextResponse.json({
success: true,
message: "Data fetched successfully",
data: fixData,
});
} catch (error) {
console.error("Error fetching notifications:", error);
return NextResponse.json(
{ success: false, message: "Failed to fetch notifications" },
{ status: 500 }
);
}
}
async function POST(request: Request, { params }: { params: { id: string } }) {
try {
const { id } = params;
const userLoginId = id;
if (!id) {
return NextResponse.json(
{ success: false, message: "ID not provided" },
{ status: 400 }
);
}
const data = await request.json();
const updatedData = await prisma.notifikasi.updateMany({
where: {
adminId: userLoginId,
},
data: {
isRead: data.isRead,
},
});
return NextResponse.json({
success: true,
message: "Notification updated successfully",
data: updatedData,
});
} catch (error) {
console.error("Error updating notification:", error);
return NextResponse.json(
{ success: false, message: "Failed to update notification" },
{ status: 500 }
);
}
}

View File

@@ -1,8 +0,0 @@
import adminNotifikasi_getByUserId from "@/app_modules/admin/notifikasi/fun/get/get_notifikasi_by_user_id";
import { NextRequest, NextResponse } from "next/server";
export async function GET(req: NextRequest) {
return NextResponse.json({ success: true });
}

View File

@@ -38,7 +38,6 @@ export default async function Layout({
<Admin_V3_MainLayout
userLoginId={userLoginId}
countNotifikasi={{} as any}
listNotifikasi={[] as []}
version={version}
>
{children}

View File

@@ -10,6 +10,7 @@ import {
Center,
Divider,
Group,
MediaQuery,
Popover,
SimpleGrid,
Stack,
@@ -18,6 +19,7 @@ import {
} from "@mantine/core";
import {
IconBell,
IconDotsVertical,
IconHierarchy2,
IconLogout,
IconReplaceUser,
@@ -27,6 +29,8 @@ import {
import { useRouter } from "next/navigation";
import { useState } from "react";
import { Admin_ComponentModal } from "../_admin_global/_component/comp_admin_modal";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
import { ComponentAdminGlobal_NotifikasiPeringatan } from "../_admin_global/admin_notifikasi/notifikasi_peringatan";
export function Admin_V3_ComponentButtonUserCircle({
dataUser,
@@ -43,20 +47,24 @@ export function Admin_V3_ComponentButtonUserCircle({
// setNavbarOpen: (open: boolean) => void;
setDrawerNotifikasi: React.Dispatch<React.SetStateAction<boolean>>;
// setDrawerNotifikasi: (open: boolean) => void;
}) {
const router = useRouter();
const [isOpenMenuUser, setOpenMenuUser] = useState(false);
// const [openPop, setOpenPop] = useState(false);
// STATE DESKTOP VIEW
const [dks_opened, setDksOpened] = useState(false);
// STATE MOBILE VIEW
const [openModalLogout, setOpenModalLogout] = useState(false);
const [openModalReplaceUser, setOpenModalReplaceUser] = useState(false);
const [loadingLogout, setLoadingLogout] = useState(false);
const [loadingReplaceUser, setLoadingReplaceUser] = useState(false);
const listMenu = [
const listMenuMobile = [
{
icon: IconUser,
label: dataUser?.username,
color: "",
onClick: () => {},
},
{
icon: IconHierarchy2,
@@ -66,15 +74,48 @@ export function Admin_V3_ComponentButtonUserCircle({
: dataUser?.masterUserRoleId == "3"
? "Super Admin"
: "",
color: "",
onClick: () => {},
},
];
const listAction = [
{
icon: IconBell,
label: "Notifikasi",
color: "",
onClick: () => setDrawerNotifikasi(true),
onClick: () => {
ComponentAdminGlobal_NotifikasiPeringatan(
"Notifikasi: Masih dalam pengembangan",
2000
);
// setDrawerNotifikasi(true);
},
},
{
icon: IconReplaceUser,
label: "Tampilan user",
color: "",
onClick: () => setOpenModalReplaceUser(true),
},
{
icon: IconLogout,
label: "Logout",
color: "red",
onClick: () => setOpenModalLogout(true),
},
];
const listMenuDekstop = [
{
icon: IconBell,
label: "Notifikasi",
color: "",
onClick: () => {
ComponentAdminGlobal_NotifikasiPeringatan(
"Notifikasi: Masih dalam pengembangan",
2000
);
// setDrawerNotifikasi(true);
},
},
{
icon: IconReplaceUser,
@@ -103,50 +144,129 @@ export function Admin_V3_ComponentButtonUserCircle({
}
}
return (
<>
<Popover opened={openPop} onChange={setOpenPop} position="left-start">
<Popover.Target>
<ActionIcon
disabled={!dataUser}
variant="transparent"
onClick={() => {
setOpenPop((o) => !o);
setNavbarOpen(false);
const PopoverButton = () => {
return (
<>
<Popover opened={openPop} onChange={setOpenPop} position="bottom-end">
<Popover.Target>
<div>
<MediaQuery largerThan={"md"} styles={{ display: "none" }}>
<ActionIcon
disabled={!dataUser}
variant="transparent"
onClick={() => {
setOpenPop((o) => !o);
setNavbarOpen(false);
}}
>
<IconUserCircle color={dataUser ? "white" : "gray"} />
</ActionIcon>
</MediaQuery>
<MediaQuery smallerThan={"md"} styles={{ display: "none" }}>
<Group spacing={"xl"}>
<Group>
<IconUser color={dataUser ? "white" : "gray"} size={25} />
<Text c="white" fz={"lg"} fw={500}>
{!dataUser?.username ? (
<CustomSkeleton height={16} width={100} radius={"xl"} />
) : (
dataUser?.username
)}
</Text>{" "}
<Divider
orientation="vertical"
color={dataUser ? "white" : "gray"}
/>
<Text c="white" fz={"lg"} fw={500}>
{!dataUser?.username ? (
<CustomSkeleton height={16} width={100} radius={"xl"} />
) : dataUser?.masterUserRoleId == "2" ? (
"Admin"
) : dataUser?.masterUserRoleId == "3" ? (
"Super Admin"
) : (
""
)}
</Text>{" "}
</Group>
<ActionIcon
disabled={!dataUser}
variant="transparent"
onClick={() => {
setOpenPop((o) => !o);
setNavbarOpen(false);
}}
>
<IconDotsVertical color={dataUser ? "white" : "gray"} />
</ActionIcon>
</Group>
</MediaQuery>
</div>
</Popover.Target>
<Popover.Dropdown
style={{
backgroundColor: AccentColor.blue,
color: AccentColor.white,
}}
>
<IconUserCircle color={dataUser ? "white" : "gray"} />
</ActionIcon>
</Popover.Target>
{/* <PopoverDropDownView /> */}
<Stack>
{/* Mobile View */}
<>
{listMenuMobile.map((e, i) => (
<MediaQuery
largerThan={"md"}
styles={{ display: "none" }}
key={i}
>
<Group onClick={e.onClick}>
<e.icon size={18} color={e.color || "white"} />
<Text c={e.color || "white"} lineClamp={1}>
{e.label}
</Text>
</Group>
</MediaQuery>
))}
</>
{/* Mobile View */}
<Popover.Dropdown
style={{
backgroundColor: AccentColor.blue,
color: AccentColor.white,
}}
>
<Stack>
{listMenu.map((e, i) => (
<Group key={i}>
<e.icon size={18} />
<Text lineClamp={1}>{e.label}</Text>
</Group>
))}
{/* Desktop View */}
<>
{listMenuDekstop.map((e, i) => (
<MediaQuery
smallerThan={"md"}
styles={{ display: "none" }}
key={i}
>
<Group
onClick={e.onClick}
style={{
cursor: "pointer",
}}
>
<e.icon size={18} color={e.color || "white"} />
<Text c={e.color || "white"} lineClamp={1}>
{e.label}
</Text>
</Group>
</MediaQuery>
))}
</>
{/* Desktop View */}
<Divider />
<Divider />
</Stack>
</Popover.Dropdown>
</Popover>
</>
);
};
<SimpleGrid cols={3}>
{listAction.map((e, i) => (
<Center key={i}>
<ActionIcon variant="transparent" onClick={e.onClick}>
<e.icon color={e.color || "white"} />
</ActionIcon>
</Center>
))}
</SimpleGrid>
</Stack>
</Popover.Dropdown>
</Popover>
return (
<>
<PopoverButton />
<Admin_ComponentModal
opened={openModalLogout}
@@ -210,7 +330,7 @@ export function Admin_V3_ComponentButtonUserCircle({
color="blue"
onClick={() => {
router.push("/dev/home", { scroll: false });
setLoadingReplaceUser(true)
setLoadingReplaceUser(true);
}}
>
Ke Tampilan User

View File

@@ -38,26 +38,24 @@ import {
} from "../_admin_global/new_global_state";
import { Admin_V3_ComponentButtonUserCircle } from "./comp_button_user_circle";
import { Admin_V3_SkeletonNavbar } from "./skeleton_navbar";
import { Admin_V3_ViewDrawerNotifikasi } from "./notifikasi/view_drawer_notifikasi";
export function Admin_V3_MainLayout({
children,
userLoginId,
countNotifikasi,
listNotifikasi,
version,
}: {
children: React.ReactNode;
userLoginId: string;
countNotifikasi: number;
listNotifikasi: MODEL_NOTIFIKASI[];
version: string;
}) {
const [dataUser, setDataUser] = useState<MODEL_USER | null>(null);
const userRoleId = dataUser?.masterUserRoleId;
const [activeId, setActiveId] = useAtom(gs_admin_navbar_menu);
const [activeChildId, setActiveChildId] = useAtom(gs_admin_navbar_subMenu);
const [dataNotifikasi, setDataNotifikasi] =
useState<MODEL_NOTIFIKASI[]>(listNotifikasi);
// Notifikasi
const [countNtf, setCountNtf] = useState(countNotifikasi);
@@ -78,26 +76,13 @@ export function Admin_V3_MainLayout({
}
} catch (error) {
console.error("Error fetching user data", error);
setDataUser(null);
}
}
const [openPop, setOpenPop] = useState(false);
const [opened, handlers] = useDisclosure(false);
const [openedDrawer, handlersDrawer] = useDisclosure(false);
const pathname = usePathname();
const navLinks = [
{ icon: IconHome, label: "Home", path: "/" },
{ icon: IconBriefcase, label: "Portfolio", path: "/portfolio" },
{ icon: IconUser, label: "About Me", path: "/about" },
{ icon: IconCoin, label: "Price List", path: "/pricing" },
{ icon: IconMessage, label: "Contact", path: "/contact" },
];
const isActive = (path: string) => {
if (path === "/" && pathname === "/") return true;
if (path !== "/" && pathname.startsWith(path)) return true;
return false;
};
return (
<>
@@ -146,41 +131,6 @@ export function Admin_V3_MainLayout({
</Group>
</Stack>
</Navbar.Section>
{/* <Box style={{ flex: "1" }}>
<Stack spacing="xs">
{navLinks.map((link) => (
<Anchor
key={link.path}
component={Link}
href={link.path}
color={isActive(link.path) ? "blue" : "dimmed"}
weight={500}
p="xs"
style={{
display: "flex",
borderRadius: theme.radius.sm,
backgroundColor: isActive(link.path)
? theme.colors.dark[6]
: "transparent",
}}
// onClick={() => {
// if (
// typeof window !== "undefined" &&
// window.innerWidth < theme.breakpoints.md
// ) {
// close();
// }
// }}
>
<Group>
<link.icon size={18} />
<Text>{link.label}</Text>
</Group>
</Anchor>
))}
</Stack>
</Box> */}
</Navbar>
}
header={
@@ -197,7 +147,7 @@ export function Admin_V3_MainLayout({
</MediaQuery>
<Text size="lg" weight={700} c={MainColor.white}>
HIMPI DASHBOARD
HIPMI DASHBOARD
</Text>
<Admin_V3_ComponentButtonUserCircle
@@ -244,7 +194,17 @@ export function Admin_V3_MainLayout({
position="right"
size={"sm"}
>
On Maintenance . . .
<Admin_V3_ViewDrawerNotifikasi
userLoginId={userLoginId}
openedDrawer={openedDrawer}
onChangeNavbar={(val: { id: string; childId: string }) => {
setActiveId(val.id as any);
setActiveChildId(val.childId);
}}
onToggleNavbar={(val: any) => {
handlersDrawer.close
}}
/>
{/* <ComponentAdmin_UIDrawerNotifikasi
newAdminNtf={newAdminNtf}
listNotifikasi={dataNotifikasi}

View File

@@ -0,0 +1,350 @@
import {
gs_adminDonasi_triggerReview,
gs_adminEvent_triggerReview,
gs_adminJob_triggerReview,
gs_adminVoting_triggerReview,
ITypeStatusNotifikasi,
} from "@/lib/global_state";
import { AccentColor } from "@/app_modules/_global/color";
import { ComponentGlobal_CardLoadingOverlay } from "@/app_modules/_global/component";
import { MODEL_NOTIFIKASI } from "@/app_modules/notifikasi/model/interface";
import { Badge, Card, Divider, Group, Stack, Text } from "@mantine/core";
import { IconCheck, IconChecks, IconSpeakerphone } from "@tabler/icons-react";
import { useAtom } from "jotai";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { clientLogger } from "@/util/clientLogger";
import moment from "moment";
import "moment/locale/id";
import {
IAdmin_ActivePage,
IAdmin_ActiveChildId,
} from "../../notifikasi/route_setting/type_of_select_page";
import { adminNotifikasi_findRouterJob } from "../../notifikasi/route_setting/job";
export default function Admin_V3_ComponentCardNotifikasi({
data,
activePage,
onChangeNavbar,
onToggleNavbar,
// onLoadCountNotif,
// onLoadDataNotifikasi,
}: {
data: MODEL_NOTIFIKASI;
activePage: number;
onChangeNavbar: (val: {
id: IAdmin_ActivePage;
childId: IAdmin_ActiveChildId;
}) => void;
onToggleNavbar: (val: any) => void;
// onLoadCountNotif: (val: any) => void;
// onLoadDataNotifikasi: (val: any) => void;
}) {
const router = useRouter();
const [visible, setVisible] = useState(false);
const [dataId, setDataId] = useState<string>("");
// Realtime
const [isAdminJob_TriggerReview, setIsAdminJob_TriggerReview] = useAtom(
gs_adminJob_triggerReview
);
const [isAdminEvent_TriggerReview, setIsAdminEvent_TriggerReview] = useAtom(
gs_adminEvent_triggerReview
);
const [isAdminVoting_TriggerReview, setIsAdminVoting_TriggerReview] = useAtom(
gs_adminVoting_triggerReview
);
const [isAdminDonasi_TriggerReview, setIsAdminDonasi_TriggerReview] = useAtom(
gs_adminDonasi_triggerReview
);
async function onRead() {
// ========================== JOB ========================== //
try {
setVisible(true);
if (data?.kategoriApp === "JOB") {
setDataId(data.id);
const checkJob = await adminNotifikasi_findRouterJob({
appId: data.appId,
notifikasiId: data.id,
router: router,
activePage: activePage,
// onLoadCountNotif(val) {
// onLoadCountNotif(val);
// },
// onLoadDataNotifikasi(val) {
// onLoadDataNotifikasi(val);
// },
onChangeNavbar(val) {
onChangeNavbar({
id: val.id,
childId: val.childId,
});
},
});
if (checkJob) {
setIsAdminJob_TriggerReview(false);
setVisible(false);
setDataId("");
onToggleNavbar(false);
}
return;
}
// ========================== JOB ========================== //
// ========================== EVENT ========================== //
// if (data.kategoriApp == "EVENT") {
// setDataId(data.id);
// const checkEvent = await adminNotifikasi_findRouterEvent({
// appId: data.appId,
// notifikasiId: data.id,
// router: router,
// activePage: activePage,
// onLoadCountNotif(val) {
// onLoadCountNotif(val);
// },
// onLoadDataNotifikasi(val) {
// onLoadDataNotifikasi(val);
// },
// onChangeNavbar(val) {
// onChangeNavbar({
// id: val.id,
// childId: val.childId,
// });
// },
// });
// if (checkEvent) {
// setIsAdminEvent_TriggerReview(false);
// setVisible(false);
// setDataId("");
// onToggleNavbar(false);
// }
// return;
// }
// ========================== EVENT ========================== //
// ========================== VOTING ========================== //
// if (data.kategoriApp == "VOTING") {
// setDataId(data.id);
// const checkVoting = await adminNotifikasi_findRouterVoting({
// router: router,
// appId: data.appId,
// notifikasiId: data.id,
// activePage: activePage,
// onLoadCountNotif(val) {
// onLoadCountNotif(val);
// },
// onLoadDataNotifikasi(val) {
// onLoadDataNotifikasi(val);
// },
// onChangeNavbar(val) {
// onChangeNavbar({
// id: val.id,
// childId: val.childId,
// });
// },
// });
// if (checkVoting) {
// setIsAdminVoting_TriggerReview(false);
// setVisible(false);
// setDataId("");
// onToggleNavbar(false);
// }
// return;
// }
// ========================== VOTING ========================== //
// ========================== DONASI ========================== //
// if (data.kategoriApp == "DONASI") {
// setDataId(data.id);
// const checkDonasi = await adminNotifikasi_findRouterDonasi({
// appId: data.appId,
// notifikasiId: data.id,
// router: router,
// status: data.status as ITypeStatusNotifikasi,
// onLoadCountNotif(val) {
// onLoadCountNotif(val);
// },
// onLoadDataNotifikasi(val) {
// onLoadDataNotifikasi(val);
// },
// onChangeNavbar(val) {
// onChangeNavbar({
// id: val.id,
// childId: val.childId,
// });
// },
// });
// if (checkDonasi) {
// setIsAdminDonasi_TriggerReview(false);
// setVisible(false);
// setDataId("");
// onToggleNavbar(false);
// }
// return;
// }
// ========================== DONASI ========================== //
// ========================== INVESTASI ========================== //
// if (data.kategoriApp == "INVESTASI") {
// setDataId(data.id);
// const checkInvestasi = await adminNotifikasi_findRouterInvestasi({
// appId: data.appId,
// notifikasiId: data.id,
// status: data.status as ITypeStatusNotifikasi,
// router: router,
// onLoadCountNotif(val) {
// onLoadCountNotif(val);
// },
// onLoadDataNotifikasi(val) {
// onLoadDataNotifikasi(val);
// },
// onChangeNavbar(val) {
// onChangeNavbar({
// id: val.id,
// childId: val.childId,
// });
// },
// });
// if (checkInvestasi) {
// setIsAdminDonasi_TriggerReview(false);
// setVisible(false);
// setDataId("");
// onToggleNavbar(false);
// }
// return;
// }
// // FORUM
// e?.kategoriApp === "FORUM" &&
// adminNotifikasi_findRouterForum({
// data: e,
// router: router,
// onChangeNavbar(val) {
// onChangeNavbar(val);
// },
// onToggleNavbar(val) {
// onToggleNavbar(val);
// },
// });
} catch (error) {
clientLogger.error("Error notifikasi function", error);
} finally {
setVisible(false);
}
}
return (
<>
<Card
style={{
transition: "0.5s",
}}
mb={"15px"}
c={"white"}
key={data.id}
bg={data.isRead ? AccentColor.blackgray : AccentColor.darkblue}
sx={{
borderColor: AccentColor.blue,
borderStyle: "solid",
borderWidth: "2px",
borderRadius: "10px",
":hover": {
// backgroundColor: AccentColor.blue,
borderColor: AccentColor.softblue,
borderStyle: "solid",
borderWidth: "2px",
},
}}
onClick={() => {
onRead();
}}
>
<Card.Section p={"sm"}>
<Stack spacing={"xs"}>
<Group position="apart">
<Group>
<IconSpeakerphone size={15} color="white" />
<Text fw={"bold"} fz={10}>
{data.kategoriApp}
</Text>
</Group>
{data.status ? (
<Badge fz={10} size="sm">
{data.status}
</Badge>
) : (
""
)}
</Group>
<Divider color="gray.3" />
</Stack>
</Card.Section>
<Card.Section px={"sm"} pb={"sm"}>
<Stack spacing={0}>
<Text lineClamp={2} fw={"bold"} fz={"xs"}>
{data.title}
</Text>
<Text lineClamp={2} fz={"xs"}>
{data.pesan}
</Text>
</Stack>
</Card.Section>
<Card.Section p={"sm"}>
<Group position="apart">
<Text fz={10} color="gray">
{moment(data.createdAt).format("LLL")}
</Text>
{/* <Text fz={10}>
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "long",
}).format(data.createdAt)}
<Text span inherit fz={10}>
{", "}
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "short",
}).format(data.createdAt)}
</Text>
</Text> */}
{data.isRead ? (
<Group spacing={5}>
<IconChecks size={10} />
<Text fz={10}>Sudah dilihat</Text>
</Group>
) : (
<Group spacing={5}>
<IconCheck size={10} />
<Text fz={10}>Belum dilihat</Text>
</Group>
)}
</Group>
{visible && dataId === data.id && (
<ComponentGlobal_CardLoadingOverlay />
)}
</Card.Section>
</Card>
</>
);
}

View File

@@ -0,0 +1,213 @@
import { MODEL_NOTIFIKASI } from "@/app_modules/notifikasi/model/interface";
import {
Box,
Button,
Center,
Group,
Loader,
Paper,
Stack,
Text,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader";
import adminNotifikasi_getByUserId from "../../notifikasi/fun/get/get_notifikasi_by_user_id";
import { useState } from "react";
import {
apiGetNotifikasiByUserId,
apiPostIsReadNotifikasi,
} from "../../notifikasi/lib/api_fetch_notifikasi";
import AdminNotifikasi_ViewCardDrawer from "../../notifikasi/view_card_drawer";
import Admin_V3_ComponentCardNotifikasi from "./comp_card_notifikasi";
import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
import {
IAdmin_ActivePage,
IAdmin_ActiveChildId,
} from "../../notifikasi/route_setting/type_of_select_page";
export function Admin_V3_ViewDrawerNotifikasi({
userLoginId,
openedDrawer,
onChangeNavbar,
onToggleNavbar,
}: {
userLoginId: string;
openedDrawer: boolean;
onChangeNavbar: (val: {
id: IAdmin_ActivePage;
childId: IAdmin_ActiveChildId;
}) => void;
onToggleNavbar: (val: any) => void;
}) {
// newAdminNtf,
// listNotifikasi,
// onChangeNavbar,
// }: {
// newAdminNtf: number;
// listNotifikasi: MODEL_NOTIFIKASI[];
// onChangeNavbar: (val: {
// id: IAdmin_ActivePage;
// childId: IAdmin_ActiveChildId;
// }) => void;
const [data, setData] = useState<MODEL_NOTIFIKASI[] | null>(null);
const [activePage, setActivePage] = useState<number>(1);
// Action Button
const [isRead, setIsRead] = useState<boolean>(false);
const [isUnRead, setIsUnRead] = useState<boolean>(false);
useShallowEffect(() => {
if (openedDrawer || isRead || isUnRead) {
handleLoadtData();
}
}, [openedDrawer, isRead, isUnRead]);
async function handleLoadtData() {
try {
const response = await apiGetNotifikasiByUserId({
id: userLoginId,
page: `${activePage}`,
});
if (response && response.success) {
setData(response.data);
setIsRead(false);
setIsUnRead(false);
} else {
console.error("Failed to fetch user data", response);
setData(null);
}
} catch (error) {
console.error("Error fetching data:", error);
setData(null);
}
}
async function handleMoreData() {
try {
const nextPage = activePage + 1;
const response = await apiGetNotifikasiByUserId({
id: userLoginId,
page: `${nextPage}`,
});
if (response && response.success) {
setActivePage(nextPage);
return response.data;
} else {
console.error("Failed to fetch user data", response);
return null;
}
} catch (error) {
console.error("Error fetching data:", error);
return null;
}
}
async function handleUpdateReadAll() {
try {
const response = await apiPostIsReadNotifikasi({
id: userLoginId,
isRead: true,
});
if (response && response.success) {
console.log("Berhasil tandai baca semua");
setIsRead(true);
} else {
console.error("Failed to update notification", response);
return null;
}
} catch (error) {
console.error("Error updating notification:", error);
return null;
}
}
async function handleUpdateUnRead() {
try {
const response = await apiPostIsReadNotifikasi({
id: userLoginId,
isRead: false,
});
if (response && response.success) {
console.log("Berhasil tandai belum baca");
setIsUnRead(true);
} else {
console.error("Failed to update notification", response);
return null;
}
} catch (error) {
console.error("Error updating notification:", error);
return null;
}
}
if (!data) {
return (
<>
<Stack pt="sm">
{Array.from({ length: 3 }, (_, i) => (
<CustomSkeleton key={i} height={150} />
))}
</Stack>
</>
);
}
return (
<>
<Stack pt={"sm"} pb={"xl"}>
<Group>
<Button
radius={"xl"}
onClick={() => {
handleUpdateReadAll();
}}
>
Tandai baca semua
</Button>
<Button
radius={"xl"}
onClick={() => {
handleUpdateUnRead();
}}
>
Tandai belum baca
</Button>
</Group>
{_.isEmpty(data) ? (
<Center>
<Text c={"gray"} fz={"xs"}>
Tidak ada notifikasi
</Text>
</Center>
) : (
<ScrollOnly
height="80vh"
renderLoading={() => (
<Center mt={"lg"}>
<Loader color={"yellow"} />
</Center>
)}
data={data}
setData={setData as any}
moreData={handleMoreData}
>
{(item) => (
<Admin_V3_ComponentCardNotifikasi
data={item}
activePage={activePage}
onChangeNavbar={(val) => onChangeNavbar(val)}
onToggleNavbar={(val) => onToggleNavbar(val)}
// onLoadCountNotif={(val) => onLoadCountNotif(val)}
// onLoadDataNotifikasi={(val) => setData(val)}
/>
)}
</ScrollOnly>
)}
</Stack>
</>
);
}

View File

@@ -3,10 +3,13 @@
import prisma from "@/lib/prisma";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
export default async function adminNotifikasi_getByUserId({page}: {page: number}) {
export default async function adminNotifikasi_getByUserId({
page,
}: {
page: number;
}) {
const userLoginId = await funGetUserIdByToken();
const takeData = 10;
const skipData = page * takeData - takeData;
@@ -26,6 +29,6 @@ export default async function adminNotifikasi_getByUserId({page}: {page: number}
userRoleId: "2",
},
});
return data;
}

View File

@@ -0,0 +1,83 @@
export { apiGetNotifikasiByUserId, apiPostIsReadNotifikasi };
const apiGetNotifikasiByUserId = async ({
page,
id,
}: {
page?: string;
id: string;
}) => {
try {
// Fetch token from cookie
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
if (!token) {
console.error("No token found");
return null;
}
const isPage = page ? `?page=${page}` : "";
const response = await fetch(`/api/admin/notifikasi/${id}${isPage}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `Bearer ${token}`,
},
});
// Check if the response is OK
if (!response.ok) {
const errorData = await response.json().catch(() => null);
console.error("Failed to get notifikasi admin", response.statusText, errorData);
throw new Error(errorData?.message || "Failed to get notifikasi admin");
}
// Return the JSON response
const data = await response.json();
return data
} catch (error) {
console.error("Error get all forum", error);
throw error; // Re-throw the error to handle it in the calling function
}
};
const apiPostIsReadNotifikasi = async ({
id,
isRead,
}: {
id: string;
isRead: boolean;
}) => {
try {
// Fetch token from cookie
const { token } = await fetch("/api/get-cookie").then((res) => res.json());
if (!token) {
console.error("No token found");
return null;
}
const response = await fetch(`/api/admin/notifikasi/${id}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ isRead }),
});
// Check if the response is OK
if (!response.ok) {
const errorData = await response.json().catch(() => null);
console.error("Failed to post notifikasi admin", response.statusText, errorData);
throw new Error(errorData?.message || "Failed to post notifikasi admin");
}
// Return the JSON response
const data = await response.json();
return data
} catch (error) {
console.error("Error get all forum", error);
throw error; // Re-throw the error to handle it in the calling function
}
};

View File

@@ -12,16 +12,16 @@ export async function adminNotifikasi_findRouterJob({
notifikasiId,
router,
activePage,
onLoadCountNotif,
onLoadDataNotifikasi,
// onLoadCountNotif,
// onLoadDataNotifikasi ,
onChangeNavbar,
}: {
appId: string;
notifikasiId: string;
router: AppRouterInstance;
activePage: number;
onLoadCountNotif: (val: any) => void;
onLoadDataNotifikasi: (val: any) => void;
// onLoadCountNotif: (val: any) => void;
// onLoadDataNotifikasi: (val: any) => void;
onChangeNavbar: (val: {
id: IAdmin_ActivePage;
childId: IAdmin_ActiveChildId;
@@ -35,13 +35,13 @@ export async function adminNotifikasi_findRouterJob({
});
if (udpateReadNotifikasi.status == 200) {
const loadCountNotif = await adminNotifikasi_countNotifikasi();
onLoadCountNotif(loadCountNotif);
// const loadCountNotif = await adminNotifikasi_countNotifikasi();
// onLoadCountNotif(loadCountNotif);
const loadListNotifikasi = await adminNotifikasi_getByUserId({
page: 1,
});
onLoadDataNotifikasi(loadListNotifikasi);
// const loadListNotifikasi = await adminNotifikasi_getByUserId({
// page: 1,
// });
// onLoadDataNotifikasi(loadListNotifikasi);
const path = `/dev/admin/job/child/${check.statusName}`;

View File

@@ -68,31 +68,31 @@ export default function AdminNotifikasi_ViewCardDrawer({
if (data?.kategoriApp === "JOB") {
setDataId(data.id);
const checkJob = await adminNotifikasi_findRouterJob({
appId: data.appId,
notifikasiId: data.id,
router: router,
activePage: activePage,
onLoadCountNotif(val) {
onLoadCountNotif(val);
},
onLoadDataNotifikasi(val) {
onLoadDataNotifikasi(val);
},
onChangeNavbar(val) {
onChangeNavbar({
id: val.id,
childId: val.childId,
});
},
});
// const checkJob = await adminNotifikasi_findRouterJob({
// appId: data.appId,
// notifikasiId: data.id,
// router: router,
// activePage: activePage,
// onLoadCountNotif(val) {
// onLoadCountNotif(val);
// },
// onLoadDataNotifikasi(val) {
// onLoadDataNotifikasi(val);
// },
// onChangeNavbar(val) {
// onChangeNavbar({
// id: val.id,
// childId: val.childId,
// });
// },
// });
if (checkJob) {
setIsAdminJob_TriggerReview(false);
setVisible(false);
setDataId("");
onToggleNavbar(false);
}
// if (checkJob) {
// setIsAdminJob_TriggerReview(false);
// setVisible(false);
// setDataId("");
// onToggleNavbar(false);
// }
return;
}