From 99528761fa7a130f700994c25ab8cad52dc7de0b Mon Sep 17 00:00:00 2001 From: juwon5272 Date: Mon, 25 Nov 2024 23:53:47 +0900 Subject: [PATCH 01/18] =?UTF-8?q?[FE][Reafactor]=20#14=20:=20=EB=B0=94?= =?UTF-8?q?=ED=85=80=EC=8B=9C=ED=8A=B8=20=EB=A7=A4=EB=81=84=EB=9F=BD?= =?UTF-8?q?=EA=B2=8C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/component/bottomsheet/BottomSheet.tsx | 81 +++++++++++-------- 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/frontend/src/component/bottomsheet/BottomSheet.tsx b/frontend/src/component/bottomsheet/BottomSheet.tsx index 661fa928..cf46ee2d 100644 --- a/frontend/src/component/bottomsheet/BottomSheet.tsx +++ b/frontend/src/component/bottomsheet/BottomSheet.tsx @@ -1,5 +1,4 @@ -import React from 'react'; -import { useBottomSheet } from '@/hooks/useBottomSheet'; +import React, { useState, useRef } from 'react'; interface IBottomSheetProps { minHeight: number; @@ -7,47 +6,61 @@ interface IBottomSheetProps { children: React.ReactNode; } -/** - * `BottomSheet` 컴포넌트는 하단에서 올라오는 시트 형태의 UI를 제공합니다. - * - * @param {IBottomSheetProps} props - `children`을 포함한 컴포넌트 속성 - * @param {number} props.minHeight - Bottom Sheet의 최소 높이를 화면 비율로 나타냅니다 (0.0 - 1.0). - * @param {number} props.maxHeight - Bottom Sheet의 최대 높이를 화면 비율로 나타냅니다 (0.0 - 1.0). - * @param {ReactNode} props.children - Bottom Sheet 내부에 렌더링할 콘텐츠입니다. - * @returns {ReactNode} - 하단 시트를 렌더링합니다. - * - * @remarks - * - 드래그 동작을 통해 시트를 열고 닫을 수 있습니다. - * - `useBottomSheet` 훅을 사용하여 위치 및 드래그 동작을 관리합니다. - * - `minHeight`는 Bottom Sheet가 닫힌 상태의 높이 비율을 나타냅니다. - * - `maxHeight`는 Bottom Sheet가 열린 상태의 최대 높이 비율을 나타냅니다. - * - * @example - * ```tsx - * - *
- *

예시 콘텐츠

- *

BottomSheet의 children

