Merge branch 'fe/refactor/notification-popover' into 'fe/develop'

Refactor: 알림 컴포넌트에서 하위 컴포넌트 분리, 알림 컴포넌트 스크롤 처리

See merge request s11-s-project/S11P21S002!235
This commit is contained in:
정현조 2024-09-29 21:32:42 +09:00
commit f5de5a9c48
2 changed files with 94 additions and 70 deletions

View File

@ -0,0 +1,74 @@
import { cn } from '@/lib/utils';
import { AlarmResponse } from '@/types';
import { Mail, MailOpen, Trash2 } from 'lucide-react';
export default function AlarmItem({
alarm,
onRead,
onDelete,
}: {
alarm: AlarmResponse;
onRead: (alarmId: number) => void;
onDelete: (alarmId: number) => void;
}) {
const timeAgo = (date: string | Date) => {
const now = new Date();
const past = new Date(date);
const diffInSeconds = Math.floor((now.getTime() - past.getTime()) / 1000);
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 handleRead = () => {
onRead(alarm.id);
};
const handleDelete = () => {
onDelete(alarm.id);
};
return (
<div className="flex w-full items-center bg-white py-2 pr-[18px] duration-150 hover:bg-gray-200">
<div className={cn('mx-1.5 h-1.5 w-1.5 rounded-full', alarm.isRead ? 'bg-transparent' : 'bg-blue-500')}></div>
<div className="flex flex-1 flex-col">
<p className={cn('body-small', alarm.isRead ? 'text-gray-400' : 'text-black')}>
[{alarm.id}] {alarm.type} .
</p>
<p className="caption text-gray-500">{timeAgo(alarm.createdAt)}</p>
</div>
{alarm.isRead ? (
<button
className="p-1"
disabled
>
<MailOpen
size={16}
className="stroke-gray-400"
/>
</button>
) : (
<button
className="p-1"
onClick={handleRead}
>
<Mail size={16} />
</button>
)}
<button
className="p-1"
onClick={handleDelete}
>
<Trash2
size={16}
className="stroke-red-500"
/>
</button>
</div>
);
}

View File

@ -1,7 +1,10 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { Bell } from 'lucide-react';
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
import { onMessage } from 'firebase/messaging'; import { onMessage } from 'firebase/messaging';
import { messaging } from '@/api/firebaseConfig'; import { messaging } from '@/api/firebaseConfig';
import AlarmItem from './AlarmItem';
import useFcmTokenQuery from '@/queries/auth/useFcmTokenQuery'; import useFcmTokenQuery from '@/queries/auth/useFcmTokenQuery';
import useGetAlarmListQuery from '@/queries/alarms/useGetAlarmListQuery'; import useGetAlarmListQuery from '@/queries/alarms/useGetAlarmListQuery';
import useResetAlarmListQuery from '@/queries/alarms/useResetAlarmListQuery'; import useResetAlarmListQuery from '@/queries/alarms/useResetAlarmListQuery';
@ -9,26 +12,10 @@ import useCreateAlarmTestQuery from '@/queries/alarms/useCreateAlarmTestQuery';
import useReadAlarmQuery from '@/queries/alarms/useReadAlarmQuery'; import useReadAlarmQuery from '@/queries/alarms/useReadAlarmQuery';
import useDeleteAlarmQuery from '@/queries/alarms/useDeleteAlarmQuery'; import useDeleteAlarmQuery from '@/queries/alarms/useDeleteAlarmQuery';
import useDeleteAllAlarmQuery from '@/queries/alarms/useDeleteAllAlarmQuery'; 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() { export default function AlarmPopover() {
const [unread, setUnread] = useState<boolean>(false); const [unread, setUnread] = useState<boolean>(false);
const timeAgo = (date: string | Date) => {
const now = new Date();
const past = new Date(date);
const diffInSeconds = Math.floor((now.getTime() - past.getTime()) / 1000);
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 resetAlarmList = useResetAlarmListQuery(); const resetAlarmList = useResetAlarmListQuery();
const createAlarmTest = useCreateAlarmTestQuery(); const createAlarmTest = useCreateAlarmTestQuery();
const readAlarm = useReadAlarmQuery(); const readAlarm = useReadAlarmQuery();
@ -101,7 +88,7 @@ export default function AlarmPopover() {
> >
</button> </button>
{unread ? ( {/* {unread ? (
<button <button
className="body-small p-1" className="body-small p-1"
onClick={() => {}} onClick={() => {}}
@ -115,7 +102,7 @@ export default function AlarmPopover() {
> >
</button> </button>
)} )} */}
<button <button
className="body-small p-1 text-red-500" className="body-small p-1 text-red-500"
onClick={handleDeleteAllAlarm} onClick={handleDeleteAllAlarm}
@ -125,62 +112,25 @@ export default function AlarmPopover() {
</div> </div>
<hr /> <hr />
{alarms.length == 0 && ( {alarms.length === 0 ? (
<div className="flex w-full items-center px-[18px] py-3 duration-150"> <div className="flex w-full items-center px-[18px] py-3 duration-150">
<p className="body-small text-gray-500"> .</p> <p className="body-small text-gray-500"> .</p>
</div> </div>
)} ) : (
<div className="flex max-h-[500px] w-full flex-col items-center overflow-y-auto">
{alarms {alarms
.slice() .slice()
.reverse() .reverse()
.map((alarm) => ( .map((alarm) => (
<div <AlarmItem
key={alarm.id} key={alarm.id}
className="flex w-full items-center bg-white py-2 pr-[18px] duration-150 hover:bg-gray-200" alarm={alarm}
> onRead={handleReadAlarm}
<div onDelete={handleDeleteAlarm}
className={cn('mx-1.5 h-1.5 w-1.5 rounded-full', alarm.isRead ? 'bg-transparent' : 'bg-blue-500')}
></div>
<div className="flex flex-1 flex-col">
<p className="body-small">
[{alarm.id}] {alarm.type} .
</p>
<p className="caption text-gray-500">{timeAgo(alarm.createdAt)}</p>
</div>
{alarm.isRead ? (
<button
className="p-1"
onClick={() => {}}
>
<MailOpen
size={16}
className="stroke-gray-400"
/>
</button>
) : (
<button
className="p-1"
onClick={() => {
handleReadAlarm(alarm.id);
}}
>
<Mail size={16} />
</button>
)}
<button
className="p-1"
onClick={() => {
handleDeleteAlarm(alarm.id);
}}
>
<Trash2
size={16}
className="stroke-red-500"
/> />
</button> ))}
</div> </div>
))} )}
</PopoverContent> </PopoverContent>
</Popover> </Popover>
); );