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

[FE] QA를 dev에 반영한다. #1068

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
6 changes: 5 additions & 1 deletion frontend/src/components/RoomCompare/CompareCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 17,11 @@ interface Props {
const CompareCard = ({ room, openOptionModal, openCategoryModal }: Props) => {
return (
<S.Container>
<CompareCardItem height={7} label={'주소'} item={<S.Item>{room.address}</S.Item>} />
<CompareCardItem
height={7}
label={'주소'}
item={<S.Item>{room.address?.length ? room.address : EMPTY_INDICATOR}</S.Item>}
/>
<CompareCardItem label={'층수'} item={<S.Item>{room.floor ? `${room.floor}층` : EMPTY_INDICATOR}</S.Item>} />
<CompareCardItem
label={'보증금 / 월세'}
Expand Down
137 changes: 137 additions & 0 deletions frontend/src/components/RoomCompare/RoomCompareContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 1,137 @@
import styled from '@emotion/styled';
import { useSearchParams } from 'react-router-dom';

import RoomCompareMap from '@/components/_common/Map/RoomCompareMap';
import Marker from '@/components/_common/Marker/Marker';
import CategoryDetailModal from '@/components/RoomCompare/CategoryDetailModal';
import CompareCard from '@/components/RoomCompare/CompareCard';
import OptionDetailModal from '@/components/RoomCompare/OptionDetailModal';
import SkRoomCompare from '@/components/skeleton/RoomCompare/SkRoomCompare';
import { OPTIONS } from '@/constants/options';
import useGetCompareRoomsQuery from '@/hooks/query/useGetCompareRoomsQuery';
import useModal from '@/hooks/useModal';
import { OptionDetail } from '@/pages/RoomComparePage';
import { flexCenter, flexRow } from '@/styles/common';
import theme from '@/styles/theme';

const RoomCompareContent = () => {
const [searchParams, setSearchParams] = useSearchParams();
const { isModalOpen: isOptionModalOpen, openModal: openOptionModal, closeModal: closeOptionModal } = useModal();
const { isModalOpen: isCategoryModalOpen, openModal: openCategoryModal, closeModal: closeCategoryModal } = useModal();

const roomId1 = Number(searchParams.get('roomId1'));
const roomId2 = Number(searchParams.get('roomId2'));

const { data: rooms, isLoading } = useGetCompareRoomsQuery(roomId1, roomId2);

if (isLoading) return <SkRoomCompare />;

if (!rooms) throw new Error('데이터를 불러오는데 실패했습니다.');

const positions = rooms?.map(room => ({
latitude: room?.latitude ?? null,
longitude: room?.longitude ?? null,
}));

const formattedOptionDetail = () => {
const optionsState: OptionDetail[] = OPTIONS.map(option => ({
optionId: option.id,
optionName: option.displayName,
hasOption: [false, false],
}));

rooms?.forEach((room, index) => {
room.options.forEach(optionId => {
const targetOption = optionsState.find(option => option.optionId === optionId)!;
targetOption.hasOption[index] = true;
});
});
return optionsState;
};

const handleOpenCategoryDetailModal = (roomId: number, categoryId: number) => {
openCategoryModal();
searchParams.append('targetRoomId', String(roomId));
searchParams.append('categoryId', String(categoryId));
setSearchParams(searchParams);
};

const handleCloseategoryDetailModal = () => {
closeCategoryModal();
searchParams.delete('targetRoomId');
searchParams.delete('categoryId');
setSearchParams(searchParams);
};

return (
<>
<S.RoomGrid>
<S.TitleFlex>
<S.RoomTitle>
<S.Title key={rooms[0].checklistId}>{rooms[0].roomName}</S.Title>
<Marker isCircle={true} size={'medium'} backgroundColor={theme.palette.yellow500} text={'A'} />
</S.RoomTitle>
<S.RoomTitle>
<S.Title key={rooms[1].checklistId}>{rooms[1].roomName}</S.Title>
<Marker isCircle={true} size={'medium'} backgroundColor={theme.palette.green500} text={'B'} />
</S.RoomTitle>
</S.TitleFlex>
</S.RoomGrid>
{positions && <RoomCompareMap positions={positions} />}
<S.RoomGrid>
{rooms?.map((room, index) => (
<CompareCard
key={room.checklistId}
room={room}
index={index}
openOptionModal={openOptionModal}
openCategoryModal={handleOpenCategoryDetailModal}
/>
))}
</S.RoomGrid>
{/*방 옵션 비교 모달*/}
{isOptionModalOpen && (
<OptionDetailModal
optionCounts={[rooms[0].options.length, rooms[1].options.length]}
hasOptions={formattedOptionDetail()}
roomTitle1={rooms[0].roomName ?? ''}
roomTitle2={rooms[1].roomName ?? ''}
isOpen={isOptionModalOpen}
closeModal={closeOptionModal}
/>
)}
{/*방 카테고리 디테일 모달*/}
{isCategoryModalOpen && (
<CategoryDetailModal isOpen={isCategoryModalOpen} closeModal={handleCloseategoryDetailModal} />
)}
</>
);
};

export default RoomCompareContent;

const S = {
RoomGrid: styled.div`
${flexRow}
`,
TitleFlex: styled.div`
display: flex;
width: 100vw;
`,
RoomTitle: styled.div`
width: 50%;
margin-bottom: 0.5rem;
${flexCenter}
gap:0.8rem;
`,
Title: styled.span`
display: inline;
width: calc(100% - 3rem);
padding: 0.8rem 0;

font-weight: ${({ theme }) => theme.text.weight.bold};
font-size: 1.8rem;
text-align: center;
border-radius: 0.8rem;
`,
};
10 changes: 9 additions & 1 deletion frontend/src/components/_common/Map/RealTimeMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 50,15 @@ const RealTimeMap = ({
mapRef.current = map;

/*마커 생성*/
const marker = createMarker(kakao, map, new kakao.maps.LatLng(position.latitude, position.longitude), 'primary');
const marker = createMarker(
kakao,
map,
new kakao.maps.LatLng(
position.latitude ?? DEFAULT_POSITION.latitude,
position.longitude ?? DEFAULT_POSITION.longitude,
),
'primary',
);
markerRef.current = marker;

/*인포윈도우 생성*/
Expand Down
164 changes: 120 additions & 44 deletions frontend/src/components/_common/Map/RoomCompareMap.tsx
Original file line number Diff line number Diff line change
@@ -1,6 1,7 @@
import styled from '@emotion/styled';
import { useEffect, useRef } from 'react';

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

const [{ latitude: room1Latitude, longitude: room1Logitude }, { latitude: room2Latitude, longitude: room2Logitude }] =
positions;

const hasAddressRoom1 = room1Latitude && room1Logitude;
const hasAddressRoom2 = room2Latitude && room2Logitude;

useEffect(() => {
const initializeMap = () => {
const { kakao } = window as any;

const centerOfPosition = {
latitude: (positions[0].latitude positions[1].latitude) / 2,
longitude: (positions[0].longitude positions[1].longitude) / 2,
};

const diff = getDistanceFromLatLonInKm(
positions[0].latitude,
positions[0].longitude,
positions[1].latitude,
positions[1].longitude,
);

/* 두 지점의 거리를 재서 적당한 Map level 설정 */
const mapLevel = getMapLevel(diff);

kakao.maps.load(() => {
if (!mapElement.current) return;
const mapOption = {
center: new kakao.maps.LatLng(centerOfPosition.latitude, centerOfPosition.longitude),
level: mapLevel,
if (hasAddressRoom1 && !hasAddressRoom2) {
kakao.maps.load(() => {
if (!mapElement.current) return;
const mapOption = {
center: new kakao.maps.LatLng(room1Latitude, room1Logitude),
level: 3,
};

const map = new kakao.maps.Map(mapElement.current, mapOption);
mapRef.current = map;

const { createMarker } = createKakaoMapElements();

const marker2 = createMarker(
kakao,
map,
new kakao.maps.LatLng(room1Latitude, room1Logitude),
'primary',
'first',
);
marker2.setMap(map);
});
}

if (!hasAddressRoom1 && hasAddressRoom2) {
kakao.maps.load(() => {
if (!mapElement.current) return;
const mapOption = {
center: new kakao.maps.LatLng(room2Latitude, room2Logitude),
level: 3,
};

const map = new kakao.maps.Map(mapElement.current, mapOption);
mapRef.current = map;

const { createMarker } = createKakaoMapElements();

const marker2 = createMarker(
kakao,
map,
new kakao.maps.LatLng(room2Latitude, room2Logitude),
'secondary',
'second',
);
marker2.setMap(map);
});
}

if (hasAddressRoom1 && hasAddressRoom2) {
const centerOfPosition = {
latitude: (room1Latitude room2Latitude) / 2,
longitude: (room1Logitude room2Logitude) / 2,
};

const map = new kakao.maps.Map(mapElement.current, mapOption);
mapRef.current = map;

const { createMarker } = createKakaoMapElements();

const marker1 = createMarker(
kakao,
map,
new kakao.maps.LatLng(positions[0].latitude, positions[0].longitude),
'primary',
'first',
);

const marker2 = createMarker(
kakao,
map,
new kakao.maps.LatLng(positions[1].latitude, positions[1].longitude),
'secondary',
'second',
);

marker1.setMap(map);
marker2.setMap(map);
});
const diff = getDistanceFromLatLonInKm(room1Latitude, room1Logitude, room2Latitude, room2Logitude);
/* 두 지점의 거리를 재서 적당한 Map level 설정 */
const mapLevel = getMapLevel(diff);

kakao.maps.load(() => {
if (!mapElement.current) return;
const mapOption = {
center: new kakao.maps.LatLng(centerOfPosition.latitude, centerOfPosition.longitude),
level: mapLevel,
};

const map = new kakao.maps.Map(mapElement.current, mapOption);
mapRef.current = map;

const { createMarker } = createKakaoMapElements();
const marker1 = createMarker(
kakao,
map,
new kakao.maps.LatLng(room1Latitude, room1Logitude),
'primary',
'first',
);
marker1.setMap(map);

const marker2 = createMarker(
kakao,
map,
new kakao.maps.LatLng(room2Latitude, room2Logitude),
'secondary',
'second',
);

marker2.setMap(map);
});
}
};

if (location) {
Expand All @@ -85,20 135,34 @@ const RoomCompareMap = ({ positions }: { positions: Position[] }) => {
}
};

if (!hasAddressRoom1 && !hasAddressRoom2) {
return (
<S.Box>
<S.DefaultImgBox src={defaultMap} />
<S.CenterText>
주소를 설정하시면 <br />
지도가 표시됩니다.
</S.CenterText>
</S.Box>
);
}

return (
<>
{location && (
<S.Box>
<S.Map ref={mapElement}>
<S.RoomMarkBox>
<Marker
disabled={!hasAddressRoom1}
isCircle={false}
backgroundColor={theme.palette.yellow500}
text={'A방'}
size={'medium'}
onClick={() => handleRoomMarkerClick(0)}
/>
<Marker
disabled={!hasAddressRoom2}
isCircle={false}
backgroundColor={theme.palette.green500}
text={'B방'}
Expand All @@ -115,6 179,7 @@ const RoomCompareMap = ({ positions }: { positions: Position[] }) => {

const S = {
Box: styled.div`
position: relative;
width: 100%;
height: 20rem;

Expand All @@ -138,6 203,17 @@ const S = {
gap: 1rem;
border-radius: 0.3rem;
`,
CenterText: styled.span`
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
`,
DefaultImgBox: styled.img`
width: 100%;
height: 100%;
object-fit: cover;
`,
};

export default RoomCompareMap;
Loading
Loading