diff --git a/frontend/src/api/alarmApi.ts b/frontend/src/api/alarmApi.ts index de4d95a..6d9fc4c 100644 --- a/frontend/src/api/alarmApi.ts +++ b/frontend/src/api/alarmApi.ts @@ -5,7 +5,7 @@ export async function getAlarmList() { return api.get('/alarm').then(({ data }) => data); } -export async function createTestAlarm() { +export async function createAlarmTest() { return api.post('/alarm/test').then(({ data }) => data); } diff --git a/frontend/src/components/Header/AlarmPopover.tsx b/frontend/src/components/Header/AlarmPopover.tsx index c8d401d..5f241b8 100644 --- a/frontend/src/components/Header/AlarmPopover.tsx +++ b/frontend/src/components/Header/AlarmPopover.tsx @@ -1,68 +1,186 @@ -import { Bell } from 'lucide-react'; -import { Button } from '../ui/button'; -import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover'; +import { useEffect, useState } from 'react'; +import { cn } from '@/lib/utils'; import { onMessage } from 'firebase/messaging'; import { messaging } from '@/api/firebaseConfig'; -import useGetAlarmListQuery from '@/queries/alarms/useGetAlarmListQuery'; import useFcmTokenQuery from '@/queries/auth/useFcmTokenQuery'; -import useCreateTestAlarmQuery from '@/queries/alarms/useCreateTestAlarmQuery'; -// import useDeleteAlarmQuery from '@/queries/alarms/useDeleteAlarmQuery'; +import useGetAlarmListQuery from '@/queries/alarms/useGetAlarmListQuery'; +import useResetAlarmListQuery from '@/queries/alarms/useResetAlarmListQuery'; +import useCreateAlarmTestQuery from '@/queries/alarms/useCreateAlarmTestQuery'; +import useReadAlarmQuery from '@/queries/alarms/useReadAlarmQuery'; +import useDeleteAlarmQuery from '@/queries/alarms/useDeleteAlarmQuery'; import useDeleteAllAlarmQuery from '@/queries/alarms/useDeleteAllAlarmQuery'; +import { Bell, Mail, MailOpen, Trash2 } from 'lucide-react'; +import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover'; export default function AlarmPopover() { - useFcmTokenQuery(); + const [unread, setUnread] = useState(false); - const { data: alarms } = useGetAlarmListQuery(); + const timeAgo = (date: string | Date) => { + const now = new Date(); + const past = new Date(date); + const diffInSeconds = Math.floor((now.getTime() - past.getTime()) / 1000); - onMessage(messaging, (payload) => { - if (!payload.data) return; - - console.log(payload.data); - }); - - const createTestAlarm = useCreateTestAlarmQuery(); - // const deleteAlarm = useDeleteAlarmQuery(); - const deleteAllAlarm = useDeleteAllAlarmQuery(); - - const handleCreateTestAlarm = () => { - createTestAlarm.mutate(); + if (diffInSeconds < 60) return `${Math.max(diffInSeconds, 0)}초 전`; + const diffInMinutes = Math.floor(diffInSeconds / 60); + if (diffInMinutes < 60) return `${diffInMinutes}분 전`; + const diffInHours = Math.floor(diffInMinutes / 60); + if (diffInHours < 24) return `${diffInHours}시간 전`; + const diffInDays = Math.floor(diffInHours / 24); + return `${diffInDays}일 전`; }; - // const handleDeleteAlarm = (alarmId: number) => { - // deleteAlarm.mutate(alarmId); - // }; + const resetAlarmList = useResetAlarmListQuery(); + const createAlarmTest = useCreateAlarmTestQuery(); + const readAlarm = useReadAlarmQuery(); + const deleteAlarm = useDeleteAlarmQuery(); + const deleteAllAlarm = useDeleteAllAlarmQuery(); + + const handleResetAlarmList = () => { + resetAlarmList.mutate(); + }; + + const handleCreateAlarmTest = () => { + createAlarmTest.mutate(); + }; + + const handleReadAlarm = (alarmId: number) => { + readAlarm.mutate(alarmId); + }; + + const handleDeleteAlarm = (alarmId: number) => { + deleteAlarm.mutate(alarmId); + }; const handleDeleteAllAlarm = () => { deleteAllAlarm.mutate(); }; + useFcmTokenQuery(); + const { data: alarms } = useGetAlarmListQuery(); + + onMessage(messaging, (payload) => { + if (!payload.data) return; + + console.log('new message arrived'); + handleResetAlarmList(); + }); + + useEffect(() => { + const unreadCnt = alarms.filter((alarm) => !alarm.isRead).length; + + if (unreadCnt > 0) { + setUnread(true); + } else { + setUnread(false); + } + }, [alarms]); + return ( -
+
+
+
- - {alarms.map((alarm, index) => ( -
- {alarm.id} {alarm.type} + + +
+

알림

+ + {unread ? ( + + ) : ( + + )} + +
+
+ + {alarms.length == 0 && ( +
+

알림이 없습니다.

- ))} - - + )} + + {alarms + .slice() + .reverse() + .map((alarm) => ( +
+
+
+

+ [{alarm.id}] {alarm.type} 알림입니다. +

+

{timeAgo(alarm.createdAt)}

+
+ {alarm.isRead ? ( + + ) : ( + + )} + +
+ ))}
); diff --git a/frontend/src/components/Header/index.tsx b/frontend/src/components/Header/index.tsx index 37797fc..9e8a78f 100644 --- a/frontend/src/components/Header/index.tsx +++ b/frontend/src/components/Header/index.tsx @@ -39,7 +39,7 @@ export default function Header({ className, ...props }: HeaderProps) {
{!isHomePage && profile && ( -
+
diff --git a/frontend/src/queries/alarms/useCreateTestAlarmQuery.ts b/frontend/src/queries/alarms/useCreateAlarmTestQuery.ts similarity index 63% rename from frontend/src/queries/alarms/useCreateTestAlarmQuery.ts rename to frontend/src/queries/alarms/useCreateAlarmTestQuery.ts index afcf652..84c6388 100644 --- a/frontend/src/queries/alarms/useCreateTestAlarmQuery.ts +++ b/frontend/src/queries/alarms/useCreateAlarmTestQuery.ts @@ -1,11 +1,11 @@ -import { createTestAlarm } from '@/api/alarmApi'; +import { createAlarmTest } from '@/api/alarmApi'; import { useMutation, useQueryClient } from '@tanstack/react-query'; -export default function useCreateTestAlarmQuery() { +export default function useCreateAlarmTestQuery() { const queryClient = useQueryClient(); return useMutation({ - mutationFn: createTestAlarm, + mutationFn: createAlarmTest, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['alarmList'] }); }, diff --git a/frontend/src/queries/alarms/useResetAlarmListQuery.ts b/frontend/src/queries/alarms/useResetAlarmListQuery.ts new file mode 100644 index 0000000..75fd6d4 --- /dev/null +++ b/frontend/src/queries/alarms/useResetAlarmListQuery.ts @@ -0,0 +1,12 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +export default function useUpdateAlarmQuery() { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async () => {}, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['alarmList'] }); + }, + }); +}