Add: - types/type-notification-category.ts Fix: - app/(application)/(user)/notifications/index.tsx - app/(application)/(user)/test-notifications.tsx - app/(application)/admin/notification/index.tsx - components/Notification/NotificationInitializer.tsx - hooks/use-notification-store.tsx - service/api-notifications.ts - utils/formatChatTime.ts ### No Issue
147 lines
3.6 KiB
TypeScript
147 lines
3.6 KiB
TypeScript
// hooks/useNotificationStore.ts
|
|
import {
|
|
apiNotificationMarkAsRead,
|
|
apiNotificationUnreadCount,
|
|
} from "@/service/api-notifications";
|
|
import {
|
|
createContext,
|
|
ReactNode,
|
|
useContext,
|
|
useEffect,
|
|
useState,
|
|
} from "react";
|
|
import { useAuth } from "./use-auth";
|
|
|
|
type AppNotification = {
|
|
id: string;
|
|
title: string;
|
|
body: string;
|
|
data?: Record<string, string>;
|
|
isRead: boolean;
|
|
timestamp: number;
|
|
type: "announcement" | "trigger";
|
|
// untuk id dari setiap kategori app
|
|
appId?: string;
|
|
kategoriApp?:
|
|
| "JOB"
|
|
| "VOTING"
|
|
| "EVENT"
|
|
| "DONASI"
|
|
| "INVESTASI"
|
|
| "COLLABORATION"
|
|
| "FORUM"
|
|
| "ACCESS"; // Untuk trigger akses user;
|
|
};
|
|
|
|
type NotificationContextType = {
|
|
notifications: AppNotification[];
|
|
unreadCount: number;
|
|
addNotification: (
|
|
notif: Omit<AppNotification, "id" | "isRead" | "timestamp">
|
|
) => void;
|
|
markAsRead: (id: string) => void;
|
|
syncUnreadCount: () => Promise<void>;
|
|
};
|
|
|
|
const NotificationContext = createContext<NotificationContextType>({
|
|
notifications: [],
|
|
unreadCount: 0,
|
|
addNotification: () => {},
|
|
markAsRead: () => {},
|
|
syncUnreadCount: async () => {},
|
|
});
|
|
|
|
export const NotificationProvider = ({ children }: { children: ReactNode }) => {
|
|
const { user } = useAuth();
|
|
const [notifications, setNotifications] = useState<AppNotification[]>([]);
|
|
const [unreadCount, setUnreadCount] = useState(0);
|
|
|
|
console.log(
|
|
"🚀 Notifications Masuk:",
|
|
JSON.stringify(notifications, null, 2)
|
|
);
|
|
|
|
// Sync unread count dari backend saat provider di-mount
|
|
useEffect(() => {
|
|
fetchUnreadCount();
|
|
}, [user?.id]);
|
|
|
|
const fetchUnreadCount = async () => {
|
|
try {
|
|
const count = await apiNotificationUnreadCount({
|
|
id: user?.id as any,
|
|
role: user?.masterUserRoleId as any,
|
|
}); // ← harus return number
|
|
const result = count.data;
|
|
console.log("📖 Unread count:", result);
|
|
setUnreadCount(result);
|
|
} catch (error) {
|
|
console.error("Gagal fetch unread count:", error);
|
|
}
|
|
};
|
|
|
|
const addNotification = (
|
|
notif: Omit<AppNotification, "id" | "isRead" | "timestamp">
|
|
) => {
|
|
setNotifications((prev) => [
|
|
{
|
|
...notif,
|
|
id: Date.now().toString(),
|
|
isRead: false,
|
|
timestamp: Date.now(),
|
|
},
|
|
...prev,
|
|
]);
|
|
|
|
setUnreadCount((prev) => prev + 1);
|
|
};
|
|
|
|
const markAsRead = async (id: string) => {
|
|
try {
|
|
const response = await apiNotificationMarkAsRead({ id });
|
|
console.log("🚀 Response Mark As Read:", response);
|
|
|
|
if (response.success) {
|
|
const cloneNotifications = [...notifications];
|
|
const index = cloneNotifications.findIndex((n) => n?.data?.id === id);
|
|
if (index !== -1) {
|
|
cloneNotifications[index].isRead = true;
|
|
setNotifications(cloneNotifications);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error("Gagal mark as read:", error);
|
|
}
|
|
};
|
|
|
|
const syncUnreadCount = async () => {
|
|
try {
|
|
const count = await apiNotificationUnreadCount({
|
|
id: user?.id as any,
|
|
role: user?.masterUserRoleId as any,
|
|
}); // ← harus return number
|
|
const result = count.data;
|
|
console.log("📖 Unread count sync:", result);
|
|
setUnreadCount(result);
|
|
} catch (error) {
|
|
console.warn("⚠️ Gagal sync unread count:", error);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<NotificationContext.Provider
|
|
value={{
|
|
notifications,
|
|
addNotification,
|
|
markAsRead,
|
|
unreadCount,
|
|
syncUnreadCount,
|
|
}}
|
|
>
|
|
{children}
|
|
</NotificationContext.Provider>
|
|
);
|
|
};
|
|
|
|
export const useNotificationStore = () => useContext(NotificationContext);
|