Fix notifikasi count di home
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -35,7 +35,7 @@ yarn-error.log*
|
|||||||
.vercel
|
.vercel
|
||||||
|
|
||||||
# logs
|
# logs
|
||||||
logs
|
/logs
|
||||||
|
|
||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
|||||||
138
src/app/(admin)/logs/logs.module.css
Normal file
138
src/app/(admin)/logs/logs.module.css
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/* app/admin/logs/logs.module.css */
|
||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterContainer {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logsContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logItem {
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorLog {
|
||||||
|
background-color: #fef2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warnLog {
|
||||||
|
background-color: #fefce8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoLog {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timestamp {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level {
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorLevel {
|
||||||
|
background-color: #fee2e2;
|
||||||
|
color: #991b1b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warnLevel {
|
||||||
|
background-color: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoLevel {
|
||||||
|
background-color: #dbeafe;
|
||||||
|
color: #1e40af;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata {
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 8px;
|
||||||
|
background-color: #f9fafb;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
text-align: center;
|
||||||
|
padding: 24px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: #dc2626;
|
||||||
|
text-align: center;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover effects */
|
||||||
|
.logItem:hover {
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select:hover {
|
||||||
|
border-color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Focus states */
|
||||||
|
.select:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #2563eb;
|
||||||
|
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive adjustments */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.container {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logHeader {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
106
src/app/(admin)/logs/page.tsx
Normal file
106
src/app/(admin)/logs/page.tsx
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
// app/admin/logs/page.tsx
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
import styles from "./logs.module.css";
|
||||||
|
|
||||||
|
interface LogEntry {
|
||||||
|
timestamp: string;
|
||||||
|
level: string;
|
||||||
|
message: string;
|
||||||
|
metadata?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function LogsPage() {
|
||||||
|
const [logs, setLogs] = useState<LogEntry[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [filter, setFilter] = useState<"all" | "error" | "info" | "warn">(
|
||||||
|
"all"
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchLogs();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function fetchLogs() {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/logs/view");
|
||||||
|
if (!response.ok) throw new Error("Failed to fetch logs");
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
setLogs(data.logs);
|
||||||
|
} catch (err) {
|
||||||
|
setError(err instanceof Error ? err.message : "Error fetching logs");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredLogs = logs.filter((log) =>
|
||||||
|
filter === "all" ? true : log.level === filter
|
||||||
|
);
|
||||||
|
|
||||||
|
if (loading) return <div className={styles.loading}>Loading logs...</div>;
|
||||||
|
if (error) return <div className={styles.error}>Error: {error}</div>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<h1 className={styles.title}>System Logs</h1>
|
||||||
|
|
||||||
|
<div className={styles.filterContainer}>
|
||||||
|
<select
|
||||||
|
value={filter}
|
||||||
|
onChange={(e) => setFilter(e.target.value as any)}
|
||||||
|
className={styles.select}
|
||||||
|
>
|
||||||
|
<option value="all">All Logs</option>
|
||||||
|
<option value="error">Errors</option>
|
||||||
|
<option value="warn">Warnings</option>
|
||||||
|
<option value="info">Info</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.logsContainer}>
|
||||||
|
{filteredLogs.map((log, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`${styles.logItem} ${
|
||||||
|
log.level === "error"
|
||||||
|
? styles.errorLog
|
||||||
|
: log.level === "warn"
|
||||||
|
? styles.warnLog
|
||||||
|
: styles.infoLog
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className={styles.logHeader}>
|
||||||
|
<span className={styles.timestamp}>
|
||||||
|
{format(new Date(log.timestamp), "yyyy-MM-dd HH:mm:ss")}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className={`${styles.level} ${
|
||||||
|
log.level === "error"
|
||||||
|
? styles.errorLevel
|
||||||
|
: log.level === "warn"
|
||||||
|
? styles.warnLevel
|
||||||
|
: styles.infoLevel
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{log.level.toUpperCase()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.message}>{log.message}</div>
|
||||||
|
|
||||||
|
{log.metadata && (
|
||||||
|
<pre className={styles.metadata}>
|
||||||
|
{JSON.stringify(log.metadata, null, 2)}
|
||||||
|
</pre>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
71
src/app/api/logs/view/route.ts
Normal file
71
src/app/api/logs/view/route.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// app/api/logs/view/route.ts
|
||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
import fs from "fs/promises";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
interface LogEntry {
|
||||||
|
timestamp: string;
|
||||||
|
level: string;
|
||||||
|
message: string;
|
||||||
|
metadata?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readLogFiles(directory: string): Promise<LogEntry[]> {
|
||||||
|
try {
|
||||||
|
const logPath = path.join(process.cwd(), directory);
|
||||||
|
const files = await fs.readdir(logPath);
|
||||||
|
const logFiles = files.filter((file) => file.endsWith(".log"));
|
||||||
|
|
||||||
|
const allLogs: LogEntry[] = [];
|
||||||
|
|
||||||
|
for (const file of logFiles) {
|
||||||
|
const filePath = path.join(logPath, file);
|
||||||
|
const content = await fs.readFile(filePath, "utf-8");
|
||||||
|
|
||||||
|
// Parse setiap baris log
|
||||||
|
const logs = content
|
||||||
|
.split("\n")
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((line) => {
|
||||||
|
try {
|
||||||
|
return JSON.parse(line);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
allLogs.push(...logs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort berdasarkan timestamp, terbaru di atas
|
||||||
|
return allLogs.sort(
|
||||||
|
(a, b) =>
|
||||||
|
new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error reading log files:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
// Baca logs dari frontend dan backend
|
||||||
|
const frontendLogs = await readLogFiles("logs/frontend");
|
||||||
|
const backendLogs = await readLogFiles("logs/backend");
|
||||||
|
|
||||||
|
// Gabungkan dan sort semua logs
|
||||||
|
const allLogs = [...frontendLogs, ...backendLogs].sort(
|
||||||
|
(a, b) =>
|
||||||
|
new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
return NextResponse.json({ logs: allLogs });
|
||||||
|
} catch (error) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Failed to fetch logs" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +1,9 @@
|
|||||||
import { HomeViewNew } from "@/app_modules/home";
|
import { HomeViewNew } from "@/app_modules/home";
|
||||||
import notifikasi_countUserNotifikasi from "@/app_modules/notifikasi/fun/count/fun_count_by_id";
|
|
||||||
|
|
||||||
export default async function PageHome() {
|
export default async function PageHome() {
|
||||||
// const userLoginId = await funGetUserIdByToken();
|
|
||||||
// const dataUser = await user_getOneByUserId(userLoginId as string);
|
|
||||||
// const dataJob = await job_getTwoForHomeView();
|
|
||||||
const countNotifikasi = await notifikasi_countUserNotifikasi();
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* <HomeView
|
<HomeViewNew />
|
||||||
dataUser={dataUser as any}
|
|
||||||
dataJob={dataJob as any}
|
|
||||||
countNotifikasi={countNotifikasi}
|
|
||||||
/> */}
|
|
||||||
<HomeViewNew countNotifikasi={countNotifikasi}/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,13 @@ export default async function Layout({
|
|||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
|
const userId = await newFunGetUserId();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RealtimeProvider
|
<RealtimeProvider
|
||||||
|
userId={userId}
|
||||||
WIBU_REALTIME_TOKEN={
|
WIBU_REALTIME_TOKEN={
|
||||||
ServerEnv.value?.NEXT_PUBLIC_WIBU_REALTIME_TOKEN as string
|
ServerEnv.value?.NEXT_PUBLIC_WIBU_REALTIME_TOKEN as string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ process.on("SIGINT", async () => {
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("==> Test prisma");
|
// console.log("==> Test prisma");
|
||||||
|
|
||||||
export default prisma;
|
export default prisma;
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ import {
|
|||||||
gs_votingTiggerBeranda,
|
gs_votingTiggerBeranda,
|
||||||
IRealtimeData,
|
IRealtimeData,
|
||||||
} from "./global_state";
|
} from "./global_state";
|
||||||
import { newFunGetUserId } from "./new_fun_user_id";
|
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
// const WIBU_REALTIME_TOKEN: string | undefined =
|
// const WIBU_REALTIME_TOKEN: string | undefined =
|
||||||
// process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN;
|
// process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN;
|
||||||
@@ -28,15 +26,16 @@ export type TypeNotification = {
|
|||||||
type: "message" | "notification" | "trigger";
|
type: "message" | "notification" | "trigger";
|
||||||
pushNotificationTo: "ADMIN" | "USER";
|
pushNotificationTo: "ADMIN" | "USER";
|
||||||
dataMessage?: IRealtimeData;
|
dataMessage?: IRealtimeData;
|
||||||
userLoginId?: string;
|
userId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RealtimeProvider({
|
export default function RealtimeProvider({
|
||||||
|
userId,
|
||||||
WIBU_REALTIME_TOKEN,
|
WIBU_REALTIME_TOKEN,
|
||||||
}: {
|
}: {
|
||||||
|
userId: string;
|
||||||
WIBU_REALTIME_TOKEN: string;
|
WIBU_REALTIME_TOKEN: string;
|
||||||
}) {
|
}) {
|
||||||
const [userLoginId, setUserLoginId] = useState("");
|
|
||||||
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);
|
||||||
@@ -72,15 +71,7 @@ export default function RealtimeProvider({
|
|||||||
gs_donasiTriggerBeranda
|
gs_donasiTriggerBeranda
|
||||||
);
|
);
|
||||||
|
|
||||||
async function loadUserId() {
|
|
||||||
const userId = await newFunGetUserId();
|
|
||||||
|
|
||||||
setUserLoginId(userId as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
loadUserId();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
WibuRealtime.init({
|
WibuRealtime.init({
|
||||||
project: "hipmi",
|
project: "hipmi",
|
||||||
@@ -97,7 +88,7 @@ export default function RealtimeProvider({
|
|||||||
if (
|
if (
|
||||||
data.type == "notification" &&
|
data.type == "notification" &&
|
||||||
data.pushNotificationTo == "USER" &&
|
data.pushNotificationTo == "USER" &&
|
||||||
data.dataMessage?.userId == userLoginId
|
data.dataMessage?.userId == userId
|
||||||
) {
|
) {
|
||||||
setNewUserNtf((e) => e + 1);
|
setNewUserNtf((e) => e + 1);
|
||||||
setDataRealtime(data.dataMessage as any);
|
setDataRealtime(data.dataMessage as any);
|
||||||
@@ -144,7 +135,7 @@ export default function RealtimeProvider({
|
|||||||
data.type == "notification" &&
|
data.type == "notification" &&
|
||||||
data.pushNotificationTo == "USER" &&
|
data.pushNotificationTo == "USER" &&
|
||||||
data.dataMessage?.status == "Peserta Event" &&
|
data.dataMessage?.status == "Peserta Event" &&
|
||||||
userLoginId !== data.dataMessage?.userId
|
userId !== data.dataMessage?.userId
|
||||||
) {
|
) {
|
||||||
setNewUserNtf((e) => e + 1);
|
setNewUserNtf((e) => e + 1);
|
||||||
}
|
}
|
||||||
@@ -172,7 +163,7 @@ export default function RealtimeProvider({
|
|||||||
data.type == "notification" &&
|
data.type == "notification" &&
|
||||||
data.pushNotificationTo == "USER" &&
|
data.pushNotificationTo == "USER" &&
|
||||||
data.dataMessage?.status == "Voting Masuk" &&
|
data.dataMessage?.status == "Voting Masuk" &&
|
||||||
userLoginId !== data.dataMessage?.userId
|
userId !== data.dataMessage?.userId
|
||||||
) {
|
) {
|
||||||
setNewUserNtf((e) => e + 1);
|
setNewUserNtf((e) => e + 1);
|
||||||
}
|
}
|
||||||
@@ -200,9 +191,9 @@ export default function RealtimeProvider({
|
|||||||
// data.type == "notification" &&
|
// data.type == "notification" &&
|
||||||
// data.pushNotificationTo == "ADMIN" &&
|
// data.pushNotificationTo == "ADMIN" &&
|
||||||
// data.dataMessage?.status == "Menunggu" &&
|
// data.dataMessage?.status == "Menunggu" &&
|
||||||
// userLoginId !== data.dataMessage?.userId
|
// userId !== data.dataMessage?.userId
|
||||||
// ) {
|
// ) {
|
||||||
// console.log("yes");
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// ---------------------- DONASI ------------------------- //
|
// ---------------------- DONASI ------------------------- //
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { IRealtimeData } from "@/app/lib/global_state";
|
||||||
import { RouterAdminJob } from "@/app/lib/router_admin/router_admin_job";
|
import { RouterAdminJob } from "@/app/lib/router_admin/router_admin_job";
|
||||||
import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
|
import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
|
||||||
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
|
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
|
||||||
@@ -8,7 +9,6 @@ import { ComponentAdminGlobal_TitlePage } from "@/app_modules/admin/_admin_globa
|
|||||||
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/_admin_global/header_tamplate";
|
import ComponentAdminGlobal_HeaderTamplate from "@/app_modules/admin/_admin_global/header_tamplate";
|
||||||
import adminNotifikasi_funCreateToUser from "@/app_modules/admin/notifikasi/fun/create/fun_create_notif_user";
|
import adminNotifikasi_funCreateToUser from "@/app_modules/admin/notifikasi/fun/create/fun_create_notif_user";
|
||||||
import { MODEL_JOB } from "@/app_modules/job/model/interface";
|
import { MODEL_JOB } from "@/app_modules/job/model/interface";
|
||||||
import mqtt_client from "@/util/mqtt_client";
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Center,
|
Center,
|
||||||
@@ -22,11 +22,12 @@ import {
|
|||||||
Table,
|
Table,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Textarea
|
Textarea,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { IconBan, IconPhotoCheck, IconSearch } from "@tabler/icons-react";
|
import { IconBan, IconPhotoCheck, IconSearch } from "@tabler/icons-react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { WibuRealtime } from "wibu-pkg";
|
||||||
import { AdminJob_funEditCatatanById } from "../../fun/edit/fun_edit_catatan_by_id";
|
import { AdminJob_funEditCatatanById } from "../../fun/edit/fun_edit_catatan_by_id";
|
||||||
import adminJob_getListReject from "../../fun/get/get_list_reject";
|
import adminJob_getListReject from "../../fun/get/get_list_reject";
|
||||||
|
|
||||||
@@ -311,7 +312,7 @@ async function onReject({
|
|||||||
const loadData = await adminJob_getListReject({ page: 1 });
|
const loadData = await adminJob_getListReject({ page: 1 });
|
||||||
onSetData(loadData);
|
onSetData(loadData);
|
||||||
|
|
||||||
const dataNotif = {
|
const dataNotifikasi: IRealtimeData = {
|
||||||
appId: reject.data?.id as any,
|
appId: reject.data?.id as any,
|
||||||
status: reject.data?.MasterStatus?.name as any,
|
status: reject.data?.MasterStatus?.name as any,
|
||||||
userId: reject.data?.authorId as any,
|
userId: reject.data?.authorId as any,
|
||||||
@@ -321,14 +322,15 @@ async function onReject({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const notif = await adminNotifikasi_funCreateToUser({
|
const notif = await adminNotifikasi_funCreateToUser({
|
||||||
data: dataNotif as any,
|
data: dataNotifikasi as any,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (notif.status === 201) {
|
if (notif.status === 201) {
|
||||||
mqtt_client.publish(
|
WibuRealtime.setData({
|
||||||
"USER",
|
type: "notification",
|
||||||
JSON.stringify({ userId: reject?.data?.authorId, count: 1 })
|
pushNotificationTo: "USER",
|
||||||
);
|
dataMessage: dataNotifikasi,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentGlobal_NotifikasiBerhasil(reject.message);
|
ComponentGlobal_NotifikasiBerhasil(reject.message);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import { API_RouteNotifikasi } from "@/app/lib/api_user_router/route_api_notifikasi";
|
||||||
import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state";
|
import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state";
|
||||||
|
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
||||||
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 { ActionIcon, Indicator, Text } from "@mantine/core";
|
import { ActionIcon, Indicator, Text } from "@mantine/core";
|
||||||
@@ -9,46 +11,35 @@ import { useAtom } from "jotai";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { MainColor } from "../_global/color";
|
import { MainColor } from "../_global/color";
|
||||||
import { ComponentGlobal_NotifikasiPeringatan } from "../_global/notif_global";
|
|
||||||
import UIGlobal_LayoutHeaderTamplate from "../_global/ui/ui_header_tamplate";
|
import UIGlobal_LayoutHeaderTamplate from "../_global/ui/ui_header_tamplate";
|
||||||
import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate";
|
import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate";
|
||||||
import notifikasi_countUserNotifikasi from "../notifikasi/fun/count/fun_count_by_id";
|
import { gs_notifikasi_kategori_app } from "../notifikasi/lib";
|
||||||
import BodyHome from "./component/body_home";
|
import BodyHome from "./component/body_home";
|
||||||
import FooterHome from "./component/footer_home";
|
import FooterHome from "./component/footer_home";
|
||||||
import { apiGetDataHome } from "./fun/get/api_home";
|
import { apiGetDataHome } from "./fun/get/api_home";
|
||||||
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
|
||||||
import { gs_notifikasi_kategori_app } from "../notifikasi/lib";
|
|
||||||
|
|
||||||
export default function HomeViewNew({
|
export default function HomeViewNew() {
|
||||||
countNotifikasi,
|
const [countNtf, setCountNtf] = useAtom(gs_count_ntf);
|
||||||
}: {
|
|
||||||
countNotifikasi: number;
|
|
||||||
}) {
|
|
||||||
const [countNtf, setCountNtf] = useState(countNotifikasi);
|
|
||||||
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
|
const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
|
||||||
const [countLoadNtf, setCountLoadNtf] = useAtom(gs_count_ntf);
|
|
||||||
const [dataUser, setDataUser] = useState<any>({});
|
const [dataUser, setDataUser] = useState<any>({});
|
||||||
const [categoryPage, setCategoryPage] = useAtom(gs_notifikasi_kategori_app);
|
const [categoryPage, setCategoryPage] = useAtom(gs_notifikasi_kategori_app);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
onLoadNotifikasi({
|
onLoadNotifikasi();
|
||||||
onLoad(val) {
|
}, []);
|
||||||
setCountNtf(val);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
setCountNtf(countLoadNtf as any);
|
|
||||||
}, [countLoadNtf, setCountNtf]);
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
setCountNtf(countNtf + newUserNtf);
|
if (countNtf != null) {
|
||||||
setNewUserNtf(0);
|
setCountNtf(countNtf + newUserNtf);
|
||||||
}, [newUserNtf, setCountNtf]);
|
setNewUserNtf(0);
|
||||||
|
}
|
||||||
|
}, [newUserNtf, countNtf]);
|
||||||
|
|
||||||
async function onLoadNotifikasi({ onLoad }: { onLoad: (val: any) => void }) {
|
async function onLoadNotifikasi() {
|
||||||
const loadNotif = await notifikasi_countUserNotifikasi();
|
const loadNotif = await fetch(API_RouteNotifikasi.get_count_by_id());
|
||||||
onLoad(loadNotif);
|
const data = await loadNotif.json().then((res) => res.data);
|
||||||
|
setCountNtf(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
@@ -75,6 +66,7 @@ export default function HomeViewNew({
|
|||||||
customButtonLeft={
|
customButtonLeft={
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
radius={"xl"}
|
radius={"xl"}
|
||||||
|
disabled={countNtf == null}
|
||||||
variant={"transparent"}
|
variant={"transparent"}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (
|
if (
|
||||||
@@ -93,6 +85,7 @@ export default function HomeViewNew({
|
|||||||
customButtonRight={
|
customButtonRight={
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
variant="transparent"
|
variant="transparent"
|
||||||
|
disabled={countNtf == null}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (
|
if (
|
||||||
dataUser.profile === undefined ||
|
dataUser.profile === undefined ||
|
||||||
@@ -100,24 +93,23 @@ export default function HomeViewNew({
|
|||||||
) {
|
) {
|
||||||
router.push(RouterProfile.create, { scroll: false });
|
router.push(RouterProfile.create, { scroll: false });
|
||||||
} else {
|
} else {
|
||||||
setCategoryPage("Semua")
|
setCategoryPage("Semua");
|
||||||
router.push(
|
router.push(
|
||||||
RouterNotifikasi.categoryApp({ name: "semua" }),
|
RouterNotifikasi.categoryApp({ name: "semua" }),
|
||||||
{
|
{
|
||||||
scroll: false,
|
scroll: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{countNotifikasi > 0 ? (
|
{countNtf != null && countNtf > 0 ? (
|
||||||
<Indicator
|
<Indicator
|
||||||
processing
|
processing
|
||||||
color={MainColor.yellow}
|
color={MainColor.yellow}
|
||||||
label={
|
label={
|
||||||
<Text fz={10} c={MainColor.darkblue}>
|
<Text fz={10} c={MainColor.darkblue}>
|
||||||
{countNotifikasi > 99 ? "99+" : countNotifikasi}
|
{countNtf > 99 ? "99+" : countNtf}
|
||||||
</Text>
|
</Text>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -137,137 +129,3 @@ export default function HomeViewNew({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// "use client";
|
|
||||||
// import { API_RouteNotifikasi } from "@/app/lib/api_user_router/route_api_notifikasi";
|
|
||||||
// import { gs_count_ntf, gs_user_ntf } from "@/app/lib/global_state";
|
|
||||||
// import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
|
|
||||||
// import { RouterNotifikasi } from "@/app/lib/router_hipmi/router_notifikasi";
|
|
||||||
// import { RouterUserSearch } from "@/app/lib/router_hipmi/router_user_search";
|
|
||||||
// import { ActionIcon, Indicator, Text } from "@mantine/core";
|
|
||||||
// import { useShallowEffect } from "@mantine/hooks";
|
|
||||||
// import { IconBell, IconUserSearch } from "@tabler/icons-react";
|
|
||||||
// import { useAtom } from "jotai";
|
|
||||||
// import { useRouter } from "next/navigation";
|
|
||||||
// import { useState } from "react";
|
|
||||||
// import { MainColor } from "../_global/color";
|
|
||||||
// import UIGlobal_LayoutHeaderTamplate from "../_global/ui/ui_header_tamplate";
|
|
||||||
// import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate";
|
|
||||||
// import { gs_notifikasi_kategori_app } from "../notifikasi/lib";
|
|
||||||
// import BodyHome from "./component/body_home";
|
|
||||||
// import FooterHome from "./component/footer_home";
|
|
||||||
// import { apiGetDataHome } from "./fun/get/api_home";
|
|
||||||
|
|
||||||
// export default function HomeViewNew() {
|
|
||||||
// const [countNtf, setCountNtf] = useAtom(gs_count_ntf);
|
|
||||||
// const [newUserNtf, setNewUserNtf] = useAtom(gs_user_ntf);
|
|
||||||
// const [dataUser, setDataUser] = useState<any>({});
|
|
||||||
// const [categoryPage, setCategoryPage] = useAtom(gs_notifikasi_kategori_app);
|
|
||||||
// const router = useRouter();
|
|
||||||
|
|
||||||
// useShallowEffect(() => {
|
|
||||||
// onLoadNotifikasi();
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
// useShallowEffect(() => {
|
|
||||||
// if (countNtf != null) {
|
|
||||||
// setCountNtf(countNtf + newUserNtf);
|
|
||||||
// setNewUserNtf(0);
|
|
||||||
// }
|
|
||||||
// console.log("notif baru", newUserNtf);
|
|
||||||
// console.log("notif baru", countNtf);
|
|
||||||
// }, [newUserNtf, countNtf]);
|
|
||||||
|
|
||||||
// async function onLoadNotifikasi() {
|
|
||||||
// const loadNotif = await fetch(API_RouteNotifikasi.get_count_by_id());
|
|
||||||
// const data = await loadNotif.json().then((res) => res.data);
|
|
||||||
// setCountNtf(data);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// useShallowEffect(() => {
|
|
||||||
// cekUserLogin();
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
// async function cekUserLogin() {
|
|
||||||
// try {
|
|
||||||
// const response = await apiGetDataHome("?cat=cek_profile");
|
|
||||||
// if (response.success) {
|
|
||||||
// setDataUser(response.data);
|
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error(error);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <>
|
|
||||||
// <UIGlobal_LayoutTamplate
|
|
||||||
// header={
|
|
||||||
// <UIGlobal_LayoutHeaderTamplate
|
|
||||||
// title="HIPMI"
|
|
||||||
// customButtonLeft={
|
|
||||||
// <ActionIcon
|
|
||||||
// radius={"xl"}
|
|
||||||
// disabled={countNtf == null}
|
|
||||||
// variant={"transparent"}
|
|
||||||
// onClick={() => {
|
|
||||||
// if (
|
|
||||||
// dataUser.profile === undefined ||
|
|
||||||
// dataUser?.profile === null
|
|
||||||
// ) {
|
|
||||||
// router.push(RouterProfile.create, { scroll: false });
|
|
||||||
// } else {
|
|
||||||
// router.push(RouterUserSearch.main, { scroll: false });
|
|
||||||
// }
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// <IconUserSearch color="white" />
|
|
||||||
// </ActionIcon>
|
|
||||||
// }
|
|
||||||
// customButtonRight={
|
|
||||||
// <ActionIcon
|
|
||||||
// variant="transparent"
|
|
||||||
// disabled={countNtf == null}
|
|
||||||
// onClick={() => {
|
|
||||||
// if (
|
|
||||||
// dataUser.profile === undefined ||
|
|
||||||
// dataUser?.profile === null
|
|
||||||
// ) {
|
|
||||||
// router.push(RouterProfile.create, { scroll: false });
|
|
||||||
// } else {
|
|
||||||
// setCategoryPage("Semua");
|
|
||||||
// router.push(
|
|
||||||
// RouterNotifikasi.categoryApp({ name: "semua" }),
|
|
||||||
// {
|
|
||||||
// scroll: false,
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// {countNtf != null && countNtf > 0 ? (
|
|
||||||
// <Indicator
|
|
||||||
// processing
|
|
||||||
// color={MainColor.yellow}
|
|
||||||
// label={
|
|
||||||
// <Text fz={10} c={MainColor.darkblue}>
|
|
||||||
// {countNtf > 99 ? "99+" : countNtf}
|
|
||||||
// </Text>
|
|
||||||
// }
|
|
||||||
// >
|
|
||||||
// <IconBell color="white" />
|
|
||||||
// </Indicator>
|
|
||||||
// ) : (
|
|
||||||
// <IconBell color="white" />
|
|
||||||
// )}
|
|
||||||
// </ActionIcon>
|
|
||||||
// }
|
|
||||||
// />
|
|
||||||
// }
|
|
||||||
// footer={<FooterHome />}
|
|
||||||
// >
|
|
||||||
// <BodyHome />
|
|
||||||
// </UIGlobal_LayoutTamplate>
|
|
||||||
// </>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|||||||
Reference in New Issue
Block a user