From 1a68ae792ec5a0241fa5febeb2a53bd0dc18b821 Mon Sep 17 00:00:00 2001 From: SeongHyun Kim Date: Wed, 10 Dec 2025 17:42:34 +0900 Subject: [PATCH] =?UTF-8?q?fix(repeat-screen-modal):=20=EC=99=B8=EB=B6=80?= =?UTF-8?q?=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=ED=96=89=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=A6=89=EC=8B=9C=20DELETE=20API=20=ED=98=B8?= =?UTF-8?q?=EC=B6=9C=20=EB=B0=A9=EC=8B=9D=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 소프트 삭제(_isDeleted 플래그) 방식에서 즉시 삭제로 변경 - DB에 저장된 기존 행: DELETE API 즉시 호출 후 UI에서 제거 - 새로 추가된 행: UI에서만 제거 (DB에 없음) - _originalData.id 존재 여부로 DB 데이터 판단 - 삭제 후 집계 재계산 정상 작동 --- .../RepeatScreenModalComponent.tsx | 82 ++++++++++++++----- 1 file changed, 63 insertions(+), 19 deletions(-) diff --git a/frontend/lib/registry/components/repeat-screen-modal/RepeatScreenModalComponent.tsx b/frontend/lib/registry/components/repeat-screen-modal/RepeatScreenModalComponent.tsx index 360a1585..662dacea 100644 --- a/frontend/lib/registry/components/repeat-screen-modal/RepeatScreenModalComponent.tsx +++ b/frontend/lib/registry/components/repeat-screen-modal/RepeatScreenModalComponent.tsx @@ -1154,26 +1154,70 @@ export function RepeatScreenModalComponent({ } }; - // 🆕 v3.1: 외부 테이블 행 삭제 실행 (소프트 삭제 - _isDeleted 플래그 설정) - const handleDeleteExternalRow = (cardId: string, rowId: string, contentRowId: string) => { + // 🆕 v3.14: 외부 테이블 행 삭제 실행 (즉시 DELETE API 호출) + const handleDeleteExternalRow = async (cardId: string, rowId: string, contentRowId: string) => { const key = `${cardId}-${contentRowId}`; - setExternalTableData((prev) => { - const newData = { - ...prev, - [key]: (prev[key] || []).map((row) => - row._rowId === rowId - ? { ...row, _isDeleted: true, _isDirty: true } - : row - ), - }; - - // 🆕 v3.5: 행 삭제 시 집계 재계산 (삭제된 행 제외) - setTimeout(() => { - recalculateAggregationsWithExternalData(newData); - }, 0); - - return newData; - }); + const rows = externalTableData[key] || []; + const targetRow = rows.find((row) => row._rowId === rowId); + + // 기존 DB 데이터인 경우 (id가 있는 경우) 즉시 삭제 + if (targetRow?._originalData?.id) { + try { + const contentRow = contentRows.find((r) => r.id === contentRowId); + const targetTable = contentRow?.tableCrud?.targetTable || contentRow?.tableDataSource?.sourceTable; + + if (!targetTable) { + console.error("[RepeatScreenModal] 삭제 대상 테이블을 찾을 수 없습니다."); + return; + } + + console.log(`[RepeatScreenModal] DELETE API 호출: ${targetTable}, id=${targetRow._originalData.id}`); + + // 백엔드는 배열 형태의 데이터를 기대함 + await apiClient.request({ + method: "DELETE", + url: `/table-management/tables/${targetTable}/delete`, + data: [{ id: targetRow._originalData.id }], + }); + + console.log(`[RepeatScreenModal] DELETE 성공: ${targetTable}, id=${targetRow._originalData.id}`); + + // 성공 시 UI에서 완전히 제거 + setExternalTableData((prev) => { + const newData = { + ...prev, + [key]: prev[key].filter((row) => row._rowId !== rowId), + }; + + // 행 삭제 시 집계 재계산 + setTimeout(() => { + recalculateAggregationsWithExternalData(newData); + }, 0); + + return newData; + }); + } catch (error: any) { + console.error(`[RepeatScreenModal] DELETE 실패:`, error.response?.data || error.message); + // 에러 시에도 다이얼로그 닫기 + } + } else { + // 새로 추가된 행 (아직 DB에 없음) - UI에서만 제거 + console.log(`[RepeatScreenModal] 새 행 삭제 (DB 없음): rowId=${rowId}`); + setExternalTableData((prev) => { + const newData = { + ...prev, + [key]: prev[key].filter((row) => row._rowId !== rowId), + }; + + // 행 삭제 시 집계 재계산 + setTimeout(() => { + recalculateAggregationsWithExternalData(newData); + }, 0); + + return newData; + }); + } + setDeleteConfirmOpen(false); setPendingDeleteInfo(null); };