본문 바로가기
개인공부/메인프로젝트

지도페이지 완료

by 뭉지야 2023. 5. 17.
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