Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#75 동반가능시설 API 연동 #78

Merged
merged 11 commits into from
Dec 11, 2024
18 changes: 16 additions & 2 deletions src/app/place/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,22 @@ const PlacePage = () => {
}

const handleImageClick = () => {
router.push(`/place/placesearch`);
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude } = position.coords;
router.push(`/place/placesearch?lat=${latitude}&lng=${longitude}`);
},
() => {
alert("현재 위치를 가져올 수 없습니다.");
router.push(`/place/placesearch`);
}
);
} else {
alert("Geolocation을 지원하지 않는 브라우저입니다.");
router.push(`/place/placesearch`);
}
};

const handleImageClick2 = () => {
router.push(`/recommend`);
Expand Down
45 changes: 34 additions & 11 deletions src/app/place/placedetail/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const PlaceDetailPage = () => {

const ActualPlaceDetailPage = () => {
const searchParams = useSearchParams();
const id = parseInt(searchParams.get("id"), 10);
const placeId = parseInt(searchParams.get("placeId"), 10);
const router = useRouter();
const [isClient, setIsClient] = useState(false);
const [isMapBottomSheetOpen, setIsMapBottomSheetOpen] = useState(false);
Expand All @@ -36,7 +36,8 @@ const ActualPlaceDetailPage = () => {
const [isUploadAction, setIsUploadAction] = useState(false);
const fileInputRef = useRef(null);
const { setPlaceName, setVisitDate, setCategory } = useReviewStore();
const selectedCard = cards.find((card) => card.id === id);
const [selectedCard, setSelectedCard] = useState(null);
const [isLoading, setIsLoading] = useState(true);

const { isLoaded } = useJsApiLoader({
googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY,
Expand All @@ -54,21 +55,37 @@ const ActualPlaceDetailPage = () => {
if (data.status === "OK" && data.results.length > 0) {
const { lat, lng } = data.results[0].geometry.location;
setCenter({ lat, lng });
} else {
alert("주소에 대한 좌표를 가져올 수 없습니다.");
}
} catch (error) {
console.error("Error fetching coordinates:", error);
}
};

useEffect(() => {
if (placeId) {
fetchPlaceDetails(placeId);
}
}, [placeId]);
const fetchPlaceDetails = async (placeId) => {
try {
const response = await axios.get(`https://api.daengplace.com/places/${placeId}`);
console.log(response.data);
setSelectedCard(response.data.data);
} catch (error) {
console.error("Error fetching place details:", error);
setSelectedCard(null);
} finally {
setIsLoading(false);
}
};

useEffect(() => {
if (selectedCard) {
setPlaceName(selectedCard.title);
setPlaceName(selectedCard.name);
setCategory(selectedCard.category);
setIsClient(true);
setAddress(selectedCard.address);
fetchCoordinates(selectedCard.address);
setAddress(selectedCard.location);
fetchCoordinates(selectedCard.location);
}
}, [selectedCard]);

Expand Down Expand Up @@ -168,12 +185,18 @@ const ActualPlaceDetailPage = () => {
<PlaceInfo
isLiked={isLiked}
toggleLike={toggleLike}
address={selectedCard.address}
address={selectedCard.location}
handleAddressClick={handleAddressClick}
category={selectedCard.category}
placeName={selectedCard.title}
openingHours={selectedCard.hours}
features={selectedCard.features}
placeName={selectedCard.name}
openhours={selectedCard.operationHour}
features={{
inside: selectedCard.inside,
outside: selectedCard.outside,
isParking: selectedCard.is_parking,
petFee: selectedCard.pet_fee,
weightLimit: selectedCard.weight_limit,
}}
/>
<ReviewSection />
<WriteReviewButton onClick={handleWriteReviewButtonClick} />
Expand Down
211 changes: 197 additions & 14 deletions src/app/place/placemap/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import styled from "styled-components";
import { useRouter, useSearchParams } from "next/navigation";
import { useJsApiLoader } from "@react-google-maps/api";
import { sidoOptions, gunguOptions } from "@/data/data";
import axios from "axios";
import SearchBar from "@/components/place/placemap/SearchBar/SearchBar";
import Tabs from "@/components/place/placemap/Tabs/Tabs";
import FilterButtons from "@/components/place/placemap/FilterButtons/FilterButtons";
Expand All @@ -29,8 +30,8 @@ const ActualPlaceMap = () => {
const lat = parseFloat(searchParams.get("lat"));
const lng = parseFloat(searchParams.get("lng"));

const [center, setCenter] = useState({ lat: 37.5665, lng: 126.978 });
const [zoom, setZoom] = useState(14);
const [center, setCenter] = useState({lat: 37.5665, lng: 126.9780});
const [zoom, setZoom] = useState(20);
const [userLocation, setUserLocation] = useState(null);
const [selectedCategory, setSelectedCategory] = useState("전체");
const [hoveredCategory, setHoveredCategory] = useState(null);
Expand All @@ -40,19 +41,108 @@ const ActualPlaceMap = () => {
const [selectedSido, setSelectedSido] = useState("");
const [selectedGungu, setSelectedGungu] = useState("");
const [showGunguDropdown, setShowGunguDropdown] = useState(false);
const [allMarkers, setAllMarkers] = useState([]);
const [markers, setMarkers] = useState([]);

const { isLoaded } = useJsApiLoader({
googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY,
});

useEffect(() => {
if (!isNaN(lat) && !isNaN(lng)) {
const searchname = searchParams.get("name");

if (searchname) {
fetchPlaces(null, null, searchname);
} else if (!isNaN(lat) && !isNaN(lng)) {
setCenter({ lat, lng });
setUserLocation({ lat, lng });
setZoom(14);
fetchPlaces(lat, lng);
}
}, [lat, lng, searchParams]);

useEffect(() => {
if (!userLocation) {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude } = position.coords;
setUserLocation({ lat: latitude, lng: longitude });
},
() => {
alert("현재 위치를 가져올 수 없습니다.");
}
);
}
}
}, [lat, lng]);
}, []);


useEffect(() => {
if (userLocation) {
setSelectedCategory("전체");
fetchPlaces(userLocation.lat, userLocation.lng);
}
}, [userLocation]);

const fetchPlaces = async (latitude, longitude, searchname = null) => {
try {
const params = {
page: 1,
size: 20,
};
if (latitude && longitude) {
params.latitude = latitude;
params.longitude = longitude;
}

if (searchname) {
params.search = searchname;
}

const response = await axios.get("https://api.daengplace.com/places", { params });
const places = response.data.data.places || [];
const fetchedMarkers = places.map((place) => ({
id: place.placeId,
position: { lat: place.latitude, lng: place.longitude },
name: place.name,
category: place.category,
is_parking: place.is_parking,
inside: place.inside,
outside: place.outside,
weight_limit: place.weight_limit,
pet_fee: place.pet_fee,
operationHour: place.operationHour,
}));
console.log("Fetched Markers:", fetchedMarkers);
setAllMarkers(fetchedMarkers);
setMarkers(fetchedMarkers);
if (searchname) {
const filteredMarkers = fetchedMarkers.filter((marker) =>
marker.name.includes(searchname)
);
console.log("Filtered Markers:", filteredMarkers);
setMarkers(filteredMarkers);
if (filteredMarkers.length > 0) {
const { lat, lng } = filteredMarkers[0].position;
if (!isNaN(lat) && !isNaN(lng)) {
setCenter({ lat, lng });
setZoom(16);
} else {
console.error("Invalid marker coordinates:", { lat, lng });
}
} else {
alert(`${searchname}에 대한 결과를 찾을 수 없습니다.`);
if (userLocation) {
setCenter(userLocation);
setZoom(14);
}
}
}
} catch (error) {
console.error("Error fetching places:", error);
}
};
const handleSidoChange = (event) => {
const value = event.target.value;
setSelectedSido(value);
Expand All @@ -63,12 +153,109 @@ const ActualPlaceMap = () => {
const handleGunguChange = (event) => setSelectedGungu(event.target.value);

const handleBackToList = () => {
router.push("/place/placesearch");
const searchname = searchParams.get("name");

if (searchname) {
if (userLocation) {
router.push(`/place/placesearch?lat=${userLocation.lat}&lng=${userLocation.lng}`);
} else {
alert("사용자 위치를 가져올 수 없습니다.");
}
} else {
if (!isNaN(lat) && !isNaN(lng)) {
router.push(`/place/placesearch?lat=${lat}&lng=${lng}`);
} else if (userLocation) {
router.push(`/place/placesearch?lat=${userLocation.lat}&lng=${userLocation.lng}`);
} else {
alert("지도 데이터를 불러올 수 없습니다.");
}
}
};


const categoryMapping = {
미용: "서비스",
반려동물용품: "서비스",
위탁관리: "서비스",
식당: "음식점",
카페: "음식점",
문예회관: "문화시설",
박물관: "문화시설",
미술관: "문화시설",
여행지: "문화시설",
동물병원: "의료시설",
동물약국: "의료시설",
};

const handleCategoryClick = (category) => {
setSelectedCategory(category);
setSelectedFilters([]);
const updatedFilters = [...selectedFilters];
filterMarkers(category, selectedFilters);
};

const handleFilterClick = (filter) => {
setSelectedFilters((prevFilters) => {
const updatedFilters = prevFilters.includes(filter)
? prevFilters.filter((f) => f !== filter)
: [...prevFilters, filter];
filterMarkers(selectedCategory, updatedFilters);
return updatedFilters;
});
};

const filterMarkers = (category, filters) => {
let filteredMarkers = allMarkers;

if (category !== "전체") {
filteredMarkers = filteredMarkers.filter((marker) => {
const mainCategory = categoryMapping[marker.category];
return mainCategory === category;
});
}

if (filters.length > 0) {
filters.forEach((filter) => {
if (filter === "주차 가능") {
filteredMarkers = filteredMarkers.filter((marker) => marker.is_parking);
} else if (filter === "실내공간") {
filteredMarkers = filteredMarkers.filter((marker) => marker.inside);
} else if (filter === "야외공간") {
filteredMarkers = filteredMarkers.filter((marker) => marker.outside);
} else if (filter === "무게 제한 없음") {
filteredMarkers = filteredMarkers.filter((marker) => marker.weight_limit === 0);
} else if (filter === "애견 동반 요금 없음") {
filteredMarkers = filteredMarkers.filter((marker) => marker.pet_fee === 0);
} else if (filter === "영업중") {
filteredMarkers = filteredMarkers.filter((marker) => {
const { todayOpen, todayClose } = marker.operationHour || {};
if (!todayOpen || !todayClose) return false;

const now = new Date();
const [openHour, openMinute] = todayOpen.split(":").map(Number);
const [closeHour, closeMinute] = todayClose.split(":").map(Number);

const openTime = new Date();
openTime.setHours(openHour, openMinute);

const closeTime = new Date();
closeTime.setHours(closeHour, closeMinute);

if (closeTime <= openTime) {
closeTime.setDate(closeTime.getDate() + 1);
}

return now >= openTime && now <= closeTime;
});
}
});
}

setMarkers(filteredMarkers);
console.log("Filtered Markers:", filteredMarkers);
console.log("All Markers:", allMarkers);
console.log("Selected Filters:", filters);
console.log("All Markers with Parking Info:", allMarkers.map((marker) => marker.pet_fee));

};

if (!isLoaded) {
Expand Down Expand Up @@ -98,17 +285,13 @@ const ActualPlaceMap = () => {
/>
<hr></hr>
<FilterButtons
filters={["주차 가능", "실내공간", "야외공간", "무게 제한 없음", "애견 동반 요금 없음"]}
filters={["주차 가능", "실내공간", "야외공간", "무게 제한 없음", "애견 동반 요금 없음", "영업중"]}
selectedFilters={selectedFilters}
onFilterClick={(filter) =>
setSelectedFilters((prev) =>
prev.includes(filter) ? prev.filter((f) => f !== filter) : [...prev, filter]
)
}
onFilterClick={handleFilterClick}
hoveredFilter={hoveredFilter}
setHoveredFilter={setHoveredFilter}
/>
<Map center={center} zoom={zoom} userLocation={userLocation} />
<Map center={center} zoom={zoom} markers={markers} userLocation={userLocation} />
<FloatingButton onClick={handleBackToList} />
<BottomSheet
isOpen={isBottomSheetOpen}
Expand Down
Loading