139 lines
4.0 KiB
TypeScript
139 lines
4.0 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { getNotifications } from "@/service/notifications/notifications";
|
|
import {
|
|
CalendarCheck,
|
|
CheckCheck,
|
|
ChevronLeft,
|
|
ChevronRight,
|
|
CircleAlert,
|
|
Clock7,
|
|
MessageCircle,
|
|
SquareCheck,
|
|
UploadIcon,
|
|
} from "lucide-react";
|
|
import { useRouter } from "next/navigation";
|
|
|
|
export type Notification = {
|
|
id: number;
|
|
notificationTypeId: number;
|
|
message: string;
|
|
createdAt: string;
|
|
isActive: boolean;
|
|
isPublic: boolean;
|
|
isRead: boolean;
|
|
redirectUrl: string;
|
|
userGroupIdDst: string | null;
|
|
userIdDst: string | null;
|
|
userLevelIdDst: string;
|
|
userLevelNumberDst: string | null;
|
|
userRoleIdDst: string;
|
|
};
|
|
|
|
const getNotificationIcon = (notificationTypeId: number) => {
|
|
switch (notificationTypeId) {
|
|
case 2:
|
|
return <MessageCircle className="h-8 w-8 text-success" />;
|
|
case 3:
|
|
return <UploadIcon className="h-5 w-5 text-warning" />;
|
|
case 4:
|
|
return <CheckCheck className="h-5 w-5 text-primary" />;
|
|
case 5:
|
|
return <SquareCheck className="h-5 w-5 text-warning" />;
|
|
case 6:
|
|
return <CalendarCheck className="h-5 w-5 text-danger" />;
|
|
case 7:
|
|
return <CircleAlert className="h-5 w-5 text-danger" />;
|
|
case 8:
|
|
return <Clock7 className="h-5 w-5 text-danger" />;
|
|
default:
|
|
return <SquareCheck className="h-5 w-5 text-danger" />;
|
|
}
|
|
};
|
|
|
|
const NotificationsList: React.FC = () => {
|
|
const router = useRouter();
|
|
const [notifications, setNotifications] = useState<Notification[]>([]);
|
|
const [totalData, setTotalData] = useState<number>(0);
|
|
const [page, setPage] = useState<number>(1);
|
|
const [pageSize] = useState<number>(10);
|
|
const [totalPage, setTotalPage] = useState<number>(1);
|
|
|
|
useEffect(() => {
|
|
async function fetchNotifications() {
|
|
const response = await getNotifications(page - 1, pageSize);
|
|
setNotifications(response?.data?.data?.content || []);
|
|
setTotalData(response?.data?.data?.totalElements || 0);
|
|
setTotalPage(response?.data?.data?.totalPages);
|
|
}
|
|
fetchNotifications();
|
|
}, [page, pageSize]);
|
|
|
|
const handleNotificationClick = (redirectUrl: string) => {
|
|
router.push(redirectUrl);
|
|
};
|
|
|
|
const handlePageChange = (newPage: number) => {
|
|
setPage(newPage);
|
|
};
|
|
|
|
return (
|
|
<div className="mx-3">
|
|
<div className="space-y-3">
|
|
{notifications.length > 0 ? (
|
|
notifications?.map((notification) => (
|
|
<div
|
|
key={notification.id}
|
|
className="flex items-start space-x-4 p-4 border rounded-lg shadow-sm bg-white cursor-pointer"
|
|
onClick={() => handleNotificationClick(notification.redirectUrl)}
|
|
>
|
|
<div className="flex-shrink-0">
|
|
<div className="flex-none">
|
|
{getNotificationIcon(notification.notificationTypeId)}
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-medium">{notification.message}</p>
|
|
<p className="text-xs text-gray-500">
|
|
{new Date(notification.createdAt).toLocaleString()}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
))
|
|
) : (
|
|
<p className="text-gray-500 text-sm">Tidak ada notifikasi.</p>
|
|
)}
|
|
</div>
|
|
|
|
{/* Pagination */}
|
|
<div className="flex justify-end items-center mt-6 gap-3 mb-3">
|
|
<Button
|
|
onClick={() => handlePageChange(page - 1)}
|
|
disabled={page === 1}
|
|
variant="outline"
|
|
className="rounded-full"
|
|
size="sm"
|
|
>
|
|
<ChevronLeft size={20} />
|
|
</Button>
|
|
<p className="text-sm">
|
|
Page {page} of {totalPage}
|
|
</p>
|
|
<Button
|
|
onClick={() => handlePageChange(page + 1)}
|
|
disabled={page === totalPage}
|
|
variant="outline"
|
|
className="rounded-full"
|
|
size="sm"
|
|
>
|
|
<ChevronRight size={20} />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default NotificationsList;
|