From 3756df82b116792cf94f2cc7f2f0df2db797b479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=96=B4=EC=8A=B9=EC=A4=80?= Date: Sat, 30 Dec 2023 18:34:43 +0900 Subject: [PATCH 01/75] =?UTF-8?q?Remove:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F?= =?UTF-8?q?=20=EC=83=81=EC=84=B8=EC=84=B9=EC=85=98=EB=B0=94=ED=85=80=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DetailSectionBottom/A.tsx | 17 +++++++++++++++++ src/components/DetailSectionBottom/B.tsx | 17 +++++++++++++++++ src/components/DetailSectionBottom/C.tsx | 17 +++++++++++++++++ .../DetailSectionBottom/DetailSectionBottom.tsx | 12 ++++++++++++ src/components/DetailSectionBottom/index.tsx | 5 +++++ src/components/abc/A.tsx | 3 --- src/components/abc/B.tsx | 3 --- src/components/abc/index.tsx | 4 ---- src/components/def/C.tsx | 3 --- src/components/def/D.tsx | 3 --- src/components/def/index.tsx | 4 ---- src/pages/abc/abc.page.tsx | 14 -------------- src/pages/detail/detail.page.tsx | 3 ++- src/router/mainRouter.tsx | 2 -- 14 files changed, 70 insertions(+), 37 deletions(-) create mode 100644 src/components/DetailSectionBottom/A.tsx create mode 100644 src/components/DetailSectionBottom/B.tsx create mode 100644 src/components/DetailSectionBottom/C.tsx create mode 100644 src/components/DetailSectionBottom/DetailSectionBottom.tsx create mode 100644 src/components/DetailSectionBottom/index.tsx delete mode 100644 src/components/abc/A.tsx delete mode 100644 src/components/abc/B.tsx delete mode 100644 src/components/abc/index.tsx delete mode 100644 src/components/def/C.tsx delete mode 100644 src/components/def/D.tsx delete mode 100644 src/components/def/index.tsx delete mode 100644 src/pages/abc/abc.page.tsx diff --git a/src/components/DetailSectionBottom/A.tsx b/src/components/DetailSectionBottom/A.tsx new file mode 100644 index 00000000..02d459fb --- /dev/null +++ b/src/components/DetailSectionBottom/A.tsx @@ -0,0 +1,17 @@ +import { ReactComponent as PenIcon } from '../../assets/images/Pen.svg'; +import { ReactComponent as CalendarIcon } from '../../assets/images/Calendar.svg'; + +export default function A() { + return ( +
+ + +
+ ); +} diff --git a/src/components/DetailSectionBottom/B.tsx b/src/components/DetailSectionBottom/B.tsx new file mode 100644 index 00000000..e056a3b0 --- /dev/null +++ b/src/components/DetailSectionBottom/B.tsx @@ -0,0 +1,17 @@ +import { ReactComponent as PenIcon } from '../../assets/images/Pen.svg'; +import { ReactComponent as CalendarIcon } from '../../assets/images/Calendar.svg'; + +export default function B() { + return ( +
+ + +
+ ); +} diff --git a/src/components/DetailSectionBottom/C.tsx b/src/components/DetailSectionBottom/C.tsx new file mode 100644 index 00000000..ca97236d --- /dev/null +++ b/src/components/DetailSectionBottom/C.tsx @@ -0,0 +1,17 @@ +import { ReactComponent as PenIcon } from '../../assets/images/Pen.svg'; +import { ReactComponent as CalendarIcon } from '../../assets/images/Calendar.svg'; + +export default function C() { + return ( +
+ + +
+ ); +} diff --git a/src/components/DetailSectionBottom/DetailSectionBottom.tsx b/src/components/DetailSectionBottom/DetailSectionBottom.tsx new file mode 100644 index 00000000..f94332cf --- /dev/null +++ b/src/components/DetailSectionBottom/DetailSectionBottom.tsx @@ -0,0 +1,12 @@ +import { A, B, C } from '.'; + +// 담당 컴포넌트들 호출하는 컴포넌트(분업 때문에 페이지 느낌으로 나눠봤습니다), API 호출 컴포넌트, +export default function DetailSectionBottom() { + return ( + <> + + + + + ); +} diff --git a/src/components/DetailSectionBottom/index.tsx b/src/components/DetailSectionBottom/index.tsx new file mode 100644 index 00000000..399513bc --- /dev/null +++ b/src/components/DetailSectionBottom/index.tsx @@ -0,0 +1,5 @@ +import A from './A'; +import B from './B'; +import C from './C'; + +export { A, B, C }; diff --git a/src/components/abc/A.tsx b/src/components/abc/A.tsx deleted file mode 100644 index 2c7b9087..00000000 --- a/src/components/abc/A.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function A() { - return
A
; -} diff --git a/src/components/abc/B.tsx b/src/components/abc/B.tsx deleted file mode 100644 index 856cfd77..00000000 --- a/src/components/abc/B.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function B() { - return
B
; -} diff --git a/src/components/abc/index.tsx b/src/components/abc/index.tsx deleted file mode 100644 index 3e935a15..00000000 --- a/src/components/abc/index.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import A from '@components/abc/A'; -import B from '@components/abc/B'; - -export { A, B }; diff --git a/src/components/def/C.tsx b/src/components/def/C.tsx deleted file mode 100644 index 604abfd4..00000000 --- a/src/components/def/C.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function C() { - return
C
; -} diff --git a/src/components/def/D.tsx b/src/components/def/D.tsx deleted file mode 100644 index 7e0690b5..00000000 --- a/src/components/def/D.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function D() { - return
D
; -} diff --git a/src/components/def/index.tsx b/src/components/def/index.tsx deleted file mode 100644 index 9e8fb509..00000000 --- a/src/components/def/index.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import C from '@components/def/C'; -import D from '@components/def/D'; - -export { C, D }; diff --git a/src/pages/abc/abc.page.tsx b/src/pages/abc/abc.page.tsx deleted file mode 100644 index 1de578c9..00000000 --- a/src/pages/abc/abc.page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { A } from '@components/abc'; -import { C, D } from '@components/def'; - -const ABC = () => { - return ( -
- - - -
- ); -}; - -export default ABC; diff --git a/src/pages/detail/detail.page.tsx b/src/pages/detail/detail.page.tsx index 57a571aa..22223af7 100644 --- a/src/pages/detail/detail.page.tsx +++ b/src/pages/detail/detail.page.tsx @@ -1,12 +1,13 @@ import { DetailHeader } from '@components/common/header'; import DetailSectionTop from '@components/DetailSectionTop/DetailSectionTop'; +import DetailSectionBottom from '@components/DetailSectionBottom/DetailSectionBottom'; const DetailTours = () => { return ( <> - {/* 추천 : DetailSectionBottom => 이런 점이 좋았어요, 리뷰 */} + ); }; diff --git a/src/router/mainRouter.tsx b/src/router/mainRouter.tsx index f948b509..7e1d43a2 100644 --- a/src/router/mainRouter.tsx +++ b/src/router/mainRouter.tsx @@ -2,7 +2,6 @@ import { Outlet, Route, Routes } from 'react-router-dom'; import styled from 'styled-components'; import { Header } from '@components/common/header'; import { Footer } from '@components/common/footer'; -import ABC from '@pages/abc/abc.page'; import Main from '@pages/main/main.page'; import Detail from '@pages/detail/detail.page'; @@ -25,7 +24,6 @@ const MainRouter = () => { }> } /> } /> - } /> From 08bdb79b5d6bb8a138e2e1cb346af1b0f23ea747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=96=B4=EC=8A=B9=EC=A4=80?= Date: Sat, 30 Dec 2023 20:01:19 +0900 Subject: [PATCH 02/75] =?UTF-8?q?Feat:=20=EB=A6=AC=EB=B7=B0=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99=20=EC=A4=80=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/tours.ts | 1 + src/components/DetailSectionBottom/A.tsx | 16 +--------------- src/components/DetailSectionBottom/B.tsx | 17 ----------------- src/components/DetailSectionBottom/C.tsx | 17 ----------------- .../DetailSectionBottom/DetailReview.tsx | 10 ++++++++++ .../DetailSectionBottom/DetailSectionBottom.tsx | 5 ++--- src/components/DetailSectionBottom/index.tsx | 5 ++--- .../{DetailToutsMap.tsx => DetailToursMap.tsx} | 0 src/components/DetailSectionTop/index.tsx | 2 +- 9 files changed, 17 insertions(+), 56 deletions(-) delete mode 100644 src/components/DetailSectionBottom/B.tsx delete mode 100644 src/components/DetailSectionBottom/C.tsx create mode 100644 src/components/DetailSectionBottom/DetailReview.tsx rename src/components/DetailSectionTop/{DetailToutsMap.tsx => DetailToursMap.tsx} (100%) diff --git a/src/api/tours.ts b/src/api/tours.ts index 5b9c7837..0ff880ee 100644 --- a/src/api/tours.ts +++ b/src/api/tours.ts @@ -19,6 +19,7 @@ export const getDetailTours = async (tourItemId: number) => { // 여행 상품 리뷰 조회 export const getToursReviews = async (tourItemId: number) => { const res = await client.get(`tours/${tourItemId}/reviews`); + console.log('res', res.data.data.reviewInfos); return res; }; diff --git a/src/components/DetailSectionBottom/A.tsx b/src/components/DetailSectionBottom/A.tsx index 02d459fb..e03f98b2 100644 --- a/src/components/DetailSectionBottom/A.tsx +++ b/src/components/DetailSectionBottom/A.tsx @@ -1,17 +1,3 @@ -import { ReactComponent as PenIcon } from '../../assets/images/Pen.svg'; -import { ReactComponent as CalendarIcon } from '../../assets/images/Calendar.svg'; - export default function A() { - return ( -
- - -
- ); + return
이런 점이 좋았어요
; } diff --git a/src/components/DetailSectionBottom/B.tsx b/src/components/DetailSectionBottom/B.tsx deleted file mode 100644 index e056a3b0..00000000 --- a/src/components/DetailSectionBottom/B.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { ReactComponent as PenIcon } from '../../assets/images/Pen.svg'; -import { ReactComponent as CalendarIcon } from '../../assets/images/Calendar.svg'; - -export default function B() { - return ( -
- - -
- ); -} diff --git a/src/components/DetailSectionBottom/C.tsx b/src/components/DetailSectionBottom/C.tsx deleted file mode 100644 index ca97236d..00000000 --- a/src/components/DetailSectionBottom/C.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { ReactComponent as PenIcon } from '../../assets/images/Pen.svg'; -import { ReactComponent as CalendarIcon } from '../../assets/images/Calendar.svg'; - -export default function C() { - return ( -
- - -
- ); -} diff --git a/src/components/DetailSectionBottom/DetailReview.tsx b/src/components/DetailSectionBottom/DetailReview.tsx new file mode 100644 index 00000000..c74bb349 --- /dev/null +++ b/src/components/DetailSectionBottom/DetailReview.tsx @@ -0,0 +1,10 @@ +import { getToursReviews } from '@api/tours'; +import { useEffect } from 'react'; + +export default function DetailReview() { + const tourItemId = 1; + useEffect(() => { + getToursReviews(tourItemId); + }, []); + return
리뷰
; +} diff --git a/src/components/DetailSectionBottom/DetailSectionBottom.tsx b/src/components/DetailSectionBottom/DetailSectionBottom.tsx index f94332cf..ac4ad43a 100644 --- a/src/components/DetailSectionBottom/DetailSectionBottom.tsx +++ b/src/components/DetailSectionBottom/DetailSectionBottom.tsx @@ -1,12 +1,11 @@ -import { A, B, C } from '.'; +import { A, DetailReview } from '.'; // 담당 컴포넌트들 호출하는 컴포넌트(분업 때문에 페이지 느낌으로 나눠봤습니다), API 호출 컴포넌트, export default function DetailSectionBottom() { return ( <>
- - + ); } diff --git a/src/components/DetailSectionBottom/index.tsx b/src/components/DetailSectionBottom/index.tsx index 399513bc..70f9c29e 100644 --- a/src/components/DetailSectionBottom/index.tsx +++ b/src/components/DetailSectionBottom/index.tsx @@ -1,5 +1,4 @@ import A from './A'; -import B from './B'; -import C from './C'; +import DetailReview from './DetailReview'; -export { A, B, C }; +export { A, DetailReview }; diff --git a/src/components/DetailSectionTop/DetailToutsMap.tsx b/src/components/DetailSectionTop/DetailToursMap.tsx similarity index 100% rename from src/components/DetailSectionTop/DetailToutsMap.tsx rename to src/components/DetailSectionTop/DetailToursMap.tsx diff --git a/src/components/DetailSectionTop/index.tsx b/src/components/DetailSectionTop/index.tsx index cc88b9e9..3d938ea5 100644 --- a/src/components/DetailSectionTop/index.tsx +++ b/src/components/DetailSectionTop/index.tsx @@ -1,6 +1,6 @@ import DetailToursInfo from './DetailToursInfo'; import DetailToursRating from './DetailToursRating'; -import DetailToursMap from './DetailToutsMap'; +import DetailToursMap from './DetailToursMap'; import DetailTourButtons from './DetailTourButtons'; export { From 35a63ab8b0745c639ca11a07e7a57fdede21c554 Mon Sep 17 00:00:00 2001 From: NohWookJin Date: Sat, 30 Dec 2023 23:41:56 +0900 Subject: [PATCH 03/75] feat: kakao map sdk --- index.html | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/index.html b/index.html index 3ba384e2..82c2ddf2 100644 --- a/index.html +++ b/index.html @@ -1,16 +1,17 @@ + + + + + TenTen + - - - - - TenTen - - - -
- - - - \ No newline at end of file + +
+ + + + From 4f8033216d9fd865c23c088a93d533abae61b1a4 Mon Sep 17 00:00:00 2001 From: NohWookJin Date: Sat, 30 Dec 2023 23:42:47 +0900 Subject: [PATCH 04/75] =?UTF-8?q?refactor:=20=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20api=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/tours.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/api/tours.ts b/src/api/tours.ts index 5b9c7837..888e7b7c 100644 --- a/src/api/tours.ts +++ b/src/api/tours.ts @@ -12,8 +12,14 @@ export const getTours = async (region: number, page: number, size: number) => { // 여행지 상세 조회 export const getDetailTours = async (tourItemId: number) => { - const res = await client.get(`tours/${tourItemId}`); - return res; + try { + const { + data: { data }, + } = await client.get(`tours/${tourItemId}`); + return data; + } catch (e) { + console.error(e); + } }; // 여행 상품 리뷰 조회 From 56d13fbfce41a5ffc44c9fc5a2282fcafd2444b8 Mon Sep 17 00:00:00 2001 From: NohWookJin Date: Sat, 30 Dec 2023 23:43:19 +0900 Subject: [PATCH 05/75] =?UTF-8?q?feat:=20=EC=8B=A4=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DetailSectionTop/DetailSectionTop.tsx | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/components/DetailSectionTop/DetailSectionTop.tsx b/src/components/DetailSectionTop/DetailSectionTop.tsx index 08443ac9..a663f268 100644 --- a/src/components/DetailSectionTop/DetailSectionTop.tsx +++ b/src/components/DetailSectionTop/DetailSectionTop.tsx @@ -1,3 +1,9 @@ +// import { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import { useQuery } from '@tanstack/react-query'; + +import { getDetailTours } from '@api/tours'; + import { DetailToursInfo, DetailToursRating, @@ -5,14 +11,25 @@ import { DetailTourButtons, } from '.'; -// 담당 컴포넌트들 호출하는 컴포넌트(분업 때문에 페이지 느낌으로 나눠봤습니다), API 호출 컴포넌트, export default function DetailSectionTop() { - return ( - <> - - - - - - ); + const params = useParams(); + const tourId = Number(params.id); + + const { isError, isLoading, isFetching, data } = useQuery({ + queryKey: ['details', tourId], + queryFn: () => getDetailTours(tourId), + }); + + if (data) { + return ( + <> + + + + + + ); + } + + if (isError) console.log('error'); } From ebb14bc14a65136c9aefac2a12d45dad51ab321a Mon Sep 17 00:00:00 2001 From: NohWookJin Date: Sat, 30 Dec 2023 23:43:27 +0900 Subject: [PATCH 06/75] =?UTF-8?q?feat:=20=EC=8B=A4=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DetailSectionTop/DetailToursInfo.tsx | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/components/DetailSectionTop/DetailToursInfo.tsx b/src/components/DetailSectionTop/DetailToursInfo.tsx index 8e5194bb..90707f55 100644 --- a/src/components/DetailSectionTop/DetailToursInfo.tsx +++ b/src/components/DetailSectionTop/DetailToursInfo.tsx @@ -1,20 +1,32 @@ import { ReactComponent as HeartIcon } from '../../assets/images/Heart.svg'; -export default function DetailToursInfo() { +interface InfoProps { + infoData: tourDetail; +} + +export default function DetailToursInfo({ infoData }: InfoProps) { + const { title, liked, originalThumbnailUrl } = infoData; + return ( <>
tour-image
-

강릉 세인트존스 호텔

-
- -
+

{title}

+ {liked ? ( +
+ +
+ ) : ( +
+ +
+ )}
); From 72aee7a17cd8bae4dcfaa8253521a04fe59d97c9 Mon Sep 17 00:00:00 2001 From: NohWookJin Date: Sat, 30 Dec 2023 23:43:36 +0900 Subject: [PATCH 07/75] =?UTF-8?q?feat:=20=EC=8B=A4=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DetailSectionTop/DetailToutsMap.tsx | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/components/DetailSectionTop/DetailToutsMap.tsx b/src/components/DetailSectionTop/DetailToutsMap.tsx index 40730658..a5ac0af8 100644 --- a/src/components/DetailSectionTop/DetailToutsMap.tsx +++ b/src/components/DetailSectionTop/DetailToutsMap.tsx @@ -2,20 +2,38 @@ import { ReactComponent as MapIcon } from '../../assets/images/Map.svg'; import { ReactComponent as CheckIcon } from '../../assets/images/Check.svg'; import { ReactComponent as PhoneIcon } from '../../assets/images/Phone.svg'; -export default function DetailToursMap() { +import { Map, MapMarker } from 'react-kakao-maps-sdk'; + +interface MapProps { + mapData: tourDetail; +} + +export default function DetailToursMap({ mapData }: MapProps) { + const { fullAddress, longitude, latitude, tel } = mapData; + return (
- 강원 강릉시 창해로 307 + {fullAddress}
-
지도 정보
+ + +
- 064-743-0703 + {tel}
); From ee28e8342f5fa39fc4012fdf9ca268224e909fb4 Mon Sep 17 00:00:00 2001 From: NohWookJin Date: Sat, 30 Dec 2023 23:44:16 +0900 Subject: [PATCH 08/75] feat: kakao-map type --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index a1751e9c..15c45d0c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,7 +26,7 @@ "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", - "types": ["vite/client"], + "types": ["vite/client", "kakao.maps.d.ts"], /* Linting */ "strict": true, "noUnusedLocals": true, From d9585fa1349da596bd1f30bc6688615724b1a565 Mon Sep 17 00:00:00 2001 From: NohWookJin Date: Sat, 30 Dec 2023 23:44:58 +0900 Subject: [PATCH 09/75] =?UTF-8?q?feat:=20Global=20Type=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/@types/detail.types.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/@types/detail.types.ts diff --git a/src/@types/detail.types.ts b/src/@types/detail.types.ts new file mode 100644 index 00000000..8c65e79c --- /dev/null +++ b/src/@types/detail.types.ts @@ -0,0 +1,11 @@ +interface tourDetail { + id: number; + title: string; + liked: boolean; + fullAddress: string; + zipcode: string; + longitude: string; + latitude: string; + tel: string; + originalThumbnailUrl: string; +} From 54022f7dcacfb6791a7c6814c84e33afe67bbd5b Mon Sep 17 00:00:00 2001 From: NohWookJin Date: Sat, 30 Dec 2023 23:48:01 +0900 Subject: [PATCH 10/75] =?UTF-8?q?feat:=20kakao-map=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 80 +++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/package-lock.json b/package-lock.json index e9c713ff..4b259404 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,17 +9,16 @@ "version": "0.0.0", "dependencies": { "@pnpm-monorepo/shared": "^1.0.0", - "@radix-ui/react-aspect-ratio": "^1.0.3", "@radix-ui/react-collapsible": "^1.0.3", "@svgr/rollup": "^8.1.0", "@tanstack/react-query": "^5.14.6", "@tanstack/react-query-devtools": "^5.14.6", "axios": "^1.6.2", - "clsx": "^2.0.0", "msw": "0.36.3", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-kakao-maps-sdk": "^1.1.24", "react-router-dom": "^6.21.1", "recoil": "^0.7.7", "styled-components": "^6.1.3" @@ -2580,29 +2579,6 @@ "@babel/runtime": "^7.13.10" } }, - "node_modules/@radix-ui/react-aspect-ratio": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.0.3.tgz", - "integrity": "sha512-fXR5kbMan9oQqMuacfzlGG/SQMcmMlZ4wrvpckv8SgUulD0MMpspxJrxg/Gp/ISV3JfV1AeSWTYK9GvxA4ySwA==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - }, - "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 - } - } - }, "node_modules/@radix-ui/react-collapsible": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz", @@ -4297,14 +4273,6 @@ "node": ">=0.8" } }, - "node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", - "engines": { - "node": ">=6" - } - }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -5797,6 +5765,11 @@ "node": ">=6" } }, + "node_modules/kakao.maps.d.ts": { + "version": "0.1.39", + "resolved": "https://registry.npmjs.org/kakao.maps.d.ts/-/kakao.maps.d.ts-0.1.39.tgz", + "integrity": "sha512-KXENJ8hHYtjb5G+0vf8TXx/PwWW4j5ndDiQTSMvGtF7EFWu2P3N/+Zivcj9/UKn3j29Iz/sIUaA7WL8Ug3IDGQ==" + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -6883,6 +6856,19 @@ "react": "^18.2.0" } }, + "node_modules/react-kakao-maps-sdk": { + "version": "1.1.24", + "resolved": "https://registry.npmjs.org/react-kakao-maps-sdk/-/react-kakao-maps-sdk-1.1.24.tgz", + "integrity": "sha512-leLbFwBj6zbTdDg6A9U7EwYT2oq0+2F+NHZSVTyCmmvyc4yt2zpRvUmcAt8I6h2SDUdgHbpvKAV1sZoRIxD4JQ==", + "dependencies": { + "@babel/runtime": "^7.22.15", + "kakao.maps.d.ts": "^0.1.39" + }, + "peerDependencies": { + "react": "^16.8 || ^17 || ^18", + "react-dom": "^16.8 || ^17 || ^18" + } + }, "node_modules/react-refresh": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", @@ -9688,15 +9674,6 @@ "@babel/runtime": "^7.13.10" } }, - "@radix-ui/react-aspect-ratio": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.0.3.tgz", - "integrity": "sha512-fXR5kbMan9oQqMuacfzlGG/SQMcmMlZ4wrvpckv8SgUulD0MMpspxJrxg/Gp/ISV3JfV1AeSWTYK9GvxA4ySwA==", - "requires": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - } - }, "@radix-ui/react-collapsible": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz", @@ -10731,11 +10708,6 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" }, - "clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==" - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -11806,6 +11778,11 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, + "kakao.maps.d.ts": { + "version": "0.1.39", + "resolved": "https://registry.npmjs.org/kakao.maps.d.ts/-/kakao.maps.d.ts-0.1.39.tgz", + "integrity": "sha512-KXENJ8hHYtjb5G+0vf8TXx/PwWW4j5ndDiQTSMvGtF7EFWu2P3N/+Zivcj9/UKn3j29Iz/sIUaA7WL8Ug3IDGQ==" + }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -12502,6 +12479,15 @@ "scheduler": "^0.23.0" } }, + "react-kakao-maps-sdk": { + "version": "1.1.24", + "resolved": "https://registry.npmjs.org/react-kakao-maps-sdk/-/react-kakao-maps-sdk-1.1.24.tgz", + "integrity": "sha512-leLbFwBj6zbTdDg6A9U7EwYT2oq0+2F+NHZSVTyCmmvyc4yt2zpRvUmcAt8I6h2SDUdgHbpvKAV1sZoRIxD4JQ==", + "requires": { + "@babel/runtime": "^7.22.15", + "kakao.maps.d.ts": "^0.1.39" + } + }, "react-refresh": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", From 6e084466cb8ecd4e4b6d13f70226311d1c64338f Mon Sep 17 00:00:00 2001 From: NohWookJin Date: Sat, 30 Dec 2023 23:48:15 +0900 Subject: [PATCH 11/75] =?UTF-8?q?feat:=20kakao-map=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 25a5135a..50bdf042 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-kakao-maps-sdk": "^1.1.24", "react-router-dom": "^6.21.1", "recoil": "^0.7.7", "styled-components": "^6.1.3" From 22fffcb826e4ac5e4a9564af671cd342fea6c17b Mon Sep 17 00:00:00 2001 From: NohWookJin Date: Sat, 30 Dec 2023 23:48:27 +0900 Subject: [PATCH 12/75] =?UTF-8?q?refactor:=20=EC=A0=88=EB=8C=80=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DetailSectionTop/DetailTourButtons.tsx | 4 ++-- src/components/DetailSectionTop/DetailToursInfo.tsx | 2 +- src/components/DetailSectionTop/DetailToursRating.tsx | 2 +- src/components/DetailSectionTop/DetailToutsMap.tsx | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/DetailSectionTop/DetailTourButtons.tsx b/src/components/DetailSectionTop/DetailTourButtons.tsx index a8900595..7038e566 100644 --- a/src/components/DetailSectionTop/DetailTourButtons.tsx +++ b/src/components/DetailSectionTop/DetailTourButtons.tsx @@ -1,5 +1,5 @@ -import { ReactComponent as PenIcon } from '../../assets/images/Pen.svg'; -import { ReactComponent as CalendarIcon } from '../../assets/images/Calendar.svg'; +import { ReactComponent as PenIcon } from '@assets/images/Pen.svg'; +import { ReactComponent as CalendarIcon } from '@assets/images/Calendar.svg'; export default function DetailTourButtons() { return ( diff --git a/src/components/DetailSectionTop/DetailToursInfo.tsx b/src/components/DetailSectionTop/DetailToursInfo.tsx index 90707f55..46021d11 100644 --- a/src/components/DetailSectionTop/DetailToursInfo.tsx +++ b/src/components/DetailSectionTop/DetailToursInfo.tsx @@ -1,4 +1,4 @@ -import { ReactComponent as HeartIcon } from '../../assets/images/Heart.svg'; +import { ReactComponent as HeartIcon } from '@assets/images/Heart.svg'; interface InfoProps { infoData: tourDetail; diff --git a/src/components/DetailSectionTop/DetailToursRating.tsx b/src/components/DetailSectionTop/DetailToursRating.tsx index e3ccc13b..b1fdf0bf 100644 --- a/src/components/DetailSectionTop/DetailToursRating.tsx +++ b/src/components/DetailSectionTop/DetailToursRating.tsx @@ -1,4 +1,4 @@ -import { ReactComponent as StarIcon } from '../../assets/images/Star.svg'; +import { ReactComponent as StarIcon } from '@assets/images/Star.svg'; export default function DetailToursRating() { return ( diff --git a/src/components/DetailSectionTop/DetailToutsMap.tsx b/src/components/DetailSectionTop/DetailToutsMap.tsx index a5ac0af8..fabac7e6 100644 --- a/src/components/DetailSectionTop/DetailToutsMap.tsx +++ b/src/components/DetailSectionTop/DetailToutsMap.tsx @@ -1,6 +1,6 @@ -import { ReactComponent as MapIcon } from '../../assets/images/Map.svg'; -import { ReactComponent as CheckIcon } from '../../assets/images/Check.svg'; -import { ReactComponent as PhoneIcon } from '../../assets/images/Phone.svg'; +import { ReactComponent as MapIcon } from '@assets/images/Map.svg'; +import { ReactComponent as CheckIcon } from '@assets/images/Check.svg'; +import { ReactComponent as PhoneIcon } from '@assets/images/Phone.svg'; import { Map, MapMarker } from 'react-kakao-maps-sdk'; From 98918f0ee132b95c9ceb3f2f56183dd7949a2fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=96=B4=EC=8A=B9=EC=A4=80?= Date: Mon, 1 Jan 2024 19:38:51 +0900 Subject: [PATCH 13/75] =?UTF-8?q?Feat:=20=EC=83=81=EC=84=B8=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EB=A6=AC=EB=B7=B0=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 --- package.json | 2 + src/api/tours.ts | 3 +- .../2023-12-30T203310.200 (1).json | 325 ++++++++++++++++++ .../DetailSectionBottom/DetailReview.tsx | 62 +++- .../DetailSectionBottom/ReviewItem.tsx | 96 ++++++ 5 files changed, 483 insertions(+), 5 deletions(-) create mode 100644 src/components/DetailSectionBottom/2023-12-30T203310.200 (1).json create mode 100644 src/components/DetailSectionBottom/ReviewItem.tsx diff --git a/package.json b/package.json index 25a5135a..76cf8dbf 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-infinite-scroller": "^1.2.6", "react-router-dom": "^6.21.1", "recoil": "^0.7.7", "styled-components": "^6.1.3" @@ -27,6 +28,7 @@ "devDependencies": { "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", + "@types/react-infinite-scroller": "^1.2.5", "@typescript-eslint/eslint-plugin": "^6.14.0", "@typescript-eslint/parser": "^6.14.0", "@vitejs/plugin-react": "^4.2.1", diff --git a/src/api/tours.ts b/src/api/tours.ts index 0ff880ee..646c63ff 100644 --- a/src/api/tours.ts +++ b/src/api/tours.ts @@ -19,7 +19,8 @@ export const getDetailTours = async (tourItemId: number) => { // 여행 상품 리뷰 조회 export const getToursReviews = async (tourItemId: number) => { const res = await client.get(`tours/${tourItemId}/reviews`); - console.log('res', res.data.data.reviewInfos); + console.log('res', res); + console.log('res.data.data.reviewInfos', res.data.data.reviewInfos); return res; }; diff --git a/src/components/DetailSectionBottom/2023-12-30T203310.200 (1).json b/src/components/DetailSectionBottom/2023-12-30T203310.200 (1).json new file mode 100644 index 00000000..6ad3e634 --- /dev/null +++ b/src/components/DetailSectionBottom/2023-12-30T203310.200 (1).json @@ -0,0 +1,325 @@ +{ + "status": 200, + "message": "SUCCESS", + "data": { + "ratingAverage": 4.125, + "reviewTotalCount": 8, + "keywordTotalCount": 38, + "reviewInfos": { + "content": [ + { + "reviewId": 15, + "authorNickname": "익명 사용자1", + "authorProfileImageUrl": "https://common.hanmi.co.kr/upfile/ces/product/p_2011_tenten_p_400.jpg", + "rating": 4, + "createdTime": "2023-12-30T20:02:06.03406", + "content": "좋은 여행지였습니다.", + "keywords": [ + { + "keywordId": 1, + "content": "깨끗해요", + "type": "ACCOMMODATION_KEYWORD" + }, + { + "keywordId": 2, + "content": "친절해요", + "type": "ACCOMMODATION_KEYWORD" + } + ], + "commentCount": 0 + }, + { + "reviewId": 23, + "authorNickname": "익명 사용자1", + "authorProfileImageUrl": "https://common.hanmi.co.kr/upfile/ces/product/p_2011_tenten_p_400.jpg", + "rating": 4, + "createdTime": "2023-12-30T20:03:17.978397", + "content": "좋은 여행지였습니다.", + "keywords": [ + { + "keywordId": 1, + "content": "깨끗해요", + "type": "ACCOMMODATION_KEYWORD" + }, + { + "keywordId": 2, + "content": "친절해요", + "type": "ACCOMMODATION_KEYWORD" + } + ], + "commentCount": 0 + }, + { + "reviewId": 24, + "authorNickname": "익명 사용자1", + "authorProfileImageUrl": "https://common.hanmi.co.kr/upfile/ces/product/p_2011_tenten_p_400.jpg", + "rating": 4, + "createdTime": "2023-12-30T20:03:18.970952", + "content": "좋은 여행지였습니다.", + "keywords": [ + { + "keywordId": 1, + "content": "깨끗해요", + "type": "ACCOMMODATION_KEYWORD" + }, + { + "keywordId": 2, + "content": "친절해요", + "type": "ACCOMMODATION_KEYWORD" + } + ], + "commentCount": 0 + }, + { + "reviewId": 25, + "authorNickname": "익명 사용자1", + "authorProfileImageUrl": "https://common.hanmi.co.kr/upfile/ces/product/p_2011_tenten_p_400.jpg", + "rating": 4, + "createdTime": "2023-12-30T20:03:20.335173", + "content": "좋은 여행지였습니다.", + "keywords": [ + { + "keywordId": 1, + "content": "깨끗해요", + "type": "ACCOMMODATION_KEYWORD" + }, + { + "keywordId": 2, + "content": "친절해요", + "type": "ACCOMMODATION_KEYWORD" + } + ], + "commentCount": 0 + }, + { + "reviewId": 26, + "authorNickname": "익명 사용자1", + "authorProfileImageUrl": "https://common.hanmi.co.kr/upfile/ces/product/p_2011_tenten_p_400.jpg", + "rating": 4, + "createdTime": "2023-12-30T20:03:21.924918", + "content": "좋은 여행지였습니다.", + "keywords": [ + { + "keywordId": 1, + "content": "깨끗해요", + "type": "ACCOMMODATION_KEYWORD" + }, + { + "keywordId": 2, + "content": "친절해요", + "type": "ACCOMMODATION_KEYWORD" + } + ], + "commentCount": 0 + } + ], + "pageable": { + "pageNumber": 0, + "pageSize": 20, + "sort": { + "sorted": false, + "empty": true, + "unsorted": true + }, + "offset": 0, + "paged": true, + "unpaged": false + }, + "last": true, + "totalElements": 5, + "totalPages": 1, + "size": 20, + "number": 0, + "sort": { + "sorted": false, + "empty": true, + "unsorted": true + }, + "first": true, + "numberOfElements": 5, + "empty": false + }, + "tourKeywordInfos": [ + { + "keywordId": 1, + "content": "깨끗해요", + "type": "ACCOMMODATION_KEYWORD", + "keywordCount": 5 + }, + { + "keywordId": 2, + "content": "친절해요", + "type": "ACCOMMODATION_KEYWORD", + "keywordCount": 5 + }, + { + "keywordId": 3, + "content": "뷰가 좋아요", + "type": "ACCOMMODATION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 4, + "content": "침구가 좋아요", + "type": "ACCOMMODATION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 5, + "content": "주차하기 편해요", + "type": "ACCOMMODATION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 6, + "content": "냉난방이 잘돼요", + "type": "ACCOMMODATION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 7, + "content": "대중교통이 편해요", + "type": "ACCOMMODATION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 8, + "content": "호캉스하기 좋아요", + "type": "ACCOMMODATION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 9, + "content": "조식이 맛있어요", + "type": "ACCOMMODATION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 10, + "content": "사진 찍기 좋아요", + "type": "ACCOMMODATION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 11, + "content": "음식이 맛있어요", + "type": "DINING_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 12, + "content": "친절해요", + "type": "DINING_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 13, + "content": "인테리어가 멋져요", + "type": "DINING_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 14, + "content": "매장이 청결해요", + "type": "DINING_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 15, + "content": "특별한 메뉴가 있어요", + "type": "DINING_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 16, + "content": "가성비가 좋아요", + "type": "DINING_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 17, + "content": "재료가 신선해요", + "type": "DINING_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 18, + "content": "사진찍기 좋아요", + "type": "DINING_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 19, + "content": "주차하기 편해요", + "type": "DINING_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 20, + "content": "화장실이 깨끗해요", + "type": "DINING_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 21, + "content": "사진이 잘 나와요", + "type": "ATTRACTION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 22, + "content": "뷰가 좋아요", + "type": "ATTRACTION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 23, + "content": "관리가 잘 되어있어요", + "type": "ATTRACTION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 24, + "content": "볼거리가 많아요", + "type": "ATTRACTION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 25, + "content": "편의시설이 잘 되어 있어요", + "type": "ATTRACTION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 26, + "content": "대중교통이 편해요", + "type": "ATTRACTION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 27, + "content": "주차하기 편해요", + "type": "ATTRACTION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 28, + "content": "화장실이 깨끗해요", + "type": "ATTRACTION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 29, + "content": "가격이 합리적이에요", + "type": "ATTRACTION_KEYWORD", + "keywordCount": 1 + }, + { + "keywordId": 30, + "content": "방문객이 많아요", + "type": "ATTRACTION_KEYWORD", + "keywordCount": 1 + } + ] + } +} \ No newline at end of file diff --git a/src/components/DetailSectionBottom/DetailReview.tsx b/src/components/DetailSectionBottom/DetailReview.tsx index c74bb349..0fd10874 100644 --- a/src/components/DetailSectionBottom/DetailReview.tsx +++ b/src/components/DetailSectionBottom/DetailReview.tsx @@ -1,10 +1,64 @@ import { getToursReviews } from '@api/tours'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; +import InfiniteScroll from 'react-infinite-scroller'; +import { useInfiniteQuery } from '@tanstack/react-query'; +import ReviewItem from './ReviewItem'; export default function DetailReview() { + const [reviewDataLength, setReviewDataLength] = useState(0); const tourItemId = 1; + + const { + data: toursReviews, + fetchNextPage, + hasNextPage, + } = useInfiniteQuery({ + queryKey: ['toursReviews'], + queryFn: ({ pageParam }) => getToursReviews(tourItemId), + initialPageParam: 0, + getNextPageParam: (lastPage, allPages, lastPageParam) => { + const lastData = lastPage?.data?.data?.reviewInfos; + return lastData && lastData.length === 4 ? lastPageParam + 1 : undefined; + }, + }); + useEffect(() => { - getToursReviews(tourItemId); - }, []); - return
리뷰
; + if (toursReviews) { + const totalCount = toursReviews.pages.reduce( + (accumulator, page) => + accumulator + (page?.data?.data?.reviewInfos?.length || 0), + 0, + ); + setReviewDataLength(totalCount); + } + }, [toursReviews]); + + return ( + <> +
+ 리뷰 {reviewDataLength} +
+ fetchNextPage()} + initialLoad={false}> + {toursReviews?.pages?.map((page, pageIndex) => ( +
+ {page?.data?.data?.reviewInfos?.map((item: any, index: number) => ( + + ))} +
+ ))} +
+ + ); } diff --git a/src/components/DetailSectionBottom/ReviewItem.tsx b/src/components/DetailSectionBottom/ReviewItem.tsx new file mode 100644 index 00000000..b93cb606 --- /dev/null +++ b/src/components/DetailSectionBottom/ReviewItem.tsx @@ -0,0 +1,96 @@ +import { useEffect } from 'react'; +import { StarIcon, ChatIcon } from '@components/common/icons/Icons'; + +interface Keyword { + keywordId: number; + content: string; + type: string; +} + +interface ItemProps { + authorNickname: string; + authorProfileImageUrl: string; + rating: number; + createdTime: any; + content: string; + keywords: Keyword[]; // keywordId, content, type + commentCount: number; +} + +const Item: React.FC = (props: ItemProps) => { + const { + authorNickname, + authorProfileImageUrl, + rating, + createdTime, + content, + keywords, + commentCount, + } = props; + + const formatCreatedTime = (timeString: string): string => { + const date = new Date(timeString); + const formattedDate = new Intl.DateTimeFormat('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + }).format(date); + + return formattedDate; + }; + useEffect(() => { + console.log('commentCount', commentCount); + }, []); + return ( +
+
+ {/* {authorProfileImageUrl} */} +
+ 유저 프로필 +
+
+
{authorNickname}
+
+ {Array.from({ length: 5 }, (_, index) => ( + + ))} +
+
+
+ {formatCreatedTime(createdTime)} +
+
+
{content}
+
+
+ {keywords.map((keyword, idx) => { + return ( +
+ {keyword.content} +
+ ); + })} +
+
+ +
{commentCount}
+
+
+
+ ); +}; + +export default Item; From dd49ab11a32ef60ae803d786d5e429e718cb0928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=96=B4=EC=8A=B9=EC=A4=80?= Date: Mon, 1 Jan 2024 20:56:46 +0900 Subject: [PATCH 14/75] =?UTF-8?q?Feat:=20=EB=A6=AC=EB=B7=B0=20=EC=93=B0?= =?UTF-8?q?=EA=B8=B0=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 --- .../2023-12-30T203310.200 (1).json | 325 ------------------ src/components/Review/Review.tsx | 15 + src/components/Review/ReviewButton.tsx | 5 + src/components/Review/ReviewKeyword.tsx | 47 +++ src/components/Review/ReviewPosting.tsx | 24 ++ src/components/Review/ReviewRating.tsx | 19 + src/components/Review/index.tsx | 6 + .../postingReview/postingReview.page.tsx | 11 + src/router/mainRouter.tsx | 2 + 9 files changed, 129 insertions(+), 325 deletions(-) delete mode 100644 src/components/DetailSectionBottom/2023-12-30T203310.200 (1).json create mode 100644 src/components/Review/Review.tsx create mode 100644 src/components/Review/ReviewButton.tsx create mode 100644 src/components/Review/ReviewKeyword.tsx create mode 100644 src/components/Review/ReviewPosting.tsx create mode 100644 src/components/Review/ReviewRating.tsx create mode 100644 src/components/Review/index.tsx create mode 100644 src/pages/postingReview/postingReview.page.tsx diff --git a/src/components/DetailSectionBottom/2023-12-30T203310.200 (1).json b/src/components/DetailSectionBottom/2023-12-30T203310.200 (1).json deleted file mode 100644 index 6ad3e634..00000000 --- a/src/components/DetailSectionBottom/2023-12-30T203310.200 (1).json +++ /dev/null @@ -1,325 +0,0 @@ -{ - "status": 200, - "message": "SUCCESS", - "data": { - "ratingAverage": 4.125, - "reviewTotalCount": 8, - "keywordTotalCount": 38, - "reviewInfos": { - "content": [ - { - "reviewId": 15, - "authorNickname": "익명 사용자1", - "authorProfileImageUrl": "https://common.hanmi.co.kr/upfile/ces/product/p_2011_tenten_p_400.jpg", - "rating": 4, - "createdTime": "2023-12-30T20:02:06.03406", - "content": "좋은 여행지였습니다.", - "keywords": [ - { - "keywordId": 1, - "content": "깨끗해요", - "type": "ACCOMMODATION_KEYWORD" - }, - { - "keywordId": 2, - "content": "친절해요", - "type": "ACCOMMODATION_KEYWORD" - } - ], - "commentCount": 0 - }, - { - "reviewId": 23, - "authorNickname": "익명 사용자1", - "authorProfileImageUrl": "https://common.hanmi.co.kr/upfile/ces/product/p_2011_tenten_p_400.jpg", - "rating": 4, - "createdTime": "2023-12-30T20:03:17.978397", - "content": "좋은 여행지였습니다.", - "keywords": [ - { - "keywordId": 1, - "content": "깨끗해요", - "type": "ACCOMMODATION_KEYWORD" - }, - { - "keywordId": 2, - "content": "친절해요", - "type": "ACCOMMODATION_KEYWORD" - } - ], - "commentCount": 0 - }, - { - "reviewId": 24, - "authorNickname": "익명 사용자1", - "authorProfileImageUrl": "https://common.hanmi.co.kr/upfile/ces/product/p_2011_tenten_p_400.jpg", - "rating": 4, - "createdTime": "2023-12-30T20:03:18.970952", - "content": "좋은 여행지였습니다.", - "keywords": [ - { - "keywordId": 1, - "content": "깨끗해요", - "type": "ACCOMMODATION_KEYWORD" - }, - { - "keywordId": 2, - "content": "친절해요", - "type": "ACCOMMODATION_KEYWORD" - } - ], - "commentCount": 0 - }, - { - "reviewId": 25, - "authorNickname": "익명 사용자1", - "authorProfileImageUrl": "https://common.hanmi.co.kr/upfile/ces/product/p_2011_tenten_p_400.jpg", - "rating": 4, - "createdTime": "2023-12-30T20:03:20.335173", - "content": "좋은 여행지였습니다.", - "keywords": [ - { - "keywordId": 1, - "content": "깨끗해요", - "type": "ACCOMMODATION_KEYWORD" - }, - { - "keywordId": 2, - "content": "친절해요", - "type": "ACCOMMODATION_KEYWORD" - } - ], - "commentCount": 0 - }, - { - "reviewId": 26, - "authorNickname": "익명 사용자1", - "authorProfileImageUrl": "https://common.hanmi.co.kr/upfile/ces/product/p_2011_tenten_p_400.jpg", - "rating": 4, - "createdTime": "2023-12-30T20:03:21.924918", - "content": "좋은 여행지였습니다.", - "keywords": [ - { - "keywordId": 1, - "content": "깨끗해요", - "type": "ACCOMMODATION_KEYWORD" - }, - { - "keywordId": 2, - "content": "친절해요", - "type": "ACCOMMODATION_KEYWORD" - } - ], - "commentCount": 0 - } - ], - "pageable": { - "pageNumber": 0, - "pageSize": 20, - "sort": { - "sorted": false, - "empty": true, - "unsorted": true - }, - "offset": 0, - "paged": true, - "unpaged": false - }, - "last": true, - "totalElements": 5, - "totalPages": 1, - "size": 20, - "number": 0, - "sort": { - "sorted": false, - "empty": true, - "unsorted": true - }, - "first": true, - "numberOfElements": 5, - "empty": false - }, - "tourKeywordInfos": [ - { - "keywordId": 1, - "content": "깨끗해요", - "type": "ACCOMMODATION_KEYWORD", - "keywordCount": 5 - }, - { - "keywordId": 2, - "content": "친절해요", - "type": "ACCOMMODATION_KEYWORD", - "keywordCount": 5 - }, - { - "keywordId": 3, - "content": "뷰가 좋아요", - "type": "ACCOMMODATION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 4, - "content": "침구가 좋아요", - "type": "ACCOMMODATION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 5, - "content": "주차하기 편해요", - "type": "ACCOMMODATION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 6, - "content": "냉난방이 잘돼요", - "type": "ACCOMMODATION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 7, - "content": "대중교통이 편해요", - "type": "ACCOMMODATION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 8, - "content": "호캉스하기 좋아요", - "type": "ACCOMMODATION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 9, - "content": "조식이 맛있어요", - "type": "ACCOMMODATION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 10, - "content": "사진 찍기 좋아요", - "type": "ACCOMMODATION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 11, - "content": "음식이 맛있어요", - "type": "DINING_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 12, - "content": "친절해요", - "type": "DINING_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 13, - "content": "인테리어가 멋져요", - "type": "DINING_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 14, - "content": "매장이 청결해요", - "type": "DINING_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 15, - "content": "특별한 메뉴가 있어요", - "type": "DINING_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 16, - "content": "가성비가 좋아요", - "type": "DINING_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 17, - "content": "재료가 신선해요", - "type": "DINING_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 18, - "content": "사진찍기 좋아요", - "type": "DINING_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 19, - "content": "주차하기 편해요", - "type": "DINING_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 20, - "content": "화장실이 깨끗해요", - "type": "DINING_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 21, - "content": "사진이 잘 나와요", - "type": "ATTRACTION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 22, - "content": "뷰가 좋아요", - "type": "ATTRACTION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 23, - "content": "관리가 잘 되어있어요", - "type": "ATTRACTION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 24, - "content": "볼거리가 많아요", - "type": "ATTRACTION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 25, - "content": "편의시설이 잘 되어 있어요", - "type": "ATTRACTION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 26, - "content": "대중교통이 편해요", - "type": "ATTRACTION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 27, - "content": "주차하기 편해요", - "type": "ATTRACTION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 28, - "content": "화장실이 깨끗해요", - "type": "ATTRACTION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 29, - "content": "가격이 합리적이에요", - "type": "ATTRACTION_KEYWORD", - "keywordCount": 1 - }, - { - "keywordId": 30, - "content": "방문객이 많아요", - "type": "ATTRACTION_KEYWORD", - "keywordCount": 1 - } - ] - } -} \ No newline at end of file diff --git a/src/components/Review/Review.tsx b/src/components/Review/Review.tsx new file mode 100644 index 00000000..6114bb50 --- /dev/null +++ b/src/components/Review/Review.tsx @@ -0,0 +1,15 @@ +import ReviewButton from './ReviewButton'; +import ReviewKeyword from './ReviewKeyword'; +import ReviewPosting from './ReviewPosting'; +import ReviewRating from './ReviewRating'; + +export default function Review() { + return ( + <> + + + + + + ); +} diff --git a/src/components/Review/ReviewButton.tsx b/src/components/Review/ReviewButton.tsx new file mode 100644 index 00000000..eaf9c5a4 --- /dev/null +++ b/src/components/Review/ReviewButton.tsx @@ -0,0 +1,5 @@ +import { ButtonPrimary } from '@components/common/button/Button'; + +export default function ReviewButton() { + return {}}>완료; +} diff --git a/src/components/Review/ReviewKeyword.tsx b/src/components/Review/ReviewKeyword.tsx new file mode 100644 index 00000000..79bb0f5e --- /dev/null +++ b/src/components/Review/ReviewKeyword.tsx @@ -0,0 +1,47 @@ +export default function ReviewKeyword() { + return ( +
+
어떤 점이 좋았나요?
+
+
+
+ 깨끗해요 +
+
+ 친절해요 +
+
+ 뷰가 좋아요 +
+
+
+
+ 침구가 좋아요 +
+
+ 주차하기 편해요 +
+
+ 냉난방이 잘돼요 +
+
+
+
+ 대중교통이 편해요 +
+
+ 호캉스하기 좋아요 +
+
+
+
+ 조식이 맛있어요 +
+
+ 사진 찍기 좋아요 +
+
+
+
+ ); +} diff --git a/src/components/Review/ReviewPosting.tsx b/src/components/Review/ReviewPosting.tsx new file mode 100644 index 00000000..d50a518c --- /dev/null +++ b/src/components/Review/ReviewPosting.tsx @@ -0,0 +1,24 @@ +import { useState, ChangeEvent } from 'react'; + +export default function ReviewPosting() { + const [textLength, setTextLength] = useState(0); + + const handleTextChange = (event: ChangeEvent) => { + const inputText = event.target.value; + setTextLength(inputText.length); + }; + + return ( +
+
리뷰를 작성해주세요
+
+