Skip to content
Snippets Groups Projects
Commit c936b541 authored by pjookim's avatar pjookim
Browse files

fix: error in map add place

parent cfcea534
Branches
No related tags found
No related merge requests found
......@@ -76,7 +76,8 @@ const MapSearch = ({ map, onSearchResult, clearMap, setMarkers, trips }) => {
const newPlace = {
id: place.id,
name: place.name,
location: place.address,
address: place.address,
type: 77,
coordinates: place.coordinates,
tel: place.phone
};
......
......@@ -3,6 +3,7 @@ import axios from 'axios';
import { FaMapMarkerAlt, FaPhoneAlt, FaCalendarAlt, FaClock, FaParking, FaMoneyBillWave } from 'react-icons/fa'; // 필요한 아이콘 가져오기
import '../styles/PlaceDetails.css';
import PlaceReview from './PlaceReview';
import ShimmerImage from './ShimmerImage';
const PlaceDetails = ({ place, onClose }) => {
const [placeDetails, setPlaceDetails] = useState(null);
......@@ -56,6 +57,19 @@ const PlaceDetails = ({ place, onClose }) => {
};
}, [onClose]);
// HTML 문자열을 안전하게 렌더링하는 함수
const renderHTML = (htmlString) => {
if (!htmlString) return null;
// <br> 태그를 줄바꿈으로 변환
return htmlString.split('<br>').map((text, index, array) => (
<React.Fragment key={index}>
{text}
{index < array.length - 1 && <br />}
</React.Fragment>
));
};
if (loading) {
return <p>로딩 ...</p>;
}
......@@ -68,7 +82,7 @@ const PlaceDetails = ({ place, onClose }) => {
<div className="place-detail" ref={detailsRef}>
<h2>{place.name}</h2>
{place.image && (
<img
<ShimmerImage
src={place.image}
alt={place.name}
className="detail-image"
......@@ -76,40 +90,68 @@ const PlaceDetails = ({ place, onClose }) => {
)}
<div className="detail-info">
<p className="location">
<FaMapMarkerAlt className="icon" /> <strong>주소:</strong> {place.address}
<FaMapMarkerAlt className="icon" />
<strong>주소:</strong>
<span>{renderHTML(place.location || place.address)}</span>
</p>
{place.tel && (
<p className="tel">
<FaPhoneAlt className="icon" /> <strong>전화:</strong> {place.tel}
<FaPhoneAlt className="icon" />
<strong>전화:</strong>
<span>{renderHTML(place.tel)}</span>
</p>
)}
{/* 관광지일 경우 - 문자열 대신 숫자로 비교 */}
{/* 관광지일 경우 */}
{(place.type === 12 || place.type === '12') && (
<>
{placeDetails.restdate && (
<p><FaCalendarAlt className="icon" /> <strong>쉬는날:</strong> {placeDetails.restdate}</p>
<p>
<FaCalendarAlt className="icon" />
<strong>쉬는날:</strong>
<span>{renderHTML(placeDetails.restdate)}</span>
</p>
)}
{placeDetails.usetime && (
<p><FaClock className="icon" /> <strong>이용시간:</strong> {placeDetails.usetime}</p>
<p>
<FaClock className="icon" />
<strong>이용시간:</strong>
<span>{renderHTML(placeDetails.usetime)}</span>
</p>
)}
{placeDetails.parking && (
<p><FaParking className="icon" /> <strong>주차장:</strong> {placeDetails.parking}</p>
<p>
<FaParking className="icon" />
<strong>주차장:</strong>
<span>{renderHTML(placeDetails.parking)}</span>
</p>
)}
</>
)}
{/* 지역 축제일 경우 - 문자열 대신 숫자로 비교 */}
{/* 지역 축제일 경우 */}
{(place.type === 15 || place.type === '15') && (
<>
{placeDetails.eventstartdate && placeDetails.eventenddate && (
<p><FaCalendarAlt className="icon" /> <strong>기간:</strong> {`${placeDetails.eventstartdate} ~ ${placeDetails.eventenddate}`}</p>
<p>
<FaCalendarAlt className="icon" />
<strong>기간:</strong>
<span>{`${placeDetails.eventstartdate} ~ ${placeDetails.eventenddate}`}</span>
</p>
)}
{placeDetails.sponsor1 && (
<p><FaPhoneAlt className="icon" /> <strong>주최자:</strong> {placeDetails.sponsor1}</p>
<p>
<FaPhoneAlt className="icon" />
<strong>주최자:</strong>
<span>{renderHTML(placeDetails.sponsor1)}</span>
</p>
)}
{placeDetails.usetimefestival && (
<p><FaMoneyBillWave className="icon" /> <strong>이용 요금:</strong> {placeDetails.usetimefestival}</p>
<p>
<FaMoneyBillWave className="icon" />
<strong>이용 요금:</strong>
<span>{renderHTML(placeDetails.usetimefestival)}</span>
</p>
)}
</>
)}
......
import React, { useState } from 'react';
import '../styles/ShimmerImage.css';
const ShimmerImage = ({ src, alt, className }) => {
const [isLoaded, setIsLoaded] = useState(false);
const handleImageLoad = () => {
setIsLoaded(true);
};
return (
<div className="shimmer-wrapper">
{!isLoaded && <div className="shimmer" />}
<img
src={src}
alt={alt}
className={`shimmer-image ${isLoaded ? 'loaded' : ''} ${className || ''}`}
onLoad={handleImageLoad}
/>
</div>
);
};
export default ShimmerImage;
\ No newline at end of file
......@@ -2,6 +2,7 @@
font-weight: bold;
font-size: 1.25rem;
margin-bottom: 1rem;
word-break: keep-all;
}
.detail-image {
......@@ -12,17 +13,33 @@
.detail-info {
margin-top: 20px;
width: 100%;
}
.detail-info p {
display: flex;
align-items: center;
align-items: flex-start;
font-size: 16px;
margin-bottom: 10px;
line-height: 1.5;
word-break: keep-all;
}
.icon {
margin-right: 8px;
min-width: 16px;
margin-top: 4px;
color: var(--primary-color);
}
.detail-info p strong {
margin-right: 8px;
white-space: nowrap;
}
.detail-info p span {
flex: 1;
word-break: break-all;
}
.location,
......@@ -35,12 +52,20 @@
.sponsor1,
.usetimefestival {
font-size: 16px;
}
.icon {
color: var(--primary-color);
width: 100%;
}
h2 {
font-size: 24px;
}
@media screen and (max-width: 480px) {
.detail-info p {
flex-wrap: wrap;
gap: 4px;
}
.detail-info p strong {
min-width: 60px;
}
}
\ No newline at end of file
.place-reviews {
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid #eee;
}
.place-reviews .title {
font-size: 1.2rem;
font-weight: bold;
margin-bottom: 24px;
}
.review-form {
background: #f8f9fa;
padding: 1rem;
......@@ -85,7 +97,7 @@
}
.reviews-list {
margin-top: 25px;
margin-top: 30px;
}
.review-item {
......
.shimmer-wrapper {
position: relative;
width: 100%;
height: auto;
background: #f6f7f8;
overflow: hidden;
}
.shimmer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.2) 50%,
rgba(255, 255, 255, 0) 100%
);
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
.shimmer-image {
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
.shimmer-image.loaded {
opacity: 1;
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment