From c56c140e4b04fbaa6fe44a20b07fea308b3276c4 Mon Sep 17 00:00:00 2001 From: kent Date: Tue, 13 Jan 2026 19:47:03 +0900 Subject: [PATCH] =?UTF-8?q?feat(WEB):=20FCM=20=ED=91=B8=EC=8B=9C=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EA=B3=B5=ED=86=B5=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B8=B0=EC=95=88=ED=95=A8=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FCM 공통 모듈 생성 (src/lib/actions/fcm.ts) - sendFcmNotification: 기본 FCM 발송 함수 - sendApprovalNotification: 결재 알림 프리셋 - sendWorkOrderNotification: 작업지시 알림 프리셋 - sendNoticeNotification: 공지사항 알림 프리셋 - 기안함 페이지에 '문서완료' 버튼 추가 - Bell 아이콘 + FCM 발송 기능 - 발송 결과 토스트 메시지 표시 --- src/components/approval/DraftBox/actions.ts | 2 +- src/components/approval/DraftBox/index.tsx | 24 ++++ src/lib/actions/fcm.ts | 148 ++++++++++++++++++++ 3 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 src/lib/actions/fcm.ts diff --git a/src/components/approval/DraftBox/actions.ts b/src/components/approval/DraftBox/actions.ts index 88bd718f..1e7c495d 100644 --- a/src/components/approval/DraftBox/actions.ts +++ b/src/components/approval/DraftBox/actions.ts @@ -457,4 +457,4 @@ export async function cancelDraft(id: string): Promise<{ success: boolean; error error: '서버 오류가 발생했습니다.', }; } -} \ No newline at end of file +} diff --git a/src/components/approval/DraftBox/index.tsx b/src/components/approval/DraftBox/index.tsx index 39fc90d4..21759ca9 100644 --- a/src/components/approval/DraftBox/index.tsx +++ b/src/components/approval/DraftBox/index.tsx @@ -8,6 +8,7 @@ import { Trash2, Plus, Pencil, + Bell, } from 'lucide-react'; import { toast } from 'sonner'; import { @@ -19,6 +20,7 @@ import { submitDraft, submitDrafts, } from './actions'; +import { sendApprovalNotification } from '@/lib/actions/fcm'; import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { Badge } from '@/components/ui/badge'; @@ -243,6 +245,24 @@ export function DraftBox() { router.push('/ko/approval/draft/new'); }, [router]); + // ===== FCM 알림 발송 핸들러 ===== + const handleSendNotification = useCallback(async () => { + startTransition(async () => { + try { + const result = await sendApprovalNotification(); + if (result.success) { + toast.success(`결재 알림을 발송했습니다. (${result.sentCount || 0}건)`); + } else { + toast.error(result.error || '알림 발송에 실패했습니다.'); + } + } catch (error) { + if (isNextRedirectError(error)) throw error; + console.error('Notification error:', error); + toast.error('알림 발송 중 오류가 발생했습니다.'); + } + }); + }, []); + // ===== 문서 클릭/수정 핸들러 (조건부 로직) ===== // 임시저장 → 문서 작성 페이지 (수정 모드) // 그 외 → 문서 상세 모달 (상세 API 호출하여 content 포함된 데이터 가져옴) @@ -597,6 +617,10 @@ export function DraftBox() { )} +