Deskripsi:
- Fix notifikasi admin to user
- Fix trigger autoload
This commit is contained in:
2024-11-12 13:49:51 +08:00
parent aa612d24bc
commit 1b58ba7d90
15 changed files with 168 additions and 117 deletions

View File

@@ -4,6 +4,8 @@ import { Admin_NewLayout } from "@/app_modules/admin";
import adminNotifikasi_countNotifikasi from "@/app_modules/admin/notifikasi/fun/count/count_is_read"; import adminNotifikasi_countNotifikasi from "@/app_modules/admin/notifikasi/fun/count/count_is_read";
import adminNotifikasi_getByUserId from "@/app_modules/admin/notifikasi/fun/get/get_notifikasi_by_user_id"; import adminNotifikasi_getByUserId from "@/app_modules/admin/notifikasi/fun/get/get_notifikasi_by_user_id";
import React from "react"; import React from "react";
import versionUpdate from "../../../../package.json";
export default async function Layout({ export default async function Layout({
children, children,
@@ -11,6 +13,7 @@ export default async function Layout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
const userLoginId = await funGetUserIdByToken(); const userLoginId = await funGetUserIdByToken();
const version = versionUpdate.version
const dataUser = await funGlobal_getUserById({ userId: userLoginId }); const dataUser = await funGlobal_getUserById({ userId: userLoginId });
const listNotifikasi = await adminNotifikasi_getByUserId(); const listNotifikasi = await adminNotifikasi_getByUserId();
@@ -30,6 +33,7 @@ export default async function Layout({
user={dataUser as any} user={dataUser as any}
countNotifikasi={countNotifikasi as any} countNotifikasi={countNotifikasi as any}
listNotifikasi={listNotifikasi as []} listNotifikasi={listNotifikasi as []}
version={version}
> >
{children} {children}
</Admin_NewLayout> </Admin_NewLayout>

View File

@@ -5,6 +5,7 @@ import { TokenProvider } from "./lib/token";
import dotenv from "dotenv"; import dotenv from "dotenv";
import { ServerEnv } from "./lib/server_env"; import { ServerEnv } from "./lib/server_env";
import { RealtimeProvider } from "./lib"; import { RealtimeProvider } from "./lib";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
dotenv.config({ dotenv.config({
path: ".env", path: ".env",
}); });
@@ -35,18 +36,20 @@ const envObject = {
}; };
ServerEnv.set(envObject); ServerEnv.set(envObject);
export default function RootLayout({ export default async function RootLayout({
children, children,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
}) { }) {
const userLoginId = await funGetUserIdByToken();
if (!token) return <>Require Token Storage</>; if (!token) return <>Require Token Storage</>;
return ( return (
<RootStyleRegistry> <RootStyleRegistry>
<MqttLoader /> {/* <MqttLoader />
<TokenProvider token={token} envObject={envObject} /> <TokenProvider token={token} envObject={envObject} /> */}
<RealtimeProvider /> <RealtimeProvider userLoginId={userLoginId} />
{children} {children}
</RootStyleRegistry> </RootStyleRegistry>
); );

View File

@@ -21,3 +21,7 @@ export const gs_realtimeData = atom<IRealtimeData | null>(null);
export const gs_admin_ntf = atom<number>(0); export const gs_admin_ntf = atom<number>(0);
export const gs_user_ntf = atom<number>(0); export const gs_user_ntf = atom<number>(0);
// job
export const gs_job_trigger = atom<boolean>(false)

View File

@@ -5,23 +5,29 @@ import { useAtom } from "jotai";
import { WibuRealtime } from "wibu-pkg"; import { WibuRealtime } from "wibu-pkg";
import { import {
gs_admin_ntf, gs_admin_ntf,
gs_job_trigger,
gs_realtimeData, gs_realtimeData,
gs_user_ntf, gs_user_ntf,
IRealtimeData, IRealtimeData,
} from "./global_state"; } from "./global_state";
export type TypeNotification = { export type TypeNotification = {
type: "message" | "notification" type: "message" | "notification" | "trigger";
pushNotificationTo: "ADMIN" | "USER"; pushNotificationTo: "ADMIN" | "USER";
dataMessage?: IRealtimeData; dataMessage?: IRealtimeData;
userLoginId?: string; userLoginId?: string;
}; };
const WIBU_REALTIME_TOKEN: any = process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN; const WIBU_REALTIME_TOKEN: any = process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN;
export default function RealtimeProvider() { export default function RealtimeProvider({
userLoginId,
}: {
userLoginId: string;
}) {
const [dataRealtime, setDataRealtime] = useAtom(gs_realtimeData); const [dataRealtime, setDataRealtime] = useAtom(gs_realtimeData);
const [newAdminNtf, setNewAdminNtf] = useAtom(gs_admin_ntf); const [newAdminNtf, setNewAdminNtf] = useAtom(gs_admin_ntf);
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf); const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
const [triggerJob, setTriggerJob] = useAtom(gs_job_trigger);
useShallowEffect(() => { useShallowEffect(() => {
WibuRealtime.init({ WibuRealtime.init({
@@ -30,14 +36,21 @@ export default function RealtimeProvider() {
setNewAdminNtf((e) => e + 1); setNewAdminNtf((e) => e + 1);
} }
if (data.type == "notification" && data.pushNotificationTo == "USER") { if (
data.type == "notification" &&
data.pushNotificationTo == "USER" &&
data.dataMessage?.userId == userLoginId
) {
setNewUserNtf((e) => e + 1); setNewUserNtf((e) => e + 1);
setDataRealtime(data.dataMessage as any); setDataRealtime(data.dataMessage as any);
} }
if (data.type == "message") { if (
// console.log(data.dataMessage); data.type == "trigger" &&
setDataRealtime(data.dataMessage as any); data.pushNotificationTo == "USER" &&
data.dataMessage?.kategoriApp == "JOB"
) {
setTriggerJob(true);
} }
}, },
project: "hipmi", project: "hipmi",

View File

@@ -355,6 +355,12 @@ async function onPublish({
pushNotificationTo: "USER", pushNotificationTo: "USER",
dataMessage: dataNotifikasi, dataMessage: dataNotifikasi,
}); });
WibuRealtime.setData({
type: "trigger",
pushNotificationTo: "USER",
dataMessage: dataNotifikasi,
});
} }
ComponentGlobal_NotifikasiBerhasil(publish.message); ComponentGlobal_NotifikasiBerhasil(publish.message);

View File

@@ -39,11 +39,13 @@ export function Admin_NewLayout({
user, user,
countNotifikasi, countNotifikasi,
listNotifikasi, listNotifikasi,
version,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
user: MODEL_USER; user: MODEL_USER;
countNotifikasi: number; countNotifikasi: number;
listNotifikasi: MODEL_NOTIFIKASI[]; listNotifikasi: MODEL_NOTIFIKASI[];
version: string
}) { }) {
const matches = useMediaQuery("(min-width: 1024px)"); const matches = useMediaQuery("(min-width: 1024px)");
const [dataUser, setDataUser] = useState(user); const [dataUser, setDataUser] = useState(user);
@@ -150,7 +152,7 @@ export function Admin_NewLayout({
<Divider /> <Divider />
<Group position="center"> <Group position="center">
<Text fs={"italic"} c={"white"} fz={"xs"}> <Text fs={"italic"} c={"white"} fz={"xs"}>
V 1.0.0 V {version}
</Text> </Text>
</Group> </Group>
</Stack> </Stack>

View File

@@ -1,6 +1,7 @@
"use server"; "use server";
import { prisma } from "@/app/lib"; import { prisma } from "@/app/lib";
import _ from "lodash";
export async function admin_funCheckStatusJob({ id }: { id: string }) { export async function admin_funCheckStatusJob({ id }: { id: string }) {
const data = await prisma.job.findUnique({ const data = await prisma.job.findUnique({
@@ -12,9 +13,11 @@ export async function admin_funCheckStatusJob({ id }: { id: string }) {
}, },
}); });
if (data?.MasterStatus?.name === "Review") { if (!data)
return true; return { status: 400, message: "Id tidak ditemukan", statusName: "" };
} else { return {
return false; status: 200,
} message: "Id ditemukan",
statusName: _.lowerCase(data.MasterStatus?.name),
};
} }

View File

@@ -10,15 +10,21 @@ export async function adminNotifikasi_findRouterJob({
}) { }) {
const check = await admin_funCheckStatusJob({ id: data.appId }); const check = await admin_funCheckStatusJob({ id: data.appId });
if (check) { if (check.status == 200) {
const udpateReadNotifikasi = await adminNotifikasi_funUpdateIsReadById({ const udpateReadNotifikasi = await adminNotifikasi_funUpdateIsReadById({
notifId: data?.id, notifId: data?.id,
}); });
if (udpateReadNotifikasi.status == 200) { if (udpateReadNotifikasi.status == 200) {
return true; return {
success: true,
statusName: check.statusName,
};
} else { } else {
return false; return {
success: false,
statusName: ""
};
} }
} else { } else {
ComponentAdminGlobal_NotifikasiPeringatan("Status telah dirubah oleh user"); ComponentAdminGlobal_NotifikasiPeringatan("Status telah dirubah oleh user");

View File

@@ -49,7 +49,7 @@ export function ComponentAdmin_UIDrawerNotifikasi({
data: data, data: data,
}); });
if (checkJob) { if (checkJob?.success) {
setVisible(true); setVisible(true);
setDataId(data.id); setDataId(data.id);
@@ -65,7 +65,9 @@ export function ComponentAdmin_UIDrawerNotifikasi({
childId: "Job_3", childId: "Job_3",
}); });
router.push("/dev/admin/job/child/review"); const path = `/dev/admin/job/child/${checkJob.statusName}`;
router.push(path);
setVisible(false); setVisible(false);
setDataId(""); setDataId("");
} }

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { gs_realtimeData, gs_user_ntf } from "@/app/lib/global_state"; import { gs_user_ntf } from "@/app/lib/global_state";
import { RouterNotifikasi } from "@/app/lib/router_hipmi/router_notifikasi"; import { RouterNotifikasi } from "@/app/lib/router_hipmi/router_notifikasi";
import { RouterUserSearch } from "@/app/lib/router_hipmi/router_user_search"; import { RouterUserSearch } from "@/app/lib/router_hipmi/router_user_search";
import { import {
@@ -66,15 +66,16 @@ export function ComponentHome_ButtonHeaderRight({
// Notifikasi // Notifikasi
const [countNtf, setCountNtf] = useState(countNotifikasi); const [countNtf, setCountNtf] = useState(countNotifikasi);
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf); const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
const [dataRealtime, setDataRealtime] = useAtom(gs_realtimeData);
useShallowEffect(() => { useShallowEffect(() => {
if (dataRealtime?.userId == dataUser.id) { // console.log(newUserNtf, "new notif");
setCountNtf((e) => e + newUserNtf), setNewUserNtf(0); // console.log(countNtf, "count ntf");
} setCountNtf(countNtf + newUserNtf);
setNewUserNtf(0);
onLoadNotifikasi({ onLoadNotifikasi({
onLoad(val) { onLoad(val) {
console.log(val, "total notif");
setCountNtf(val); setCountNtf(val);
}, },
}); });

View File

@@ -8,17 +8,20 @@ export function Job_ComponentButtonUpdateBeranda({
onSetData, onSetData,
onSetIsNewPost, onSetIsNewPost,
}: { }: {
onSetData: (val: any) => void; onSetData: (val : {data: any[]}) => void;
onSetIsNewPost: (val: any) => void; onSetIsNewPost: (val: any) => void;
}) { }) {
const [scroll, scrollTo] = useWindowScroll(); const [scroll, scrollTo] = useWindowScroll();
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
async function onLoadData() { async function onLoadData() {
setIsLoading(true)
const loadData = await job_getAllListPublish({ page: 1 }); const loadData = await job_getAllListPublish({ page: 1 });
if (loadData) { if (loadData) {
onSetData(loadData); onSetData({
data: loadData,
});
onSetIsNewPost(false); onSetIsNewPost(false);
setIsLoading(false); setIsLoading(false);
} }

View File

@@ -1,33 +1,38 @@
"use client"; "use client";
import { gs_job_trigger } from "@/app/lib/global_state";
import { RouterJob } from "@/app/lib/router_hipmi/router_job"; import { RouterJob } from "@/app/lib/router_hipmi/router_job";
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 { import { Center, Loader, Stack, TextInput } from "@mantine/core";
Affix, import { useShallowEffect } from "@mantine/hooks";
Button,
Center,
Loader,
rem,
Stack,
TextInput,
} from "@mantine/core";
import { IconSearch } from "@tabler/icons-react"; import { IconSearch } from "@tabler/icons-react";
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 ComponentJob_BerandaCardView from "../../component/beranda/card_view"; import ComponentJob_BerandaCardView from "../../component/beranda/card_view";
import { job_getAllListPublish } from "../../fun/get/get_all_publish"; import { job_getAllListPublish } from "../../fun/get/get_all_publish";
import { MODEL_JOB } from "../../model/interface"; import { MODEL_JOB } from "../../model/interface";
import { useShallowEffect } from "@mantine/hooks";
import mqtt_client from "@/util/mqtt_client";
import { Job_ComponentButtonUpdateBeranda } from "../../component";
export function Job_UiBeranda({ listData }: { listData: MODEL_JOB[] }) { export function Job_UiBeranda({ listData }: { listData: MODEL_JOB[] }) {
const [data, setData] = useState(listData); const [data, setData] = useState(listData);
const [activePage, setActivePage] = useState(1); const [activePage, setActivePage] = useState(1);
const [isSearch, setIsSearch] = useState(""); const [isSearch, setIsSearch] = useState("");
const [isNewPost, setIsNewPost] = useState(false); // const [isNewPost, setIsNewPost] = useState(false);
const [triggerJob, setTriggerJob] = useAtom(gs_job_trigger);
useShallowEffect(() => {
if (triggerJob) {
// setIsNewPost(true);
setTriggerJob(false);
onLoadNewData({
onLoad(val) {
setData(val);
},
});
}
}, [triggerJob, setData]);
async function onSearch(text: string) { async function onSearch(text: string) {
setIsSearch(text); setIsSearch(text);
@@ -39,21 +44,6 @@ export function Job_UiBeranda({ listData }: { listData: MODEL_JOB[] }) {
setActivePage(1); setActivePage(1);
} }
useShallowEffect(() => {
onLoadNewData({
onLoad(val) {
setData(val);
},
});
mqtt_client.subscribe("Job_new_post");
mqtt_client.on("message", (topic, message) => {
if (topic === "Job_new_post") {
setIsNewPost(true);
}
});
}, [setIsNewPost, setData]);
async function onLoadNewData({ onLoad }: { onLoad: (val: any) => void }) { async function onLoadNewData({ onLoad }: { onLoad: (val: any) => void }) {
const loadData = await job_getAllListPublish({ page: 1 }); const loadData = await job_getAllListPublish({ page: 1 });
onLoad(loadData); onLoad(loadData);
@@ -62,12 +52,17 @@ export function Job_UiBeranda({ listData }: { listData: MODEL_JOB[] }) {
return ( return (
<> <>
<Stack my={1} spacing={30}> <Stack my={1} spacing={30}>
{isNewPost && ( {/* {isNewPost && (
<Job_ComponentButtonUpdateBeranda <Job_ComponentButtonUpdateBeranda
onSetIsNewPost={(val) => setIsNewPost(val)} onSetIsNewPost={(val) => {
onSetData={(val) => setData(val)} setIsNewPost(val);
}}
onSetData={(val: { data: any[] }) => {
setData(val.data);
}}
/> />
)} )} */}
<ComponentGlobal_CreateButton path={RouterJob.create} /> <ComponentGlobal_CreateButton path={RouterJob.create} />
<TextInput <TextInput
@@ -102,6 +97,8 @@ export function Job_UiBeranda({ listData }: { listData: MODEL_JOB[] }) {
page: activePage + 1, page: activePage + 1,
search: isSearch, search: isSearch,
}); });
console.log(loadData, "load daat");
setActivePage((val) => val + 1); setActivePage((val) => val + 1);
return loadData; return loadData;

View File

@@ -13,9 +13,7 @@ export async function notifikasi_jobCheckStatus({
id: appId, id: appId,
}); });
console.log(check); if (check.status == 200) {
if (check) {
const updateReadNotifikasi = await notifikasi_funUpdateIsReadById({ const updateReadNotifikasi = await notifikasi_funUpdateIsReadById({
notifId: dataId, notifId: dataId,
}); });

View File

@@ -11,11 +11,14 @@ export default async function notifikasi_getByUserId({
page: number; page: number;
kategoriApp?: string; kategoriApp?: string;
}) { }) {
console.log(page, "ini page");
console.log(kategoriApp, "ini kategori");
const userLoginId = await funGetUserIdByToken(); const userLoginId = await funGetUserIdByToken();
const takeData = 10; const takeData = 10;
const skipData = page * takeData - takeData; const skipData = page * takeData - takeData;
if (kategoriApp === "Semua" ) { if (kategoriApp === "Semua") {
const data = await prisma.notifikasi.findMany({ const data = await prisma.notifikasi.findMany({
take: takeData, take: takeData,
skip: skipData, skip: skipData,

View File

@@ -15,7 +15,6 @@ import {
gs_investas_menu, gs_investas_menu,
gs_investasi_status, gs_investasi_status,
} from "@/app_modules/investasi/g_state"; } from "@/app_modules/investasi/g_state";
import { gs_job_hot_menu } from "@/app_modules/job/global_state";
import { import {
gs_vote_hotMenu, gs_vote_hotMenu,
gs_vote_status, gs_vote_status,
@@ -72,6 +71,7 @@ export function Notifikasi_UiView({
setData(loadNotifikasi as any); setData(loadNotifikasi as any);
} }
return ( return (
<> <>
<Stack spacing={"xs"}> <Stack spacing={"xs"}>
@@ -97,6 +97,7 @@ export function Notifikasi_UiView({
}} }}
onClick={() => { onClick={() => {
setActiveKategori(e.name); setActiveKategori(e.name);
// onLoadDataNotifikasi(e.name);
}} }}
> >
{e.name} {e.name}
@@ -105,64 +106,69 @@ export function Notifikasi_UiView({
</Flex> </Flex>
</Box> </Box>
{_.isEmpty(data) ? ( <Box>
<ComponentGlobal_IsEmptyData text="Tidak ada pemberitahuan" /> {_.isEmpty(data) ? (
) : ( <ComponentGlobal_IsEmptyData text="Tidak ada pemberitahuan" />
<ScrollOnly ) : (
height="85vh" <ScrollOnly
renderLoading={() => ( height="85vh"
<Center mt={"lg"}> renderLoading={() => (
<ComponentGlobal_Loader /> <Center mt={"lg"}>
</Center> <ComponentGlobal_Loader />
)} </Center>
data={data} )}
setData={setData} data={data}
moreData={async () => { setData={setData}
const loadData = await notifikasi_getByUserId({ moreData={async () => {
page: activePage + 1, const loadData = await notifikasi_getByUserId({
}); page: activePage + 1,
setActivePage((val) => val + 1); kategoriApp: activeKategori,
});
// console.log(loadData);
return loadData; setActivePage((val) => val + 1);
}}
>
{(item) => (
<ComponentNotifiaksi_CardView
data={item}
onLoadData={setData}
activePage={activePage}
activeKategori={activeKategori}
// onSetMenu={(val) => {
// if (item?.kategoriApp === "JOB") {
// setJobMenuId(val.menuId); return loadData;
// // setJobStatus(val.status); }}
// } >
{(item) => (
<ComponentNotifiaksi_CardView
data={item}
onLoadData={setData}
activePage={activePage}
activeKategori={activeKategori}
// onSetMenu={(val) => {
// if (item?.kategoriApp === "JOB") {
// // if (item?.kategoriApp === "VOTING") { // setJobMenuId(val.menuId);
// // setVoteMenu(val.menuId); // // setJobStatus(val.status);
// // setVoteStatus(val.status); // }
// // }
// // if (item?.kategoriApp === "EVENT") { // // if (item?.kategoriApp === "VOTING") {
// // setEventMenu(val.menuId); // // setVoteMenu(val.menuId);
// // setEventStatus(val.status); // // setVoteStatus(val.status);
// // } // // }
// // if (item?.kategoriApp === "DONASI") { // // if (item?.kategoriApp === "EVENT") {
// // setDonasiMenu(val.menuId); // // setEventMenu(val.menuId);
// // setDonasiStatus(val.status); // // setEventStatus(val.status);
// // } // // }
// // if (item?.kategoriApp === "INVESTASI") { // // if (item?.kategoriApp === "DONASI") {
// // setInvestasiMenu(val.menuId); // // setDonasiMenu(val.menuId);
// // setInvestasiStatus(val.status); // // setDonasiStatus(val.status);
// // } // // }
// }}
/> // // if (item?.kategoriApp === "INVESTASI") {
)} // // setInvestasiMenu(val.menuId);
</ScrollOnly> // // setInvestasiStatus(val.status);
)} // // }
// }}
/>
)}
</ScrollOnly>
)}
</Box>
</Stack> </Stack>
</> </>
); );