import { useCallback, useRef, useState } from "react";
import { MapMarker } from "react-kakao-maps-sdk";
import theme from "../../assets/theme";
import { Position } from "../../types/commonTypes";
import { isEqualPosition } from "../../utils/map";
import Button from "../base/Button";
import Text from "../base/Text";
import Mapbox from "../Mapbox/Mapbox";
import PlaceSearchForm from "./PlaceSearchForm";
import {
ButtonContainer,
Container,
Guide,
MapFloatContainer,
PlaceSearchFormWrapper,
SearchContainer,
} from "./styles";
interface Props {
initialCenter: Position;
}
const MapgakcoMap = ({ initialCenter }: Props) => {
const memoCenter = useRef(initialCenter);
const [center, setCenter] = useState({
lat: initialCenter.lat,
lng: initialCenter.lng,
});
const [currentCenter, setCurrentCenter] = useState({
lat: initialCenter.lat,
lng: initialCenter.lng,
});
const [target, setTarget] = useState({
y: null,
x: null,
});
const handleKeywordSubmit = useCallback((place) => {
setTarget((prev) => ({
...prev,
...place,
}));
setCenter({
lat: place.y,
lng: place.x,
});
}, []);
const handleMyPositionClick = useCallback(() => {
if (isEqualPosition(currentCenter, memoCenter.current)) {
return;
}
Promise.resolve().then(() => {
setCenter(() => ({
lat: currentCenter.lat,
lng: currentCenter.lng,
}));
setCenter(() => ({
lat: memoCenter.current.lat,
lng: memoCenter.current.lng,
}));
});
}, [currentCenter]);
const handleCenterChange = useCallback(({ lat, lng }) => {
setCurrentCenter({
lat,
lng,
});
}, []);
const buttonStyle = {
padding: "8px",
backgroundColor: theme.colors.white,
minWidth: "80px",
display: "flex",
justifyContent: "center",
borderRadius: "8px",
boxShadow: theme.boxShadows.primary,
};
const guideTextStyle = {
background: theme.colors.white,
padding: "8px",
borderRadius: "8px",
fontSize: "12px",
color: "#91979a",
};
return (
<Container>
<MapFloatContainer>
<SearchContainer>
<PlaceSearchFormWrapper>
<PlaceSearchForm onSubmit={handleKeywordSubmit} />
</PlaceSearchFormWrapper>
<ButtonContainer>
<Button style={buttonStyle} onClick={handleMyPositionClick}>
나의 위치
</Button>
<Button style={buttonStyle} onClick={() => ({})}>
데둥이 위치
</Button>
<Button style={buttonStyle} onClick={() => ({})}>
모각코
</Button>
<Button style={buttonStyle} onClick={() => ({})}>
등록
</Button>
</ButtonContainer>
</SearchContainer>
<Guide>
<Text style={guideTextStyle}>
위치를 지정한 후 등록 버튼을 눌러주세요.
</Text>
</Guide>
</MapFloatContainer>
<Mapbox
center={{ lat: center.lat, lng: center.lng }}
isPanto
hasControl={false}
onCenterChanged={handleCenterChange}
>
{target.x && target.y && (
<MapMarker
position={{
lat: target.y,
lng: target.x,
}}
/>
)}
</Mapbox>
{JSON.stringify(currentCenter)}
</Container>
);
};
export default MapgakcoMap;
import { useCallback, useRef, useState } from "react";
import { BsArrowRightCircle, BsEye } from "react-icons/bs";
import { MapMarker } from "react-kakao-maps-sdk";
import theme from "../../assets/theme";
import useMapClick from "../../hooks/useMapClick";
import { Position } from "../../types/commonTypes";
import { ImageMarkerOverlay } from "../../types/mapTypes";
import { isEqualPosition } from "../../utils/map";
import Button from "../base/Button";
import Text from "../base/Text";
import Mapbox from "../Mapbox/Mapbox";
import PlaceSearchForm from "./PlaceSearchForm";
import {
ButtonContainer,
Container,
Guide,
MapFloatContainer,
PlaceSearchFormWrapper,
SearchContainer,
} from "./styles";
interface Props {
initialCenter: Position;
userMarkerOverlays: ImageMarkerOverlay[];
}
const MapgakcoMap = ({ initialCenter, userMarkerOverlays }: Props) => {
const memoCenter = useRef(initialCenter);
const [userClickPosition, click, initializeClick] = useMapClick();
const [center, setCenter] = useState({
lat: initialCenter.lat,
lng: initialCenter.lng,
});
const [currentCenter, setCurrentCenter] = useState({
lat: initialCenter.lat,
lng: initialCenter.lng,
});
const [targetPlace, setTargetPlace] = useState({
y: null,
x: null,
});
const handleKeywordSubmit = useCallback(
(place) => {
setTargetPlace((prev) => ({
...prev,
...place,
}));
setCenter({
lat: place.y,
lng: place.x,
});
initializeClick();
},
[initializeClick]
);
const handleMyPositionClick = useCallback(() => {
if (isEqualPosition(currentCenter, memoCenter.current)) {
return;
}
Promise.resolve().then(() => {
setCenter(() => ({
lat: currentCenter.lat,
lng: currentCenter.lng,
}));
setCenter(() => ({
lat: memoCenter.current.lat,
lng: memoCenter.current.lng,
}));
});
}, [currentCenter]);
const handleCenterChange = useCallback(({ lat, lng }) => {
setCurrentCenter({
lat,
lng,
});
}, []);
const buttonStyle = {
padding: "8px",
backgroundColor: theme.colors.white,
minWidth: "80px",
display: "flex",
justifyContent: "center",
borderRadius: "8px",
boxShadow: theme.boxShadows.primary,
};
const guideTextStyle = {
background: theme.colors.white,
padding: "8px",
borderRadius: "8px",
fontSize: "12px",
color: "#91979a",
};
return (
<Container>
<MapFloatContainer>
<SearchContainer>
<PlaceSearchFormWrapper>
<PlaceSearchForm onSubmit={handleKeywordSubmit} />
</PlaceSearchFormWrapper>
<ButtonContainer>
<Button style={buttonStyle} onClick={handleMyPositionClick}>
<BsArrowRightCircle style={{ marginRight: 4 }} /> 나의 위치
</Button>
<Button style={buttonStyle} onClick={() => ({})}>
<BsEye style={{ marginRight: 4 }} /> 데둥이
</Button>
<Button style={buttonStyle} onClick={() => ({})}>
<BsEye style={{ marginRight: 4 }} />
모각코
</Button>
<Button style={buttonStyle} onClick={() => ({})}>
등록
</Button>
</ButtonContainer>
</SearchContainer>
<Guide>
<Text style={guideTextStyle}>
위치를 지정한 후 등록 버튼을 눌러주세요.
</Text>
</Guide>
</MapFloatContainer>
<Mapbox
center={{ lat: center.lat, lng: center.lng }}
isPanto
hasControl={false}
onCenterChanged={handleCenterChange}
onClick={click}
>
{userMarkerOverlays.map(({ position, imageUrl }) => (
<MapMarker
key={`${position.lat}-${position.lng}`}
position={{
lat: position.lat,
lng: position.lng,
}}
image={{
src: imageUrl,
size: {
width: 40,
height: 40,
},
options: {
shape: "circle",
},
}}
/>
))}
{userClickPosition.lat && userClickPosition.lng ? (
<MapMarker
position={{
lat: userClickPosition.lat,
lng: userClickPosition.lng,
}}
/>
) : targetPlace.x && targetPlace.y ? (
<MapMarker
position={{
lat: targetPlace.y,
lng: targetPlace.x,
}}
/>
) : null}
</Mapbox>
</Container>
);
};
export default MapgakcoMap;
"import/no-extraneous-dependencies": [
"error",
{
devDependencies: [
"**/*.test.js",
"**/*.test.jsx",
"**/*.test.ts",
"**/*.test.tsx",
"__mocks__/*.ts",
],
},
],