From 0b312885a0723d80d73ff9da2397678089a17913 Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Thu, 18 Jan 2024 05:54:03 +0900 Subject: [PATCH 01/10] =?UTF-8?q?Design:=20=EA=B3=B5=EC=9C=A0=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EB=A7=88=ED=81=AC=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 35 ++++++++++++++++ src/api/trips.ts | 12 ++++++ src/components/Share/CopyBox.tsx | 38 +++++++++++++++++ src/components/Share/CopyToast.tsx | 36 ++++++++++++++++ src/components/Trip/TripSectionTop.tsx | 5 ++- src/components/common/BackBox/BackBox.tsx | 6 ++- src/pages/share/share.page.tsx | 51 +++++++++++++++++++++++ src/router/socketRouter.tsx | 2 + tailwind.config.js | 2 + 10 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 src/components/Share/CopyBox.tsx create mode 100644 src/components/Share/CopyToast.tsx create mode 100644 src/pages/share/share.page.tsx diff --git a/package.json b/package.json index 753474f8..a47d801e 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@radix-ui/react-radio-group": "^1.1.3", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-toggle-group": "^1.0.4", "@stomp/stompjs": "^7.0.0", "@svgr/rollup": "^8.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d42035a..ed96f9f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,9 @@ dependencies: '@radix-ui/react-tabs': specifier: ^1.0.4 version: 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-toast': + specifier: ^1.1.5 + version: 1.1.5(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-toggle-group': specifier: ^1.0.4 version: 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) @@ -2424,6 +2427,38 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-toast@1.1.5(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-fRLn227WHIBRSzuRzGJ8W+5YALxofH23y0MlPLddaIpLpCDqdE0NZlS2NRQDRiptfxDeeCjgFIpexB1/zkxDlw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.18 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-toggle-group@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Uaj/M/cMyiyT9Bx6fOZO0SAG4Cls0GptBWiBmBxofmDbNVnYYoyRWj/2M/6VCi/7qcXFWnHhRUfdfZFvvkuu8A==} peerDependencies: diff --git a/src/api/trips.ts b/src/api/trips.ts index 3441cb6b..e704e469 100644 --- a/src/api/trips.ts +++ b/src/api/trips.ts @@ -68,3 +68,15 @@ export const getTripsSurvey = async (tripId: number) => { const res = await client.get(`trips/${tripId}/survey`); return res; }; + +// 여정 참여 코드 조회 +export const getTripsjoin = async (tripId: number) => { + const res = await authClient.get(`trips/${tripId}/join`); + return res; +}; + +// 여정 참여 +export const postTripsjoin = async (tripId: number, joinCode: number) => { + const res = await client.post(`trips/${tripId}/join`, { joinCode }); + return res; +}; diff --git a/src/components/Share/CopyBox.tsx b/src/components/Share/CopyBox.tsx new file mode 100644 index 00000000..7dc6a289 --- /dev/null +++ b/src/components/Share/CopyBox.tsx @@ -0,0 +1,38 @@ +import CopyToast from './CopyToast'; + +interface Props { + title: string; + subTitle: string; + copyValue: string; +} + +const CopyBox = ({ title, subTitle, copyValue }: Props) => { + const onCopyClick = () => { + navigator.clipboard.writeText(copyValue); + }; + + return ( +
+
+ {`${title} 복사`} + {subTitle} +
+
+ + +
+ 복사 +
+
+
+
+ ); +}; + +export default CopyBox; diff --git a/src/components/Share/CopyToast.tsx b/src/components/Share/CopyToast.tsx new file mode 100644 index 00000000..4f7492a3 --- /dev/null +++ b/src/components/Share/CopyToast.tsx @@ -0,0 +1,36 @@ +import * as Toast from '@radix-ui/react-toast'; +import { ReactNode, useState } from 'react'; +import { ReactComponent as CircleCheckIcon } from '@assets/images/CircleCheck.svg'; + +interface Props { + title: string; + children: ReactNode; +} + +const CopyToast = ({ title, children }: Props) => { + const [open, setOpen] = useState(false); + + return ( + + + + + + + {`${title}가 복사되었습니다.`} + + + + + ); +}; + +export default CopyToast; diff --git a/src/components/Trip/TripSectionTop.tsx b/src/components/Trip/TripSectionTop.tsx index 82e03c8e..de28b0a6 100644 --- a/src/components/Trip/TripSectionTop.tsx +++ b/src/components/Trip/TripSectionTop.tsx @@ -13,10 +13,13 @@ const TripSectionTop = () => {
{ navigate(-1); }} + showShare={true} + shareHandler={() => { + navigate('share'); + }} /> diff --git a/src/components/common/BackBox/BackBox.tsx b/src/components/common/BackBox/BackBox.tsx index 4af0db0f..0d29c96f 100644 --- a/src/components/common/BackBox/BackBox.tsx +++ b/src/components/common/BackBox/BackBox.tsx @@ -10,6 +10,7 @@ interface Props { showSave?: boolean; saveHandler?: VoidFunction; showShare?: boolean; + shareHandler?: VoidFunction; } const BackBox = ({ @@ -21,6 +22,7 @@ const BackBox = ({ showSave, saveHandler, showShare, + shareHandler, }: Props) => { const onBackClick = () => { backHandler && backHandler(); @@ -55,7 +57,9 @@ const BackBox = ({ )} {showShare && ( - )} diff --git a/src/pages/share/share.page.tsx b/src/pages/share/share.page.tsx new file mode 100644 index 00000000..afa87318 --- /dev/null +++ b/src/pages/share/share.page.tsx @@ -0,0 +1,51 @@ +import { getTripsjoin } from '@api/trips'; +import CopyBox from '@components/Share/CopyBox'; +import { BackBox } from '@components/common'; +import { useEffect, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; + +const Share = () => { + const navigate = useNavigate(); + const [joinCode, setJoinCode] = useState(null); + + useEffect(() => { + const getTripCode = async () => { + try { + const { data } = await getTripsjoin(27); + if (data.status === 200) { + setJoinCode(data.data); + } + } catch (err) { + console.error(err); + } + }; + getTripCode(); + }, []); + return ( +
+ { + navigate(-1); + }}> + 공유하기 + +
+ + {joinCode && ( + + )} +
+
+ ); +}; + +export default Share; diff --git a/src/router/socketRouter.tsx b/src/router/socketRouter.tsx index 4503f830..53fcb1ca 100644 --- a/src/router/socketRouter.tsx +++ b/src/router/socketRouter.tsx @@ -7,6 +7,7 @@ import Trip from '@pages/trip/trip.page'; import MainLayout from './routerLayout'; import { useRecoilValue } from 'recoil'; import { tripIdState, visitDateState } from '@recoil/socket'; +import Share from '@pages/share/share.page'; const SocketRoutes = () => { const tripId = useRecoilValue(tripIdState); @@ -31,6 +32,7 @@ const SocketRouter = () => { }> } /> + } /> } /> diff --git a/tailwind.config.js b/tailwind.config.js index 0ec3313f..44bf1e11 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -6,6 +6,8 @@ export default { colors: { main1: '#062139', main2: '#29DDF6', + main3: '#DAF9FF', + main4: '#F2FDFF', sub1: '#FFEC3E', sub2: '#FF2167', gray1: '#f8f8f8', From d377689f99e698833c506d32d516078d9d435ee0 Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Thu, 18 Jan 2024 07:34:13 +0900 Subject: [PATCH 02/10] =?UTF-8?q?Design:=20=EC=BD=94=EB=93=9C=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A7=88=ED=81=AC?= =?UTF-8?q?=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/trips.ts | 2 +- src/pages/share/shareCode.page.tsx | 82 ++++++++++++++++++++++++++++++ src/router/socketRouter.tsx | 2 + 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/pages/share/shareCode.page.tsx diff --git a/src/api/trips.ts b/src/api/trips.ts index e704e469..b2803936 100644 --- a/src/api/trips.ts +++ b/src/api/trips.ts @@ -76,7 +76,7 @@ export const getTripsjoin = async (tripId: number) => { }; // 여정 참여 -export const postTripsjoin = async (tripId: number, joinCode: number) => { +export const postTripsjoin = async (tripId: number, joinCode: string) => { const res = await client.post(`trips/${tripId}/join`, { joinCode }); return res; }; diff --git a/src/pages/share/shareCode.page.tsx b/src/pages/share/shareCode.page.tsx new file mode 100644 index 00000000..431f8e90 --- /dev/null +++ b/src/pages/share/shareCode.page.tsx @@ -0,0 +1,82 @@ +import { postTripsjoin } from '@api/trips'; +import { BackBox } from '@components/common'; +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; + +const shareCode = () => { + const navigate = useNavigate(); + const [inputCode, setInputCode] = useState(''); + const [showError, setShowError] = useState(false); + + const onCodeChange = async (e: React.ChangeEvent) => { + const changeValue = e.target.value; + if (changeValue.length <= 5) { + setInputCode(e.target.value); + } + if (changeValue.length === 5) { + try { + const res = await postTripsjoin(27, changeValue); + console.log(res); + } catch (err) { + setShowError(true); + setInputCode(''); + console.error('참여 코드 요청 중 에러 발생', err); + } + } + }; + + return ( +
+ { + navigate(-1); + }} + /> +
+
+ 편집 참여 코드 입력 + + 편집 참여 코드를 입력하면 여행 계획을 편집할 수 있어요. + +
+ +
+ + {inputCode.split('').map((code, index) => { + return ( +
+ {code} +
+ ); + })} + {Array(5 - inputCode.length) + .fill(null) + .map((_, index) => { + return ( +
+ ); + })} +
+ {showError && ( +
+ 편집 참여 코드를 다시 한번 확인해주세요. +
+ )} +
+
+ ); +}; + +export default shareCode; diff --git a/src/router/socketRouter.tsx b/src/router/socketRouter.tsx index 53fcb1ca..111d60bd 100644 --- a/src/router/socketRouter.tsx +++ b/src/router/socketRouter.tsx @@ -8,6 +8,7 @@ import MainLayout from './routerLayout'; import { useRecoilValue } from 'recoil'; import { tripIdState, visitDateState } from '@recoil/socket'; import Share from '@pages/share/share.page'; +import ShareCode from '@pages/share/shareCode.page'; const SocketRoutes = () => { const tripId = useRecoilValue(tripIdState); @@ -33,6 +34,7 @@ const SocketRouter = () => { }> } /> } /> + } /> } /> From a0a37b27487b5767f012a38f9ebb9b79e842407c Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Sat, 20 Jan 2024 02:04:08 +0900 Subject: [PATCH 03/10] =?UTF-8?q?Refactor:=20=ED=8E=B8=EC=A7=91=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9A=94=EC=B2=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/trips.ts | 4 ++-- src/pages/share/share.page.tsx | 24 ++++++++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/api/trips.ts b/src/api/trips.ts index b2803936..c9c42736 100644 --- a/src/api/trips.ts +++ b/src/api/trips.ts @@ -70,13 +70,13 @@ export const getTripsSurvey = async (tripId: number) => { }; // 여정 참여 코드 조회 -export const getTripsjoin = async (tripId: number) => { +export const getTripsjoin = async (tripId: string) => { const res = await authClient.get(`trips/${tripId}/join`); return res; }; // 여정 참여 export const postTripsjoin = async (tripId: number, joinCode: string) => { - const res = await client.post(`trips/${tripId}/join`, { joinCode }); + const res = await authClient.post(`trips/${tripId}/join`, { joinCode }); return res; }; diff --git a/src/pages/share/share.page.tsx b/src/pages/share/share.page.tsx index afa87318..ecd87444 100644 --- a/src/pages/share/share.page.tsx +++ b/src/pages/share/share.page.tsx @@ -2,25 +2,33 @@ import { getTripsjoin } from '@api/trips'; import CopyBox from '@components/Share/CopyBox'; import { BackBox } from '@components/common'; import { useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; const Share = () => { const navigate = useNavigate(); const [joinCode, setJoinCode] = useState(null); + const params = useParams(); + const tripId = params.id; useEffect(() => { const getTripCode = async () => { - try { - const { data } = await getTripsjoin(27); - if (data.status === 200) { - setJoinCode(data.data); + if (tripId) { + try { + const { data } = await getTripsjoin(tripId); + if (data.status === 200) { + setJoinCode(data.data); + } + } catch (err) { + console.error('편집 참여 코드 요청 중 에러 발생', err); } - } catch (err) { - console.error(err); } }; getTripCode(); }, []); + + const url = window.location.href; + const shareUrl = url.replace('/share', ''); + return (
{ {joinCode && ( Date: Sat, 20 Jan 2024 02:40:09 +0900 Subject: [PATCH 04/10] =?UTF-8?q?Refactor:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/share/share.page.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/share/share.page.tsx b/src/pages/share/share.page.tsx index ecd87444..7d6d5887 100644 --- a/src/pages/share/share.page.tsx +++ b/src/pages/share/share.page.tsx @@ -7,8 +7,7 @@ import { useNavigate, useParams } from 'react-router-dom'; const Share = () => { const navigate = useNavigate(); const [joinCode, setJoinCode] = useState(null); - const params = useParams(); - const tripId = params.id; + const { id: tripId } = useParams(); useEffect(() => { const getTripCode = async () => { From 8ac1555950862a7d4ce76418153311e67b3cc912 Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Sat, 20 Jan 2024 02:41:58 +0900 Subject: [PATCH 05/10] =?UTF-8?q?Feat:=20=EC=9D=B4=EB=AF=B8=20=ED=8E=B8?= =?UTF-8?q?=EC=A7=91=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EB=A6=AC=EB=8B=A4=EC=9D=B4=EB=A0=89=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/share/shareCode.page.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/pages/share/shareCode.page.tsx b/src/pages/share/shareCode.page.tsx index 431f8e90..86909ae8 100644 --- a/src/pages/share/shareCode.page.tsx +++ b/src/pages/share/shareCode.page.tsx @@ -1,10 +1,20 @@ import { postTripsjoin } from '@api/trips'; import { BackBox } from '@components/common'; -import { useState } from 'react'; +import { useGetTripsAuthority } from '@hooks/useGetTripsAuthority'; +import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; const shareCode = () => { const navigate = useNavigate(); + const { tripAuthority, TripId } = useGetTripsAuthority(); + + useEffect(() => { + if (tripAuthority === 'WRITE' && TripId) { + alert('이미 편집 가능한 여정입니다.'); + navigate(`/trip/${TripId}`); + } + }, [tripAuthority, TripId]); + const [inputCode, setInputCode] = useState(''); const [showError, setShowError] = useState(false); @@ -13,9 +23,9 @@ const shareCode = () => { if (changeValue.length <= 5) { setInputCode(e.target.value); } - if (changeValue.length === 5) { + if (changeValue.length === 5 && TripId) { try { - const res = await postTripsjoin(27, changeValue); + const res = await postTripsjoin(TripId, changeValue); console.log(res); } catch (err) { setShowError(true); From 0080ff78ebfcf16fd85740656ab15c37281910e8 Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Sat, 20 Jan 2024 04:12:53 +0900 Subject: [PATCH 06/10] =?UTF-8?q?Feat:=20=EC=B0=B8=EC=97=AC=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=9E=85=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=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 --- src/components/Share/IsEditableModal.tsx | 69 ++++++++++++++++++++++++ src/components/Trip/TripSectionTop.tsx | 12 ++++- src/components/common/icons/Icons.tsx | 50 +++++++++++++++++ src/pages/share/shareCode.page.tsx | 8 +-- 4 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 src/components/Share/IsEditableModal.tsx diff --git a/src/components/Share/IsEditableModal.tsx b/src/components/Share/IsEditableModal.tsx new file mode 100644 index 00000000..31dccb96 --- /dev/null +++ b/src/components/Share/IsEditableModal.tsx @@ -0,0 +1,69 @@ +import * as Dialog from '@radix-ui/react-dialog'; +import { EditStarIcon } from '@components/common/icons/Icons'; +import Alert from '@components/common/alert/Alert'; +import { useNavigate } from 'react-router-dom'; +import { getItem } from '@utils/localStorageFun'; + +interface Props { + isEditable: boolean; + setIsEditable: React.Dispatch>; +} + +const IsEditableModal = ({ isEditable, setIsEditable }: Props) => { + const navigate = useNavigate(); + const isLogin = getItem('accessToken'); + + const handleConfirm = () => { + navigate('/login'); + }; + + return ( + + + + + + + + + 편집 참여 코드를 입력하시면 +
+ 여행 계획을 함께 편집할 수 있어요! +
+ + + + {isLogin ? ( + + ) : ( + + 편집 참여 코드 입력을 위해 로그인이 필요해요. +
+ 로그인하시겠어요? + + } + onConfirm={handleConfirm}> + +
+ )} + + + +
+
+
+ ); +}; + +export default IsEditableModal; diff --git a/src/components/Trip/TripSectionTop.tsx b/src/components/Trip/TripSectionTop.tsx index 5c124851..d1388108 100644 --- a/src/components/Trip/TripSectionTop.tsx +++ b/src/components/Trip/TripSectionTop.tsx @@ -6,15 +6,25 @@ import { useNavigate } from 'react-router-dom'; import PlanTripButton from './PlanTripButton'; import { LikedToursList } from './LikedToursList'; import { useGetTripsAuthority } from '@hooks/useGetTripsAuthority'; +import { useEffect, useState } from 'react'; +import IsEditableModal from '@components/Share/IsEditableModal'; const TripSectionTop = () => { const navigate = useNavigate(); const { tripAuthority } = useGetTripsAuthority(); + const [isEditable, setIsEditable] = useState(false); - console.log(tripAuthority); + useEffect(() => { + if (tripAuthority !== null) { + if (tripAuthority !== 'WRITE') { + setIsEditable(true); + } + } + }, [tripAuthority]); return (
+ { diff --git a/src/components/common/icons/Icons.tsx b/src/components/common/icons/Icons.tsx index ab793d75..a86f092a 100644 --- a/src/components/common/icons/Icons.tsx +++ b/src/components/common/icons/Icons.tsx @@ -1562,6 +1562,56 @@ export const OrangeIcon: React.FC = ({ size = 20, className }) => { ); }; +export const EditStarIcon = () => { + return ( + + + + + + + + + + + + + ); +}; + export const GreenIcon: React.FC = ({ size = 20, className }) => { return ( { useEffect(() => { if (tripAuthority === 'WRITE' && TripId) { alert('이미 편집 가능한 여정입니다.'); - navigate(`/trip/${TripId}`); + navigate(`/trip/${TripId}`, { replace: true }); } }, [tripAuthority, TripId]); @@ -25,8 +25,10 @@ const shareCode = () => { } if (changeValue.length === 5 && TripId) { try { - const res = await postTripsjoin(TripId, changeValue); - console.log(res); + const { data } = await postTripsjoin(TripId, changeValue); + if (data.status === 200) { + navigate(`/trip/${TripId}`, { replace: true }); + } } catch (err) { setShowError(true); setInputCode(''); From 0008df4cc0c45becfcb7969aa713524de79e90e5 Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Sat, 20 Jan 2024 04:33:39 +0900 Subject: [PATCH 07/10] =?UTF-8?q?Feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=9B=84=20=EC=BD=94=EB=93=9C=20=EC=9E=85=EB=A0=A5=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Auth/Login/LoginForm.tsx | 10 ++++++++-- src/components/Plan/PlanSectionTop.tsx | 1 - src/components/Share/IsEditableModal.tsx | 9 ++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/components/Auth/Login/LoginForm.tsx b/src/components/Auth/Login/LoginForm.tsx index db12f7bc..d1e88621 100644 --- a/src/components/Auth/Login/LoginForm.tsx +++ b/src/components/Auth/Login/LoginForm.tsx @@ -1,7 +1,7 @@ import type { AuthRequest } from '@/@types/auth.types'; import { SubmitHandler, useForm } from 'react-hook-form'; import { postEmailLogin } from '@api/auth'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import { AxiosError } from 'axios'; import { useState } from 'react'; import SubmitBtn from '@components/common/button/SubmitBtn'; @@ -26,6 +26,8 @@ const LoginForm = () => { }); const navigate = useNavigate(); + const { state } = useLocation(); + // const [userInfo, setUserInfo] = useRecoilState(UserInfoState); const onLoginSubmit: SubmitHandler = async (data) => { @@ -38,7 +40,11 @@ const LoginForm = () => { if (res.data.status === 200) { setItem('accessToken', res.data.data.tokenInfo.accessToken); // setUserInfo(res.data.data.memberDto); - navigate('/'); + if (state) { + navigate(`${state.prevPath}/code`); + } else { + navigate('/'); + } } } catch (err) { if (err instanceof AxiosError) { diff --git a/src/components/Plan/PlanSectionTop.tsx b/src/components/Plan/PlanSectionTop.tsx index 5f99f5d4..114ee5a5 100644 --- a/src/components/Plan/PlanSectionTop.tsx +++ b/src/components/Plan/PlanSectionTop.tsx @@ -13,7 +13,6 @@ import { dayState, dateState } from '@recoil/plan'; import { tripIdState, memberIdState } from '@recoil/socket'; import { calculateDayAndDate } from '@utils/utils'; import { TripSchedule } from '@components/Trip/TripSchedule'; -import { getItem } from '@utils/localStorageFun'; const PlanSectionTop = () => { const navigate = useNavigate(); diff --git a/src/components/Share/IsEditableModal.tsx b/src/components/Share/IsEditableModal.tsx index 31dccb96..ee917224 100644 --- a/src/components/Share/IsEditableModal.tsx +++ b/src/components/Share/IsEditableModal.tsx @@ -1,7 +1,7 @@ import * as Dialog from '@radix-ui/react-dialog'; import { EditStarIcon } from '@components/common/icons/Icons'; import Alert from '@components/common/alert/Alert'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import { getItem } from '@utils/localStorageFun'; interface Props { @@ -11,19 +11,18 @@ interface Props { const IsEditableModal = ({ isEditable, setIsEditable }: Props) => { const navigate = useNavigate(); + const { pathname } = useLocation(); + const isLogin = getItem('accessToken'); const handleConfirm = () => { - navigate('/login'); + navigate('/login', { state: { prevPath: pathname } }); }; return ( - - - 편집 참여 코드를 입력하시면 From a85edc758713cbc22c6323d8147a9776339edaa3 Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Sat, 20 Jan 2024 06:18:28 +0900 Subject: [PATCH 08/10] =?UTF-8?q?Feat:=20=EB=AA=A8=EB=8B=AC=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=20=EC=BD=94=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Share/CodeInput.tsx | 39 ++++++++++++++++++ src/components/Trip/EditCodeModal.tsx | 59 +++++++++++++++++++++++++++ src/components/Trip/TripSchedule.tsx | 5 +-- src/components/common/alert/Alert.tsx | 14 ++++--- 4 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 src/components/Share/CodeInput.tsx create mode 100644 src/components/Trip/EditCodeModal.tsx diff --git a/src/components/Share/CodeInput.tsx b/src/components/Share/CodeInput.tsx new file mode 100644 index 00000000..3fca6375 --- /dev/null +++ b/src/components/Share/CodeInput.tsx @@ -0,0 +1,39 @@ +interface Props { + inputCode: string; + setInputCode: React.Dispatch>; + showError: boolean; +} + +const CodeInput = ({ inputCode, setInputCode, showError }: Props) => { + const onCodeChange = async (e: React.ChangeEvent) => { + const changeValue = e.target.value; + if (changeValue.length <= 5) { + setInputCode(e.target.value); + } + }; + return ( +
+
+ +
+ {showError && ( +
+ 편집 참여 코드를 다시 한번 확인해주세요. +
+ )} +
+ ); +}; + +export default CodeInput; diff --git a/src/components/Trip/EditCodeModal.tsx b/src/components/Trip/EditCodeModal.tsx new file mode 100644 index 00000000..09609bfb --- /dev/null +++ b/src/components/Trip/EditCodeModal.tsx @@ -0,0 +1,59 @@ +import { postTripsjoin } from '@api/trips'; +import CodeInput from '@components/Share/CodeInput'; +import Alert from '@components/common/alert/Alert'; +import { useGetTripsAuthority } from '@hooks/useGetTripsAuthority'; +import { useState } from 'react'; +import { useParams } from 'react-router-dom'; + +const EditCodeModal = () => { + const [isModalOpen, setIsModalOpen] = useState(false); + const [inputCode, setInputCode] = useState(''); + const [showError, setShowError] = useState(false); + + const { id: tripId } = useParams(); + const { tripAuthority } = useGetTripsAuthority(); + + const handleConfirm = async () => { + if (tripId) { + try { + const { data } = await postTripsjoin(Number(tripId), inputCode); + if (data.status === 200) { + setIsModalOpen(false); + } + } catch (err) { + setShowError(true); + setInputCode(''); + console.error('참여 코드 요청 중 에러 발생', err); + } + } + }; + + return ( + <> + {tripAuthority === 'WRITE' ? ( + + ) : ( + + } + isOpen={isModalOpen} + setIsOpen={setIsModalOpen} + onConfirm={handleConfirm}> + + + )} + + ); +}; + +export default EditCodeModal; diff --git a/src/components/Trip/TripSchedule.tsx b/src/components/Trip/TripSchedule.tsx index ad55e20e..9d6ea0cd 100644 --- a/src/components/Trip/TripSchedule.tsx +++ b/src/components/Trip/TripSchedule.tsx @@ -1,4 +1,5 @@ import { UserIcon } from '@components/common/icons/Icons'; +import EditCodeModal from './EditCodeModal'; export const TripSchedule = () => { return ( @@ -12,9 +13,7 @@ export const TripSchedule = () => { 5
- +
23.12.23 - 23.12.25 diff --git a/src/components/common/alert/Alert.tsx b/src/components/common/alert/Alert.tsx index df7f1dd1..dbb26a3f 100644 --- a/src/components/common/alert/Alert.tsx +++ b/src/components/common/alert/Alert.tsx @@ -3,13 +3,15 @@ import * as Dialog from '@radix-ui/react-dialog'; interface AlertProps { title: string; - message: ReactNode; + message?: ReactNode; onConfirm: (() => void) | ((e: React.MouseEvent) => void); onCancel?: (() => void) | ((e: React.MouseEvent) => void); children: ReactNode; content?: ReactNode; closeOnConfirm?: boolean; isCheck?: number | null; + isOpen?: boolean; + setIsOpen?: React.Dispatch>; } const Alert: FC = ({ @@ -21,8 +23,10 @@ const Alert: FC = ({ content, closeOnConfirm = false, isCheck = true, + isOpen, + setIsOpen, }) => ( - + {children} @@ -31,10 +35,10 @@ const Alert: FC = ({ + } fixed left-[50%] top-[50%] z-[130] flex min-h-[192px] w-[309px] translate-x-[-50%] translate-y-[-50%] flex-col items-center justify-center rounded-2xl bg-white px-[14px] shadow-lg focus:outline-none`}>

= ({ From 19fd1d6228dcf1275dbce28c15d7f35f06eea6e3 Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Sat, 20 Jan 2024 06:28:07 +0900 Subject: [PATCH 09/10] =?UTF-8?q?Refactor:=20=EA=B3=B5=EC=9C=A0=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9D=B4=EB=8F=99=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 --- src/components/Plan/PlanSectionTop.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/Plan/PlanSectionTop.tsx b/src/components/Plan/PlanSectionTop.tsx index 114ee5a5..99be9d1f 100644 --- a/src/components/Plan/PlanSectionTop.tsx +++ b/src/components/Plan/PlanSectionTop.tsx @@ -51,10 +51,13 @@ const PlanSectionTop = () => {

{ navigate(-1); }} + showShare={true} + shareHandler={() => { + navigate(`/trip/${tripId}/share`); + }} /> From 191b514634ec3e4f180a76aadc510188234355cf Mon Sep 17 00:00:00 2001 From: jisu Seo Date: Sat, 20 Jan 2024 06:32:48 +0900 Subject: [PATCH 10/10] =?UTF-8?q?Refactor:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=ED=9B=84=20url=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Auth/Login/LoginForm.tsx | 2 +- src/components/Share/IsEditableModal.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Auth/Login/LoginForm.tsx b/src/components/Auth/Login/LoginForm.tsx index d1e88621..0491d686 100644 --- a/src/components/Auth/Login/LoginForm.tsx +++ b/src/components/Auth/Login/LoginForm.tsx @@ -41,7 +41,7 @@ const LoginForm = () => { setItem('accessToken', res.data.data.tokenInfo.accessToken); // setUserInfo(res.data.data.memberDto); if (state) { - navigate(`${state.prevPath}/code`); + navigate(state.prevPath); } else { navigate('/'); } diff --git a/src/components/Share/IsEditableModal.tsx b/src/components/Share/IsEditableModal.tsx index ee917224..1465ff79 100644 --- a/src/components/Share/IsEditableModal.tsx +++ b/src/components/Share/IsEditableModal.tsx @@ -16,7 +16,7 @@ const IsEditableModal = ({ isEditable, setIsEditable }: Props) => { const isLogin = getItem('accessToken'); const handleConfirm = () => { - navigate('/login', { state: { prevPath: pathname } }); + navigate('/login', { state: { prevPath: `${pathname}/code` } }); }; return (