diff --git a/src/apis/booth.js b/src/apis/booth.js index 3932b85..90a4926 100644 --- a/src/apis/booth.js +++ b/src/apis/booth.js @@ -7,9 +7,20 @@ export const getBoothList = async ({ is_reservable, }) => { try { - const res = await instance.get( - `api/v1/booth/?day=${day}&category=${category}&location=${location}&is_night=${is_night}&is_reservable=${is_reservable}` - ); + // URLSearchParams 객체 생성 + const params = new URLSearchParams(); + + // 파라미터가 존재할 때만 추가 + if (day) params.append("day", day); + if (category) params.append("category", category); + if (location) params.append("location", location); + if (is_night !== undefined) params.append("is_night", is_night); + if (is_reservable !== undefined) + params.append("is_reservable", is_reservable); + + // 파라미터들을 포함한 GET 요청 + const res = await instance.get(`api/v1/booth/?${params.toString()}`); + console.log("booth.js에서의 res 값", res); return res; } catch (err) { console.log(err); diff --git a/src/apis/boothDetail.js b/src/apis/boothDetail.js index 49dc800..b787b1d 100644 --- a/src/apis/boothDetail.js +++ b/src/apis/boothDetail.js @@ -1,5 +1,5 @@ import { instance } from "./instance"; -export const getBoothDetail = async ({ booth_id }) => { +export const getBoothDetail = async (booth_id) => { try { const res = await instance.get(`api/v1/booth/detail/${booth_id}`); return res; diff --git a/src/assets/images/tabling.svg b/src/assets/images/tabling.svg new file mode 100644 index 0000000..26a1bdb --- /dev/null +++ b/src/assets/images/tabling.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/components/common/BoothDetail/BoothDetail.jsx b/src/components/common/BoothDetail/BoothDetail.jsx new file mode 100644 index 0000000..61e4c09 --- /dev/null +++ b/src/components/common/BoothDetail/BoothDetail.jsx @@ -0,0 +1,108 @@ +import * as S from "./styled"; +import { useState, useRef } from "react"; +import tablingImg from "../../../assets/images/tabling.svg"; +import CancelIcon from "../../../assets/images/X_Icon.svg"; +import { useNavigate } from "react-router-dom"; +import { + Detailtitle, + BoothDetailData, +} from "../../../constant/StarDetail/data"; +import { useBoothDetailData } from "../../../hook/useBoothDetail"; + +export const BoothDetail = ({ onClose, booth_id }) => { + const navigate = useNavigate(); + const [currentIndex, setCurrentIndex] = useState(0); + const imgWrapperRef = useRef(null); + const { boothDetailData } = useBoothDetailData(booth_id); + console.log("boothDetail컴포넌트에서 :", boothDetailData); + if (!boothDetailData) { + return
Loading...
; + } + const totalImages = BoothDetailData[0].src.length; + + const handleTouchStart = (e) => { + imgWrapperRef.current.startX = e.touches[0].clientX; + }; + + const handleTouchEnd = (e) => { + const endX = e.changedTouches[0].clientX; + const difference = imgWrapperRef.current.startX - endX; + + if (difference > 50) { + handleNext(); + } else if (difference < -50) { + handlePrev(); + } + }; + + const handlePrev = () => { + setCurrentIndex((prevIndex) => + prevIndex === 0 ? totalImages - 1 : prevIndex - 1 + ); + }; + + const handleNext = () => { + setCurrentIndex((prevIndex) => + prevIndex === totalImages - 1 ? 0 : prevIndex + 1 + ); + }; + + const MoveonTabling = () => { + navigate("/"); + }; + // const DetailData = useBoothDetailData(); + return ( + + + +
{BoothDetailData[0].booth_name}
+ {/* {BoothDetailData[0].id_night===true && } */} + +
+ {BoothDetailData[0].is_night ? "밤부스" : "낮부스"} +
+
{BoothDetailData[0].location}
+
{BoothDetailData[0].category}
+
+ +
+ + + + {currentIndex + 1}/{totalImages} + + + + + {Detailtitle.map((title, index) => ( +
+
+ {title} + + {index === 0 && BoothDetailData[0].description} + {index === 1 && BoothDetailData[0].operation} + {index === 2 && BoothDetailData[0].time} + {index === 3 && BoothDetailData[0].fee} + {index === 4 && BoothDetailData[0].menu} + {index === 5 && BoothDetailData[0].insta} + +
+ {index === 2 && } + {index === 4 && } +
+ ))} +
+
+
+ + +
+ ); +}; diff --git a/src/components/common/BoothDetail/styled.js b/src/components/common/BoothDetail/styled.js new file mode 100644 index 0000000..c4f30f9 --- /dev/null +++ b/src/components/common/BoothDetail/styled.js @@ -0,0 +1,177 @@ +import styled, { keyframes } from "styled-components"; +const slideUp = keyframes` + 0% { + transform: translateY(100%); + + } + 100% { + transform: translateY(0); + } +`; +export const DetailWrapper = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + position: fixed; + bottom: 0; + width: 370px; + height: 55%; + gap: 20px; + background-color: #fff; + border-radius: 20px 20px 0px 0px; + box-shadow: 0px 2px 40px 0px rgba(0, 0, 0, 0.7); + z-index: 10; + + animation: ${slideUp} 0.5s ease-out forwards; + + @media (max-width: 375px) { + height: 80%; + } +`; +export const DetailContent = styled.div` + display: flex; + flex-direction: column; + width: 90%; + gap: 15px; + @media (max-width: 375px) { + margin-top: 1rem; + } +`; + +export const NameContainer = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + gap: 15px; + .BoothName { + color: #000; + text-align: center; + ${({ theme }) => theme.fonts.AppleSDGothicNeoB00}; + + font-size: 15px; + } +`; + +export const tagContainer = styled.div` + display: flex; + flex-direction: row; + + gap: 5px; + + .tag { + display: flex; + align-items: center; + justify-content: center; + width: 46px; + height: 16px; + border-radius: 5px; + padding: 7px; + text-align: center; + font-family: ${({ theme }) => + theme.fonts.AppleSDGothicNeoL00["font-family"]}; + font-size: 10px; + } + + .tag:nth-child(1) { + background-color: #d4eaff; + color: #00326d; + } + .tag:nth-child(2) { + background-color: #ffd5d5; + color: #f00; + } + .tag:nth-child(3) { + background-color: #ffd9a1; + color: #db4200; + } +`; +export const CloseBtn = styled.img` + cursor: pointer; + margin-left: auto; +`; +export const imgWrapper = styled.div` + display: flex; + position: relative; +`; +export const BoothDetailImage = styled.img` + width: 100%; + height: 240px; + object-fit: cover; +`; +export const imgCount = styled.div` + display: flex; + width: 27.463px; + height: 15.152px; + padding: 7px 10px; + justify-content: center; + align-items: center; + gap: 10px; + flex-shrink: 0; + border-radius: 30px; + background-color: #fff; + z-index: 2; + position: absolute; + right: 10px; + top: 10px; +`; +export const DetailInfo = styled.div` + display: flex; + flex-direction: column; +`; + +export const Details = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + gap: 10px; + .InfoContainer { + display: flex; + flex-direction: row; + gap: 20px; + } + .InfoWrapper { + display: flex; + flex-direction: column; + } +`; + +export const DetailTitle = styled.div` + display: flex; + justify-content: start; + align-items: center; + width: 20%; + font-family: ${({ theme }) => theme.fonts.AppleSDGothicNeoB00["font-family"]}; + font-size: 12px; +`; +export const DetailContext = styled.div` + display: flex; + background-color: ${(props) => (props.index === 5 ? "#ffe3e3" : "FFE1DA")}; + color: ${(props) => (props.index === 5 ? "#ED6308" : "000")}; + + border-radius: ${(props) => (props.index === 5 ? "5px" : "0")}; + padding: ${(props) => (props.index === 5 ? "0.2rem" : "0")}; + + font-family: ${({ theme }) => theme.fonts.AppleSDGothicNeoR00["font-family"]}; + font-size: 10px; +`; +export const Divider = styled.div` + display: flex; + width: 100%; + height: 1px; + margin-top: 6px; + background-color: #b6b6b6; +`; +export const tabling = styled.img` + display: flex; + width: 90%; + padding: 7px 59px 3px 68px; + justify-content: flex-end; + align-items: flex-start; + gap: 10px; + border-radius: 5.25px; + background: #e9ff99; + object-fit: cover; + margin-bottom: 10px; +`; diff --git a/src/components/performanceP/StarDetail/StarDetail.jsx b/src/components/performanceP/StarDetail/StarDeatil.jsx similarity index 96% rename from src/components/performanceP/StarDetail/StarDetail.jsx rename to src/components/performanceP/StarDetail/StarDeatil.jsx index 4740697..ad94e1f 100644 --- a/src/components/performanceP/StarDetail/StarDetail.jsx +++ b/src/components/performanceP/StarDetail/StarDeatil.jsx @@ -1,4 +1,4 @@ -import * as S from "./styled"; +import * as S from "../../common/BoothDetail/styled"; import CancelIcon from "../../../assets/images/X_Icon.svg"; import { StarDetailInfo, Detailtitle } from "../../../constant/StarDetail/data"; export const StarDetail = ({ onClose }) => { diff --git a/src/components/performanceP/StarDetail/styled.js b/src/components/performanceP/StarDetail/styled.js deleted file mode 100644 index 2ad553d..0000000 --- a/src/components/performanceP/StarDetail/styled.js +++ /dev/null @@ -1,108 +0,0 @@ -import styled, { keyframes } from "styled-components"; -const slideUp = keyframes` - 0% { - transform: translateY(100%); - - } - 100% { - transform: translateY(0); - } -`; -export const DetailWrapper = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - position: fixed; - bottom: 0; - width: 100%; - height: 68%; - background-color: #fff; - border-radius: 20px 20px 0px 0px; - box-shadow: 0px 2px 40px 0px rgba(0, 0, 0, 0.7); - z-index: 10; - padding-bottom: 0.5rem; - - animation: ${slideUp} 0.5s ease-out forwards; -`; -export const DetailContent = styled.div` - display: flex; - flex-direction: column; - width: 90%; - gap: 15px; -`; - -export const NameContainer = styled.div` - display: flex; - justify-content: space-between; - align-items: center; - - .StarName { - color: #000; - text-align: center; - ${({ theme }) => theme.fonts.AppleSDGothicNeoB00}; - - font-size: 15px; - } -`; - -export const CloseBtn = styled.img` - cursor: pointer; -`; -export const StarDetailImage = styled.img` - width: 100%; - height: 240px; - object-fit: cover; -`; - -export const DetailInfo = styled.div` - display: flex; - flex-direction: column; -`; - -export const Details = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - gap: 10px; - .InfoContainer { - display: flex; - flex-direction: row; - gap: 20px; - } - .InfoWrapper { - display: flex; - flex-direction: column; - } -`; - -export const DetailTitle = styled.div` - display: flex; - justify-content: start; - align-items: center; - width: 20%; - font-family: ${({ theme }) => theme.fonts.AppleSDGothicNeoB00["font-family"]}; - font-size: 12px; -`; -export const DetailContext = styled.div` - display: flex; - background-color: ${(props) => - props.index === 2 ? "#ffe3e3" : props.index === 3 ? "#FFEADA" : "FFE1DA"}; - color: ${(props) => - props.index === 2 ? "#ED6308" : props.index === 3 ? "#ED3F08" : "000"}; - - border-radius: ${(props) => - props.index === 2 || props.index === 3 ? "5px" : "0"}; - padding: ${(props) => - props.index === 2 || props.index === 3 ? "0.2rem" : "0"}; - - font-family: ${({ theme }) => theme.fonts.AppleSDGothicNeoR00["font-family"]}; - font-size: 10px; -`; -export const Divider = styled.div` - display: flex; - width: 100%; - height: 1px; - margin-top: 6px; - background-color: #b6b6b6; -`; diff --git a/src/constant/StarDetail/data.js b/src/constant/StarDetail/data.js index 5898a2f..c197a80 100644 --- a/src/constant/StarDetail/data.js +++ b/src/constant/StarDetail/data.js @@ -1,15 +1,30 @@ -const StarDetailInfo = [ +const Detailtitle = [ + "한줄소개", + "운영주체", + "운영시간", + "입장료", + "대표메뉴", + "인스타", +]; + +const BoothDetailData = [ { - id: 1, - star: "에스파", - starImg: + booth_id: 1, + booth_name: "치즈네컷", + is_night: false, + location: "팔정도", + category: "부스", + img_total_count: "4", + src: [ "https://cdn2.smentertainment.com/wp-content/uploads/2024/08/%EC%97%90%EC%8A%A4%ED%8C%8C-%EC%B2%AB-%EC%A0%95%EA%B7%9C-Armageddon-%EC%9D%B4%EB%AF%B8%EC%A7%80.jpg", - description: "안녕하세요! 4세대 대표 아이돌 에스파입니다!", - song: "supernova", + "https://i.namu.wiki/i/8IHblumlMpEi-m7qx5W95uJ1wotTls8j_UcFe2eWqhU9r_8bENxsmZX5jK8JddOptXUGaY0FVyNF-CHqw0XM8Q.webp", + ], + description: "냉동 치즈 녹이기", + operation: "전효준", + time: "15:00-17:00", + fee: "1.5", + menu: "오뎅탕", insta: "@gj1111", - youtube: "youtube link", }, ]; - -const Detailtitle = ["한줄소개", "대표곡", "인스타그램", "유튜브"]; -export { StarDetailInfo, Detailtitle }; +export { Detailtitle, BoothDetailData }; diff --git a/src/hook/useBooth.js b/src/hook/useBooth.js index c81678c..3ca25e5 100644 --- a/src/hook/useBooth.js +++ b/src/hook/useBooth.js @@ -1,11 +1,15 @@ // src/hooks/useMain.js import { useState, useEffect } from "react"; import { getBoothList } from "../apis/booth"; -import { useParams } from "react-router-dom"; -export const useBoothData = () => { +export const useBoothData = ({ + day, + category, + location, + is_night, + is_reservable, +}) => { const [boothData, setBoothData] = useState(null); - const { day, category, location, is_night, is_reservable } = useParams(); const fetchBoothData = async () => { try { const res = await getBoothList( @@ -26,7 +30,7 @@ export const useBoothData = () => { useEffect(() => { fetchBoothData(); - }, []); + }, [day, category, location, is_night, is_reservable]); return { boothData }; }; diff --git a/src/hook/useBoothDetail.js b/src/hook/useBoothDetail.js index c75305c..81a72d6 100644 --- a/src/hook/useBoothDetail.js +++ b/src/hook/useBoothDetail.js @@ -1,11 +1,9 @@ // src/hooks/useMain.js import { useState, useEffect } from "react"; import { getBoothDetail } from "../apis/boothDetail"; -import { useParams } from "react-router-dom"; -export const useBoothDetailData = () => { +export const useBoothDetailData = (booth_id) => { const [boothDetailData, setBoothDetailData] = useState(null); - const { booth_id } = useParams(); const fetchBoothDetailData = async () => { try { const res = await getBoothDetail(booth_id); @@ -19,8 +17,10 @@ export const useBoothDetailData = () => { }; useEffect(() => { - fetchBoothDetailData(); - }, []); + if (booth_id) { + fetchBoothDetailData(); + } + }, [booth_id]); return { boothDetailData }; }; diff --git a/src/pages/about/AboutPage.jsx b/src/pages/about/AboutPage.jsx index e84190f..7eee1a2 100644 --- a/src/pages/about/AboutPage.jsx +++ b/src/pages/about/AboutPage.jsx @@ -1,7 +1,7 @@ import * as S from "./AboutPage.styled"; -import { AboutCard } from "@components/about/AboutCard/AboutCard" -import { LikeLionLink } from "@components/about/LikeLionLink/LikeLionLink" -import { Review } from "@components/about/Review/Review" +import { AboutCard } from "@components/about/AboutCard/AboutCard"; +import { LikeLionLink } from "@components/about/LikeLionLink/LikeLionLink"; +import { Review } from "@components/about/Review/Review"; export const AboutPage = () => { return ( diff --git a/src/pages/booth/BoothPage.jsx b/src/pages/booth/BoothPage.jsx index cf1056d..6b3cdcd 100644 --- a/src/pages/booth/BoothPage.jsx +++ b/src/pages/booth/BoothPage.jsx @@ -10,25 +10,43 @@ import nonselect_GI from "../../assets/images/nonselect_GI.png"; import nonselect_JU from "../../assets/images/nonselect_JU.png"; import select_GI from "../../assets/images/select_GI.png"; import select_JU from "../../assets/images/select_JU.png"; - +import { BoothDetail } from "@components/common/BoothDetail/BoothDetail"; export const BoothPage = () => { // 모달 상태 추가 const [isModalOpen, setIsModalOpen] = useState(false); const openModal = () => setIsModalOpen(true); const closeModal = () => setIsModalOpen(false); + // 초기 날짜 선택 용 + const getDayFromDate = (dateString) => { + const dayPart = dateString.split("(")[1]; // 요일 부분 추출 + return dayPart ? dayPart.replace(")", "") : ""; // ")" 기호 제거 후 반환 + }; + + const translateDayToEnglish = (day) => { + const dayMap = { + 월: "Mon", + 화: "Tue", + }; + return dayMap[day] || ""; // 해당 요일의 영어 이름 반환 + }; - const { boothData } = useBoothData(); + const [selectedDate, setSelectedDate] = useState("10/7(월)"); + const dayInKorean = getDayFromDate(selectedDate); // "월" 추출 + const dayInEnglish = translateDayToEnglish(dayInKorean); // "Mon"으로 변환 - // 초기 날짜 선택 용 - const [selectedDate, setSelectedDate] = useState('10/7(월)'); + //목록리스트 API + const { boothData } = useBoothData({ + day: dayInEnglish, + }); + console.log("boothpage:", boothData); // 부스 리스트를 띄울 지 말지 const [isBoothListOpen, setIsBoothListOpen] = useState(true); // 부스 필터링 용 - const [selectedTime, setSelectedTime] = useState('시간'); - const [selectedType, setSelectedType] = useState('유형'); - const [selectedLocation, setSelectedLocation] = useState('위치'); + const [selectedTime, setSelectedTime] = useState("시간"); + const [selectedType, setSelectedType] = useState("유형"); + const [selectedLocation, setSelectedLocation] = useState("위치"); const [isDropdownOpen, setIsDropdownOpen] = useState({ time: false, type: false, @@ -42,7 +60,6 @@ export const BoothPage = () => { const [highlightedBooth, setHighlightedBooth] = useState(null); const boothRefs = useRef({}); - // 마킹 용 배열 const mapRef = useRef(null); const markersRef = useRef([]); @@ -57,29 +74,29 @@ export const BoothPage = () => { }; const handleSelect = (type, value) => { - if (type === 'time') setSelectedTime(value); - if (type === 'type') setSelectedType(value); - if (type === 'location') setSelectedLocation(value); + if (type === "time") setSelectedTime(value); + if (type === "type") setSelectedType(value); + if (type === "location") setSelectedLocation(value); setIsDropdownOpen((prevState) => ({ ...prevState, - [type]: prevState[type], // 선택 후 필터를 닫는 겁니다아 + [type]: prevState[type], // 선택 후 필터를 닫는 겁니다아 })); }; const resetFilters = (e) => { - setSelectedTime('시간'); - setSelectedType('유형'); - setSelectedLocation('위치'); + setSelectedTime("시간"); + setSelectedType("유형"); + setSelectedLocation("위치"); const button = e.currentTarget; - button.style.transform = 'rotate(0deg)'; - button.style.transition = 'none'; - + button.style.transform = "rotate(0deg)"; + button.style.transition = "none"; + setTimeout(() => { - button.style.transition = 'transform 1s ease'; - button.style.transform = 'rotate(-360deg)'; + button.style.transition = "transform 1s ease"; + button.style.transform = "rotate(-360deg)"; }, 10); }; @@ -87,7 +104,7 @@ export const BoothPage = () => { const handleBoothLocation = (boothId) => { const booth = BoothData.find((booth) => booth.id === boothId); setHighlightedBooth(booth); - } + }; // 날짜 선택 용 const handleDateChange = (date) => { @@ -106,9 +123,13 @@ export const BoothPage = () => { }; const filteredBooths = BoothData.filter((booth) => { - const timeMatch = selectedTime === '시간' || booth.filters.time === selectedTime; - const typeMatch = selectedType === '유형' || booth.filters.type === selectedType; - const locationMatch = selectedLocation === '위치' || booth.filters.location === selectedLocation; + const timeMatch = + selectedTime === "시간" || booth.filters.time === selectedTime; + const typeMatch = + selectedType === "유형" || booth.filters.type === selectedType; + const locationMatch = + selectedLocation === "위치" || + booth.filters.location === selectedLocation; // 모든 필터 조건을 만족하는 부스만 반환 return timeMatch && typeMatch && locationMatch; @@ -116,21 +137,25 @@ export const BoothPage = () => { // 부스 유형에 따른 초기 마커 이미지 설정 함수 const getInitialMarkerImage = (booth) => { - let markerImage = booth.filters.type === '주점' ? nonselect_JU : nonselect_GI; + let markerImage = + booth.filters.type === "주점" ? nonselect_JU : nonselect_GI; - return new window.kakao.maps.MarkerImage(markerImage, new window.kakao.maps.Size(30, 36)); + return new window.kakao.maps.MarkerImage( + markerImage, + new window.kakao.maps.Size(30, 36) + ); }; // 카카오맵 마커 생성 useEffect(() => { - const script = document.createElement('script'); + const script = document.createElement("script"); script.src = `https://dapi.kakao.com/v2/maps/sdk.js?appkey=972351b156b1bdfe825cb095c12d1e56&autoload=false`; script.async = true; document.head.appendChild(script); script.onload = () => { window.kakao.maps.load(() => { - const container = document.getElementById('map'); + const container = document.getElementById("map"); const options = { center: new window.kakao.maps.LatLng(37.5567, 127.0003), level: 3, @@ -139,7 +164,10 @@ export const BoothPage = () => { // 초기 마커 생성 filteredBooths.forEach((booth) => { - const markerPosition = new window.kakao.maps.LatLng(booth.latitude, booth.longitude); + const markerPosition = new window.kakao.maps.LatLng( + booth.latitude, + booth.longitude + ); const markerImage = getInitialMarkerImage(booth); // 유형에 따라 초기 마커 이미지 설정 const marker = new window.kakao.maps.Marker({ position: markerPosition, @@ -148,7 +176,7 @@ export const BoothPage = () => { }); // 마커 클릭 이벤트 설정 - window.kakao.maps.event.addListener(marker, 'click', () => { + window.kakao.maps.event.addListener(marker, "click", () => { handleBoothLocation(booth.id); // 부스 선택 }); @@ -163,13 +191,12 @@ export const BoothPage = () => { }; }, []); - // 선택된 부스에 따라 마커 이미지 변경 useEffect(() => { // 선택된 부스가 없으면 모든 마커를 초기화 if (!highlightedBooth) { markersRef.current.forEach(({ marker, boothId }) => { - const booth = BoothData.find(b => b.id === boothId); // 해당 부스 데이터 찾기 + const booth = BoothData.find((b) => b.id === boothId); // 해당 부스 데이터 찾기 if (booth) { // 초기 마커 이미지로 변경 const initialImage = getInitialMarkerImage(booth); @@ -181,28 +208,35 @@ export const BoothPage = () => { if (highlightedBooth && mapRef.current) { // 선택된 부스의 위치 좌표로 맵의 중심 이동 - const newCenter = new window.kakao.maps.LatLng(highlightedBooth.latitude, highlightedBooth.longitude); + const newCenter = new window.kakao.maps.LatLng( + highlightedBooth.latitude, + highlightedBooth.longitude + ); mapRef.current.panTo(newCenter); } - + // 선택된 부스가 있을 경우, 해당 마커만 업데이트 markersRef.current.forEach(({ boothId, marker }) => { const isHighlighted = highlightedBooth && highlightedBooth.id === boothId; - + // 선택된 부스의 마커를 변경 if (isHighlighted) { let markerImage; - if (highlightedBooth.filters.type === '주점') { + if (highlightedBooth.filters.type === "주점") { markerImage = select_JU; // 선택된 주점일 경우 - } else if (highlightedBooth.filters.type === '기타') { + } else if (highlightedBooth.filters.type === "기타") { markerImage = select_GI; // 선택된 기타일 경우 } else { - } - marker.setImage(new window.kakao.maps.MarkerImage(markerImage, new window.kakao.maps.Size(32, 40))); + marker.setImage( + new window.kakao.maps.MarkerImage( + markerImage, + new window.kakao.maps.Size(32, 40) + ) + ); } else { // 선택되지 않은 부스는 초기 이미지로 유지 - const booth = BoothData.find(b => b.id === boothId); // 해당 부스 데이터 찾기 + const booth = BoothData.find((b) => b.id === boothId); // 해당 부스 데이터 찾기 if (booth) { const initialImage = getInitialMarkerImage(booth); marker.setImage(initialImage); @@ -213,7 +247,10 @@ export const BoothPage = () => { useEffect(() => { if (highlightedBooth && boothRefs.current[highlightedBooth.id]) { - boothRefs.current[highlightedBooth.id].scrollIntoView({ behavior: 'smooth', block: 'start' }); + boothRefs.current[highlightedBooth.id].scrollIntoView({ + behavior: "smooth", + block: "start", + }); } }, [highlightedBooth]); @@ -227,37 +264,43 @@ export const BoothPage = () => { mapRef.current.relayout(); setTimeout(() => { - window.kakao.maps.event.trigger(mapRef.current, 'resize'); + window.kakao.maps.event.trigger(mapRef.current, "resize"); if (highlightedBooth) { - const newCenter = new window.kakao.maps.LatLng(highlightedBooth.latitude, highlightedBooth.longitude); + const newCenter = new window.kakao.maps.LatLng( + highlightedBooth.latitude, + highlightedBooth.longitude + ); mapRef.current.panTo(newCenter); } }, 200); } } }, [isBoothListOpen, selectBooth, highlightedBooth]); - return ( <> {/* 상단 날짜 선택 버튼 */} - + {/* 카카오맵 자리 */} - + handleDateChange('10/7(월)')} + $active={selectedDate === "10/7(월)"} + onClick={() => handleDateChange("10/7(월)")} > 10/7(월) handleDateChange('10/8(화)')} + $active={selectedDate === "10/8(화)"} + onClick={() => handleDateChange("10/8(화)")} > 10/8(화) @@ -265,49 +308,104 @@ export const BoothPage = () => { - {/* 부스 리스트 */} - {isBoothListOpen ? : } + + {isBoothListOpen ? : } + {/* 필터 섹션 (부스 리스트 안에) */} - toggleDropdown('time')}> + toggleDropdown("time")} + > {selectedTime} - + + + {isDropdownOpen.time && ( - handleSelect('time', '시간')}>전체 - handleSelect('time', '낮')}>낮 - handleSelect('time', '밤')}>밤 + handleSelect("time", "시간")} + > + 전체 + + handleSelect("time", "낮")}> + 낮 + + handleSelect("time", "밤")}> + 밤 + )} - toggleDropdown('type')}> + toggleDropdown("type")} + > {selectedType} - + + + {isDropdownOpen.type && ( - handleSelect('type', '유형')}>전체 - handleSelect('type', '푸드트럭')}>푸드트럭 - handleSelect('type', '주점')}>주점 - handleSelect('type', '기타')}>기타 + handleSelect("type", "유형")} + > + 전체 + + handleSelect("type", "푸드트럭")} + > + 푸드트럭 + + handleSelect("type", "주점")} + > + 주점 + + handleSelect("type", "기타")} + > + 기타 + )} - toggleDropdown('location')}> + toggleDropdown("location")} + > {selectedLocation} - + + + {isDropdownOpen.location && ( - handleSelect('location', '위치')}>전체 - handleSelect('location', '팔정도')}>팔정도 - handleSelect('location', '만해광장')}>만해광장 + handleSelect("location", "위치")} + > + 전체 + + handleSelect("location", "팔정도")} + > + 팔정도 + + handleSelect("location", "만해광장")} + > + 만해광장 + )} @@ -319,13 +417,17 @@ export const BoothPage = () => { {/* 부스 리스트 */} - 부스 클릭 시 테이블링 예약 링크로 이동 가능합니다. + + 부스 클릭 시 테이블링 예약 링크로 이동 가능합니다. + {filteredBooths.length > 0 ? ( filteredBooths.map((booth) => ( boothRefs.current[booth.id] = el} // 각 부스에 ref 추가 - $isColored={highlightedBooth && highlightedBooth.id === booth.id} + ref={(el) => (boothRefs.current[booth.id] = el)} // 각 부스에 ref 추가 + $isColored={ + highlightedBooth && highlightedBooth.id === booth.id + } onClick={() => handleSelectBooth(booth)} > {/* 나중에 좋아요순으로 수정 */} @@ -336,94 +438,29 @@ export const BoothPage = () => { {booth.owner} - { - e.stopPropagation(); - handleBoothLocation(booth.id) - }}> + { + e.stopPropagation(); + handleBoothLocation(booth.id); + }} + > 위치 보기 )) ) : ( - - 현재 운영중인 부스가 없어요! - + 현재 운영중인 부스가 없어요! )} {/* 선택한 부스 디테일 */} {selectBooth && ( - <> - {/* setSelectBooth(null)} /> */} - - - setSelectBooth(null)}>X - - - {selectBooth.boothName} - - {selectBooth.filters.time}부스 - {selectBooth.filters.type} - {selectBooth.filters.location} - - - - - - - {selectBooth.description && ( - - 한줄소개 - {selectBooth.description} - - )} - {selectBooth.owner && ( - - 운영주체 - {selectBooth.owner} - - )} - {selectBooth.operationTime && ( - - 운영시간 - {selectBooth.operationTime} - - )} - - {selectBooth.entranceFee && ( - - 입장료 - {selectBooth.entranceFee} - - )} - {selectBooth.menu && ( - - 대표메뉴 - {selectBooth.menu} - - )} - - {selectBooth.instagram && ( - - 인스타 - {selectBooth.instagram} - - )} - {selectBooth.filters.type === "주점" && ( - - 테이블링 예약하기 - - - )} - - - - + setSelectBooth(null)} + /> )} {isModalOpen && } diff --git a/src/router.jsx b/src/router.jsx index 54d625a..ea6e8d4 100644 --- a/src/router.jsx +++ b/src/router.jsx @@ -15,10 +15,6 @@ export const router = createBrowserRouter([ element: , }, //부스페이지 - { - path: "/:booth_id/:day/:category/:location/:is_night/:is_reservable", - element: , - }, { path: "/booth-test", element: ,