Skip to content

Commit

Permalink
Merge pull request #114 from capstone-maru/feat/user-marker
Browse files Browse the repository at this point in the history
feat: Add recommended user-marker
  • Loading branch information
cjeongmin authored May 29, 2024
2 parents e52ac6a + 2deed0f commit a891097
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
}
],
"no-empty-pattern": ["warn", { "allowObjectPatternsAsParameters": true }],
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-floating-promises": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-empty-function": ["off", {}],
Expand Down
117 changes: 115 additions & 2 deletions src/app/pages/main-page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
'use client';

import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useEffect, useRef, useState } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import styled from 'styled-components';

import { CircularButton } from '@/components';
import { CircularButton, CircularProfileImage } from '@/components';
import { UserCard } from '@/components/main-page';
import { useAuthValue } from '@/features/auth';
import { getGeolocation } from '@/features/geocoding';
import { fromAddrToCoord, getGeolocation } from '@/features/geocoding';
import { useRecommendMates } from '@/features/profile';

const styles = {
Expand Down Expand Up @@ -97,6 +99,36 @@ const styles = {
`,
};

function Marker({
nickname,
profileImage,
score,
}: {
score: number;
profileImage: string;
nickname: string;
}) {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '0.75rem',
scale: 0.75,
}}
>
<CircularProfileImage
diameter={100}
percentage={score}
url={profileImage}
hideScore={false}
/>
<p>{nickname}</p>
</div>
);
}

export function MainPage() {
const auth = useAuthValue();

Expand All @@ -109,6 +141,8 @@ export function MainPage() {

const scrollRef = useRef<HTMLDivElement>(null);

const router = useRouter();

const handleScrollRight = () => {
if (scrollRef.current !== null) {
scrollRef.current.scrollBy({ left: 300, behavior: 'smooth' });
Expand Down Expand Up @@ -143,6 +177,85 @@ export function MainPage() {
});
}, []);

const [createdMarkers, setCreatedMarkers] = useState<naver.maps.Marker[]>([]);

useEffect(() => {
if (map == null) return;

recommendationMates?.data.forEach(mate => {
fromAddrToCoord({ query: mate.location }).then(res => {
const address = res.shift();
if (address == null) return;

const spot = new naver.maps.LatLng(+address.y, +address.x);
const marker = new naver.maps.Marker({
position: spot,
map,
icon: {
content: renderToStaticMarkup(
<Marker
nickname={mate.nickname}
profileImage={mate.profileImageUrl}
score={mate.score}
/>,
),
},
});

marker.addListener('click', () => {
router.push(`/profile/${mate.memberId}`);
});

setCreatedMarkers(prev => prev.concat(marker));
});
});
}, [map, recommendationMates?.data, router]);

useEffect(() => {
if (map == null) return () => {};

const showMarker = (
targetMap: naver.maps.Map,
marker: naver.maps.Marker,
) => {
if (marker.getMap() != null) return;
marker.setMap(targetMap);
};

const hideMarker = (marker: naver.maps.Marker) => {
if (marker.getMap() == null) return;
marker.setMap(null);
};

const updateMarkers = (
targetMap: naver.maps.Map | null,
markers: naver.maps.Marker[],
) => {
if (targetMap == null) return;

const mapBounds = targetMap.getBounds();
let marker: naver.maps.Marker, position;

for (let i = 0; i < markers.length; i += 1) {
marker = markers[i];
position = marker.getPosition();

if (mapBounds.hasPoint(position)) {
showMarker(targetMap, marker);
} else {
hideMarker(marker);
}
}
};

const MoveEventListner = naver.maps.Event.addListener(map, 'idle', () => {
updateMarkers(map, createdMarkers);
});
return () => {
naver.maps.Event.removeListener(MoveEventListner);
};
}, [createdMarkers, map]);

return (
<styles.container>
<styles.map id="map">
Expand Down
116 changes: 115 additions & 1 deletion src/app/pages/mobile/mobile-main-page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
'use client';

import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import styled from 'styled-components';

import { CircularProfileImage } from '@/components';
import { UserCard } from '@/components/main-page';
import { useAuthValue } from '@/features/auth';
import { getGeolocation } from '@/features/geocoding';
import { fromAddrToCoord, getGeolocation } from '@/features/geocoding';
import { useRecommendMates } from '@/features/profile';

const styles = {
Expand Down Expand Up @@ -103,6 +106,36 @@ const styles = {
`,
};

function Marker({
nickname,
profileImage,
score,
}: {
score: number;
profileImage: string;
nickname: string;
}) {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '0.75rem',
scale: 0.75,
}}
>
<CircularProfileImage
diameter={100}
percentage={score}
url={profileImage}
hideScore={false}
/>
<p>{nickname}</p>
</div>
);
}