- *
- *
- * ``` - */ - -export const BottomSheet = (props: IBottomSheetProps) => { - const { sheet } = useBottomSheet({ minHeight: props.minHeight, maxHeight: props.maxHeight }); +export const BottomSheet = ({ minHeight, maxHeight, children }: IBottomSheetProps) => { + const [sheetHeight, setSheetHeight] = useState(minHeight); + const startY = useRef(0); + const startHeight = useRef(minHeight); + + const handleStart = (y: number) => { + startY.current = y; + startHeight.current = sheetHeight; + }; + + const handleMove = (y: number) => { + const deltaY = startY.current - y; + const newHeight = startHeight.current + deltaY / window.innerHeight; + setSheetHeight(Math.max(minHeight, Math.min(maxHeight, newHeight))); + }; + + const handleTouchStart = (e: React.TouchEvent) => { + handleStart(e.touches[0].clientY); + }; + + const handleTouchMove = (e: React.TouchEvent) => { + handleMove(e.touches[0].clientY); + }; + + const handleMouseMove = (e: MouseEvent) => { + handleMove(e.clientY); + }; + + const handleMouseUp = () => { + window.removeEventListener('mousemove', handleMouseMove); + window.removeEventListener('mouseup', handleMouseUp); + }; + + const handleMouseDown = (e: React.MouseEvent) => { + handleStart(e.clientY); + window.addEventListener('mousemove', handleMouseMove); + window.addEventListener('mouseup', handleMouseUp); + }; return (
- {props.children} + +
{children}
); }; From 8bed5a8880105c81d7d68ed312b6c2dd9c612bbe Mon Sep 17 00:00:00 2001 From: juwon5272 Date: Tue, 26 Nov 2024 00:12:15 +0900 Subject: [PATCH 02/18] =?UTF-8?q?[FE][Feat]=20#28=20:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=9C=A0=EB=AC=B4=EC=97=90=20=EB=94=B0=EB=9D=BC=20?= =?UTF-8?q?=EB=B0=94=ED=85=80=EC=8B=9C=ED=8A=B8=EC=9D=98=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EB=B3=B4=EC=97=AC=EC=A4=80=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/Main.tsx | 106 ++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 34 deletions(-) diff --git a/frontend/src/pages/Main.tsx b/frontend/src/pages/Main.tsx index 7ecea493..2c54ec3a 100644 --- a/frontend/src/pages/Main.tsx +++ b/frontend/src/pages/Main.tsx @@ -7,33 +7,11 @@ import { FooterContext } from '@/component/layout/footer/LayoutFooterProvider'; import { useNavigate } from 'react-router-dom'; import { NaverMap } from '@/component/maps/NaverMapSample.tsx'; import { buttonActiveType } from '@/component/layout/enumTypes'; -import { loadLocalData, saveLocalData } from '@/utils/common/manageLocalData.ts'; +import { loadLocalData, saveLocalData, removeLocalData } from '@/utils/common/manageLocalData.ts'; import { AppConfig } from '@/constants.ts'; import { v4 as uuidv4 } from 'uuid'; - -const contentData = [ - { - id: '1', - title: '아들네 집으로', - time: '0시간 34분', - person: 2, - link: '/test1', - }, - { - id: '2', - title: '손자네 집으로', - time: '2시간 32분', - person: 0, - link: '/test2', - }, - { - id: '3', - title: '마을회관으로', - time: '0시간 12분', - person: 1, - link: '/test3', - }, -]; +import { AuthModal } from '@/component/authmodal/AuthModal'; +import { getUserChannels } from '@/api/channel.api.ts'; export const Main = () => { const { setFooterTitle, setFooterTransparency, setFooterOnClick, setFooterActive } = @@ -41,10 +19,30 @@ export const Main = () => { const { lat, lng, error } = getUserLocation(); const navigate = useNavigate(); const [otherLocations, setOtherLocations] = useState([]); - const MIN_HEIGHT = 0.5; - const MAX_HEIGHT = 0.8; + const MIN_HEIGHT = 0.35; + const MAX_HEIGHT = 0.9; + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [showLoginModal, setShowLoginModal] = useState(false); + const [channels, setChannels] = useState([]); + + useEffect(() => { + const token = loadLocalData(AppConfig.KEYS.LOGIN_TOKEN); + setIsLoggedIn(!!token); + + if (token) { + const userId = loadLocalData(AppConfig.KEYS.LOGIN_USER); + if (userId) { + getUserChannels(userId) + .then(response => { + if (response?.data?.channels) setChannels(response.data.channels); + }) + .catch(err => { + console.error('채널 찾기 실패 : ', err); + }); + } + } + }, []); - // eslint-disable-next-line consistent-return useEffect(() => { if (lat && lng) { if (!loadLocalData(AppConfig.KEYS.BROWSER_TOKEN)) { @@ -76,6 +74,7 @@ export const Main = () => { }; return () => ws.close(); } + return undefined; }, [lat, lng]); const goToAddChannel = () => { @@ -87,12 +86,35 @@ export const Main = () => { setFooterTransparency(false); setFooterActive(buttonActiveType.ACTIVE); }, []); + + const handleLoginRequest = () => { + setShowLoginModal(true); + }; + + const handleCloseLoginModal = () => { + setShowLoginModal(false); + setIsLoggedIn(true); + }; + + const handleLogout = () => { + removeLocalData(AppConfig.KEYS.LOGIN_TOKEN); + removeLocalData(AppConfig.KEYS.LOGIN_USER); + setIsLoggedIn(!isLoggedIn); + }; + + const isUserLoggedIn = loadLocalData(AppConfig.KEYS.LOGIN_TOKEN) !== null; + return (
+ {isUserLoggedIn && ( + + )}
{
- {contentData.map(item => ( - - -
-
- ))} + {isUserLoggedIn ? ( + channels.map(item => ( + + +
+
+ )) + ) : ( +
+ 로그인을 진행하여 +
+ 더 많은 기능을 +
+ 사용해보세요 +
+ )}
+ + {/* 로그인 모달 */} +
); }; From b83cc220fff29aa35a856a546e7a93c87caa6306 Mon Sep 17 00:00:00 2001 From: juwon5272 Date: Tue, 26 Nov 2024 00:17:24 +0900 Subject: [PATCH 03/18] =?UTF-8?q?[FE][Feat]=20#59=20:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=EC=8B=9C=20=EB=AA=A8=EB=8B=AC=EC=B0=BD=20=EB=8B=AB?= =?UTF-8?q?=ED=9E=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/component/authmodal/AuthModal.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/component/authmodal/AuthModal.tsx b/frontend/src/component/authmodal/AuthModal.tsx index b7f4b96e..bba55525 100644 --- a/frontend/src/component/authmodal/AuthModal.tsx +++ b/frontend/src/component/authmodal/AuthModal.tsx @@ -56,10 +56,11 @@ export const AuthModal = (props: IAuthModalProps) => { const handleLoginClick = () => { doLogin(loginData.id, loginData.pw) .then(el => { - if (el.data?.token && el.data?.userId) { - saveLocalData(AppConfig.KEYS.LOGIN_TOKEN, el.data.token); - saveLocalData(AppConfig.KEYS.LOGIN_USER, el.data.userId); + if (el.data?.data.token && el.data?.data.userId) { + saveLocalData(AppConfig.KEYS.LOGIN_TOKEN, el.data?.data.token); + saveLocalData(AppConfig.KEYS.LOGIN_USER, el.data?.data.userId); } + props.onClose(); // 부모 컴포넌트의 로그인 상태를 변경 window.location.reload(); }) .catch(() => { From bb6e1508dec83250f924f8fd0348ee9fbf164a6a Mon Sep 17 00:00:00 2001 From: effozen Date: Tue, 26 Nov 2024 13:05:09 +0900 Subject: [PATCH 04/18] =?UTF-8?q?[FE][Feat]=20#264=20:=20=EC=84=9C?= =?UTF-8?q?=EB=B2=84=EC=97=90=EC=84=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EB=B0=9B=EC=95=84=EC=99=80=EC=84=9C=20=EC=A7=80=EB=8F=84?= =?UTF-8?q?=EC=99=80=20=EC=BA=94=EB=B2=84=EC=8A=A4=EC=97=90=20=EC=A0=84?= =?UTF-8?q?=EB=8B=AC=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../canvasWithMapForView/MapCanvasForView.tsx | 1 + frontend/src/lib/types/canvasInterface.ts | 8 ++- frontend/src/pages/HostView.tsx | 51 +++++++++++++++++-- frontend/src/types/channel.types.ts | 1 + 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/frontend/src/component/canvasWithMap/canvasWithMapForView/MapCanvasForView.tsx b/frontend/src/component/canvasWithMap/canvasWithMapForView/MapCanvasForView.tsx index 45596aeb..f65c1d9e 100644 --- a/frontend/src/component/canvasWithMap/canvasWithMapForView/MapCanvasForView.tsx +++ b/frontend/src/component/canvasWithMap/canvasWithMapForView/MapCanvasForView.tsx @@ -36,6 +36,7 @@ export const MapCanvasForView = ({ endImageRef.current = new Image(); endImageRef.current.src = endmarker; + console.log(guests); }, []); useEffect(() => { diff --git a/frontend/src/lib/types/canvasInterface.ts b/frontend/src/lib/types/canvasInterface.ts index 924592a5..51baf572 100644 --- a/frontend/src/lib/types/canvasInterface.ts +++ b/frontend/src/lib/types/canvasInterface.ts @@ -25,12 +25,16 @@ export interface IOtherLiveLocations { token: string; } +export interface IMarkerStyle { + color: string; +} + export interface IGuestDataInMapProps { - guestName: string; - guestUUID: string; + name: string; startPoint: IPoint; endPoint: IPoint; paths: IPoint[]; + markerStyle: IMarkerStyle; } export interface IMapCanvasViewProps { diff --git a/frontend/src/pages/HostView.tsx b/frontend/src/pages/HostView.tsx index ea188923..9fd0e110 100644 --- a/frontend/src/pages/HostView.tsx +++ b/frontend/src/pages/HostView.tsx @@ -1,13 +1,18 @@ import { HeaderContext } from '@/component/layout/header/LayoutHeaderProvider'; import { useContext, useEffect, useState } from 'react'; -import { CanvasWithMap } from '@/component/canvas/CanvasWithMap.tsx'; -import { IUserChannelInfo } from '@/types/channel.types.ts'; +import { IGuest, IUserChannelInfo } from '@/types/channel.types.ts'; import { getChannelInfo } from '@/api/channel.api.ts'; import { useLocation } from 'react-router-dom'; +import { MapCanvasForView } from '@/component/canvasWithMap/canvasWithMapForView/MapCanvasForView.tsx'; +import { IGuestDataInMapProps, IPoint } from '@/lib/types/canvasInterface.ts'; export const HostView = () => { const [userChannels, setUserChannels] = useState(); const [userNames, setUserNames] = useState(['사용자 1']); + const [guestList, setGuestList] = useState([]); + const [mapProps, setMapProps] = useState([]); + + const [component, setComponent] = useState(); const headerContext = useContext(HeaderContext); @@ -16,13 +21,32 @@ export const HostView = () => { const fetchChannelInfo = (id: string) => { getChannelInfo(id) .then(res => { - if (res.data) setUserChannels(res.data); + if (res.data) setUserChannels(res.data as IUserChannelInfo); + setGuestList(res.data?.guests as IGuest[]); }) .catch((error: any) => { console.error(error); }); }; + const transformType = (props: IGuest) => { + return { + name: props.name ?? '', + startPoint: { + lat: props.start_location?.lat ?? 0, + lng: props.start_location?.lng ?? 0, + }, + endPoint: { + lat: props.end_location?.lat ?? 0, + lng: props.end_location?.lng ?? 0, + }, + paths: (props.path as IPoint[]) ?? [], + markerStyle: { + color: props.marker_style?.color ?? '', + }, + }; + }; + useEffect(() => { headerContext.setRightButton('dropdown'); headerContext.setLeftButton('back'); @@ -35,13 +59,32 @@ export const HostView = () => { if (userChannels?.guests) { const names = userChannels.guests.filter(Boolean).map(guest => guest.name!); setUserNames(names); + guestList.map(el => setMapProps(prev => [...prev, transformType(el)])); + // guestList.map(el => mapProps.push(transformType(el))); + // console.log(mapProps); } }, [userChannels]); + useEffect(() => { + if (mapProps.length > 1) { + setComponent( + , + ); + } + // console.log(mapProps); + }, [mapProps]); + useEffect(() => { headerContext.setItems(userNames); }, [userNames]); // TODO: geoCoding API를 이용해서 현재 위치나 시작위치를 기반으로 자동 좌표 설정 구현 (현재: 하드코딩) - return ; + // return ; + return
{component}
; }; diff --git a/frontend/src/types/channel.types.ts b/frontend/src/types/channel.types.ts index c96961e0..318b7331 100644 --- a/frontend/src/types/channel.types.ts +++ b/frontend/src/types/channel.types.ts @@ -8,6 +8,7 @@ export interface IGuestMarkerStyle { } export interface IGuest { + id: string | undefined; name: string | undefined; start_location: ILocation | undefined; end_location: ILocation | undefined; From 24af0b90a76d0d3e4c3a44e237e0e24224f1319f Mon Sep 17 00:00:00 2001 From: effozen Date: Tue, 26 Nov 2024 14:36:45 +0900 Subject: [PATCH 05/18] =?UTF-8?q?[FE][Refactor]=20#264=20:=20=ED=86=B5?= =?UTF-8?q?=EC=8B=A0=20=EA=B3=BC=EC=A0=95=EC=97=90=EC=84=9C=20=EC=93=B8?= =?UTF-8?q?=EB=8D=B0=EC=97=86=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=B0=8F=20=ED=83=80=EC=9E=85=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/channel.api.ts | 7 ++- frontend/src/api/dto/channel.dto.ts | 12 ++++ frontend/src/lib/types/canvasInterface.ts | 1 + frontend/src/pages/HostView.tsx | 75 +++++++++++++---------- frontend/src/types/channel.types.ts | 29 ++++----- 5 files changed, 75 insertions(+), 49 deletions(-) diff --git a/frontend/src/api/channel.api.ts b/frontend/src/api/channel.api.ts index de9d6fe4..1907acdc 100644 --- a/frontend/src/api/channel.api.ts +++ b/frontend/src/api/channel.api.ts @@ -2,6 +2,7 @@ import { ResponseDto } from '@/api/dto/response.dto.ts'; import { createChannelReqEntity, createChannelResEntity, + getChannelResEntity, getUserChannelsResEntity, } from '@/api/dto/channel.dto.ts'; import { getApiClient } from '@/api/client.api.ts'; @@ -56,9 +57,9 @@ export const getUserChannels = (userId: string): Promise> => { +export const getChannelInfo = (userId: string): Promise> => { const promiseFn = ( - fnResolve: (value: ResponseDto) => void, + fnResolve: (value: ResponseDto) => void, fnReject: (reason?: any) => void, ) => { const apiClient = getApiClient(); @@ -69,7 +70,7 @@ export const getChannelInfo = (userId: string): Promise(res.data)); + fnResolve(new ResponseDto(res.data)); } }) .catch(err => { diff --git a/frontend/src/api/dto/channel.dto.ts b/frontend/src/api/dto/channel.dto.ts index 58150eeb..d07fb3a5 100644 --- a/frontend/src/api/dto/channel.dto.ts +++ b/frontend/src/api/dto/channel.dto.ts @@ -9,6 +9,8 @@ export class guestMarkerStyleEntity { } export class guestEntity { + id: string | undefined; + name: string | undefined; start_location: locationEntity | undefined; @@ -57,3 +59,13 @@ export class channelListEntity { export class getUserChannelsResEntity { channels: channelListEntity[] | undefined; } + +export class getChannelResEntity { + id: string | undefined; + + name: string | undefined; + + host_id: string | undefined; + + guests: guestEntity[] | undefined; +} diff --git a/frontend/src/lib/types/canvasInterface.ts b/frontend/src/lib/types/canvasInterface.ts index 51baf572..15445017 100644 --- a/frontend/src/lib/types/canvasInterface.ts +++ b/frontend/src/lib/types/canvasInterface.ts @@ -30,6 +30,7 @@ export interface IMarkerStyle { } export interface IGuestDataInMapProps { + id: string; name: string; startPoint: IPoint; endPoint: IPoint; diff --git a/frontend/src/pages/HostView.tsx b/frontend/src/pages/HostView.tsx index 9fd0e110..9cf9890e 100644 --- a/frontend/src/pages/HostView.tsx +++ b/frontend/src/pages/HostView.tsx @@ -1,36 +1,25 @@ import { HeaderContext } from '@/component/layout/header/LayoutHeaderProvider'; -import { useContext, useEffect, useState } from 'react'; -import { IGuest, IUserChannelInfo } from '@/types/channel.types.ts'; +import { ReactNode, useContext, useEffect, useState } from 'react'; +import { IGuest, IChannelInfo } from '@/types/channel.types.ts'; import { getChannelInfo } from '@/api/channel.api.ts'; import { useLocation } from 'react-router-dom'; import { MapCanvasForView } from '@/component/canvasWithMap/canvasWithMapForView/MapCanvasForView.tsx'; import { IGuestDataInMapProps, IPoint } from '@/lib/types/canvasInterface.ts'; +import { getChannelResEntity, guestEntity } from '@/api/dto/channel.dto.ts'; export const HostView = () => { - const [userChannels, setUserChannels] = useState(); + const [channelInfo, setChannelInfo] = useState(); const [userNames, setUserNames] = useState(['사용자 1']); - const [guestList, setGuestList] = useState([]); const [mapProps, setMapProps] = useState([]); - - const [component, setComponent] = useState(); + const [component, setComponent] = useState(); const headerContext = useContext(HeaderContext); const location = useLocation(); - const fetchChannelInfo = (id: string) => { - getChannelInfo(id) - .then(res => { - if (res.data) setUserChannels(res.data as IUserChannelInfo); - setGuestList(res.data?.guests as IGuest[]); - }) - .catch((error: any) => { - console.error(error); - }); - }; - - const transformType = (props: IGuest) => { + const transformTypeGuestEntityToIGuest = (props: guestEntity): IGuest => { return { + id: props.id ?? '', name: props.name ?? '', startPoint: { lat: props.start_location?.lat ?? 0, @@ -47,6 +36,29 @@ export const HostView = () => { }; }; + const transformTypeFromResToInfo = (props: getChannelResEntity): IChannelInfo => { + const guests = props.guests?.map(guest => transformTypeGuestEntityToIGuest(guest)) ?? []; + + return { + name: props.name ?? '', + hostId: props.host_id ?? '', + channelId: props.id ?? '', + guests, + }; + }; + + const fetchChannelInfo = (userId: string) => { + getChannelInfo(userId) + .then(res => { + if (!res.data) throw new Error('🚀 Fetch Error: responsed undefined'); + const transfromedData = transformTypeFromResToInfo(res.data); + setChannelInfo(transfromedData); + }) + .catch((error: any) => { + console.error(error); + }); + }; + useEffect(() => { headerContext.setRightButton('dropdown'); headerContext.setLeftButton('back'); @@ -56,14 +68,18 @@ export const HostView = () => { }, []); useEffect(() => { - if (userChannels?.guests) { - const names = userChannels.guests.filter(Boolean).map(guest => guest.name!); + if (channelInfo?.guests) { + const names = channelInfo.guests.filter(Boolean).map(guest => guest.name!); setUserNames(names); - guestList.map(el => setMapProps(prev => [...prev, transformType(el)])); - // guestList.map(el => mapProps.push(transformType(el))); - // console.log(mapProps); + channelInfo.guests?.map(guest => + setMapProps(prev => [...prev, guest as IGuestDataInMapProps]), + ); } - }, [userChannels]); + }, [channelInfo]); + + useEffect(() => { + headerContext.setItems(userNames); + }, [userNames]); useEffect(() => { if (mapProps.length > 1) { @@ -77,14 +93,9 @@ export const HostView = () => { />, ); } - // console.log(mapProps); }, [mapProps]); - useEffect(() => { - headerContext.setItems(userNames); - }, [userNames]); - - // TODO: geoCoding API를 이용해서 현재 위치나 시작위치를 기반으로 자동 좌표 설정 구현 (현재: 하드코딩) - // return ; - return
{component}
; + return ( +
{component}
+ ); }; diff --git a/frontend/src/types/channel.types.ts b/frontend/src/types/channel.types.ts index 318b7331..98ecafb8 100644 --- a/frontend/src/types/channel.types.ts +++ b/frontend/src/types/channel.types.ts @@ -1,23 +1,24 @@ -export interface ILocation { - lat: number | undefined; - lng: number | undefined; +export interface IPoint { + lat: number; + lng: number; } export interface IGuestMarkerStyle { - color: string | undefined; + color: string; } export interface IGuest { - id: string | undefined; - name: string | undefined; - start_location: ILocation | undefined; - end_location: ILocation | undefined; - path: ILocation[] | undefined; - marker_style: IGuestMarkerStyle | undefined; + id: string; + name: string; + startPoint: IPoint; + endPoint: IPoint; + paths: IPoint[]; + markerStyle: IGuestMarkerStyle; } -export interface IUserChannelInfo { - host_id: string | undefined; - name: string | undefined; - guests: IGuest[] | undefined; +export interface IChannelInfo { + channelId: string; + hostId: string; + name: string; + guests: IGuest[]; } From 4350dbd8a16e4735d43550429a990c922912cae6 Mon Sep 17 00:00:00 2001 From: juwon5272 Date: Tue, 26 Nov 2024 15:00:57 +0900 Subject: [PATCH 06/18] =?UTF-8?q?[FE][Feat]=20#59=20:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8,=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=EC=8B=9C=20?= =?UTF-8?q?=EB=B6=88=EA=B0=80=EB=8A=A5=ED=95=9C=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=EC=95=88=EB=82=B4=EB=AC=B8=EA=B5=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/component/authmodal/AuthModal.tsx | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/frontend/src/component/authmodal/AuthModal.tsx b/frontend/src/component/authmodal/AuthModal.tsx index bba55525..3b4478fd 100644 --- a/frontend/src/component/authmodal/AuthModal.tsx +++ b/frontend/src/component/authmodal/AuthModal.tsx @@ -28,6 +28,7 @@ export const AuthModal = (props: IAuthModalProps) => { }); const [modalType, setModalType] = useState<'login' | 'register'>(props.type); + const [error, setError] = useState(''); const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target; @@ -46,43 +47,60 @@ export const AuthModal = (props: IAuthModalProps) => { }; const switchToRegister = () => { + setError(''); setModalType('register'); }; const switchToLogin = () => { + setError(''); setModalType('login'); }; const handleLoginClick = () => { + if (loginData.id || loginData.pw === '') { + setError('작성하지 않은 항목이 있습니다.'); + return; + } doLogin(loginData.id, loginData.pw) .then(el => { if (el.data?.data.token && el.data?.data.userId) { saveLocalData(AppConfig.KEYS.LOGIN_TOKEN, el.data?.data.token); saveLocalData(AppConfig.KEYS.LOGIN_USER, el.data?.data.userId); } - props.onClose(); // 부모 컴포넌트의 로그인 상태를 변경 + setError(''); + props.onClose(); + window.location.reload(); }) .catch(() => { - alert('아이디와 비밀번호를 다시 확인해주세요.'); + setError('아이디 혹은 비밀번호를 다시 확인해주세요.'); }); }; const handleSignUpClick = () => { if (registerData.pw !== registerData.confirmPw) { - alert('비밀번호가 일치하지 않습니다.'); + setError('비밀번호가 일치하지 않습니다.'); + return; + } + if ( + registerData.id || + registerData.email || + registerData.pw || + registerData.confirmPw || + registerData.name === '' + ) { + setError('작성하지 않은 항목이 있습니다.'); return; } doRegister(registerData.id, registerData.name, registerData.pw, registerData.email) .then(el => { if (el.data) { - alert('회원가입에 성공했습니다. 로그인해주세요.'); switchToLogin(); } }) .catch(() => { - alert( - '회원가입에 실패했습니다. 다시 확인해주세요.\nid는 4자 이상, 비밀번호는 6자리 이상이어야 합니다.', + setError( + `회원가입에 실패했습니다. 다시 확인해주세요.\nid는 4자 이상, 비밀번호는 6자리 이상이어야 합니다.`, ); }); }; @@ -106,6 +124,7 @@ export const AuthModal = (props: IAuthModalProps) => { value={loginData.pw} onChange={handleChange} /> + {error ?

{error}

: ''} { value={registerData.confirmPw} onChange={handleChange} /> + {error ?

{error}

: ''} + Date: Tue, 26 Nov 2024 15:01:41 +0900 Subject: [PATCH 07/18] =?UTF-8?q?[FE][Design]=20:=20Tailwind=20=EC=83=89?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/tailwind.config.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 325b5e83..74c5f62d 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -14,9 +14,12 @@ module.exports = { 75: '#E2E8F0', 100: '#EDF2F7', 150: '#AAB6C7', + 175: '#7A7A7A', + 180: '#7676801F', 200: '#6D6D6D', 400: '#555555', 800: '#3E3E3E', + 850: '#3C3C4399', 900: '#1C1C1C', }, blueGray: { From 27ab2207c2746ef4d7d374d19653beb059e38c0e Mon Sep 17 00:00:00 2001 From: juwon5272 Date: Tue, 26 Nov 2024 15:04:15 +0900 Subject: [PATCH 08/18] =?UTF-8?q?[FE][Feat]=20#14=20:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=97=AC=EB=B6=80=EC=97=90=20=EB=94=B0=EB=9D=BC=20?= =?UTF-8?q?=EB=B0=94=ED=85=80=EC=8B=9C=ED=8A=B8=20=EC=83=89=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/Main.tsx | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/frontend/src/pages/Main.tsx b/frontend/src/pages/Main.tsx index 2c54ec3a..36eab57a 100644 --- a/frontend/src/pages/Main.tsx +++ b/frontend/src/pages/Main.tsx @@ -139,27 +139,29 @@ export const Main = () => { )} - - {isUserLoggedIn ? ( - channels.map(item => ( + {isUserLoggedIn ? ( + + {channels.map(item => ( - +
- )) - ) : ( + ))} +
+ ) : ( +
- 로그인을 진행하여 -
- 더 많은 기능을 -
- 사용해보세요 +
+

로그인을 진행하여

+

더 많은 기능을

+

사용해보세요

+
- )} -
+
+ )} {/* 로그인 모달 */} From d9559f7a599cb3afafa65e56cfce9be24c928bc3 Mon Sep 17 00:00:00 2001 From: juwon5272 Date: Tue, 26 Nov 2024 15:05:42 +0900 Subject: [PATCH 09/18] =?UTF-8?q?[FE][Feat]=20#14=20:=20=EB=B0=94=ED=85=80?= =?UTF-8?q?=EC=8B=9C=ED=8A=B8=20=EB=82=B4=EC=9A=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/component/content/Content.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend/src/component/content/Content.tsx b/frontend/src/component/content/Content.tsx index 615d58d7..294382f3 100644 --- a/frontend/src/component/content/Content.tsx +++ b/frontend/src/component/content/Content.tsx @@ -2,7 +2,6 @@ import { MdGroup, MdMoreVert } from 'react-icons/md'; interface IContentProps { title: string; - time: string; person: number; link: string; } @@ -31,14 +30,14 @@ interface IContentProps { export const Content = (props: IContentProps) => { return (
{props.title}
- - {props.time} + {/* + {props.time} */} {props.person > 0 && ( <> From 0e0d50c27099c25f6fa1dded705c52b9faf217b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=EC=9C=A8?= Date: Tue, 26 Nov 2024 16:06:51 +0900 Subject: [PATCH 10/18] =?UTF-8?q?[FE][Fix]=20#257=20:=20=EC=BD=98=EC=86=94?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/component/searchbox/SearchBox.tsx | 3 +-- frontend/src/component/tooldescription/ToolDescription.tsx | 2 +- frontend/src/pages/AddChannel.tsx | 1 - frontend/src/pages/DrawRoute.tsx | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/frontend/src/component/searchbox/SearchBox.tsx b/frontend/src/component/searchbox/SearchBox.tsx index 95fd8a4b..8d5d85a8 100644 --- a/frontend/src/component/searchbox/SearchBox.tsx +++ b/frontend/src/component/searchbox/SearchBox.tsx @@ -79,7 +79,6 @@ export const SearchBox = (props: ISearchBoxProps) => { lat: parseFloat(item.mapy) / 1e7, lng: parseFloat(item.mapx) / 1e7, })); - console.log(data); setSearchResults(formattedResults); // 검색 결과 상태 업데이트 } catch (err) { setError(err instanceof Error ? err.message : '알 수 없는 오류'); @@ -177,7 +176,7 @@ export const SearchBox = (props: ISearchBoxProps) => { {searchResults.map(result => ( {isUserLoggedIn && ( )} @@ -143,7 +143,12 @@ export const Main = () => { {channels.map(item => ( - +
))} @@ -151,7 +156,7 @@ export const Main = () => { ) : (
From d8535a2dbba2e58f6bb137e019ee74ce8fc8a378 Mon Sep 17 00:00:00 2001 From: juwon5272 Date: Tue, 26 Nov 2024 16:48:19 +0900 Subject: [PATCH 12/18] =?UTF-8?q?[FE][Fix]=20:=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/channel.api.ts | 4 ++-- .../src/component/authmodal/AuthModal.tsx | 14 ------------ .../src/component/bottomsheet/BottomSheet.tsx | 22 ++++++++++++++++++- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/frontend/src/api/channel.api.ts b/frontend/src/api/channel.api.ts index b1eb3aad..4644f31d 100644 --- a/frontend/src/api/channel.api.ts +++ b/frontend/src/api/channel.api.ts @@ -21,7 +21,7 @@ export const createChannel = ( console.error(res); fnReject(`msg.${res}`); } else { - fnResolve(new ResponseDto(res)); + fnResolve(new ResponseDto(res.data)); } }) .catch(err => { @@ -45,7 +45,7 @@ export const getUserChannels = (userId: string): Promise(res)); + fnResolve(new ResponseDto(res.data)); } }) .catch(err => { diff --git a/frontend/src/component/authmodal/AuthModal.tsx b/frontend/src/component/authmodal/AuthModal.tsx index 3b4478fd..a09174da 100644 --- a/frontend/src/component/authmodal/AuthModal.tsx +++ b/frontend/src/component/authmodal/AuthModal.tsx @@ -57,10 +57,6 @@ export const AuthModal = (props: IAuthModalProps) => { }; const handleLoginClick = () => { - if (loginData.id || loginData.pw === '') { - setError('작성하지 않은 항목이 있습니다.'); - return; - } doLogin(loginData.id, loginData.pw) .then(el => { if (el.data?.data.token && el.data?.data.userId) { @@ -82,16 +78,6 @@ export const AuthModal = (props: IAuthModalProps) => { setError('비밀번호가 일치하지 않습니다.'); return; } - if ( - registerData.id || - registerData.email || - registerData.pw || - registerData.confirmPw || - registerData.name === '' - ) { - setError('작성하지 않은 항목이 있습니다.'); - return; - } doRegister(registerData.id, registerData.name, registerData.pw, registerData.email) .then(el => { if (el.data) { diff --git a/frontend/src/component/bottomsheet/BottomSheet.tsx b/frontend/src/component/bottomsheet/BottomSheet.tsx index cf46ee2d..83845649 100644 --- a/frontend/src/component/bottomsheet/BottomSheet.tsx +++ b/frontend/src/component/bottomsheet/BottomSheet.tsx @@ -3,10 +3,16 @@ import React, { useState, useRef } from 'react'; interface IBottomSheetProps { minHeight: number; maxHeight: number; + backgroundColor: string; children: React.ReactNode; } -export const BottomSheet = ({ minHeight, maxHeight, children }: IBottomSheetProps) => { +export const BottomSheet = ({ + minHeight, + maxHeight, + backgroundColor, + children, +}: IBottomSheetProps) => { const [sheetHeight, setSheetHeight] = useState(minHeight); const startY = useRef(0); const startHeight = useRef(minHeight); @@ -45,10 +51,15 @@ export const BottomSheet = ({ minHeight, maxHeight, children }: IBottomSheetProp window.addEventListener('mouseup', handleMouseUp); }; + const handleClose = () => { + setSheetHeight(minHeight); + }; + return (
+
+ +
{children}
From 8db2c6c1cf1a7526f48dfc40a116262199462ae1 Mon Sep 17 00:00:00 2001 From: Hyein Jeong Date: Tue, 26 Nov 2024 17:01:23 +0900 Subject: [PATCH 13/18] =?UTF-8?q?[FE][Feat]=20#274=20:=20=EC=A7=80?= =?UTF-8?q?=EB=8F=84=20=EA=B0=80=EC=A0=B8=EC=98=AC=20=EB=95=8C=20=EB=A1=9C?= =?UTF-8?q?=EB=94=A9=20=ED=99=94=EB=A9=B4=20=EC=B6=94=EA=B0=80=20(?= =?UTF-8?q?=EB=A1=9C=EB=94=A9=20=EC=8A=A4=ED=94=BC=EB=84=88=EB=A1=9C=20?= =?UTF-8?q?=EB=8C=80=EC=B2=B4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 지도 가져올 때 로딩 화면 추가 (로딩 스피너로 대체) - 홈 화면에서 지도 로딩 화면 적용 --- frontend/src/App.css | 19 +++++++++++++++++++ .../common/loadingSpinner/LoadingSpinner.tsx | 3 +++ frontend/src/pages/Main.tsx | 9 ++++++--- 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 frontend/src/component/common/loadingSpinner/LoadingSpinner.tsx diff --git a/frontend/src/App.css b/frontend/src/App.css index e6a56888..8aab6cad 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -44,3 +44,22 @@ -ms-user-select:none; user-select:none } + +.spinner { + width: 3rem; + height: 3rem; + border: 0.5rem solid rgba(0, 0, 0, 0.1); + border-top: 0.5rem solid #1c58b3; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 10px; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/frontend/src/component/common/loadingSpinner/LoadingSpinner.tsx b/frontend/src/component/common/loadingSpinner/LoadingSpinner.tsx new file mode 100644 index 00000000..e208f6ac --- /dev/null +++ b/frontend/src/component/common/loadingSpinner/LoadingSpinner.tsx @@ -0,0 +1,3 @@ +export const LoadingSpinner = () => { + return
; +}; diff --git a/frontend/src/pages/Main.tsx b/frontend/src/pages/Main.tsx index b0c787e0..049c9680 100644 --- a/frontend/src/pages/Main.tsx +++ b/frontend/src/pages/Main.tsx @@ -10,6 +10,7 @@ import { AppConfig } from '@/lib/constants/commonConstants.ts'; import { v4 as uuidv4 } from 'uuid'; import { getUserLocation } from '@/hooks/getUserLocation.ts'; import { MapCanvasForView } from '@/component/canvasWithMap/canvasWithMapForView/MapCanvasForView.tsx'; +import { LoadingSpinner } from '@/component/common/loadingSpinner/LoadingSpinner.tsx'; const contentData = [ { @@ -103,13 +104,15 @@ export const Main = () => { otherLocations={otherLocations} /> ) : ( -
+
+ Loading map data...
) ) : ( -
- {error ? `Error: ${error}` : 'Loading'} +
+ + {error ? `Error: ${error}` : 'Loading map data...'}
)} From 19c7c43f0c770b393c12576c98e25e67a718f152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=EC=9C=A8?= Date: Tue, 26 Nov 2024 17:03:17 +0900 Subject: [PATCH 14/18] =?UTF-8?q?[FE][Feat]=20#241=20:=20createChannelAPI?= =?UTF-8?q?=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/dto/channel.dto.ts | 10 ++++- .../routebutton/RouteResultButton.tsx | 2 +- frontend/src/pages/AddChannel.tsx | 44 ++++++++++++++++++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/frontend/src/api/dto/channel.dto.ts b/frontend/src/api/dto/channel.dto.ts index 58150eeb..4cd1031b 100644 --- a/frontend/src/api/dto/channel.dto.ts +++ b/frontend/src/api/dto/channel.dto.ts @@ -1,4 +1,12 @@ export class locationEntity { + title: string | undefined; + + lat: number | undefined; + + lng: number | undefined; +} + +export class pathLocationEntity { lat: number | undefined; lng: number | undefined; @@ -15,7 +23,7 @@ export class guestEntity { end_location: locationEntity | undefined; - path: locationEntity[] | undefined; + path: pathLocationEntity[] | undefined; marker_style: guestMarkerStyleEntity | undefined; } diff --git a/frontend/src/component/routebutton/RouteResultButton.tsx b/frontend/src/component/routebutton/RouteResultButton.tsx index 59cf11e7..f064f030 100644 --- a/frontend/src/component/routebutton/RouteResultButton.tsx +++ b/frontend/src/component/routebutton/RouteResultButton.tsx @@ -29,7 +29,7 @@ export const RouteResultButton = (props: IRouteResultButtonProps) => { )} >
- {props.user.end_location.title} + {props.user.start_location.title}
diff --git a/frontend/src/pages/AddChannel.tsx b/frontend/src/pages/AddChannel.tsx index 14e53fdc..c27b8c6e 100644 --- a/frontend/src/pages/AddChannel.tsx +++ b/frontend/src/pages/AddChannel.tsx @@ -6,6 +6,8 @@ import { Outlet } from 'react-router-dom'; import { RouteResultButton } from '@/component/routebutton/RouteResultButton'; import { IUser, UserContext } from '@/context/UserContext'; import { buttonActiveType } from '@/component/layout/enumTypes'; +import { createChannelReqEntity } from '@/api/dto/channel.dto'; +import { createChannel } from '@/api/channel.api'; import { InputBox } from '../component/common/InputBox'; /** @@ -35,7 +37,8 @@ const Divider = () =>
; export const AddChannel = () => { const [channelName, setChannelName] = useState(''); const { users, setUsers } = useContext(UserContext); - const { setFooterTitle, setFooterTransparency, setFooterActive } = useContext(FooterContext); + const { setFooterTitle, setFooterTransparency, setFooterActive, footerOption, setFooterOnClick } = + useContext(FooterContext); /** * 사용자 추가 함수 @@ -127,6 +130,45 @@ export const AddChannel = () => { } }, [users, setFooterActive]); // users가 변경될 때마다 실행 + const createChannelAPI = async () => { + try { + const channelData: createChannelReqEntity = { + name: channelName, + host_id: 'jhi2359', + guests: users.map(user => ({ + name: user.name, + start_location: { + title: user.start_location.title, + lat: user.start_location.lat, + lng: user.start_location.lng, + }, + end_location: { + title: user.end_location.title, + lat: user.end_location.lat, + lng: user.end_location.lng, + }, + path: user.path.map(p => ({ + lat: p.lat, + lng: p.lng, + })), + marker_style: user.marker_style, + })), + }; + + // createChannel 호출 + const response = await createChannel(channelData); + console.log('채널 생성 성공:', response); + } catch (error) { + console.error('채널 생성 실패:', error); + } + }; + + useEffect(() => { + setFooterOnClick(() => { + createChannelAPI(); + }); + }, [footerOption.active, channelName]); // channelName이 변경될 때마다 실행 + return (
From 22a109d783f31a045d4d43a7235256af0ba98ab0 Mon Sep 17 00:00:00 2001 From: Hyein Jeong Date: Tue, 26 Nov 2024 17:05:12 +0900 Subject: [PATCH 15/18] =?UTF-8?q?[FE][Feat]=20#274=20:=20=EC=A7=80?= =?UTF-8?q?=EB=8F=84=20=EA=B0=80=EC=A0=B8=EC=98=AC=20=EB=95=8C=20=EB=A1=9C?= =?UTF-8?q?=EB=94=A9=20=ED=99=94=EB=A9=B4=20=EC=B6=94=EA=B0=80=20(?= =?UTF-8?q?=EB=A1=9C=EB=94=A9=20=EC=8A=A4=ED=94=BC=EB=84=88=EB=A1=9C=20?= =?UTF-8?q?=EB=8C=80=EC=B2=B4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 지도 가져올 때 로딩 화면 추가 (로딩 스피너로 대체) - 홈 화면에서 지도 로딩 화면 적용 --- .../src/component/common/loadingSpinner/LoadingSpinner.tsx | 7 ++++++- frontend/src/pages/Main.tsx | 5 +---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/src/component/common/loadingSpinner/LoadingSpinner.tsx b/frontend/src/component/common/loadingSpinner/LoadingSpinner.tsx index e208f6ac..a39e2c16 100644 --- a/frontend/src/component/common/loadingSpinner/LoadingSpinner.tsx +++ b/frontend/src/component/common/loadingSpinner/LoadingSpinner.tsx @@ -1,3 +1,8 @@ export const LoadingSpinner = () => { - return
; + return ( +
+
+ Loading map data... +
+ ); }; diff --git a/frontend/src/pages/Main.tsx b/frontend/src/pages/Main.tsx index 049c9680..af175535 100644 --- a/frontend/src/pages/Main.tsx +++ b/frontend/src/pages/Main.tsx @@ -104,10 +104,7 @@ export const Main = () => { otherLocations={otherLocations} /> ) : ( -
- - Loading map data... -
+ ) ) : (
From a31703d161f69f8c5e3b9c97483ea05af9e64f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=EC=9C=A8?= Date: Tue, 26 Nov 2024 17:15:19 +0900 Subject: [PATCH 16/18] =?UTF-8?q?[FE][Feat]=20#241=20:=20API=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=EC=8B=9C=20=EB=A9=94=EC=9D=B8=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/AddChannel.tsx | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/AddChannel.tsx b/frontend/src/pages/AddChannel.tsx index c27b8c6e..1eb5111f 100644 --- a/frontend/src/pages/AddChannel.tsx +++ b/frontend/src/pages/AddChannel.tsx @@ -2,7 +2,7 @@ import { useContext, useEffect, useState } from 'react'; import { HiMiniInformationCircle } from 'react-icons/hi2'; import { FooterContext } from '@/component/layout/footer/LayoutFooterProvider'; import { RouteSettingButton } from '@/component/routebutton/RouteSettingButton'; -import { Outlet } from 'react-router-dom'; +import { Outlet, useNavigate } from 'react-router-dom'; import { RouteResultButton } from '@/component/routebutton/RouteResultButton'; import { IUser, UserContext } from '@/context/UserContext'; import { buttonActiveType } from '@/component/layout/enumTypes'; @@ -37,8 +37,15 @@ const Divider = () =>
; export const AddChannel = () => { const [channelName, setChannelName] = useState(''); const { users, setUsers } = useContext(UserContext); - const { setFooterTitle, setFooterTransparency, setFooterActive, footerOption, setFooterOnClick } = - useContext(FooterContext); + const { + setFooterTitle, + setFooterTransparency, + setFooterActive, + footerOption, + setFooterOnClick, + resetFooterContext, + } = useContext(FooterContext); + const navigate = useNavigate(); /** * 사용자 추가 함수 @@ -162,10 +169,14 @@ export const AddChannel = () => { console.error('채널 생성 실패:', error); } }; - + const goToMainPage = () => { + navigate('/'); + resetFooterContext(); + }; useEffect(() => { setFooterOnClick(() => { createChannelAPI(); + goToMainPage(); }); }, [footerOption.active, channelName]); // channelName이 변경될 때마다 실행 From b5c2469a825a8f7fcd84789b70947c4be9453698 Mon Sep 17 00:00:00 2001 From: juwon5272 Date: Tue, 26 Nov 2024 17:16:40 +0900 Subject: [PATCH 17/18] =?UTF-8?q?[FE][Feat]=20:=20DTO=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/dto/auth.dto.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/frontend/src/api/dto/auth.dto.ts b/frontend/src/api/dto/auth.dto.ts index 528a074a..9d63e921 100644 --- a/frontend/src/api/dto/auth.dto.ts +++ b/frontend/src/api/dto/auth.dto.ts @@ -1,7 +1,11 @@ export class LoginResEntity { - token: string | undefined; - - userId: string | undefined; + data: { + token: string | undefined; + userId: string | undefined; + } = { + token: undefined, + userId: undefined, + }; } export class RegisterResEntity { From 5fc5f049c5baaf1a5d4ee0407158b2836e8d0639 Mon Sep 17 00:00:00 2001 From: juwon5272 Date: Tue, 26 Nov 2024 17:19:16 +0900 Subject: [PATCH 18/18] =?UTF-8?q?[FE][Fix]=20:=20=EC=B6=A9=EB=8F=8C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/Main.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontend/src/pages/Main.tsx b/frontend/src/pages/Main.tsx index ddb00cd9..f4fb9609 100644 --- a/frontend/src/pages/Main.tsx +++ b/frontend/src/pages/Main.tsx @@ -1,6 +1,5 @@ import { Fragment, useContext, useEffect, useState } from 'react'; import { MdFormatListBulleted, MdLogout } from 'react-icons/md'; -import { MdFormatListBulleted } from 'react-icons/md'; import { FooterContext } from '@/component/layout/footer/LayoutFooterProvider'; import { useNavigate } from 'react-router-dom'; import { buttonActiveType } from '@/component/layout/enumTypes'; @@ -9,13 +8,11 @@ import { AuthModal } from '@/component/authmodal/AuthModal'; import { getUserChannels } from '@/api/channel.api.ts'; import { BottomSheet } from '@/component/bottomsheet/BottomSheet.tsx'; import { Content } from '@/component/content/Content.tsx'; -import { loadLocalData, saveLocalData } from '@/utils/common/manageLocalData.ts'; import { AppConfig } from '@/lib/constants/commonConstants.ts'; import { v4 as uuidv4 } from 'uuid'; import { getUserLocation } from '@/hooks/getUserLocation.ts'; import { MapCanvasForView } from '@/component/canvasWithMap/canvasWithMapForView/MapCanvasForView.tsx'; - export const Main = () => { const { setFooterTitle, setFooterTransparency, setFooterOnClick, setFooterActive } = useContext(FooterContext);