Notifikasi
# feat: - Notifikasi di bagian admin ## No issue
This commit is contained in:
@@ -5,6 +5,14 @@ import { atomWithStorage } from "jotai/utils";
|
||||
* @type number
|
||||
* @
|
||||
*/
|
||||
export const gs_admin_hotMenu = atomWithStorage("gs_admin_hotMenu", 1)
|
||||
export const gs_admin_hotMenu = atomWithStorage("gs_admin_hotMenu", 1);
|
||||
|
||||
export const gs_admin_subMenu = atomWithStorage<number | null>("gs_admin_subMenu",null)
|
||||
export const gs_admin_subMenu = atomWithStorage<number | null>(
|
||||
"gs_admin_subMenu",
|
||||
null
|
||||
);
|
||||
|
||||
export const gs_layout_admin_isNavbarOpen = atomWithStorage(
|
||||
"gs_layout_admin_isNavbarOpen",
|
||||
false
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import AdminJob_Main from "./main";
|
||||
import AdminJob_TablePublish from "./child/table_publish";
|
||||
import AdminJob_TableReview from "./child/table_review";
|
||||
import AdminJob_TableReject from "./child/table_reject";
|
||||
import AdminJob_TablePublish from "./child/publish";
|
||||
import AdminJob_TableReview from "./child/review";
|
||||
import AdminJob_TableReject from "./child/reject";
|
||||
|
||||
export { AdminJob_Main, AdminJob_TablePublish, AdminJob_TableReview, AdminJob_TableReject };
|
||||
|
||||
@@ -3,69 +3,90 @@
|
||||
import {
|
||||
ActionIcon,
|
||||
AppShell,
|
||||
Badge,
|
||||
Box,
|
||||
Burger,
|
||||
Button,
|
||||
Card,
|
||||
Center,
|
||||
Divider,
|
||||
Drawer,
|
||||
Group,
|
||||
Header,
|
||||
Indicator,
|
||||
MediaQuery,
|
||||
NavLink,
|
||||
Navbar,
|
||||
Paper,
|
||||
ScrollArea,
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
useMantineTheme
|
||||
useMantineTheme,
|
||||
} from "@mantine/core";
|
||||
import {
|
||||
IconBell,
|
||||
IconCheck,
|
||||
IconChecks,
|
||||
IconCircleDot,
|
||||
IconCircleDotFilled,
|
||||
IconDashboard
|
||||
IconDashboard,
|
||||
IconUserSquareRounded,
|
||||
} from "@tabler/icons-react";
|
||||
import { useAtom } from "jotai";
|
||||
import _ from "lodash";
|
||||
import { useRouter } from "next/navigation";
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { auth_Logout } from "../auth/fun/fun_logout";
|
||||
import { gs_kodeId } from "../auth/state/state";
|
||||
import { ComponentGlobal_NotifikasiBerhasil } from "../component_global/notif_global/notifikasi_berhasil";
|
||||
import { ComponentGlobal_NotifikasiPeringatan } from "../component_global/notif_global/notifikasi_peringatan";
|
||||
import Admin_Logout from "./component_global/logout";
|
||||
import { gs_admin_hotMenu, gs_admin_subMenu } from "./global_state";
|
||||
import {
|
||||
gs_admin_hotMenu,
|
||||
gs_admin_subMenu,
|
||||
gs_layout_admin_isNavbarOpen,
|
||||
} from "./global_state";
|
||||
import { listAdminPage } from "./list_page";
|
||||
import { MODEL_NOTIFIKASI } from "../notifikasi/model/interface";
|
||||
import { MODEL_USER } from "../home/model/interface";
|
||||
import { useHover, useShallowEffect, useToggle } from "@mantine/hooks";
|
||||
import moment from "moment";
|
||||
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import { RouterAdminJob } from "@/app/lib/router_admin/router_admin_job";
|
||||
import adminNotifikasi_funUpdateIsReadById from "./notifikasi/fun/update/fun_update_is_read_by_id";
|
||||
import adminNotifikasi_getByUserId from "./notifikasi/fun/get/get_notifikasi_by_user_id";
|
||||
import adminNotifikasi_countNotifikasi from "./notifikasi/fun/count/count_is_read";
|
||||
import mqtt_client from "@/util/mqtt_client";
|
||||
|
||||
export default function AdminLayout({
|
||||
userRole,
|
||||
children,
|
||||
listNotif,
|
||||
dataUser,
|
||||
countNotifikasi,
|
||||
}: {
|
||||
userRole: string;
|
||||
children: React.ReactNode;
|
||||
listNotif: MODEL_NOTIFIKASI[];
|
||||
dataUser: MODEL_USER;
|
||||
countNotifikasi: number;
|
||||
}) {
|
||||
const theme = useMantineTheme();
|
||||
const [opened, setOpened] = useState(false);
|
||||
const router = useRouter();
|
||||
const [active, setActive] = useAtom(gs_admin_hotMenu);
|
||||
const [activeId, setActiveId] = useAtom(gs_admin_hotMenu);
|
||||
const [activeChild, setActiveChild] = useAtom(gs_admin_subMenu);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [kodeId, setKodeId] = useAtom(gs_kodeId);
|
||||
|
||||
async function onClickLogout() {
|
||||
// await auth_Logout(kodeId).then((res) => {
|
||||
// ComponentGlobal_NotifikasiBerhasil("Berhasil Logout");
|
||||
// });
|
||||
await auth_Logout(kodeId).then((res) => {
|
||||
if (res.status === 200) {
|
||||
ComponentGlobal_NotifikasiBerhasil(res.message);
|
||||
setKodeId("");
|
||||
} else {
|
||||
ComponentGlobal_NotifikasiPeringatan(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
const [user, setUser] = useState(dataUser);
|
||||
const userRoleId = user.masterUserRoleId;
|
||||
|
||||
const navbarItems = listAdminPage.map((e, i) => (
|
||||
const [isNotif, setIsNotif] = useState(false);
|
||||
const [dataNotif, setDataNotif] = useState(listNotif);
|
||||
|
||||
const [countNotif, setCountNotif] = useState(countNotifikasi);
|
||||
const [isNavbarOpen, setIsNavbarOpen] = useAtom(gs_layout_admin_isNavbarOpen);
|
||||
|
||||
const developerNavbar = listAdminPage.map((e, i) => (
|
||||
<Box key={e.id}>
|
||||
<NavLink
|
||||
sx={{
|
||||
@@ -73,7 +94,7 @@ export default function AdminLayout({
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
}}
|
||||
fw={active === e.id ? "bold" : "normal"}
|
||||
fw={activeId === e.id ? "bold" : "normal"}
|
||||
icon={
|
||||
// active === e.id ? loading ? <Loader size={10} /> : e.icon : e.icon
|
||||
e.icon
|
||||
@@ -81,7 +102,7 @@ export default function AdminLayout({
|
||||
label={<Text size={"sm"}>{e.name}</Text>}
|
||||
onClick={() => {
|
||||
setLoading(true);
|
||||
setActive(e.id);
|
||||
setActiveId(e.id);
|
||||
setActiveChild(null);
|
||||
e.path === "" ? router.push(e.child[0].path) : router.push(e.path);
|
||||
e.path === "" ? setActiveChild(e.child[0].id) : "";
|
||||
@@ -109,7 +130,7 @@ export default function AdminLayout({
|
||||
)
|
||||
}
|
||||
onClick={() => {
|
||||
setActive(e.id);
|
||||
setActiveId(e.id);
|
||||
setActiveChild(v.id);
|
||||
router.push(v.path);
|
||||
}}
|
||||
@@ -123,26 +144,26 @@ export default function AdminLayout({
|
||||
));
|
||||
|
||||
const bukanDeveloper = listAdminPage.slice(0, -1);
|
||||
const notAdminDev = bukanDeveloper.map((e) => (
|
||||
const adminNavbar = bukanDeveloper.map((e) => (
|
||||
<Box key={e.id}>
|
||||
<NavLink
|
||||
opened={e?.id === activeId && isNavbarOpen ? true : false}
|
||||
sx={{
|
||||
":hover": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
}}
|
||||
fw={active === e.id ? "bold" : "normal"}
|
||||
icon={
|
||||
// active === e.id ? loading ? <Loader size={10} /> : e.icon : e.icon
|
||||
e.icon
|
||||
}
|
||||
fw={activeId === e.id ? "bold" : "normal"}
|
||||
icon={e.icon}
|
||||
label={<Text size={"sm"}>{e.name}</Text>}
|
||||
onClick={() => {
|
||||
setLoading(true);
|
||||
setActive(e.id);
|
||||
setActiveId(e.id);
|
||||
setActiveChild(null);
|
||||
e.path === "" ? router.push(e.child[0].path) : router.push(e.path);
|
||||
e.path === "" ? setActiveChild(e.child[0].id) : "";
|
||||
|
||||
setIsNavbarOpen(true);
|
||||
}}
|
||||
>
|
||||
{_.isEmpty(e.child) ? (
|
||||
@@ -167,7 +188,7 @@ export default function AdminLayout({
|
||||
)
|
||||
}
|
||||
onClick={() => {
|
||||
setActive(e.id);
|
||||
setActiveId(e.id);
|
||||
setActiveChild(v.id);
|
||||
router.push(v.path);
|
||||
}}
|
||||
@@ -180,20 +201,20 @@ export default function AdminLayout({
|
||||
</Box>
|
||||
));
|
||||
|
||||
const navbarAdmin = (
|
||||
<Box>
|
||||
<NavLink
|
||||
c="orange"
|
||||
icon={<IconDashboard />}
|
||||
label="Developer"
|
||||
sx={{
|
||||
":hover": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
async function onLoadNotifikasi() {
|
||||
const loadNotif = await adminNotifikasi_getByUserId();
|
||||
setDataNotif(loadNotif as any);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
mqtt_client.subscribe("ADMIN");
|
||||
|
||||
mqtt_client.on("message", (topic: any, message: any) => {
|
||||
const data = JSON.parse(message.toString());
|
||||
// console.log(data);
|
||||
setCountNotif(countNotif + data.count);
|
||||
});
|
||||
}, [countNotif]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -201,59 +222,34 @@ export default function AdminLayout({
|
||||
padding="md"
|
||||
navbarOffsetBreakpoint="md"
|
||||
asideOffsetBreakpoint="sm"
|
||||
navbar={
|
||||
<MediaQuery smallerThan={"md"} styles={{ display: "none" }}>
|
||||
<Navbar
|
||||
h={"95%"}
|
||||
width={{ lg: 250, md: 200, sm: 200, base: 250 }}
|
||||
hiddenBreakpoint="md"
|
||||
hidden={!opened}
|
||||
p="xs"
|
||||
bg={"gray.2"}
|
||||
>
|
||||
{/* <Navbar.Section>
|
||||
<Center h={50}>
|
||||
<Title order={4} ff={"sans-serif"}>
|
||||
Dashboard Admin
|
||||
</Title>
|
||||
</Center>
|
||||
<Divider />
|
||||
</Navbar.Section> */}
|
||||
<Navbar.Section grow component={ScrollArea}>
|
||||
<Stack>{userRole === "3" ? navbarItems : notAdminDev}</Stack>
|
||||
</Navbar.Section>
|
||||
<Navbar.Section>
|
||||
<Stack>
|
||||
<Divider />
|
||||
<Group position="apart">
|
||||
<Text fs={"italic"} c={"gray"} fz={"xs"}>
|
||||
V 1.0.0
|
||||
</Text>
|
||||
<Admin_Logout />
|
||||
</Group>
|
||||
</Stack>
|
||||
</Navbar.Section>
|
||||
</Navbar>
|
||||
</MediaQuery>
|
||||
}
|
||||
header={
|
||||
<Header height={"5vh"} bg={"gray.2"}>
|
||||
<Header height={"6vh"} bg={"gray.2"}>
|
||||
{/* Web View */}
|
||||
<MediaQuery smallerThan={"md"} styles={{ display: "none" }}>
|
||||
<Group position="apart" align="center" h={"100%"} px={"md"}>
|
||||
<Text fw={"lighter"}>Dashboard Admin</Text>
|
||||
<Title order={4}> HIPMI</Title>
|
||||
{/* <Group>
|
||||
{listAdminPage.map((e) => (
|
||||
<Text key={e.id} onClick={() => router.push(e.route)}>
|
||||
{e.name}
|
||||
</Text>
|
||||
))}
|
||||
</Group> */}
|
||||
{/* <Admin_Logout /> */}
|
||||
<ActionIcon radius={"xl"}>
|
||||
<IconBell />
|
||||
</ActionIcon>
|
||||
<Title order={3}>Dashboard Admin</Title>
|
||||
|
||||
<Group>
|
||||
<ActionIcon
|
||||
radius={"xl"}
|
||||
onClick={() => {
|
||||
setIsNotif(true);
|
||||
onLoadNotifikasi();
|
||||
}}
|
||||
>
|
||||
<Indicator
|
||||
processing
|
||||
label={<Text fz={10}>{countNotif}</Text>}
|
||||
>
|
||||
<IconBell />
|
||||
</Indicator>
|
||||
</ActionIcon>
|
||||
<Divider orientation="vertical" color="dark" />
|
||||
<Group>
|
||||
<Text>{user?.username}</Text>
|
||||
<IconUserSquareRounded />
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</MediaQuery>
|
||||
|
||||
@@ -276,10 +272,39 @@ export default function AdminLayout({
|
||||
</MediaQuery>
|
||||
</Header>
|
||||
}
|
||||
navbar={
|
||||
<MediaQuery smallerThan={"md"} styles={{ display: "none" }}>
|
||||
<Navbar
|
||||
h={"94vh"}
|
||||
width={{ lg: 250, md: 200, sm: 200, base: 250 }}
|
||||
hiddenBreakpoint="md"
|
||||
hidden={!opened}
|
||||
p="xs"
|
||||
bg={"gray.2"}
|
||||
>
|
||||
<Navbar.Section grow component={ScrollArea}>
|
||||
<Stack>
|
||||
{userRoleId === "3" ? developerNavbar : adminNavbar}
|
||||
</Stack>
|
||||
</Navbar.Section>
|
||||
<Navbar.Section>
|
||||
<Stack>
|
||||
<Divider />
|
||||
<Group position="apart">
|
||||
<Text fs={"italic"} c={"gray"} fz={"xs"}>
|
||||
V 1.0.0
|
||||
</Text>
|
||||
<Admin_Logout />
|
||||
</Group>
|
||||
</Stack>
|
||||
</Navbar.Section>
|
||||
</Navbar>
|
||||
</MediaQuery>
|
||||
}
|
||||
>
|
||||
{/* {JSON.stringify(active)} */}
|
||||
{children}
|
||||
</AppShell>
|
||||
{/* Drawer Mobile View */}
|
||||
<Drawer opened={opened} onClose={() => setOpened(false)} size={"50%"}>
|
||||
<Stack spacing={"xl"}>
|
||||
{listAdminPage.map((e) => (
|
||||
@@ -289,6 +314,183 @@ export default function AdminLayout({
|
||||
))}
|
||||
</Stack>
|
||||
</Drawer>
|
||||
|
||||
{/* Drawer Notifikasi */}
|
||||
<Drawer
|
||||
title={
|
||||
<Group position="apart">
|
||||
<Text fw={"bold"} fz={"lg"}>
|
||||
Notifikasi
|
||||
</Text>
|
||||
{/* <Button compact radius={"xl"} fz={10}>Tandai terliha</Button> */}
|
||||
</Group>
|
||||
}
|
||||
opened={isNotif}
|
||||
onClose={() => setIsNotif(false)}
|
||||
position="right"
|
||||
size={"xs"}
|
||||
>
|
||||
<DrawerNotifikasi
|
||||
data={dataNotif}
|
||||
onLoadReadNotif={(val: any) => {
|
||||
setDataNotif(val);
|
||||
}}
|
||||
onChangeNavbar={(val: any) => {
|
||||
setActiveId(val.id);
|
||||
setActiveChild(val.childId);
|
||||
}}
|
||||
onToggleNavbar={setIsNavbarOpen}
|
||||
onLoadCountNotif={(val: any) => {
|
||||
setCountNotif(val);
|
||||
}}
|
||||
/>
|
||||
</Drawer>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function DrawerNotifikasi({
|
||||
data,
|
||||
onLoadReadNotif,
|
||||
onChangeNavbar,
|
||||
onToggleNavbar,
|
||||
onLoadCountNotif,
|
||||
}: {
|
||||
data: MODEL_NOTIFIKASI[];
|
||||
onLoadReadNotif: (val: any) => void;
|
||||
onChangeNavbar: (val: any) => void;
|
||||
onToggleNavbar: (val: any) => void;
|
||||
onLoadCountNotif: (val: any) => void;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
|
||||
if (_.isEmpty(data)){
|
||||
return (
|
||||
<>
|
||||
<Center>
|
||||
<Text c={"gray"} fz={"xs"}>
|
||||
Tidak ada notifikasi
|
||||
</Text>
|
||||
</Center>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Paper h={"100%"}>
|
||||
<Stack>
|
||||
{data.map((e, i) => (
|
||||
<Card
|
||||
key={e?.id}
|
||||
// withBorder
|
||||
bg={e?.isRead ? "gray.1" : "gray.4"}
|
||||
sx={{
|
||||
borderColor: "gray",
|
||||
borderStyle: "solid",
|
||||
borderWidth: "0.5px",
|
||||
":hover": {
|
||||
borderColor: "gray",
|
||||
borderStyle: "solid",
|
||||
borderWidth: "1.5px",
|
||||
},
|
||||
}}
|
||||
onClick={async () => {
|
||||
e?.kategoriApp === "JOB" &&
|
||||
findRouterJob({
|
||||
data: e,
|
||||
router: router,
|
||||
onChangeNavbar2: (val: any) => {
|
||||
onChangeNavbar(val);
|
||||
},
|
||||
onToggleNavbar2: onToggleNavbar,
|
||||
});
|
||||
|
||||
const updateIsRead = await adminNotifikasi_funUpdateIsReadById({
|
||||
notifId: e?.id,
|
||||
});
|
||||
|
||||
if (updateIsRead) {
|
||||
const loadCountNotif =
|
||||
await adminNotifikasi_countNotifikasi();
|
||||
onLoadCountNotif(loadCountNotif);
|
||||
|
||||
const loadDataNotif = await adminNotifikasi_getByUserId();
|
||||
onLoadReadNotif(loadDataNotif);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
// callBackIsNotifikasi(false);
|
||||
}}
|
||||
>
|
||||
<Card.Section p={"sm"}>
|
||||
<Group position="apart">
|
||||
<Text fw={"bold"} fz={"xs"}>
|
||||
# {e?.kategoriApp}
|
||||
</Text>
|
||||
{e?.status ? <Badge w={70}>{e?.status}</Badge> : ""}
|
||||
</Group>
|
||||
</Card.Section>
|
||||
<Card.Section p={"sm"}>
|
||||
<Text lineClamp={2}>{e?.pesan}</Text>
|
||||
</Card.Section>
|
||||
<Card.Section p={"sm"}>
|
||||
<Group position="apart">
|
||||
<Text fz={10} color="gray">
|
||||
{new Intl.DateTimeFormat("id-ID", {
|
||||
dateStyle: "long",
|
||||
}).format(e?.createdAt)}
|
||||
|
||||
<Text span inherit fz={10} color="gray">
|
||||
{", "}
|
||||
{new Intl.DateTimeFormat("id-ID", {
|
||||
timeStyle: "short",
|
||||
}).format(e?.createdAt)}
|
||||
</Text>
|
||||
</Text>
|
||||
{e?.isRead ? (
|
||||
<Group spacing={5}>
|
||||
<IconChecks color="gray" size={10} />
|
||||
<Text fz={10} color="gray">
|
||||
Sudah dilihat
|
||||
</Text>
|
||||
</Group>
|
||||
) : (
|
||||
<Group spacing={5}>
|
||||
<IconCheck color="gray" size={10} />
|
||||
<Text fz={10} color="gray">
|
||||
Belum dilihat
|
||||
</Text>
|
||||
</Group>
|
||||
)}
|
||||
</Group>
|
||||
</Card.Section>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async function findRouterJob({
|
||||
data,
|
||||
router,
|
||||
onChangeNavbar2,
|
||||
onToggleNavbar2,
|
||||
}: {
|
||||
data: MODEL_NOTIFIKASI;
|
||||
router: AppRouterInstance;
|
||||
onChangeNavbar2: (val: any) => void;
|
||||
onToggleNavbar2: (val: any) => void;
|
||||
}) {
|
||||
const routeName = "/dev/admin/job/child/";
|
||||
router.push(routeName + _.lowerCase(data.status));
|
||||
onChangeNavbar2({
|
||||
id: 6,
|
||||
childId: 63,
|
||||
});
|
||||
onToggleNavbar2(true);
|
||||
}
|
||||
|
||||
@@ -194,17 +194,17 @@ export const listAdminPage = [
|
||||
{
|
||||
id: 62,
|
||||
name: "Table Publish",
|
||||
path: RouterAdminJob.table_publish,
|
||||
path: RouterAdminJob.publish,
|
||||
},
|
||||
{
|
||||
id: 63,
|
||||
name: "Table Review",
|
||||
path: RouterAdminJob.table_review,
|
||||
path: RouterAdminJob.review,
|
||||
},
|
||||
{
|
||||
id: 64,
|
||||
name: "Table Reject",
|
||||
path: RouterAdminJob.table_reject,
|
||||
path: RouterAdminJob.reject,
|
||||
},
|
||||
{
|
||||
id: 65,
|
||||
|
||||
17
src/app_modules/admin/notifikasi/fun/count/count_is_read.ts
Normal file
17
src/app_modules/admin/notifikasi/fun/count/count_is_read.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
|
||||
|
||||
export default async function adminNotifikasi_countNotifikasi() {
|
||||
const userId = await user_getOneUserId();
|
||||
|
||||
const data = await prisma.notifikasi.findMany({
|
||||
where: {
|
||||
adminId: userId,
|
||||
isRead: false,
|
||||
},
|
||||
});
|
||||
|
||||
return data.length;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
|
||||
|
||||
export default async function adminNotifikasi_getByUserId() {
|
||||
const adminId = await user_getOneUserId();
|
||||
|
||||
const data = await prisma.notifikasi.findMany({
|
||||
orderBy:{
|
||||
createdAt: "desc"
|
||||
},
|
||||
where: {
|
||||
adminId: adminId,
|
||||
userRoleId: "2",
|
||||
},
|
||||
});
|
||||
return data;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/app/lib/prisma";
|
||||
|
||||
export default async function adminNotifikasi_funUpdateIsReadById({
|
||||
notifId,
|
||||
}: {
|
||||
notifId: string;
|
||||
}) {
|
||||
const updt = await prisma.notifikasi.update({
|
||||
where: {
|
||||
id: notifId,
|
||||
},
|
||||
data: {
|
||||
isRead: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!updt) return { status: 400 };
|
||||
return { status: 200 };
|
||||
}
|
||||
5
src/app_modules/admin/notifikasi/index.ts
Normal file
5
src/app_modules/admin/notifikasi/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
// test notif
|
||||
|
||||
import Notifikasi_MainView from "./main";
|
||||
|
||||
export { Notifikasi_MainView };
|
||||
25
src/app_modules/admin/notifikasi/main/index.tsx
Normal file
25
src/app_modules/admin/notifikasi/main/index.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import AppComponentGlobal_LayoutTamplate from "@/app_modules/component_global/component_layout_tamplate";
|
||||
import ComponentGlobal_HeaderTamplate from "@/app_modules/component_global/header_tamplate";
|
||||
import { Text } from "@mantine/core";
|
||||
|
||||
export default function Notifikasi_MainView() {
|
||||
return (
|
||||
<>
|
||||
<AppComponentGlobal_LayoutTamplate
|
||||
header={<ComponentGlobal_HeaderTamplate title="Notifikasi" />}
|
||||
>
|
||||
<MainView />
|
||||
</AppComponentGlobal_LayoutTamplate>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function MainView() {
|
||||
return (
|
||||
<>
|
||||
<Text>notif</Text>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user