From 2b24bfe0a74e2b7e159addfcd698aa4ca1fd1232 Mon Sep 17 00:00:00 2001 From: caadiq Date: Wed, 21 Jan 2026 13:02:22 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20=EC=BD=98?= =?UTF-8?q?=EC=84=9C=ED=8A=B8=20=EC=84=B9=EC=85=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PC: ConcertSection.jsx, KakaoMap.jsx 삭제 - 모바일: ConcertSection, KakaoMap 컴포넌트 제거 - CATEGORY_ID에서 콘서트 관련 상수 제거 Co-Authored-By: Claude Opus 4.5 --- .../pages/mobile/public/ScheduleDetail.jsx | 421 +----------------- .../src/pages/pc/public/ScheduleDetail.jsx | 8 +- .../schedule-sections/ConcertSection.jsx | 389 ---------------- .../pc/public/schedule-sections/KakaoMap.jsx | 88 ---- .../pc/public/schedule-sections/index.js | 2 - .../pc/public/schedule-sections/utils.js | 4 - 6 files changed, 3 insertions(+), 909 deletions(-) delete mode 100644 frontend/src/pages/pc/public/schedule-sections/ConcertSection.jsx delete mode 100644 frontend/src/pages/pc/public/schedule-sections/KakaoMap.jsx diff --git a/frontend/src/pages/mobile/public/ScheduleDetail.jsx b/frontend/src/pages/mobile/public/ScheduleDetail.jsx index 368960f..00df894 100644 --- a/frontend/src/pages/mobile/public/ScheduleDetail.jsx +++ b/frontend/src/pages/mobile/public/ScheduleDetail.jsx @@ -2,90 +2,12 @@ import { useParams, Link } from 'react-router-dom'; import { useQuery, keepPreviousData } from '@tanstack/react-query'; import { useEffect, useState, useRef } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; -import { Calendar, Clock, ChevronLeft, Check, Link2, MapPin, Navigation, ExternalLink, X, ChevronRight } from 'lucide-react'; +import { Calendar, Clock, ChevronLeft, Link2, X, ChevronRight } from 'lucide-react'; import Linkify from 'react-linkify'; import { getSchedule } from '../../../api/public/schedules'; import { formatXDateTime } from '../../../utils/date'; import '../../../mobile.css'; -// 카카오맵 SDK 키 -const KAKAO_MAP_KEY = import.meta.env.VITE_KAKAO_JS_KEY; - -// 카카오맵 컴포넌트 -function KakaoMap({ lat, lng, name }) { - const mapRef = useRef(null); - const [mapLoaded, setMapLoaded] = useState(false); - const [mapError, setMapError] = useState(false); - - useEffect(() => { - if (!KAKAO_MAP_KEY) { - setMapError(true); - return; - } - - if (!window.kakao?.maps) { - const script = document.createElement('script'); - script.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${KAKAO_MAP_KEY}&autoload=false`; - script.onload = () => { - window.kakao.maps.load(() => setMapLoaded(true)); - }; - script.onerror = () => setMapError(true); - document.head.appendChild(script); - } else { - setMapLoaded(true); - } - }, []); - - useEffect(() => { - if (!mapLoaded || !mapRef.current || mapError) return; - - try { - const position = new window.kakao.maps.LatLng(lat, lng); - const map = new window.kakao.maps.Map(mapRef.current, { - center: position, - level: 3, - }); - - const marker = new window.kakao.maps.Marker({ - position, - map, - }); - - if (name) { - const infowindow = new window.kakao.maps.InfoWindow({ - content: `
${name}
`, - }); - infowindow.open(map, marker); - } - } catch (e) { - setMapError(true); - } - }, [mapLoaded, lat, lng, name, mapError]); - - if (mapError) { - return ( - -
- -

지도에서 보기

-
-
- ); - } - - return ( -
- ); -} - // 전체화면 시 자동 가로 회전 훅 (숏츠가 아닐 때만) function useFullscreenOrientation(isShorts) { useEffect(() => { @@ -130,10 +52,6 @@ function useFullscreenOrientation(isShorts) { const CATEGORY_ID = { YOUTUBE: 2, X: 3, - ALBUM: 4, - FANSIGN: 5, - CONCERT: 6, - TICKET: 7, }; // HTML 엔티티 디코딩 함수 @@ -158,13 +76,6 @@ const formatTime = (timeStr) => { return timeStr.slice(0, 5); }; -// X URL에서 username 추출 -const extractXUsername = (url) => { - if (!url) return null; - const match = url.match(/(?:twitter\.com|x\.com)\/([^/]+)/); - return match ? match[1] : null; -}; - // 유튜브 섹션 컴포넌트 function YoutubeSection({ schedule }) { const videoId = schedule.videoId; @@ -511,334 +422,6 @@ function XSection({ schedule }) { ); } -// 콘서트 섹션 컴포넌트 -function ConcertSection({ schedule }) { - // 현재 선택된 회차 ID (내부 state로 관리 - URL 변경 없음) - const [selectedDateId, setSelectedDateId] = useState(schedule.id); - // 다이얼로그 열림 상태 - const [isDialogOpen, setIsDialogOpen] = useState(false); - // 다이얼로그 목록 ref (자동 스크롤용) - const listRef = useRef(null); - const selectedItemRef = useRef(null); - - // 표시할 데이터 state (변경된 부분만 업데이트) - const [displayData, setDisplayData] = useState({ - posterUrl: schedule.images?.[0] || null, - title: schedule.title, - date: schedule.date, - time: schedule.time, - locationName: schedule.location_name, - locationAddress: schedule.location_address, - locationLat: schedule.location_lat, - locationLng: schedule.location_lng, - description: schedule.description, - sourceUrl: schedule.source?.url, - }); - - // 선택된 회차 데이터 조회 - const { data: selectedSchedule } = useQuery({ - queryKey: ['schedule', selectedDateId], - queryFn: () => getSchedule(selectedDateId), - placeholderData: keepPreviousData, - enabled: selectedDateId !== schedule.id, - }); - - // 데이터 비교 후 변경된 부분만 업데이트 - useEffect(() => { - const newData = selectedDateId === schedule.id ? schedule : selectedSchedule; - if (!newData) return; - - setDisplayData(prev => { - const updates = {}; - const newPosterUrl = newData.images?.[0] || null; - - if (prev.posterUrl !== newPosterUrl) updates.posterUrl = newPosterUrl; - if (prev.title !== newData.title) updates.title = newData.title; - if (prev.date !== newData.date) updates.date = newData.date; - if (prev.time !== newData.time) updates.time = newData.time; - if (prev.locationName !== newData.location_name) updates.locationName = newData.location_name; - if (prev.locationAddress !== newData.location_address) updates.locationAddress = newData.location_address; - if (prev.locationLat !== newData.location_lat) updates.locationLat = newData.location_lat; - if (prev.locationLng !== newData.location_lng) updates.locationLng = newData.location_lng; - if (prev.description !== newData.description) updates.description = newData.description; - if (prev.sourceUrl !== newData.source?.url) updates.sourceUrl = newData.source?.url; - - // 변경된 것이 있을 때만 업데이트 - if (Object.keys(updates).length > 0) { - return { ...prev, ...updates }; - } - return prev; - }); - }, [selectedDateId, schedule, selectedSchedule]); - - // 다이얼로그 열릴 때 선택된 항목으로 스크롤 - useEffect(() => { - if (isDialogOpen && selectedItemRef.current) { - setTimeout(() => { - selectedItemRef.current?.scrollIntoView({ block: 'center', behavior: 'instant' }); - }, 50); - } - }, [isDialogOpen]); - - const relatedDates = schedule.related_dates || []; - const hasMultipleDates = relatedDates.length > 1; - const hasLocation = displayData.locationLat && displayData.locationLng; - - // 현재 선택된 회차 인덱스 - const selectedIndex = relatedDates.findIndex(d => d.id === selectedDateId); - - // 회차 선택 핸들러 - const handleSelectDate = (id) => { - setSelectedDateId(id); - setIsDialogOpen(false); - }; - - // 개별 날짜 포맷팅 - const formatSingleDate = (dateStr, timeStr) => { - const date = new Date(dateStr); - const dayNames = ['일', '월', '화', '수', '목', '금', '토']; - const month = date.getMonth() + 1; - const day = date.getDate(); - const weekday = dayNames[date.getDay()]; - - let result = `${month}월 ${day}일 (${weekday})`; - if (timeStr) { - result += ` ${timeStr.slice(0, 5)}`; - } - return result; - }; - - return ( - <> -
- {/* 히어로 헤더 */} -
- {/* 배경 블러 이미지 */} - {displayData.posterUrl ? ( -
- -
- ) : ( -
- )} - {/* 오버레이 그라디언트 */} -
- - {/* 콘텐츠 */} -
-
- {/* 포스터 */} - {displayData.posterUrl && ( -
- {displayData.title} -
- )} - {/* 제목 */} -

- {decodeHtmlEntities(displayData.title)} -

-
-
-
- - {/* 카드 섹션 */} -
- {/* 공연 일정 카드 */} - -
- - 공연 일정 -
- {/* 현재 회차 표시 */} -
-

- {hasMultipleDates && {selectedIndex + 1}회차 ·} - {formatSingleDate(displayData.date, displayData.time)} -

-
- {/* 다른 회차 선택 버튼 */} - {hasMultipleDates && ( - - )} -
- - {/* 장소 카드 */} - {displayData.locationName && ( - -
- - 장소 -
-

{displayData.locationName}

- {displayData.locationAddress && ( -

{displayData.locationAddress}

- )} - - {/* 지도 - 좌표가 있으면 카카오맵, 없으면 구글맵 */} - {hasLocation ? ( -
- -
- ) : ( -
-