Skip to content

Commit

Permalink
Feat : MapModal 컴포넌트 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
jymaeng1234 committed Oct 1, 2024
1 parent fca5c91 commit 1e45dac
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 10 deletions.
105 changes: 105 additions & 0 deletions src/components/MapModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { useEffect, useMemo, useRef } from 'react';
import * as S from './styles';
import ReactDOM from 'react-dom';
import { H16, P16 } from '@/components/Text';
const KAKAO_MAP_API_KEY = import.meta.env.VITE_KAKAO_MAP_API_KEY;

declare global {
interface Window {
kakao: any;
}
}

interface MapModalProps {
place: string;
phone: string;
address: string;
url: string;
visible: boolean;
width?: number;
height?: number;
latitude: number;
longitude: number;
onClose: () => void;
}

export const MapModal = ({
place,
phone,
address,
url,
visible,
width = 800,
height = 600,
latitude,
longitude,
onClose,
}: MapModalProps) => {
const containerStyle = useMemo(
() => ({
width,
height,
}),
[width, height],
);

const el = useMemo(() => document.createElement('div'), []);
const mapRef = useRef<HTMLDivElement>(null);

useEffect(() => {
document.body.appendChild(el);
return () => {
document.body.removeChild(el);
};
}, [el]);
useEffect(() => {
if (visible && mapRef.current) {
const script = document.createElement('script');
script.async = true;
script.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${KAKAO_MAP_API_KEY}&autoload=false`;
document.head.appendChild(script);

script.onload = () => {
window.kakao.maps.load(() => {
const options = {
center: new window.kakao.maps.LatLng(latitude, longitude),
level: 3,
};
const map = new window.kakao.maps.Map(mapRef.current, options);

const markerPosition = new window.kakao.maps.LatLng(latitude, longitude);
const marker = new window.kakao.maps.Marker({
position: markerPosition,
});
marker.setMap(map);
});
};

return () => {
document.head.removeChild(script);
};
}
}, [visible, latitude, longitude]);

if (!visible) return null;

return ReactDOM.createPortal(
<S.MapModal>
<S.ModalContainer style={containerStyle}>
<S.ModalHeader>
<H16>공연장 정보</H16>
<S.ModalCloseBtn onClick={onClose}>X</S.ModalCloseBtn>
</S.ModalHeader>

<S.ModalPlaceInfo>
<H16>{place}</H16>
<P16>전화번호 : {phone}</P16>
<P16>주소 : {address}</P16>
<P16>홈페이지 : {url}</P16>
<S.MapContainer ref={mapRef}></S.MapContainer>
</S.ModalPlaceInfo>
</S.ModalContainer>
</S.MapModal>,
el,
);
};
69 changes: 69 additions & 0 deletions src/components/MapModal/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { styled } from 'styled-components';
import theme from '@/styles/theme';

export const MapModal = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(255, 255, 255, 0.9);
z-index: 1000;
`;

export const ModalContainer = styled.div`
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 30px;
background-color: var(${theme.colors.black});
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.5);
box-sizing: border-box;
border-radius: 10px;
display: flex;
flex-direction: column;
min-width: 800px;
min-height: 600px;
`;

export const ModalHeader = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
&::after {
content: '';
border: 1px solid ${theme.colors.gray};
position: absolute;
bottom: -10px;
left: 0;
width: 100%;
height: 1px;
}
`;

export const ModalCloseBtn = styled.button`
border: none;
background-color: transparent;
font-size: 20px;
&:hover {
color: ${theme.colors.gray};
}
`;

export const ModalPlaceInfo = styled.div`
display: flex;
flex-direction: column;
padding: 20px 0;
gap: 10px;
flex-grow: 1;
overflow-y: auto;
`;

export const MapContainer = styled.div`
border: 1px solid ${theme.colors.gray};
flex-grow: 1;
margin-top: 20px;
`;
3 changes: 3 additions & 0 deletions src/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_KAKAO_MAP_API_KEY: string;
}
27 changes: 17 additions & 10 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import { defineConfig } from 'vite';
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react-swc';
import tsconfigPaths from 'vite-tsconfig-paths';

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), tsconfigPaths()],
server: {
proxy: {
'/api': {
target: 'http://www.kopis.or.kr/openApi/restful',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
return {
plugins: [react(), tsconfigPaths()],
server: {
proxy: {
'/api': {
target: 'http://www.kopis.or.kr/openApi/restful',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, ''),
},
},
},
},

define: {
'import.meta.env.VITE_KAKAO_MAP_API_KEY': JSON.stringify(env.VITE_KAKAO_MAP_API_KEY),
},
};
});

0 comments on commit 1e45dac

Please sign in to comment.