export function MobileMainPage() {
const auth = useAuthValue();

Expand All @@ -113,6 +146,8 @@ export function MobileMainPage() {

const [map, setMap] = useState<naver.maps.Map | null>(null);

const router = useRouter();

useEffect(() => {
getGeolocation({
onSuccess: position => {
Expand All @@ -135,6 +170,85 @@ export function MobileMainPage() {
});
}, []);

const [createdMarkers, setCreatedMarkers] = useState<naver.maps.Marker[]>([]);

useEffect(() => {
if (map == null) return;

recommendationMates?.data.forEach(mate => {
fromAddrToCoord({ query: mate.location }).then(res => {
const address = res.shift();
if (address == null) return;

const spot = new naver.maps.LatLng(+address.y, +address.x);
const marker = new naver.maps.Marker({
position: spot,
map,
icon: {
content: renderToStaticMarkup(
<Marker
nickname={mate.nickname}
profileImage={mate.profileImageUrl}
score={mate.score}
/>,
),
},
});

marker.addListener('click', () => {
router.push(`/profile/${mate.memberId}`);
});

setCreatedMarkers(prev => prev.concat(marker));
});
});
}, [map, recommendationMates?.data, router]);

useEffect(() => {
if (map == null) return () => {};

const showMarker = (
targetMap: naver.maps.Map,
marker: naver.maps.Marker,
) => {
if (marker.getMap() != null) return;
marker.setMap(targetMap);
};

const hideMarker = (marker: naver.maps.Marker) => {
if (marker.getMap() == null) return;
marker.setMap(null);
};

const updateMarkers = (
targetMap: naver.maps.Map | null,
markers: naver.maps.Marker[],
) => {
if (targetMap == null) return;

const mapBounds = targetMap.getBounds();
let marker: naver.maps.Marker, position;

for (let i = 0; i < markers.length; i += 1) {
marker = markers[i];
position = marker.getPosition();

if (mapBounds.hasPoint(position)) {
showMarker(targetMap, marker);
} else {
hideMarker(marker);
}
}
};

const MoveEventListner = naver.maps.Event.addListener(map, 'idle', () => {
updateMarkers(map, createdMarkers);
});
return () => {
naver.maps.Event.removeListener(MoveEventListner);
};
}, [createdMarkers, map]);

return (
<styles.container>
<styles.map id="map">
Expand Down
8 changes: 7 additions & 1 deletion src/components/main-page/UserCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ export function UserCard({
hideScore?: boolean;
}) {
const isMobile = useIsMobile();

const mateAgeStringify = (() => {
if (mateAge === 0) return '동갑';
if (mateAge === 11) return '상관없어요';
return `±${mateAge}`;
})();
return (
<styles.container>
<styles.profileInfo>
Expand All @@ -135,7 +141,7 @@ export function UserCard({
<styles.data>
<p className="selected">흡연 여부: {smoking}</p>
<p className="selected">룸메이트 방 공유: {roomSharingOption}</p>
<p className="selected">나이 차이: {mateAge}</p>
<p className="selected">나이 차이: {mateAgeStringify}</p>
</styles.data>
</styles.container>
);
Expand Down

0 comments on commit a891097

Please sign in to comment.