diff --git a/.env.template b/.env.template index 480d766..6282d32 100644 --- a/.env.template +++ b/.env.template @@ -21,3 +21,9 @@ KAKAO_REDIRECT_URI= NAVER_CLIENT_ID= NAVER_CLIENT_SECRET= NAVER_REDIRECT_URI= + +## KAKAO MAP +### @see https://developers.kakao.com/console/app/1102339/config/appKey +KAKAO_MAP_BASE_URL= +KAKAO_MAP_API_KEY= +DAUMCDN_POSTOCDE_URL= \ No newline at end of file diff --git a/package.json b/package.json index f552aec..c9828f2 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "invi", "version": "0.1.0", "private": true, + "type": "module", "scripts": { "dev": "next dev", "build": "next build", @@ -39,6 +40,7 @@ "@tanstack/react-form": "^0.26.1", "@tanstack/react-query": "^5.50.1", "@tanstack/zod-form-adapter": "^0.25.3", + "@types/uuid": "^10.0.0", "arctic": "^2.0.0-next.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", @@ -53,6 +55,7 @@ "sonner": "^1.5.0", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7", + "uuid": "^10.0.0", "zod": "^3.23.8", "zustand": "^4.5.4" }, diff --git a/src/app/(playground)/playground/map/_components/AddressSearchButton/index.tsx b/src/app/(playground)/playground/map/_components/AddressSearchButton/index.tsx new file mode 100644 index 0000000..3d6c6ab --- /dev/null +++ b/src/app/(playground)/playground/map/_components/AddressSearchButton/index.tsx @@ -0,0 +1,34 @@ +"use client"; + +import { useKakaoAddress } from "~/app/(playground)/playground/map/_components/KakaoAddressContext"; + +export default function AddressSearchButton() { + const { setCoordinate } = useKakaoAddress(); + + const handleClickButton = () => { + new window.daum.Postcode({ + oncomplete: (addressData: any) => { + const geocoder = new window.kakao.maps.services.Geocoder(); + geocoder.addressSearch( + addressData.address, + (result: any, status: any) => { + const currentPositions = new window.kakao.maps.LatLng( + result[0].y, + result[0].x, + ); + setCoordinate(currentPositions.Ma, currentPositions.La); + }, + ); + }, + }).open(); + }; + + return ( + + ); +} diff --git a/src/app/(playground)/playground/map/_components/KakaoAddressContext/index.tsx b/src/app/(playground)/playground/map/_components/KakaoAddressContext/index.tsx new file mode 100644 index 0000000..28207b1 --- /dev/null +++ b/src/app/(playground)/playground/map/_components/KakaoAddressContext/index.tsx @@ -0,0 +1,45 @@ +"use client"; + +import type { ReactNode } from "react"; +import { createContext, useContext, useState } from "react"; + +export interface Coordinate { + latitude: number; + longitude: number; +} + +interface KakaoAddressContextType { + coordinate: Coordinate; + setCoordinate: (latitude: number, longitude: number) => void; +} + +const KakaoAddressContext = createContext( + undefined, +); + +export function KakaoAddressProvider({ children }: { children: ReactNode }) { + const [coordinate, setCoordinateState] = useState({ + latitude: 37.566828, + longitude: 126.9786567, + }); + + const setCoordinate = (latitude: number, longitude: number) => { + setCoordinateState({ latitude, longitude }); + }; + + return ( + + {children} + + ); +} + +export function useKakaoAddress() { + const context = useContext(KakaoAddressContext); + if (context === undefined) { + throw new Error( + "useKakaoAddress must be used within a KakaoAddressProvider", + ); + } + return context; +} diff --git a/src/app/(playground)/playground/map/_components/KakaoMap/index.tsx b/src/app/(playground)/playground/map/_components/KakaoMap/index.tsx new file mode 100644 index 0000000..1da4e3b --- /dev/null +++ b/src/app/(playground)/playground/map/_components/KakaoMap/index.tsx @@ -0,0 +1,78 @@ +"use client"; + +import { useEffect, useRef } from "react"; +import { useKakaoAddress } from "~/app/(playground)/playground/map/_components/KakaoAddressContext"; + +interface KakaoMapProps { + width: string; + height: string; + level?: number; + addCenterPin?: boolean; + latitude?: number; + longitude?: number; +} + +export default function KakaoMap({ + width, + height, + level = 3, + addCenterPin = false, + latitude, + longitude, +}: KakaoMapProps) { + const { coordinate } = useKakaoAddress(); + const mapRef = useRef(null); + const mapInstanceRef = useRef(null); + const markerRef = useRef(null); + + useEffect(() => { + if (!mapRef.current) return; + + const initializeMap = () => { + const center = new window.kakao.maps.LatLng( + latitude ?? coordinate.latitude, + longitude ?? coordinate.longitude, + ); + + const mapInstance = new window.kakao.maps.Map( + mapRef.current as HTMLElement, + { + center, + level, + }, + ); + + mapInstanceRef.current = mapInstance; + + if (addCenterPin) { + const marker = new window.kakao.maps.Marker({ position: center }); + marker.setMap(mapInstance); + markerRef.current = marker; + } + }; + + if (window.kakao && window.kakao.maps) { + window.kakao.maps.load(initializeMap); + } + }, []); + + useEffect(() => { + if (mapInstanceRef.current) { + const newCenter = new window.kakao.maps.LatLng( + latitude ?? coordinate.latitude, + longitude ?? coordinate.longitude, + ); + mapInstanceRef.current.setCenter(newCenter); + + if (addCenterPin && markerRef.current) { + markerRef.current.setPosition(newCenter); + } + } + }, [coordinate]); + + return ( +
+
+
+ ); +} diff --git a/src/app/(playground)/playground/map/_components/MapUtilsButton/UtilsContainer/index.tsx b/src/app/(playground)/playground/map/_components/MapUtilsButton/UtilsContainer/index.tsx new file mode 100644 index 0000000..398f5b4 --- /dev/null +++ b/src/app/(playground)/playground/map/_components/MapUtilsButton/UtilsContainer/index.tsx @@ -0,0 +1 @@ +export default function UtilsContainer() {} diff --git a/src/app/(playground)/playground/map/_components/MapUtilsButton/index.tsx b/src/app/(playground)/playground/map/_components/MapUtilsButton/index.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/app/(playground)/playground/map/layout.tsx b/src/app/(playground)/playground/map/layout.tsx new file mode 100644 index 0000000..5c94016 --- /dev/null +++ b/src/app/(playground)/playground/map/layout.tsx @@ -0,0 +1,24 @@ +import Script from "next/script"; +import { env } from "~/lib/env"; + +export default function KaKaoMapPageLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + <> +