diff --git a/apps/admin/src/hooks/useInvalidate.ts b/apps/admin/src/hooks/useInvalidate.ts index 74e8819a3..150d8c55f 100644 --- a/apps/admin/src/hooks/useInvalidate.ts +++ b/apps/admin/src/hooks/useInvalidate.ts @@ -51,6 +51,21 @@ const useInvalidate = () => { }); }, [queryClient]); + const invalidateNotification = useCallback( + (studentId: number) => { + queryClient.invalidateQueries({ + queryKey: $api.queryOptions('get', '/api/admin/notification', { + params: { + query: { + studentId, + }, + }, + }).queryKey, + }); + }, + [queryClient] + ); + const invalidateQna = useCallback( (qnaId?: number) => { const promises: Promise[] = [ @@ -77,6 +92,7 @@ const useInvalidate = () => { invalidateProblemSet, invalidatePublish, invalidateNotice, + invalidateNotification, invalidateQna, }; }; diff --git a/apps/admin/src/routes/_GNBLayout/notification/index.tsx b/apps/admin/src/routes/_GNBLayout/notification/index.tsx index afafce498..2b6e9510a 100644 --- a/apps/admin/src/routes/_GNBLayout/notification/index.tsx +++ b/apps/admin/src/routes/_GNBLayout/notification/index.tsx @@ -1,9 +1,8 @@ import { useState } from 'react'; import { createFileRoute } from '@tanstack/react-router'; -import { Header, Modal, Input, SegmentedControl } from '@components'; +import { Header, Modal, Input, SegmentedControl, ErrorModalTemplate } from '@components'; import { getNotification, postNotification, getStudent } from '@apis'; -import { useModal, useSelectedStudent } from '@hooks'; -import { useQueryClient } from '@tanstack/react-query'; +import { useInvalidate, useModal, useSelectedStudent } from '@hooks'; import { Bell, Send, @@ -113,7 +112,7 @@ export const Route = createFileRoute('/_GNBLayout/notification/')({ function RouteComponent() { const { selectedStudent } = useSelectedStudent(); - const queryClient = useQueryClient(); + const { invalidateNotification } = useInvalidate(); // Send modal state const { @@ -122,6 +121,14 @@ function RouteComponent() { closeModal: closeSendModal, } = useModal(); + // Error modal state + const { + isOpen: isErrorModalOpen, + openModal: openErrorModal, + closeModal: closeErrorModal, + } = useModal(); + const [errorMessage, setErrorMessage] = useState(''); + // Form state for sending notification const [sendMode, setSendMode] = useState<'selected' | 'all' | 'search'>('selected'); const [notificationType, setNotificationType] = useState('SYSTEM'); @@ -171,9 +178,14 @@ function RouteComponent() { setNotificationUrl(''); setSelectedStudentIds([]); closeSendModal(); - queryClient.invalidateQueries(); } catch (error) { console.error('Failed to send notification:', error); + const message = (error as { message?: string })?.message || '알림 발송에 실패했습니다.'; + setErrorMessage(message); + closeSendModal(); + openErrorModal(); + } finally { + invalidateNotification(selectedStudent?.id || 0); } }; @@ -523,6 +535,15 @@ function RouteComponent() { + + {/* Error Modal */} + + + ); }