Skip to content
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 added apps/nowait-user/src/assets/logo/yeungnam.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const RemittanceWaitPage = () => {
})),
totalPrice,
};

const orderButton = async () => {
if (isLoading) return;
try {
Expand Down Expand Up @@ -70,6 +69,8 @@ const RemittanceWaitPage = () => {
>
<img
src={isLoaded ? loadedSrc : remittanceWaitFallback}
// src={remittanceWait}

alt="입금 대기중인 이미지"
width={"150px"}
height={"150px"}
Expand Down
163 changes: 40 additions & 123 deletions apps/nowait-user/src/pages/waiting/BoothMapManage/MapManagePage.tsx
Original file line number Diff line number Diff line change
@@ -1,135 +1,52 @@
import { useEffect, useState } from "react";
import { Button } from "@repo/ui";
import { Container as MapDiv, NaverMap, Marker } from "react-naver-maps";
import { useGeoPolygon } from "../boothMap/hooks/useGeoPolygon";
import { useMyLocation } from "../boothMap/hooks/useMyLocation";
import UniversityPolygon from "../boothMap/components/UniversityPolygon";
import MapControlButtons from "../boothMap/components/mapControls/MapControls";
import MapControls from "./components/MapControls";
import GeoDataForm from "./components/GeoDataForm";
import MapCanvas from "./components/MapCanvas";
import { useMapClick } from "./hooks/useMapClick";
import { useMarkerManager } from "./hooks/useMarkerManager";
import { useMap } from "react-naver-maps";

const MapManagePage = () => {
const [markers, setMarkers] = useState<
{ storeId: string; lat: number; lng: number }[]
>([]);
const [status, setStatus] = useState(false);
const [geoData, setGeoData] = useState<string>("");
const [map, setMap] = useState<any | null>(null);
const map = useMap();

const paths = useGeoPolygon();
const myLocation = useMyLocation();

//마커 생성 컨트롤
useEffect(() => {
if (!map) return;

const listener = window.naver.maps.Event.addListener(
map,
"click",
(e: any) => {
if (!status) return;

const inputId = prompt("스토어 아이디를 입력하세요");
if (inputId === null || inputId.trim() === "") return;
const isExist = markers.some(
(marker) => String(marker.storeId) === String(inputId)
);
if (isExist) {
alert("이미 존재하는 주점입니다.");
return;
}

const lat = e.coord.lat();
const lng = e.coord.lng();

const newMarker = { storeId: inputId, lat, lng };
setMarkers((prev) => [...prev, newMarker]);
}
);

return () => {
window.naver.maps.Event.removeListener(listener);
};
}, [map, status, markers]);
const {
markers,
isActive,
setIsActive,
addMarker,
undoMarker,
resetMarkers,
copyMarkers,
} = useMarkerManager();

useMapClick({
map,
enabled: isActive,
onClick: addMarker,
});

return (
<div className="relative top-0 left-0 min-h-dvh w-full">
<MapDiv style={{ width: "100%", height: "100vh" }}>
<NaverMap
defaultCenter={myLocation.center}
defaultZoom={16}
ref={setMap}
>
<UniversityPolygon paths={paths} />
<MapControlButtons center={myLocation.center} map={map} />
{markers.map((marker) => {
return (
<Marker
key={marker.storeId}
position={{ lat: marker.lat, lng: marker.lng }}
></Marker>
);
})}
</NaverMap>
</MapDiv>
<div className="fixed left-1/2 -translate-x-1/2 bottom-20 w-full z-50 px-2.5">
<form
onSubmit={() => {
const parsed = JSON.parse(geoData);
const polygon = [
parsed.map(({ lat, lon }: { lat: number; lon: number }) => [
lon,
lat,
]),
];
navigator.clipboard.writeText(JSON.stringify(polygon, null, 2));
alert("복사가 완료 되었습니다.");
}}
>
<textarea
className="bg-white w-full min-h-48"
onChange={(e) => setGeoData(e.target.value)}
value={geoData}
/>
<Button>데이터 변경</Button>
</form>
</div>
<div className="flex gap-1 fixed left-1/2 bottom-2.5 -translate-x-1/2 w-full z-50 px-2.5">
<Button className="text-15-medium" onClick={() => setStatus(true)}>
시작
</Button>
<Button className="text-15-medium" onClick={() => setStatus(false)}>
중지
</Button>
<Button
className="text-15-medium"
onClick={() => {
setMarkers((prev) => prev.slice(0, -1));
}}
>
뒤로가기
</Button>
<Button
className="text-15-medium"
onClick={() => {
setMarkers([]);
}}
>
초기화
</Button>
<Button
className="text-15-medium"
onClick={() => {
// 좌표를 문자열로 변환 후 복사
const formattedMarkers = markers
.map((marker) => {
return `${marker.storeId} : {lat:${marker.lat},lng:${marker.lng}}`;
})
.join(",\n");
navigator.clipboard.writeText(`${formattedMarkers}\n`);
alert("복사가 완료 되었습니다.");
}}
>
복사
</Button>
</div>
// <div className="relative top-0 left-0 min-h-dvh w-full">
<div className="fixed top-0 left-0 min-h-dvh w-full my-0!">
<MapCanvas
center={myLocation.center}
paths={paths}
markers={markers}
/>
<GeoDataForm />
<MapControls
isActive={isActive}
hasMarkers={!!markers.length}
onStart={() => setIsActive(true)}
onStop={() => setIsActive(false)}
onUndo={undoMarker}
onReset={resetMarkers}
onCopy={copyMarkers}
/>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Button } from "@repo/ui";
import { useState } from "react";

const GeoDataForm = () => {
const [geoData, setGeoData] = useState("");

const copyPolygon = () => {
const parsed = JSON.parse(geoData);
const polygon = [
parsed.map(({ lat, lon }: { lat: number; lon: number }) => [
lon,
lat,
]),
];

navigator.clipboard.writeText(JSON.stringify(polygon, null, 2));
alert("복사가 완료 되었습니다.");
};

return (
<div className="fixed left-1/2 -translate-x-1/2 bottom-20 w-full z-50 px-2.5">
<form
onSubmit={(e) => {
e.preventDefault();
copyPolygon();
}}
>
<textarea
className="bg-white w-full min-h-48 outline-none"
placeholder="데이터를 입력해주세요."
value={geoData}
onChange={(e) => setGeoData(e.target.value)}
/>
<Button>데이터 변경 및 복사</Button>
</form>
</div>
);
};

export default GeoDataForm;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Container as MapDiv, Marker, NaverMap } from "react-naver-maps";
import UniversityPolygon from "../../boothMap/components/UniversityPolygon";
import MapControlButtons from "../../boothMap/components/mapControls/MapControls";

interface PropsType {
center: { lat: number; lng: number };
paths: any;
markers: { storeId: string; lat: number; lng: number }[];
}

const MapCanvas = ({ center, paths, markers }: PropsType) => {
return (
<MapDiv style={{ width: "100%", height: "100vh" }}>
<NaverMap defaultCenter={center} defaultZoom={16}>
<MapControlButtons center={center} />

<UniversityPolygon paths={paths} />
{markers.map(({ storeId, lat, lng }) => (
<Marker key={storeId} position={{ lat, lng }} />
))}
</NaverMap>
</MapDiv>
);
};

export default MapCanvas;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Button } from "@repo/ui";

type Props = {
isActive: boolean;
hasMarkers: boolean;
onStart: () => void;
onStop: () => void;
onUndo: () => void;
onReset: () => void;
onCopy: () => void;
};

const MapControls = ({
isActive,
hasMarkers,
onStart,
onStop,
onUndo,
onReset,
onCopy,
}: Props) => {
return (
<div className="flex gap-1 fixed left-1/2 bottom-2.5 -translate-x-1/2 w-full z-50 px-2.5">
<Button disabled={isActive} onClick={onStart}>시작</Button>
<Button disabled={!isActive} onClick={onStop}>중지</Button>
<Button disabled={!hasMarkers} onClick={onUndo}>뒤로가기</Button>
<Button onClick={onReset}>초기화</Button>
<Button disabled={!hasMarkers} onClick={onCopy}>복사</Button>
</div>
);
};

export default MapControls;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useEffect } from "react";

interface PropsType {
map: any | null;
enabled: boolean;
onClick: (lat: number, lng: number) => void;
};

export const useMapClick = ({ map, enabled, onClick }: PropsType) => {
useEffect(() => {
if (!map) return;

const listener = window.naver.maps.Event.addListener(
map,
"click",
(e: any) => {
if (!enabled) return;
onClick(e.coord.lat(), e.coord.lng());
}
);

return () => {
window.naver.maps.Event.removeListener(listener);
};
}, [map, enabled, onClick]);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useCallback, useState } from "react";

export const useMarkerManager = () => {
const [markers, setMarkers] = useState<{ storeId: string; lat: number; lng: number }[]>([]);
const [isActive, setIsActive] = useState(false);

//마커 추가
const addMarker = useCallback(
(lat: number, lng: number) => {
const storeId = prompt("스토어 아이디를 입력하세요");
if (!storeId?.trim()) return;

const isExist = markers.some(
(marker) => marker.storeId === storeId
);

if (isExist) {
alert("이미 존재하는 주점입니다.");
return;
}

setMarkers((prev) => [...prev, { storeId, lat, lng }]);
},
[markers]
);

//마커 뒤로가기
const undoMarker = () =>
setMarkers((prev) => prev.slice(0, -1));

//마커 초기화
const resetMarkers = () => setMarkers([]);

//전체 마커 복사
const copyMarkers = () => {
const text = markers
.map(
({ storeId, lat, lng }) =>
`${storeId} : { lat: ${lat}, lng: ${lng} }`
)
.join(",\n");

navigator.clipboard.writeText(text);
alert("복사가 완료 되었습니다.");
};

return {
markers,
isActive,
setIsActive,
addMarker,
undoMarker,
resetMarkers,
copyMarkers,
};
};
Loading