From b653af1e43ef2e2ab70cbc9c68732f63fe837d57 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=AF=BC=EA=B7=A0?=
<97932282+skyblue1232@users.noreply.github.com>
Date: Sat, 4 Apr 2026 22:45:33 +0900
Subject: [PATCH 1/5] chore/packages
---
.../design-system/src/components/BottomSheet/BottomSheet.tsx | 2 +-
packages/design-system/src/components/Header/Header.tsx | 2 ++
packages/design-system/src/components/Header/Header.types.ts | 1 +
packages/design-system/src/icons/generated/iconNames.ts | 1 +
packages/design-system/src/icons/generated/spriteSymbols.ts | 2 +-
packages/design-system/src/icons/source/Pin.svg | 1 +
packages/design-system/src/libs/utils.ts | 1 +
packages/tailwind-config/theme.css | 2 ++
8 files changed, 10 insertions(+), 2 deletions(-)
create mode 100644 packages/design-system/src/icons/source/Pin.svg
diff --git a/packages/design-system/src/components/BottomSheet/BottomSheet.tsx b/packages/design-system/src/components/BottomSheet/BottomSheet.tsx
index ea0228f..378bade 100644
--- a/packages/design-system/src/components/BottomSheet/BottomSheet.tsx
+++ b/packages/design-system/src/components/BottomSheet/BottomSheet.tsx
@@ -37,7 +37,7 @@ export const BottomSheet = ({
{
value,
placeholder = "위치를 입력해주세요",
onChange,
+ onInputClick,
onMapPinClick,
onAlarmClick,
mapPinIconName = "MapPin",
@@ -39,6 +40,7 @@ export const Header = (props: HeaderProps) => {
name={inputName}
value={value}
onChange={onChange}
+ onClick={onInputClick}
placeholder={placeholder}
disabled={inputDisabled}
readOnly={inputReadOnly}
diff --git a/packages/design-system/src/components/Header/Header.types.ts b/packages/design-system/src/components/Header/Header.types.ts
index fa9958f..a3fa356 100644
--- a/packages/design-system/src/components/Header/Header.types.ts
+++ b/packages/design-system/src/components/Header/Header.types.ts
@@ -20,6 +20,7 @@ export interface LocationSearchHeaderProps extends HeaderBaseProps {
value?: string;
placeholder?: string;
onChange?: React.ChangeEventHandler
;
+ onInputClick?: React.MouseEventHandler;
onMapPinClick?: React.MouseEventHandler;
onAlarmClick?: React.MouseEventHandler;
mapPinIconName?: IconName;
diff --git a/packages/design-system/src/icons/generated/iconNames.ts b/packages/design-system/src/icons/generated/iconNames.ts
index 942fb9b..83ca4d0 100644
--- a/packages/design-system/src/icons/generated/iconNames.ts
+++ b/packages/design-system/src/icons/generated/iconNames.ts
@@ -26,6 +26,7 @@ export const iconNames = [
"Notice",
"Order",
"OwnerSelect",
+ "Pin",
"Plus",
"ProfileCharacter",
"RadioActive",
diff --git a/packages/design-system/src/icons/generated/spriteSymbols.ts b/packages/design-system/src/icons/generated/spriteSymbols.ts
index bda40e4..e167496 100644
--- a/packages/design-system/src/icons/generated/spriteSymbols.ts
+++ b/packages/design-system/src/icons/generated/spriteSymbols.ts
@@ -1,2 +1,2 @@
// 이 파일은 자동 생성 파일입니다. (직접 수정 금지)
-export const spriteSymbols = "";
+export const spriteSymbols = "";
diff --git a/packages/design-system/src/icons/source/Pin.svg b/packages/design-system/src/icons/source/Pin.svg
new file mode 100644
index 0000000..5e6945e
--- /dev/null
+++ b/packages/design-system/src/icons/source/Pin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/design-system/src/libs/utils.ts b/packages/design-system/src/libs/utils.ts
index c05146e..a6a73aa 100644
--- a/packages/design-system/src/libs/utils.ts
+++ b/packages/design-system/src/libs/utils.ts
@@ -22,6 +22,7 @@ const twMerge = extendTailwindMerge({
"primary-variant",
"primary-button",
"secondary",
+ "secondary-variant",
"accent",
"default",
"inverse",
diff --git a/packages/tailwind-config/theme.css b/packages/tailwind-config/theme.css
index 1132ff5..d6b15e6 100644
--- a/packages/tailwind-config/theme.css
+++ b/packages/tailwind-config/theme.css
@@ -31,6 +31,8 @@
@utility border-primary { border-color: var(--color-primary); }
@utility border-primary-variant { border-color: var(--color-primary-variant); }
+@utility border-secondary { border-color: var(--color-secondary); }
+@utility border-secondary-variant { border-color: var(--color-secondary-variant); }
@utility border-accent { border-color: var(--color-accent); }
@utility border-gray-500 { border-color: var(--color-gray-500); }
@utility border-gray-200 { border-color: var(--color-gray-200); }
From 5a5a71f4176fc20eea70021e4cfb3fcb4f638c50 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=AF=BC=EA=B7=A0?=
<97932282+skyblue1232@users.noreply.github.com>
Date: Sat, 4 Apr 2026 22:46:11 +0900
Subject: [PATCH 2/5] api/main-store
---
.../(tabs)/main/_apis/searchAddressByKakao.ts | 72 +++++++++++
.../(tabs)/main/store/_types/store-detail.ts | 29 +----
apps/customer/src/shared/api/api.ts | 4 +-
.../queries/query/store/useStoreDetail.ts | 11 ++
.../queries/query/store/useStoreSimple.ts | 11 ++
.../shared/queries/query/store/useStores.ts | 15 +++
.../queries/query/store/useStoresByAddress.ts | 16 +++
apps/customer/src/shared/types/kakao.d.ts | 116 ++++++++++++++++++
packages/api/src/models/store.ts | 23 +++-
9 files changed, 267 insertions(+), 30 deletions(-)
create mode 100644 apps/customer/src/app/(tabs)/main/_apis/searchAddressByKakao.ts
create mode 100644 apps/customer/src/shared/queries/query/store/useStoreDetail.ts
create mode 100644 apps/customer/src/shared/queries/query/store/useStoreSimple.ts
create mode 100644 apps/customer/src/shared/queries/query/store/useStores.ts
create mode 100644 apps/customer/src/shared/queries/query/store/useStoresByAddress.ts
create mode 100644 apps/customer/src/shared/types/kakao.d.ts
diff --git a/apps/customer/src/app/(tabs)/main/_apis/searchAddressByKakao.ts b/apps/customer/src/app/(tabs)/main/_apis/searchAddressByKakao.ts
new file mode 100644
index 0000000..79ace98
--- /dev/null
+++ b/apps/customer/src/app/(tabs)/main/_apis/searchAddressByKakao.ts
@@ -0,0 +1,72 @@
+"use client";
+
+import type { AddressSearchItem } from "../_types/address-search";
+
+export function searchAddressByKakao(
+ keyword: string,
+ size = 10
+): Promise {
+ return new Promise((resolve, reject) => {
+ const trimmedKeyword = keyword.trim();
+
+ if (!trimmedKeyword) {
+ resolve([]);
+ return;
+ }
+
+ if (
+ typeof window === "undefined" ||
+ !window.kakao ||
+ !window.kakao.maps ||
+ !window.kakao.maps.services
+ ) {
+ reject(new Error("Kakao services library is not loaded."));
+ return;
+ }
+
+ const geocoder = new window.kakao.maps.services.Geocoder();
+
+ geocoder.addressSearch(
+ trimmedKeyword,
+ (result: KakaoAddressSearchResult[], status: string) => {
+ const { kakao } = window;
+
+ if (status === kakao.maps.services.Status.ZERO_RESULT) {
+ resolve([]);
+ return;
+ }
+
+ if (status !== kakao.maps.services.Status.OK) {
+ reject(new Error("주소 검색 중 오류가 발생했습니다."));
+ return;
+ }
+
+ const mapped = result.slice(0, size).map(
+ (item: KakaoAddressSearchResult, index: number) => {
+ const lotNumberAddress =
+ item.address?.address_name || item.address_name || "";
+
+ const roadAddress =
+ item.road_address?.address_name || item.address_name || "";
+
+ return {
+ id: `${item.x}-${item.y}-${index}`,
+ label: roadAddress || lotNumberAddress,
+ lotNumberAddress,
+ roadAddress,
+ longitude: Number(item.x),
+ latitude: Number(item.y),
+ };
+ }
+ );
+
+ resolve(mapped);
+ },
+ {
+ page: 1,
+ size,
+ analyze_type: window.kakao.maps.services.AnalyzeType.SIMILAR,
+ }
+ );
+ });
+}
\ No newline at end of file
diff --git a/apps/customer/src/app/(tabs)/main/store/_types/store-detail.ts b/apps/customer/src/app/(tabs)/main/store/_types/store-detail.ts
index cddc6bb..631a202 100644
--- a/apps/customer/src/app/(tabs)/main/store/_types/store-detail.ts
+++ b/apps/customer/src/app/(tabs)/main/store/_types/store-detail.ts
@@ -5,31 +5,4 @@ export type DayKey =
| "thu"
| "fri"
| "sat"
- | "sun";
-
-export interface StoreBusinessHour {
- open: string;
- close: string;
-}
-
-export interface StoreMenuItem {
- id: number;
- name: string;
- remainingCount: number;
- pickupStartTime: string;
- pickupEndTime: string;
- price: number;
- originalPrice?: number;
- imageUrl: string;
-}
-
-export interface StoreDetailItem {
- id: number;
- storeName: string;
- roadAddress: string;
- lotAddress: string;
- email: string;
- thumbnailImageUrl: string;
- businessHours: Record;
- menus: StoreMenuItem[];
-}
\ No newline at end of file
+ | "sun";
\ No newline at end of file
diff --git a/apps/customer/src/shared/api/api.ts b/apps/customer/src/shared/api/api.ts
index f23758c..ee646dd 100644
--- a/apps/customer/src/shared/api/api.ts
+++ b/apps/customer/src/shared/api/api.ts
@@ -3,6 +3,7 @@
import {
createCompasserApi,
createAuthModule,
+ createStoreModule,
type TokenPair,
type TokenStore,
} from "@compasser/api";
@@ -36,4 +37,5 @@ export const compasserApi = createCompasserApi({
tokenStore,
});
-export const authModule = createAuthModule(compasserApi);
\ No newline at end of file
+export const authModule = createAuthModule(compasserApi);
+export const storeModule = createStoreModule(compasserApi);
\ No newline at end of file
diff --git a/apps/customer/src/shared/queries/query/store/useStoreDetail.ts b/apps/customer/src/shared/queries/query/store/useStoreDetail.ts
new file mode 100644
index 0000000..b5af05a
--- /dev/null
+++ b/apps/customer/src/shared/queries/query/store/useStoreDetail.ts
@@ -0,0 +1,11 @@
+"use client";
+
+import { useQuery } from "@tanstack/react-query";
+import { storeModule } from "@/shared/api/api";
+
+export function useStoreDetail(storeId: number) {
+ return useQuery({
+ ...storeModule.queries.detail(storeId),
+ enabled: Boolean(storeId),
+ });
+}
\ No newline at end of file
diff --git a/apps/customer/src/shared/queries/query/store/useStoreSimple.ts b/apps/customer/src/shared/queries/query/store/useStoreSimple.ts
new file mode 100644
index 0000000..7e6c9bc
--- /dev/null
+++ b/apps/customer/src/shared/queries/query/store/useStoreSimple.ts
@@ -0,0 +1,11 @@
+"use client";
+
+import { useQuery } from "@tanstack/react-query";
+import { storeModule } from "@/shared/api/api";
+
+export function useStoreSimple(storeId: number | null) {
+ return useQuery({
+ ...storeModule.queries.simple(storeId ?? 0),
+ enabled: Boolean(storeId),
+ });
+}
\ No newline at end of file
diff --git a/apps/customer/src/shared/queries/query/store/useStores.ts b/apps/customer/src/shared/queries/query/store/useStores.ts
new file mode 100644
index 0000000..99db86b
--- /dev/null
+++ b/apps/customer/src/shared/queries/query/store/useStores.ts
@@ -0,0 +1,15 @@
+"use client";
+
+import { useQuery } from "@tanstack/react-query";
+import { storeModule } from "@/shared/api/api";
+
+export function useStores(userLat: number | null, userLon: number | null, page = 0) {
+ return useQuery({
+ ...storeModule.queries.list({
+ userLat: userLat ?? 0,
+ userLon: userLon ?? 0,
+ page,
+ }),
+ enabled: userLat !== null && userLon !== null,
+ });
+}
\ No newline at end of file
diff --git a/apps/customer/src/shared/queries/query/store/useStoresByAddress.ts b/apps/customer/src/shared/queries/query/store/useStoresByAddress.ts
new file mode 100644
index 0000000..fcc4ec4
--- /dev/null
+++ b/apps/customer/src/shared/queries/query/store/useStoresByAddress.ts
@@ -0,0 +1,16 @@
+"use client";
+
+import { useQuery } from "@tanstack/react-query";
+import { storeModule } from "@/shared/api/api";
+
+export function useStoresByAddress(address: string, page = 0) {
+ const trimmedAddress = address.trim();
+
+ return useQuery({
+ ...storeModule.queries.byAddress({
+ address: trimmedAddress,
+ page,
+ }),
+ enabled: Boolean(trimmedAddress),
+ });
+}
\ No newline at end of file
diff --git a/apps/customer/src/shared/types/kakao.d.ts b/apps/customer/src/shared/types/kakao.d.ts
new file mode 100644
index 0000000..47cbb48
--- /dev/null
+++ b/apps/customer/src/shared/types/kakao.d.ts
@@ -0,0 +1,116 @@
+export {};
+
+declare global {
+ interface Window {
+ kakao: {
+ maps: {
+ load: (callback: () => void) => void;
+
+ LatLng: new (latitude: number, longitude: number) => KakaoLatLng;
+
+ Map: new (
+ container: HTMLElement,
+ options: {
+ center: KakaoLatLng;
+ level: number;
+ }
+ ) => KakaoMapInstance;
+
+ Marker: new (options: {
+ map?: KakaoMapInstance | null;
+ position: KakaoLatLng;
+ title?: string;
+ image?: KakaoMarkerImage;
+ }) => KakaoMarker;
+
+ MarkerImage: new (
+ src: string,
+ size: KakaoSize,
+ options?: {
+ offset?: KakaoPoint;
+ alt?: string;
+ shape?: string;
+ coords?: string;
+ spriteOrigin?: KakaoPoint;
+ spriteSize?: KakaoSize;
+ }
+ ) => KakaoMarkerImage;
+
+ Size: new (width: number, height: number) => KakaoSize;
+
+ Point: new (x: number, y: number) => KakaoPoint;
+
+ event: {
+ addListener: (
+ target: object,
+ type: string,
+ handler: (...args: unknown[]) => void
+ ) => void;
+ removeListener: (
+ target: object,
+ type: string,
+ handler: (...args: unknown[]) => void
+ ) => void;
+ };
+
+ services: {
+ Geocoder: new () => {
+ addressSearch: (
+ address: string,
+ callback: (
+ result: KakaoAddressSearchResult[],
+ status: string
+ ) => void,
+ options?: {
+ page?: number;
+ size?: number;
+ analyze_type?: string;
+ }
+ ) => void;
+ };
+
+ Status: {
+ OK: string;
+ ZERO_RESULT: string;
+ ERROR: string;
+ };
+
+ AnalyzeType: {
+ SIMILAR: string;
+ EXACT: string;
+ };
+ };
+ };
+ };
+ }
+
+ interface KakaoLatLng {}
+
+ interface KakaoMapInstance {
+ relayout: () => void;
+ setCenter: (latlng: KakaoLatLng) => void;
+ }
+
+ interface KakaoMarker {
+ setMap: (map: KakaoMapInstance | null) => void;
+ setPosition: (position: KakaoLatLng) => void;
+ }
+
+ interface KakaoMarkerImage {}
+
+ interface KakaoSize {}
+
+ interface KakaoPoint {}
+
+ interface KakaoAddressSearchResult {
+ address_name: string;
+ x: string;
+ y: string;
+ address?: {
+ address_name: string;
+ };
+ road_address?: {
+ address_name: string;
+ };
+ }
+}
\ No newline at end of file
diff --git a/packages/api/src/models/store.ts b/packages/api/src/models/store.ts
index acf42a9..ba4d2c9 100644
--- a/packages/api/src/models/store.ts
+++ b/packages/api/src/models/store.ts
@@ -14,10 +14,28 @@ export interface StoreLocationUpdateReqDTO {
inputAddress?: string;
}
+export interface StoreImageDTO {
+ id: number;
+ imageUrl: string;
+ createdAt?: string;
+}
+
+export interface RandomBoxRespDTO {
+ boxId: number;
+ storeId: number;
+ boxName: string;
+ stock: number;
+ price: number;
+ buyLimit: number;
+ content: string;
+ saleStatus: string;
+}
+
export interface StoreRespDTO {
storeId: number;
storeManagerId: number;
storeName: string;
+ storeEmail: string;
storeDetails: string;
inputAddress: string;
roadAddress: string;
@@ -26,6 +44,8 @@ export interface StoreRespDTO {
longitude: number;
businessHours?: JsonValue;
tag: StoreTag;
+ images: StoreImageDTO[];
+ randomBoxes: RandomBoxRespDTO[];
}
export interface GetStoreReqDTO {
@@ -46,6 +66,7 @@ export interface SimpleStoreInfoDTO {
storeName: string;
roadAddress: string;
jibunAddress: string;
+ storeEmail: string;
businessHours?: JsonValue;
}
@@ -67,4 +88,4 @@ export interface StoreAddressListParams {
export type StoreListResponse = ApiResponse;
export type StoreDetailResponse = ApiResponse;
export type StoreSimpleResponse = ApiResponse;
-export type StoreByAddressResponse = ApiResponse>;
\ No newline at end of file
+export type StoreByAddressResponse = ApiResponse;
\ No newline at end of file
From a7b3f5ba1783f9c2c8b6f04499e2fe42323d98e6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=AF=BC=EA=B7=A0?=
<97932282+skyblue1232@users.noreply.github.com>
Date: Sat, 4 Apr 2026 22:46:51 +0900
Subject: [PATCH 3/5] feat/address-search
---
.../_components/AddressSearchBottomSheet.tsx | 146 +++++++++++++++++
.../app/(tabs)/main/_components/KakaoMap.tsx | 126 +++++++++++---
.../(tabs)/main/_components/MainListView.tsx | 98 ++++-------
.../(tabs)/main/_components/MainMapView.tsx | 16 +-
.../main/_components/MainPageClient.tsx | 155 +++++++++++++++++-
.../(tabs)/main/_components/MainStoreCard.tsx | 85 +++++++---
.../app/(tabs)/main/_types/address-search.ts | 8 +
.../src/app/(tabs)/main/store/[id]/page.tsx | 6 +-
8 files changed, 521 insertions(+), 119 deletions(-)
create mode 100644 apps/customer/src/app/(tabs)/main/_components/AddressSearchBottomSheet.tsx
create mode 100644 apps/customer/src/app/(tabs)/main/_types/address-search.ts
diff --git a/apps/customer/src/app/(tabs)/main/_components/AddressSearchBottomSheet.tsx b/apps/customer/src/app/(tabs)/main/_components/AddressSearchBottomSheet.tsx
new file mode 100644
index 0000000..971d11e
--- /dev/null
+++ b/apps/customer/src/app/(tabs)/main/_components/AddressSearchBottomSheet.tsx
@@ -0,0 +1,146 @@
+"use client";
+
+import { useEffect, useRef, useState } from "react";
+import { BottomSheet, Input, Icon } from "@compasser/design-system";
+import type { AddressSearchItem } from "../_types/address-search";
+import { searchAddressByKakao } from "../_apis/searchAddressByKakao";
+
+interface AddressSearchBottomSheetProps {
+ open: boolean;
+ onClose: () => void;
+ onSelectAddress: (item: AddressSearchItem) => void;
+}
+
+export default function AddressSearchBottomSheet({
+ open,
+ onClose,
+ onSelectAddress,
+}: AddressSearchBottomSheetProps) {
+ const [keyword, setKeyword] = useState("");
+ const [results, setResults] = useState([]);
+ const [isSearching, setIsSearching] = useState(false);
+
+ const debounceRef = useRef(null);
+
+ useEffect(() => {
+ if (!open) {
+ setKeyword("");
+ setResults([]);
+ setIsSearching(false);
+ }
+ }, [open]);
+
+ useEffect(() => {
+ if (!open) {
+ return;
+ }
+
+ const trimmedKeyword = keyword.trim();
+
+ if (!trimmedKeyword) {
+ setResults([]);
+ setIsSearching(false);
+ return;
+ }
+
+ if (debounceRef.current) {
+ window.clearTimeout(debounceRef.current);
+ }
+
+ debounceRef.current = window.setTimeout(async () => {
+ try {
+ setIsSearching(true);
+ const searched = await searchAddressByKakao(trimmedKeyword, 10);
+ setResults(searched);
+ } catch (error) {
+ console.error(error);
+ setResults([]);
+ } finally {
+ setIsSearching(false);
+ }
+ }, 250);
+
+ return () => {
+ if (debounceRef.current) {
+ window.clearTimeout(debounceRef.current);
+ }
+ };
+ }, [keyword, open]);
+
+ const handleQuickSelect = () => {
+ onSelectAddress({
+ id: "catholic-univ",
+ label: "가톨릭대 주변 탐색",
+ lotNumberAddress: "경기도 부천시 원미구 역곡동 일대",
+ roadAddress: "가톨릭대학교 성심교정 주변",
+ longitude: 126.8016,
+ latitude: 37.4875,
+ });
+ };
+
+ const handleSelectItem = (item: AddressSearchItem) => {
+ onSelectAddress(item);
+ };
+
+ return (
+
+ setKeyword(event.target.value)}
+ placeholder="위치 입력"
+ />
+
+
+
+ {results.length > 0 && (
+
+ {results.map((item) => (
+
+ ))}
+
+ )}
+
+ {keyword.trim() && isSearching && (
+
+ 검색 중...
+
+ )}
+
+ {keyword.trim() && !isSearching && results.length === 0 && (
+
+ 검색 결과가 없습니다.
+
+ )}
+
+ );
+}
\ No newline at end of file
diff --git a/apps/customer/src/app/(tabs)/main/_components/KakaoMap.tsx b/apps/customer/src/app/(tabs)/main/_components/KakaoMap.tsx
index 215873b..6ccd953 100644
--- a/apps/customer/src/app/(tabs)/main/_components/KakaoMap.tsx
+++ b/apps/customer/src/app/(tabs)/main/_components/KakaoMap.tsx
@@ -2,14 +2,19 @@
import Script from "next/script";
import { useEffect, useRef, useState } from "react";
-import { MOCK_MAIN_STORE_LIST } from "../_constants/MockMainList";
-import type { MainCategory, MainStoreItem } from "../_types/main-list";
+import type {
+ GetStoreReqDTO,
+ SimpleStoreInfoDTO,
+ StoreTag,
+} from "@compasser/api";
+import type { MainCategory } from "../_types/main-list";
+import type { AddressSearchItem } from "../_types/address-search";
+import { useStoreSimple } from "@/shared/queries/query/store/useStoreSimple";
import MapStoreBottomSheet from "./MapStoreBottomSheet";
-declare global {
- interface Window {
- kakao: any;
- }
+interface KakaoMapProps {
+ selectedAddress: AddressSearchItem | null;
+ stores: GetStoreReqDTO[];
}
const PIN_IMAGE_MAP: Record = {
@@ -18,12 +23,16 @@ const PIN_IMAGE_MAP: Record = {
식당: "/icons/pin-restaurant.svg",
};
-export default function KakaoMap() {
+export default function KakaoMap({ selectedAddress, stores }: KakaoMapProps) {
const mapRef = useRef(null);
- const mapInstanceRef = useRef(null);
- const markerRefs = useRef([]);
+ const mapInstanceRef = useRef(null);
+ const markerRefs = useRef([]);
+ const selectedMarkerRef = useRef(null);
+
const [isLoaded, setIsLoaded] = useState(false);
- const [selectedStore, setSelectedStore] = useState(null);
+ const [selectedStoreId, setSelectedStoreId] = useState(null);
+
+ const { data: simpleStore } = useStoreSimple(selectedStoreId);
useEffect(() => {
if (window.kakao?.maps) {
@@ -46,7 +55,7 @@ export default function KakaoMap() {
});
kakaoMaps.event.addListener(mapInstanceRef.current, "click", () => {
- setSelectedStore(null);
+ setSelectedStoreId(null);
});
} else {
mapInstanceRef.current.relayout();
@@ -55,13 +64,13 @@ export default function KakaoMap() {
markerRefs.current.forEach((marker) => marker.setMap(null));
markerRefs.current = [];
- MOCK_MAIN_STORE_LIST.forEach((store) => {
+ stores.forEach((store) => {
const markerImage = new kakaoMaps.MarkerImage(
- PIN_IMAGE_MAP[store.primaryCategory],
+ PIN_IMAGE_MAP[mapServerTagToMainCategory(store.tag)],
new kakaoMaps.Size(32, 32),
{
offset: new kakaoMaps.Point(16, 16),
- },
+ }
);
const marker = new kakaoMaps.Marker({
@@ -73,36 +82,103 @@ export default function KakaoMap() {
kakaoMaps.event.addListener(marker, "click", () => {
setTimeout(() => {
- setSelectedStore(store);
+ setSelectedStoreId(store.storeId);
}, 0);
});
markerRefs.current.push(marker);
});
+
+ if (selectedAddress) {
+ const selectedPosition = new kakaoMaps.LatLng(
+ selectedAddress.latitude,
+ selectedAddress.longitude
+ );
+
+ mapInstanceRef.current.setCenter(selectedPosition);
+
+ if (selectedMarkerRef.current) {
+ selectedMarkerRef.current.setMap(null);
+ }
+
+ selectedMarkerRef.current = new kakaoMaps.Marker({
+ map: mapInstanceRef.current,
+ position: selectedPosition,
+ });
+ } else if (stores.length > 0) {
+ const firstStore = stores[0];
+ mapInstanceRef.current.setCenter(
+ new kakaoMaps.LatLng(firstStore.latitude, firstStore.longitude)
+ );
+ }
});
- }, [isLoaded]);
+ }, [isLoaded, stores, selectedAddress]);
return (
<>