728x90
이렇게 지도페이지 기능 구현은 끝낫다!!!!
//place.tsx
//지도페이지
import React, { useState, useEffect, lazy, Suspense } from "react";
import { useNavigate } from "react-router-dom";
import axios from "axios";
import styled from "styled-components";
import { ButtonDark } from "../components/Common/Button";
import { useDispatch } from "react-redux";
import { setMarker } from "../redux/slice/store";
const MapComponent = lazy(() => import("./Map"));
// import MapComponent from "./Map";
/*--------------------------------스타일--------------------------------*/
const TotalStyled = styled.section`
/* border: 10px solid black; */
display: flex;
justify-content: center;
align-items: center;
background-color: #f7f7f7;
`;
const PlaceContainer = styled.div`
/* border: 5px solid black; */
width: 100vw;
height: 100vh;
max-width: 1250px;
margin-top: 150px; //호버됬을때가 150이래서 일단 150으로 설정함.
display: flex;
flex-direction: column;
`;
//지도부분
const MapBodyStyled = styled.div`
/* border: 5px solid red; */
display: flex;
flex-direction: column;
flex-grow: 6.5;
justify-content: center;
align-items: center;
`;
//지도제목
const MapArticleStyled = styled.div`
/* border: 5px solid black; */
margin-bottom: 80px;
font-size: 18px;
`;
const MapBottomStyled = styled.div`
/* border: 3px solid blue; */
flex-grow: 1;
display: flex;
flex-grow: 3.5;
justify-content: center;
align-items: center;
margin-bottom: 50px;
`;
interface Shopitem {
address: string;
choice: boolean;
comment: string;
lat: number;
lng: number;
marketId: number;
name: string;
phone: string;
workTime: string;
}
/*-----------------------------------------------------------------------*/
const Place = () => {
const dispatch = useDispatch();
const [shoplist, setShoplist] = useState<Shopitem[]>([]);
const navigate = useNavigate();
const [select, setSelect] = useState<Shopitem | null>(null);
const King = async () => {
await axios
.get(`${process.env.REACT_APP_API_URL}/marts`, {
headers: {
"Content-Type": "application/json",
Authorization: localStorage.getItem("authToken"),
"ngrok-skip-browser-warning": "69420", // ngrok cors 에러
},
})
.then((res) => {
// console.log(res.data.content);
setShoplist(res.data.content);
})
.catch((err) => console.log(err));
};
useEffect(() => {
King();
}, []);
const handleSelect = () => {
// console.log(select);
dispatch(setMarker(select));
navigate("/cart");
};
return (
<>
<TotalStyled>
<PlaceContainer>
<MapBodyStyled>
<MapArticleStyled>픽업 매장을 선택하세요</MapArticleStyled>
<Suspense fallback={<div>loading</div>}>
<MapComponent shoplist={shoplist} setSelect={setSelect} />
{/* <MapComponent shoplist={shoplist} /> */}
</Suspense>
</MapBodyStyled>
<MapBottomStyled>
<ButtonDark width="350px" height="50%" onClick={handleSelect}>
선택
</ButtonDark>
</MapBottomStyled>
</PlaceContainer>
</TotalStyled>
</>
);
};
export default Place;
//map.tsx
import React, { useEffect } from "react";
// import { useSelector } from "react-redux";
declare global {
interface Window {
kakao: any;
closeOverlay: () => void;
}
}
interface Shopitem {
address: string;
choice: boolean;
comment: string;
lat: number;
lng: number;
marketId: number;
name: string;
phone: string;
workTime: string;
}
interface ShopProps {
shoplist: Shopitem[];
setSelect: React.Dispatch<React.SetStateAction<Shopitem | null>>;
}
// interface SelectProps {
// setSelect: React.Dispatch<React.SetStateAction<string>>;
// }
const MapComponent = ({ shoplist, setSelect }: ShopProps) => {
// const selectdata = useSelector((state) => state);
// console.log(selectdata);
useEffect(() => {
const container = document.getElementById("map");
const options = {
center: new window.kakao.maps.LatLng(37.32569664033685, 127.10734442799804),
level: 2,
};
// console.log(setSelect);
const map = new window.kakao.maps.Map(container, options);
//사용자 현재위치 정보
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
const lat = position.coords.latitude,
lon = position.coords.longitude;
const locPosition = new window.kakao.maps.LatLng(lat, lon),
message = "<div>현재위치</div>";
// console.log(locPosition, message); // 이게 현재위치 잡히는거다 !!!!!!!!
displayMarker(locPosition, message);
});
} else {
const locPosition = new window.kakao.maps.LatLng(37.57022168346011, 126.98314742271637), //종각역
message = "<div>아니야</div>";
displayMarker(locPosition, message);
}
function displayMarker(locPosition: any, message: any) {
const marker = new window.kakao.maps.Marker({
map: map,
position: locPosition,
});
const iwContent = message,
iwRemoveable = true;
const infowindow = new window.kakao.maps.InfoWindow({
content: iwContent,
removable: iwRemoveable,
});
infowindow.open(map, marker);
map.setCenter(locPosition);
}
shoplist.forEach((el: any) => {
const marker = new window.kakao.maps.Marker({
map: map,
position: new window.kakao.maps.LatLng(el.lat, el.lng),
data: el.data,
});
const content =
'<div onClick={handleChoice} className="overlayContainer" style="background-color: red;">' +
`<div style="color: black;" >${el.name}</div>` +
`<div className="shopPhone">${el.phone}</div>` +
"</div>";
const customOverlay = new window.kakao.maps.CustomOverlay({
content: content,
position: new window.kakao.maps.LatLng(el.lat, el.lng),
});
//마우스오버하면 커스텀어레이가 생성된다.
window.kakao.maps.event.addListener(marker, "mouseover", () => {
customOverlay.setMap(map);
});
//마우스아웃하면 커스텀어레이가 없어진다.
window.kakao.maps.event.addListener(marker, "mouseout", () => {
customOverlay.setMap(null);
});
window.kakao.maps.event.addListener(marker, "click", () => {
setSelect(el);
// console.log(el);
});
});
}, [shoplist]);
return <div id="map" style={{ width: "800px", height: "500px" }}></div>;
};
export default MapComponent;
//store.tsx
import { createSlice, configureStore } from "@reduxjs/toolkit";
const loginState = createSlice({
name: "login",
initialState: {
token: null,
isLogin: false,
},
reducers: {
setToken: (state, action) => {
state.token = action.payload;
},
setLogout: (state) => {
state.token = null;
state.isLogin = false;
localStorage.removeItem("authToken");
localStorage.removeItem("isLogin");
localStorage.removeItem("refresh");
localStorage.removeItem("memberId");
},
},
});
const markerState = createSlice({
name: "markerState",
initialState: {
address: "",
choice: false,
comment: "",
lat: 1,
lng: 1,
marketId: 1,
name: "",
phone: "",
workTime: "",
},
reducers: {
setMarker: (state, action) => {
return action.payload;
},
},
});
export const { setToken, setLogout } = loginState.actions;
export const { setMarker } = markerState.actions;
export default configureStore({
reducer: {
loginState: loginState.reducer,
markerState: markerState.reducer,
},
});
//app.tsx
import styled from "styled-components";
import { Route, Routes } from "react-router-dom";
//Pages
import Home from "./pages/Home";
import Cart from "./pages/Cart";
import Login from "./pages/Login/Login";
import SignupInput from "./pages/Signup/SignupInput";
import Likepage from "./pages/Mypage/likepage";
import Orderpage from "./pages/Mypage/orderpage";
import Changeinfopage from "./pages/Mypage/changeinfo";
import Payment from "./pages/Payment/Payment";
import Place from "./pages/Place";
import PaymentConfirm from "./pages/Payment/PaymentConfirm";
import Alcohol from "./pages/Alcohol";
import AlcoholDetail from "./pages/AlcoholDetail";
import Layout from "./layout/index";
import HelpCenter from "./pages/HelpCenter";
import SignupSelection from "./pages/Signup/SignupSelection";
import SignupTerm from "./pages/Signup/SignupTerm";
import FindEmail from "./pages/Login/FindEmail";
import FindPassword from "./pages/Login/FindPassword";
import FailPage from "./pages/Payment/Fail";
import Checkout from "./pages/Payment/Checkout";
import ChatComponent from "./components/Chat/ChatComponent";
const BodyContainer = styled.div`
min-height: 100vh;
${({ theme }) => theme.common.flexCol};
`;
const App = () => {
return (
<BodyContainer>
<Layout>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/alcohol" element={<Alcohol />} />
<Route path="/alcohol/detail/:id" element={<AlcoholDetail />} />
<Route path="/cart/" element={<Cart />} />
<Route path="/login" element={<Login />} />
<Route path="/signup/term" element={<SignupTerm />} />
<Route path="/mypage/likepage" element={<Likepage />} />
<Route path="/mypage/orderpage" element={<Orderpage />} />
<Route path="/mypage/changeinfo" element={<Changeinfopage />} />
<Route path="/payment" element={<Payment />} />
<Route path="/checkout" element={<Checkout />} />
<Route path="/paymentconfirm" element={<PaymentConfirm />} />
<Route path="/fail" element={<FailPage />} />
<Route path="/place" element={<Place />} />
<Route path="/helpcenter" element={<HelpCenter />} />
<Route path="/signup" element={<SignupSelection />} />
<Route path="/signup/input" element={<SignupInput />} />
<Route path="/findemail/" element={<FindEmail />} />
<Route path="/findpassword" element={<FindPassword />} />
</Routes>
<ChatComponent />
</Layout>
</BodyContainer>
);
};
export default App;
728x90
'개인공부 > 메인프로젝트' 카테고리의 다른 글
0524 기록 (0) | 2023.05.24 |
---|---|
0522 기록 (0) | 2023.05.22 |
suspense, lazy 적용 (0) | 2023.05.16 |
카카오맵-사용자위치조회,마커, 커스텀어레이 (0) | 2023.05.16 |
카카오맵 - 마커 클릭하면 설정한 창 뜨기 (0) | 2023.05.16 |