Skip to content

Commit 0231b99

Browse files
authored
[FE] QA를 dev에 반영한다. (#1068)
1 parent 95387fd commit 0231b99

File tree

11 files changed

+338
-188
lines changed

11 files changed

+338
-188
lines changed
Binary file not shown.

frontend/src/components/RoomCompare/CompareCard.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ interface Props {
1717
const CompareCard = ({ room, openOptionModal, openCategoryModal }: Props) => {
1818
return (
1919
<S.Container>
20-
<CompareCardItem height={7} label={'주소'} item={<S.Item>{room.address}</S.Item>} />
20+
<CompareCardItem
21+
height={7}
22+
label={'주소'}
23+
item={<S.Item>{room.address?.length ? room.address : EMPTY_INDICATOR}</S.Item>}
24+
/>
2125
<CompareCardItem label={'층수'} item={<S.Item>{room.floor ? `${room.floor}층` : EMPTY_INDICATOR}</S.Item>} />
2226
<CompareCardItem
2327
label={'보증금 / 월세'}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import styled from '@emotion/styled';
2+
import { useSearchParams } from 'react-router-dom';
3+
4+
import RoomCompareMap from '@/components/_common/Map/RoomCompareMap';
5+
import Marker from '@/components/_common/Marker/Marker';
6+
import CategoryDetailModal from '@/components/RoomCompare/CategoryDetailModal';
7+
import CompareCard from '@/components/RoomCompare/CompareCard';
8+
import OptionDetailModal from '@/components/RoomCompare/OptionDetailModal';
9+
import SkRoomCompare from '@/components/skeleton/RoomCompare/SkRoomCompare';
10+
import { OPTIONS } from '@/constants/options';
11+
import useGetCompareRoomsQuery from '@/hooks/query/useGetCompareRoomsQuery';
12+
import useModal from '@/hooks/useModal';
13+
import { OptionDetail } from '@/pages/RoomComparePage';
14+
import { flexCenter, flexRow } from '@/styles/common';
15+
import theme from '@/styles/theme';
16+
17+
const RoomCompareContent = () => {
18+
const [searchParams, setSearchParams] = useSearchParams();
19+
const { isModalOpen: isOptionModalOpen, openModal: openOptionModal, closeModal: closeOptionModal } = useModal();
20+
const { isModalOpen: isCategoryModalOpen, openModal: openCategoryModal, closeModal: closeCategoryModal } = useModal();
21+
22+
const roomId1 = Number(searchParams.get('roomId1'));
23+
const roomId2 = Number(searchParams.get('roomId2'));
24+
25+
const { data: rooms, isLoading } = useGetCompareRoomsQuery(roomId1, roomId2);
26+
27+
if (isLoading) return <SkRoomCompare />;
28+
29+
if (!rooms) throw new Error('데이터를 불러오는데 실패했습니다.');
30+
31+
const positions = rooms?.map(room => ({
32+
latitude: room?.latitude ?? null,
33+
longitude: room?.longitude ?? null,
34+
}));
35+
36+
const formattedOptionDetail = () => {
37+
const optionsState: OptionDetail[] = OPTIONS.map(option => ({
38+
optionId: option.id,
39+
optionName: option.displayName,
40+
hasOption: [false, false],
41+
}));
42+
43+
rooms?.forEach((room, index) => {
44+
room.options.forEach(optionId => {
45+
const targetOption = optionsState.find(option => option.optionId === optionId)!;
46+
targetOption.hasOption[index] = true;
47+
});
48+
});
49+
return optionsState;
50+
};
51+
52+
const handleOpenCategoryDetailModal = (roomId: number, categoryId: number) => {
53+
openCategoryModal();
54+
searchParams.append('targetRoomId', String(roomId));
55+
searchParams.append('categoryId', String(categoryId));
56+
setSearchParams(searchParams);
57+
};
58+
59+
const handleCloseategoryDetailModal = () => {
60+
closeCategoryModal();
61+
searchParams.delete('targetRoomId');
62+
searchParams.delete('categoryId');
63+
setSearchParams(searchParams);
64+
};
65+
66+
return (
67+
<>
68+
<S.RoomGrid>
69+
<S.TitleFlex>
70+
<S.RoomTitle>
71+
<S.Title key={rooms[0].checklistId}>{rooms[0].roomName}</S.Title>
72+
<Marker isCircle={true} size={'medium'} backgroundColor={theme.palette.yellow500} text={'A'} />
73+
</S.RoomTitle>
74+
<S.RoomTitle>
75+
<S.Title key={rooms[1].checklistId}>{rooms[1].roomName}</S.Title>
76+
<Marker isCircle={true} size={'medium'} backgroundColor={theme.palette.green500} text={'B'} />
77+
</S.RoomTitle>
78+
</S.TitleFlex>
79+
</S.RoomGrid>
80+
{positions && <RoomCompareMap positions={positions} />}
81+
<S.RoomGrid>
82+
{rooms?.map((room, index) => (
83+
<CompareCard
84+
key={room.checklistId}
85+
room={room}
86+
index={index}
87+
openOptionModal={openOptionModal}
88+
openCategoryModal={handleOpenCategoryDetailModal}
89+
/>
90+
))}
91+
</S.RoomGrid>
92+
{/*방 옵션 비교 모달*/}
93+
{isOptionModalOpen && (
94+
<OptionDetailModal
95+
optionCounts={[rooms[0].options.length, rooms[1].options.length]}
96+
hasOptions={formattedOptionDetail()}
97+
roomTitle1={rooms[0].roomName ?? ''}
98+
roomTitle2={rooms[1].roomName ?? ''}
99+
isOpen={isOptionModalOpen}
100+
closeModal={closeOptionModal}
101+
/>
102+
)}
103+
{/*방 카테고리 디테일 모달*/}
104+
{isCategoryModalOpen && (
105+
<CategoryDetailModal isOpen={isCategoryModalOpen} closeModal={handleCloseategoryDetailModal} />
106+
)}
107+
</>
108+
);
109+
};
110+
111+
export default RoomCompareContent;
112+
113+
const S = {
114+
RoomGrid: styled.div`
115+
${flexRow}
116+
`,
117+
TitleFlex: styled.div`
118+
display: flex;
119+
width: 100vw;
120+
`,
121+
RoomTitle: styled.div`
122+
width: 50%;
123+
margin-bottom: 0.5rem;
124+
${flexCenter}
125+
gap:0.8rem;
126+
`,
127+
Title: styled.span`
128+
display: inline;
129+
width: calc(100% - 3rem);
130+
padding: 0.8rem 0;
131+
132+
font-weight: ${({ theme }) => theme.text.weight.bold};
133+
font-size: 1.8rem;
134+
text-align: center;
135+
border-radius: 0.8rem;
136+
`,
137+
};

frontend/src/components/_common/Map/RealTimeMap.tsx

+9-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,15 @@ const RealTimeMap = ({
5050
mapRef.current = map;
5151

5252
/*마커 생성*/
53-
const marker = createMarker(kakao, map, new kakao.maps.LatLng(position.latitude, position.longitude), 'primary');
53+
const marker = createMarker(
54+
kakao,
55+
map,
56+
new kakao.maps.LatLng(
57+
position.latitude ?? DEFAULT_POSITION.latitude,
58+
position.longitude ?? DEFAULT_POSITION.longitude,
59+
),
60+
'primary',
61+
);
5462
markerRef.current = marker;
5563

5664
/*인포윈도우 생성*/

frontend/src/components/_common/Map/RoomCompareMap.tsx

+120-44
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import styled from '@emotion/styled';
22
import { useEffect, useRef } from 'react';
33

4+
import defaultMap from '@/assets/images/default-compare-map.webp';
45
import Marker from '@/components/_common/Marker/Marker';
56
import theme from '@/styles/theme';
67
import { Position } from '@/types/address';
@@ -14,56 +15,105 @@ const RoomCompareMap = ({ positions }: { positions: Position[] }) => {
1415
const mapElement = useRef<HTMLDivElement>(null);
1516
const mapRef = useRef<any>(null);
1617

18+
const [{ latitude: room1Latitude, longitude: room1Logitude }, { latitude: room2Latitude, longitude: room2Logitude }] =
19+
positions;
20+
21+
const hasAddressRoom1 = room1Latitude && room1Logitude;
22+
const hasAddressRoom2 = room2Latitude && room2Logitude;
23+
1724
useEffect(() => {
1825
const initializeMap = () => {
1926
const { kakao } = window as any;
2027

21-
const centerOfPosition = {
22-
latitude: (positions[0].latitude + positions[1].latitude) / 2,
23-
longitude: (positions[0].longitude + positions[1].longitude) / 2,
24-
};
25-
26-
const diff = getDistanceFromLatLonInKm(
27-
positions[0].latitude,
28-
positions[0].longitude,
29-
positions[1].latitude,
30-
positions[1].longitude,
31-
);
32-
33-
/* 두 지점의 거리를 재서 적당한 Map level 설정 */
34-
const mapLevel = getMapLevel(diff);
35-
36-
kakao.maps.load(() => {
37-
if (!mapElement.current) return;
38-
const mapOption = {
39-
center: new kakao.maps.LatLng(centerOfPosition.latitude, centerOfPosition.longitude),
40-
level: mapLevel,
28+
if (hasAddressRoom1 && !hasAddressRoom2) {
29+
kakao.maps.load(() => {
30+
if (!mapElement.current) return;
31+
const mapOption = {
32+
center: new kakao.maps.LatLng(room1Latitude, room1Logitude),
33+
level: 3,
34+
};
35+
36+
const map = new kakao.maps.Map(mapElement.current, mapOption);
37+
mapRef.current = map;
38+
39+
const { createMarker } = createKakaoMapElements();
40+
41+
const marker2 = createMarker(
42+
kakao,
43+
map,
44+
new kakao.maps.LatLng(room1Latitude, room1Logitude),
45+
'primary',
46+
'first',
47+
);
48+
marker2.setMap(map);
49+
});
50+
}
51+
52+
if (!hasAddressRoom1 && hasAddressRoom2) {
53+
kakao.maps.load(() => {
54+
if (!mapElement.current) return;
55+
const mapOption = {
56+
center: new kakao.maps.LatLng(room2Latitude, room2Logitude),
57+
level: 3,
58+
};
59+
60+
const map = new kakao.maps.Map(mapElement.current, mapOption);
61+
mapRef.current = map;
62+
63+
const { createMarker } = createKakaoMapElements();
64+
65+
const marker2 = createMarker(
66+
kakao,
67+
map,
68+
new kakao.maps.LatLng(room2Latitude, room2Logitude),
69+
'secondary',
70+
'second',
71+
);
72+
marker2.setMap(map);
73+
});
74+
}
75+
76+
if (hasAddressRoom1 && hasAddressRoom2) {
77+
const centerOfPosition = {
78+
latitude: (room1Latitude + room2Latitude) / 2,
79+
longitude: (room1Logitude + room2Logitude) / 2,
4180
};
4281

43-
const map = new kakao.maps.Map(mapElement.current, mapOption);
44-
mapRef.current = map;
45-
46-
const { createMarker } = createKakaoMapElements();
47-
48-
const marker1 = createMarker(
49-
kakao,
50-
map,
51-
new kakao.maps.LatLng(positions[0].latitude, positions[0].longitude),
52-
'primary',
53-
'first',
54-
);
55-
56-
const marker2 = createMarker(
57-
kakao,
58-
map,
59-
new kakao.maps.LatLng(positions[1].latitude, positions[1].longitude),
60-
'secondary',
61-
'second',
62-
);
63-
64-
marker1.setMap(map);
65-
marker2.setMap(map);
66-
});
82+
const diff = getDistanceFromLatLonInKm(room1Latitude, room1Logitude, room2Latitude, room2Logitude);
83+
/* 두 지점의 거리를 재서 적당한 Map level 설정 */
84+
const mapLevel = getMapLevel(diff);
85+
86+
kakao.maps.load(() => {
87+
if (!mapElement.current) return;
88+
const mapOption = {
89+
center: new kakao.maps.LatLng(centerOfPosition.latitude, centerOfPosition.longitude),
90+
level: mapLevel,
91+
};
92+
93+
const map = new kakao.maps.Map(mapElement.current, mapOption);
94+
mapRef.current = map;
95+
96+
const { createMarker } = createKakaoMapElements();
97+
const marker1 = createMarker(
98+
kakao,
99+
map,
100+
new kakao.maps.LatLng(room1Latitude, room1Logitude),
101+
'primary',
102+
'first',
103+
);
104+
marker1.setMap(map);
105+
106+
const marker2 = createMarker(
107+
kakao,
108+
map,
109+
new kakao.maps.LatLng(room2Latitude, room2Logitude),
110+
'secondary',
111+
'second',
112+
);
113+
114+
marker2.setMap(map);
115+
});
116+
}
67117
};
68118

69119
if (location) {
@@ -85,20 +135,34 @@ const RoomCompareMap = ({ positions }: { positions: Position[] }) => {
85135
}
86136
};
87137

138+
if (!hasAddressRoom1 && !hasAddressRoom2) {
139+
return (
140+
<S.Box>
141+
<S.DefaultImgBox src={defaultMap} />
142+
<S.CenterText>
143+
주소를 설정하시면 <br />
144+
지도가 표시됩니다.
145+
</S.CenterText>
146+
</S.Box>
147+
);
148+
}
149+
88150
return (
89151
<>
90152
{location && (
91153
<S.Box>
92154
<S.Map ref={mapElement}>
93155
<S.RoomMarkBox>
94156
<Marker
157+
disabled={!hasAddressRoom1}
95158
isCircle={false}
96159
backgroundColor={theme.palette.yellow500}
97160
text={'A방'}
98161
size={'medium'}
99162
onClick={() => handleRoomMarkerClick(0)}
100163
/>
101164
<Marker
165+
disabled={!hasAddressRoom2}
102166
isCircle={false}
103167
backgroundColor={theme.palette.green500}
104168
text={'B방'}
@@ -115,6 +179,7 @@ const RoomCompareMap = ({ positions }: { positions: Position[] }) => {
115179

116180
const S = {
117181
Box: styled.div`
182+
position: relative;
118183
width: 100%;
119184
height: 20rem;
120185
@@ -138,6 +203,17 @@ const S = {
138203
gap: 1rem;
139204
border-radius: 0.3rem;
140205
`,
206+
CenterText: styled.span`
207+
position: absolute;
208+
top: 50%;
209+
left: 50%;
210+
transform: translate(-50%, -50%);
211+
`,
212+
DefaultImgBox: styled.img`
213+
width: 100%;
214+
height: 100%;
215+
object-fit: cover;
216+
`,
141217
};
142218

143219
export default RoomCompareMap;

0 commit comments

Comments
 (0)