From db91c919d01eea64234382e0594480c3ff926636 Mon Sep 17 00:00:00 2001 From: Cllaude99 Date: Mon, 10 Jun 2024 00:35:08 +0900 Subject: [PATCH 1/4] chore: framer-motion --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index b3d656e..b79272b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@heroicons/react": "^2.1.3", "@tanstack/react-query": "^5.29.2", "axios": "^1.6.8", - "framer-motion": "^11.1.1", + "framer-motion": "^11.2.10", "jotai": "^2.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -7283,9 +7283,9 @@ } }, "node_modules/framer-motion": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.1.1.tgz", - "integrity": "sha512-h2Zz95boULAIvow/2y8CQTFv5MHxPQO/98DrAwMe4HoI8/fcU6hUfH+886u8W/5oedp5zCCZ7qUVS46ZWoTEuA==", + "version": "11.2.10", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.2.10.tgz", + "integrity": "sha512-/gr3PLZUVFCc86a9MqCUboVrALscrdluzTb3yew+2/qKBU8CX6nzs918/SRBRCqaPbx0TZP10CB6yFgK2C5cYQ==", "dependencies": { "tslib": "^2.4.0" }, diff --git a/package.json b/package.json index e931c6a..8c364db 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "@heroicons/react": "^2.1.3", "@tanstack/react-query": "^5.29.2", "axios": "^1.6.8", - "framer-motion": "^11.1.1", + "framer-motion": "^11.2.10", "jotai": "^2.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", From 1058573e4bd7e43dafbd7398ebad2160b987f092 Mon Sep 17 00:00:00 2001 From: Cllaude99 Date: Mon, 10 Jun 2024 02:02:30 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20sidebar=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Sidebar.tsx | 124 ++++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 37 deletions(-) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 36777ec..9ae1535 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -1,79 +1,129 @@ -import { Link, useLocation } from 'react-router-dom'; - import HomeLogo from '@/assets/imgs/Navbar/home-logo.svg?react'; -// import HomeLogoActive from '@/assets/imgs/Navbar/home-logo-active.svg?react'; import PinLogo from '@/assets/imgs/Navbar/pin-logo.svg?react'; import VoteLogo from '@/assets/imgs/Navbar/vote-logo.svg?react'; import ClockLogo from '@/assets/imgs/Navbar/clock-logo.svg?react'; - import styled from 'styled-components'; +import { useState } from 'react'; +import { AnimatePresence, motion } from 'framer-motion'; -interface LogoProps { - active: boolean; +// 메뉴 enum 정의 +enum Menu { + Home = 'home', + Pin = 'pin', + Vote = 'vote', + Clock = 'clock', } export default function SideBar() { - const location = useLocation(); + const [isOpen, setIsOpen] = useState(false); + const [selectedMenu, setSelectedMenu] = useState(null); + + const handleMenuClick = (menu: Menu) => { + setIsOpen(true); + setSelectedMenu(menu); + }; + + const handleCloseSidebar = () => { + setIsOpen(false); + setSelectedMenu(null); + }; + return ( <> -
    - - - - {/* {location.pathname === '/' ? : } */} - - - +
      + handleMenuClick(Menu.Home)}> + + + - - - - - - + handleMenuClick(Menu.Pin)}> + + + - - - - - - + handleMenuClick(Menu.Vote)}> + + + - - - - - - + handleMenuClick(Menu.Clock)}> + + +
    + + {isOpen && ( + + Close + {selectedMenu === Menu.Home &&

    Home Content

    } + {selectedMenu === Menu.Pin &&

    Pin Content

    } + {selectedMenu === Menu.Vote &&

    Vote Content

    } + {selectedMenu === Menu.Clock &&

    Clock Content

    } +
    + )} +
    ); } const SidebarContainer = styled.div` - position: sticky; + position: absolute; top: 0; left: 0; height: 100vh; - min-width: 120px; + width: 100px; background-color: #5142ff; color: white; + z-index: 1000; + padding-top: 50px; `; const NavItem = styled.li` text-transform: uppercase; cursor: pointer; padding: 1rem; + list-style: none; + text-align: center; `; -const Logo = styled.span` +const Logo = styled.span` width: 3.5rem; height: 3.5rem; border-radius: 100%; display: block; margin: 0 auto; - background-color: ${({ active }) => (active ? 'white' : 'transparent')}; +`; + +const Content = styled(motion.div)` + position: absolute; + top: 0; + left: 100px; + height: 100vh; + width: 350px; + background-color: white; + z-index: 999; + padding: 1rem; + overflow-y: auto; +`; + +const CloseButton = styled.button` + margin: 1rem; + padding: 0.5rem 1rem; + background-color: #5142ff; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; + + &:hover { + background-color: #524abd; + } `; From 1d801f5f76699092ef0c97114832168dbbea2d1f Mon Sep 17 00:00:00 2001 From: Cllaude99 Date: Mon, 10 Jun 2024 02:03:23 +0900 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/enter-location.ts | 2 +- src/apis/index.ts | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/apis/enter-location.ts b/src/apis/enter-location.ts index 9dd00f1..1749300 100644 --- a/src/apis/enter-location.ts +++ b/src/apis/enter-location.ts @@ -1,5 +1,5 @@ import axios from 'axios'; -import axiosInstance from '.'; +import { axiosInstance } from '.'; export const fetchIsValidRoomId = async (roomId: string) => { const { data } = await axios.get(`/api/rooms/${roomId}/duplicate`); diff --git a/src/apis/index.ts b/src/apis/index.ts index 802cb49..a29f1e8 100644 --- a/src/apis/index.ts +++ b/src/apis/index.ts @@ -2,9 +2,18 @@ import axios from 'axios'; -const REFRESH_URL = ''; // Refresh Token을 사용해 새로운 Access Token을 받을때 요청하는 URL +const REFRESH_URL = ''; -// access token 재발급하는 함수 +export const axiosInstance = axios.create({ + baseURL: '', +}); + +// 로그 아웃 함수 +const logout = () => { + localStorage.removeItem('accessToken'); +}; + +// accessToken, refreshToken 재발급하는 함수 const getNewToken = async () => { try { const accessToken = ''; @@ -17,15 +26,6 @@ const getNewToken = async () => { } }; -// 로그 아웃 함수 -const logout = () => { - localStorage.removeItem('accessToken'); -}; - -const axiosInstance = axios.create({ - baseURL: '', -}); - // 요청 인터셉터 axiosInstance.interceptors.request.use( (config) => { @@ -60,8 +60,6 @@ axiosInstance.interceptors.response.use( localStorage.setItem('refreshToken', newToken.refreshToken); config.headers.Authorization = `Bearer ${newToken.accessToken}`; } - return axios(config); // 재요청 + return axiosInstance(config); // 재요청 }, ); - -export default axiosInstance; From 5d172cc025b280452d72cbb400da99a2d8c616c2 Mon Sep 17 00:00:00 2001 From: Cllaude99 Date: Mon, 10 Jun 2024 03:04:13 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=EA=B0=9C=EA=B0=9C=EC=9D=B8=20?= =?UTF-8?q?=EC=9E=A5=EC=86=8C=20=EC=9E=85=EB=A0=A5=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20#13?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/location-each-form.tsx | 148 +++++++++++++++++++++++ src/pages/enter-location.tsx | 23 ++-- src/pages/location-alone.tsx | 3 +- src/pages/location-each.tsx | 161 +------------------------- 4 files changed, 170 insertions(+), 165 deletions(-) create mode 100644 src/components/location-each-form.tsx diff --git a/src/components/location-each-form.tsx b/src/components/location-each-form.tsx new file mode 100644 index 0000000..a239fea --- /dev/null +++ b/src/components/location-each-form.tsx @@ -0,0 +1,148 @@ +import { useState } from 'react'; +import { useForm } from 'react-hook-form'; +import Button from '@/components/button'; +import { useParams } from 'react-router-dom'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { fetchSavePlace } from '@/apis/enter-location'; + +// 운행 수단 +enum Transport { + public = '지하철', + car = '자동차', +} + +// 입력란의 형식 +interface IForm { + transport: Transport; + siDo: string; + siGunGu: string; + roadNameAddress: string; + addressLat: number; + addressLong: number; +} + +// 기본 입력란 형태 +const default_format: IForm = { + transport: Transport.public, + siDo: '', + siGunGu: '', + roadNameAddress: '', + addressLat: 0, + addressLong: 0, +}; + +export default function LocationEachForm() { + const { roomId } = useParams<{ roomId: string }>(); + const [formLoading, setFormLoading] = useState(false); + const queryClient = useQueryClient(); + const { register, handleSubmit, setValue, watch } = useForm({ + defaultValues: default_format, + }); + + // 주소 검색하는 함수 + const openAddressSearch = () => { + new window.daum.Postcode({ + oncomplete: function (data: any) { + const fullAddress = data.roadAddress; + const siDo = data.sido; + const siGunGu = data.sigungu; + const roadNameAddress = data.roadAddress; + + // Kakao 지도 API를 사용하여 위도와 경도 가져오기 + const geocoder = new window.kakao.maps.services.Geocoder(); + geocoder.addressSearch(fullAddress, function (result: any, status: any) { + if (status === window.kakao.maps.services.Status.OK) { + const addressLat = parseFloat(result[0].y); + const addressLong = parseFloat(result[0].x); + + // 주소와 좌표 설정 + setValue('siDo', siDo); + setValue('siGunGu', siGunGu); + setValue('roadNameAddress', roadNameAddress); + setValue('addressLat', addressLat); + setValue('addressLong', addressLong); + } + }); + }, + }).open(); + }; + + // 입력 완료 버튼 클릭시 API 요청 + const { mutate: submitLocation } = useMutation({ + mutationFn: fetchSavePlace, + onSuccess: (data, variable) => { + // 장소 입력 방에 저장된 사람들의 정보 다시 불러오기 + queryClient.invalidateQueries({ queryKey: ['placeRoomUsers', roomId] }); + console.log('API 요청 성공'); + console.log('입력 완료 API 요청시 보낸 데이터', variable); + console.log('입력 완료 API 요청 이후 받은 응답 데이터', data); + }, + onError: (error) => { + console.error(`입력 완료 API 요청 실패, 에러명 : ${error}`); + }, + }); + + const onSubmit = (data: IForm) => { + setFormLoading(true); + + const payload = { + placeRoomId: roomId, + siDo: data.siDo, + siGunGu: data.siGunGu, + roadNameAddress: data.roadNameAddress, + addressLat: data.addressLat, + addressLong: data.addressLong, + transport: data.transport === Transport.public ? 'public' : 'car', + }; + + console.log('입력 완료 요청시 서버로 보내는 값', payload); + + submitLocation(payload); + + setFormLoading(false); + }; + return ( + <> +
    +
    +
    + 이동수단 +
    + +
    + + + +
    +
    + 장소입력 +
    +
    + {watch('roadNameAddress') || '주소 입력'} +
    + +
    +
    +
    +
    +