From 9735206da7628cb5f2696f5f06f7f44721cc40cd Mon Sep 17 00:00:00 2001 From: caadiq Date: Tue, 3 Feb 2026 14:07:36 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=BD=98=EC=84=9C=ED=8A=B8=20=ED=8F=BC?= =?UTF-8?q?=20=ED=94=84=EB=A1=A0=ED=8A=B8=EC=97=94=EB=93=9C-=EB=B0=B1?= =?UTF-8?q?=EC=97=94=EB=93=9C=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - createConcertSchedule API 함수 추가 - handleSubmit에서 FormData 구성 및 API 호출 구현 - 유효성 검사 및 저장 성공 시 목록으로 이동 Co-Authored-By: Claude Opus 4.5 --- frontend/src/api/admin/concert.js | 13 ++++ .../pc/admin/common/VenueSearchDialog.jsx | 2 +- .../form/concert/ScheduleSection.jsx | 48 +++++++++++- .../pc/admin/schedules/form/concert/index.jsx | 73 +++++++++++++++++-- 4 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 frontend/src/api/admin/concert.js diff --git a/frontend/src/api/admin/concert.js b/frontend/src/api/admin/concert.js new file mode 100644 index 0000000..fce0101 --- /dev/null +++ b/frontend/src/api/admin/concert.js @@ -0,0 +1,13 @@ +/** + * 콘서트 관리자 API + */ +import { fetchFormData } from '@/api/client'; + +/** + * 콘서트 일정 생성 + * @param {FormData} formData - 콘서트 데이터 + * @returns {Promise<{success: boolean, seriesId: number}>} + */ +export async function createConcertSchedule(formData) { + return fetchFormData('/admin/concert/schedule', formData, 'POST'); +} diff --git a/frontend/src/components/pc/admin/common/VenueSearchDialog.jsx b/frontend/src/components/pc/admin/common/VenueSearchDialog.jsx index 7e0968e..e3e83ba 100644 --- a/frontend/src/components/pc/admin/common/VenueSearchDialog.jsx +++ b/frontend/src/components/pc/admin/common/VenueSearchDialog.jsx @@ -63,7 +63,7 @@ function VenueSearchDialog({ isOpen, onClose, onSelect }) { id: place.id, name: place.place_name, address: place.road_address_name || place.address_name, - country: "한국", + country: "South Korea", lat: parseFloat(place.y), lng: parseFloat(place.x), category: place.category_name, diff --git a/frontend/src/pages/pc/admin/schedules/form/concert/ScheduleSection.jsx b/frontend/src/pages/pc/admin/schedules/form/concert/ScheduleSection.jsx index efa1fa1..4476590 100644 --- a/frontend/src/pages/pc/admin/schedules/form/concert/ScheduleSection.jsx +++ b/frontend/src/pages/pc/admin/schedules/form/concert/ScheduleSection.jsx @@ -31,6 +31,13 @@ function ScheduleSection({ rounds, setRounds }) { roundId: null, }); + // 장소 삭제 확인 다이얼로그 + const [venueDeleteConfirm, setVenueDeleteConfirm] = useState({ + isOpen: false, + roundId: null, + venueName: null, + }); + // 회차 추가 const addRound = () => { const newRound = { @@ -107,9 +114,24 @@ function ScheduleSection({ rounds, setRounds }) { setLocationSearch({ isOpen: false, roundId: null }); }; - // 장소 제거 - const removeVenue = (roundId) => { - updateRound(roundId, "venue", null); + // 장소 삭제 시도 + const handleRemoveVenue = (roundId) => { + const round = rounds.find((r) => r.id === roundId); + if (round?.venue) { + setVenueDeleteConfirm({ + isOpen: true, + roundId, + venueName: round.venue.name, + }); + } + }; + + // 장소 삭제 확인 + const handleConfirmVenueDelete = () => { + if (venueDeleteConfirm.roundId !== null) { + updateRound(venueDeleteConfirm.roundId, "venue", null); + } + setVenueDeleteConfirm({ isOpen: false, roundId: null, venueName: null }); }; return ( @@ -141,6 +163,24 @@ function ScheduleSection({ rounds, setRounds }) { onSelect={handleLocationSelect} /> + {/* 장소 삭제 확인 다이얼로그 */} + + setVenueDeleteConfirm({ isOpen: false, roundId: null, venueName: null }) + } + onConfirm={handleConfirmVenueDelete} + title="장소 삭제" + message={ +

+ {venueDeleteConfirm.venueName} + 을(를) 삭제하시겠습니까? +

+ } + confirmText="삭제" + cancelText="취소" + /> +

공연 일정

@@ -221,7 +261,7 @@ function ScheduleSection({ rounds, setRounds }) {