From 7f55b1dc0fa609de3c40418bb4219c7f83c21435 Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Thu, 18 Jan 2024 16:21:49 +0900 Subject: [PATCH 01/15] Feat: delete phoneNumber underline --- .../Contents/Information/BasicInformation/BasicInformation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Detail/Contents/Information/BasicInformation/BasicInformation.tsx b/src/components/Detail/Contents/Information/BasicInformation/BasicInformation.tsx index 0a284665..e20fe598 100644 --- a/src/components/Detail/Contents/Information/BasicInformation/BasicInformation.tsx +++ b/src/components/Detail/Contents/Information/BasicInformation/BasicInformation.tsx @@ -19,7 +19,7 @@ function BasicInformation() {
- 031-771-1234 + 031-771-1234
From 2b41df34ba9252bcc5129d786bbf419e7c8409a9 Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Thu, 18 Jan 2024 16:24:14 +0900 Subject: [PATCH 02/15] Feat: delete recommend others reviews count --- .../Information/Others/OtherCard/OtherCard.module.scss | 5 ----- .../Contents/Information/Others/OtherCard/OtherCard.tsx | 3 --- 2 files changed, 8 deletions(-) diff --git a/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.module.scss b/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.module.scss index f03d6568..7dd44631 100644 --- a/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.module.scss +++ b/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.module.scss @@ -40,11 +40,6 @@ @include typography(captionSmall); margin-right: 4px; } - - &__reviewsCount { - color: $neutral400; - @include typography(captionSmall); - } } } } diff --git a/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.tsx b/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.tsx index 1ec0e776..9cd28f41 100644 --- a/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.tsx +++ b/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.tsx @@ -24,9 +24,6 @@ function OtherCard({ {point} - - ({count}) -
From 774afd969c1f1025a13eb4dfd75829b89b26f074 Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Thu, 18 Jan 2024 16:25:49 +0900 Subject: [PATCH 03/15] Feat: delete recommend others reviews count props --- .../Contents/Information/Others/OtherCard/OtherCard.tsx | 8 +------- .../Detail/Contents/Information/Others/Others.tsx | 1 - src/types/detail.ts | 1 - 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.tsx b/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.tsx index 9cd28f41..f6d22cac 100644 --- a/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.tsx +++ b/src/components/Detail/Contents/Information/Others/OtherCard/OtherCard.tsx @@ -4,13 +4,7 @@ import styles from "./OtherCard.module.scss"; import { OtherCardPropsType } from "@/types/detail"; -function OtherCard({ - image, - name, - location, - point, - count, -}: OtherCardPropsType) { +function OtherCard({ image, name, location, point }: OtherCardPropsType) { return (
diff --git a/src/components/Detail/Contents/Information/Others/Others.tsx b/src/components/Detail/Contents/Information/Others/Others.tsx index 4c1ceba6..a43e3872 100644 --- a/src/components/Detail/Contents/Information/Others/Others.tsx +++ b/src/components/Detail/Contents/Information/Others/Others.tsx @@ -91,7 +91,6 @@ function Others() { name={data.name} location={data.location} point={data.point} - count={data.count} /> ))}
diff --git a/src/types/detail.ts b/src/types/detail.ts index cf541f81..5ea37825 100644 --- a/src/types/detail.ts +++ b/src/types/detail.ts @@ -5,7 +5,6 @@ export interface OtherCardPropsType { name: string; location: string; point: string; - count: number; } export interface ReviewPropsTypes { From 90490303f4e8af2a95862455858083f86cbff254 Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Fri, 19 Jan 2024 02:26:24 +0900 Subject: [PATCH 04/15] Feat: create title heart, share btn toast --- src/components/Detail/Main/Title/Title.tsx | 47 ++++++++++++++++++- .../MeatballBottomSlide.tsx | 17 ++++++- src/recoil/detail/detail.ts | 5 ++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/components/Detail/Main/Title/Title.tsx b/src/components/Detail/Main/Title/Title.tsx index 87d6f470..f2dc8742 100644 --- a/src/components/Detail/Main/Title/Title.tsx +++ b/src/components/Detail/Main/Title/Title.tsx @@ -1,10 +1,33 @@ +import { useEffect } from "react"; import { FaRegHeart } from "react-icons/fa"; +import { FaHeart } from "react-icons/fa"; import { GoStarFill } from "react-icons/go"; import { IoShareSocialOutline } from "react-icons/io5"; +import { useRecoilState } from "recoil"; import styles from "./Title.module.scss"; +import CustomToast from "@/components/CustomToast/CustomToast"; + +import { IsHeartValued } from "@/recoil/detail/detail"; + function Title() { + const [isHeart, setIsHeart] = useRecoilState(IsHeartValued); + + const showToast = CustomToast(); + + const handleHeartClick = () => { + if (!isHeart) { + showToast("찜 목록에 저장되었습니다."); + } + + setIsHeart(!isHeart); + }; + + useEffect(() => { + setIsHeart(true); + }, []); + return (

롯데시티 호텔

@@ -17,8 +40,28 @@ function Title() {
- - + {isHeart ? ( + + ) : ( + + )} + + { + showToast("링크가 복사되었습니다."); + }} + />
); diff --git a/src/components/Detail/Navigation/MeatballBottomSlide/MeatballBottomSlide.tsx b/src/components/Detail/Navigation/MeatballBottomSlide/MeatballBottomSlide.tsx index aaa6d6f7..7f830fdd 100644 --- a/src/components/Detail/Navigation/MeatballBottomSlide/MeatballBottomSlide.tsx +++ b/src/components/Detail/Navigation/MeatballBottomSlide/MeatballBottomSlide.tsx @@ -2,12 +2,14 @@ import { BiTask } from "react-icons/bi"; import { CiEdit } from "react-icons/ci"; import { FaRegHeart } from "react-icons/fa"; import { IoShareSocialOutline } from "react-icons/io5"; +import { useRecoilState } from "recoil"; import styles from "./MeatballBottomSlide.module.scss"; import CustomToast from "@/components/CustomToast/CustomToast"; import CloseIcon from "@/assets/close.svg?react"; +import { IsHeartValued } from "@/recoil/detail/detail"; import RegistrationSlide from "../../BottomFixedBtn/RegistrationSlide/RegistrationSlide"; import ReviewBottomSlide from "../../Contents/ReviewBottomSlide/ReviewBottomSlide"; @@ -18,8 +20,17 @@ const MeatballBottomSlide = ({ onBottomSlideOpen, onClose, }: NavigationMeatballProps) => { + const [isHeart, setIsHeart] = useRecoilState(IsHeartValued); + const showToast = CustomToast(); + const handleHeartClick = () => { + if (!isHeart) { + showToast("찜 목록에 저장되었습니다."); + } + + setIsHeart(!isHeart); + }; return (
- + }} + > + + 새 투표 생성 + + ) : ( + + )}
여행 스페이스
diff --git a/src/components/Detail/Main/Title/Title.tsx b/src/components/Detail/Main/Title/Title.tsx index f2dc8742..a16c1ab8 100644 --- a/src/components/Detail/Main/Title/Title.tsx +++ b/src/components/Detail/Main/Title/Title.tsx @@ -26,7 +26,7 @@ function Title() { useEffect(() => { setIsHeart(true); - }, []); + }); return (
From 1d4f21ea4816a8dfe211b81cd8a61c9a46eba3d5 Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Fri, 19 Jan 2024 10:08:21 +0900 Subject: [PATCH 06/15] Feat: create TripSelected but not valued --- .../RegistrationSlide.module.scss | 15 ++++++ .../RegistrationSlide/RegistrationSlide.tsx | 49 ++++++++++++------- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationSlide.module.scss b/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationSlide.module.scss index 692801e1..6588ef6c 100644 --- a/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationSlide.module.scss +++ b/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationSlide.module.scss @@ -63,6 +63,21 @@ gap: 8px; } + &__voteNotValued { + margin-top: 64px; + text-align: center; + + &__top { + @include typography(subTitle); + color: $neutral400; + } + + &__bottom { + @include typography(captionSmall); + color: $neutral300; + } + } + &__bottomFixedBtn { padding: 12px 0; width: 100%; diff --git a/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationSlide.tsx b/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationSlide.tsx index e1fd0b06..e2f08032 100644 --- a/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationSlide.tsx +++ b/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationSlide.tsx @@ -24,6 +24,8 @@ function RegistrationSlide({ slideOnClose }: RegistrationSlideProps) { // useEffect fetchData + const exArray = []; + return ( <>
@@ -57,26 +59,37 @@ function RegistrationSlide({ slideOnClose }: RegistrationSlideProps) {
투표리스트
{TripSelected ? ( -
-
- 후보로 등록할 투표 제목을 선택해주세요 + exArray.length > 0 ? ( +
+
+ 후보로 등록할 투표 제목을 선택해주세요 +
+
+ + {/* 초과 글씨 ... 처리 해야함*/} + + +
-
- - {/* 초과 글씨 ... 처리 해야함*/} - - + ) : ( +
+

+ 생성된 투표가 없습니다. +

+

+ 투표 생성을 눌러 새로운 투표를 만들어주세요! +

-
+ ) ) : (
여행을 먼저 선택해주세요 From 4ff9fbd50cd5dafd9ee6467df122fffbb707598c Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Fri, 19 Jan 2024 16:13:43 +0900 Subject: [PATCH 07/15] Feat: isLogin modal --- .../Detail/BottomFixedBtn/BottomFixedBtn.tsx | 30 +++++++++++++++- .../Information/ShortReveiws/ShortReviews.tsx | 34 +++++++++++++++++-- .../Detail/Contents/Reviews/Reviews.tsx | 34 +++++++++++++++++-- src/components/Detail/Main/Title/Title.tsx | 33 ++++++++++++++---- .../MeatballBottomSlide.tsx | 32 ++++++++++++++--- src/pages/Detail/Detail.tsx | 6 ++++ src/recoil/detail/detail.ts | 5 +++ 7 files changed, 158 insertions(+), 16 deletions(-) diff --git a/src/components/Detail/BottomFixedBtn/BottomFixedBtn.tsx b/src/components/Detail/BottomFixedBtn/BottomFixedBtn.tsx index 3ac4d0b6..1269d840 100644 --- a/src/components/Detail/BottomFixedBtn/BottomFixedBtn.tsx +++ b/src/components/Detail/BottomFixedBtn/BottomFixedBtn.tsx @@ -1,8 +1,30 @@ +import { useRecoilValue, useSetRecoilState } from "recoil"; + import styles from "./BottomFixedBtn.module.scss"; +import { IsLoginState } from "@/recoil/detail/detail"; +import { isModalOpenState, modalContentState } from "@/recoil/vote/alertModal"; + import { BottomFixedBtnProps } from "@/types/detail"; function BottomFixedBtn({ onOpen }: BottomFixedBtnProps) { + const setIsModalOpen = useSetRecoilState(isModalOpenState); + const setModalContent = useSetRecoilState(modalContentState); + const isLogin = useRecoilValue(IsLoginState); + + const notLoginContent = { + title: "로그인이 필요한 기능입니다.", + subText: "로그인하고 모든 서비스를 이용해 보세요! ", + cancelText: "닫기", + actionButton: "로그인하기", + isSmallSize: true, + }; + + const showNotLoginModal = () => { + setIsModalOpen(true); + setModalContent({ ...notLoginContent }); + }; + return (
{ + if (isLogin) { + onOpen(); + } else { + showNotLoginModal(); + } + }} > 이 장소 후보로 등록하기
diff --git a/src/components/Detail/Contents/Information/ShortReveiws/ShortReviews.tsx b/src/components/Detail/Contents/Information/ShortReveiws/ShortReviews.tsx index 649de686..c2e18d2b 100644 --- a/src/components/Detail/Contents/Information/ShortReveiws/ShortReviews.tsx +++ b/src/components/Detail/Contents/Information/ShortReveiws/ShortReviews.tsx @@ -1,13 +1,34 @@ import { CiEdit } from "react-icons/ci"; import { GoStarFill } from "react-icons/go"; +import { useRecoilValue, useSetRecoilState } from "recoil"; import styles from "./ShortReviews.module.scss"; import Review from "@/components/Detail/Contents/Review/Review"; +import { IsLoginState } from "@/recoil/detail/detail"; +import { isModalOpenState, modalContentState } from "@/recoil/vote/alertModal"; + import { ContentsShortReviewsProps } from "@/types/detail"; function ShortReviews({ onOpen }: ContentsShortReviewsProps) { + const setIsModalOpen = useSetRecoilState(isModalOpenState); + const setModalContent = useSetRecoilState(modalContentState); + const isLogin = useRecoilValue(IsLoginState); + + const notLoginContent = { + title: "로그인이 필요한 기능입니다.", + subText: "로그인하고 모든 서비스를 이용해 보세요! ", + cancelText: "닫기", + actionButton: "로그인하기", + isSmallSize: true, + }; + + const showNotLoginModal = () => { + setIsModalOpen(true); + setModalContent({ ...notLoginContent }); + }; + const reviewData = [ { name: "강자밭", @@ -41,10 +62,19 @@ function ShortReviews({ onOpen }: ContentsShortReviewsProps) {

리뷰

-
+
+
diff --git a/src/components/Detail/Contents/Reviews/Reviews.tsx b/src/components/Detail/Contents/Reviews/Reviews.tsx index 67bd1ec6..bf48dbd9 100644 --- a/src/components/Detail/Contents/Reviews/Reviews.tsx +++ b/src/components/Detail/Contents/Reviews/Reviews.tsx @@ -1,13 +1,34 @@ import { CiEdit } from "react-icons/ci"; import { GoStarFill } from "react-icons/go"; +import { useRecoilValue, useSetRecoilState } from "recoil"; import styles from "./Rviews.module.scss"; import Review from "@/components/Detail/Contents/Review/Review"; +import { IsLoginState } from "@/recoil/detail/detail"; +import { isModalOpenState, modalContentState } from "@/recoil/vote/alertModal"; + import { ContentsReviewsProps } from "@/types/detail"; // 무한 스크롤 구현 필요 function Reviews({ onOpen }: ContentsReviewsProps) { + const setIsModalOpen = useSetRecoilState(isModalOpenState); + const setModalContent = useSetRecoilState(modalContentState); + const isLogin = useRecoilValue(IsLoginState); + + const notLoginContent = { + title: "로그인이 필요한 기능입니다.", + subText: "로그인하고 모든 서비스를 이용해 보세요! ", + cancelText: "닫기", + actionButton: "로그인하기", + isSmallSize: true, + }; + + const showNotLoginModal = () => { + setIsModalOpen(true); + setModalContent({ ...notLoginContent }); + }; + const reviewData = [ { name: "강자밭", @@ -118,10 +139,19 @@ function Reviews({ onOpen }: ContentsReviewsProps) {

리뷰

-
+
+
diff --git a/src/components/Detail/Main/Title/Title.tsx b/src/components/Detail/Main/Title/Title.tsx index a16c1ab8..af8071f8 100644 --- a/src/components/Detail/Main/Title/Title.tsx +++ b/src/components/Detail/Main/Title/Title.tsx @@ -3,25 +3,46 @@ import { FaRegHeart } from "react-icons/fa"; import { FaHeart } from "react-icons/fa"; import { GoStarFill } from "react-icons/go"; import { IoShareSocialOutline } from "react-icons/io5"; -import { useRecoilState } from "recoil"; +import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil"; import styles from "./Title.module.scss"; import CustomToast from "@/components/CustomToast/CustomToast"; -import { IsHeartValued } from "@/recoil/detail/detail"; +import { IsHeartValued, IsLoginState } from "@/recoil/detail/detail"; +import { isModalOpenState, modalContentState } from "@/recoil/vote/alertModal"; function Title() { const [isHeart, setIsHeart] = useRecoilState(IsHeartValued); + const setIsModalOpen = useSetRecoilState(isModalOpenState); + const setModalContent = useSetRecoilState(modalContentState); + + const isLogin = useRecoilValue(IsLoginState); + + const notLoginContent = { + title: "로그인이 필요한 기능입니다.", + subText: "로그인하고 모든 서비스를 이용해 보세요! ", + cancelText: "닫기", + actionButton: "로그인하기", + isSmallSize: true, + }; + + const showNotLoginModal = () => { + setIsModalOpen(true); + setModalContent({ ...notLoginContent }); + }; const showToast = CustomToast(); const handleHeartClick = () => { - if (!isHeart) { - showToast("찜 목록에 저장되었습니다."); + if (isLogin) { + if (!isHeart) { + showToast("찜 목록에 저장되었습니다."); + } + setIsHeart(!isHeart); + } else { + showNotLoginModal(); } - - setIsHeart(!isHeart); }; useEffect(() => { diff --git a/src/components/Detail/Navigation/MeatballBottomSlide/MeatballBottomSlide.tsx b/src/components/Detail/Navigation/MeatballBottomSlide/MeatballBottomSlide.tsx index 7f830fdd..35e2cc39 100644 --- a/src/components/Detail/Navigation/MeatballBottomSlide/MeatballBottomSlide.tsx +++ b/src/components/Detail/Navigation/MeatballBottomSlide/MeatballBottomSlide.tsx @@ -2,14 +2,15 @@ import { BiTask } from "react-icons/bi"; import { CiEdit } from "react-icons/ci"; import { FaRegHeart } from "react-icons/fa"; import { IoShareSocialOutline } from "react-icons/io5"; -import { useRecoilState } from "recoil"; +import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil"; import styles from "./MeatballBottomSlide.module.scss"; import CustomToast from "@/components/CustomToast/CustomToast"; import CloseIcon from "@/assets/close.svg?react"; -import { IsHeartValued } from "@/recoil/detail/detail"; +import { IsHeartValued, IsLoginState } from "@/recoil/detail/detail"; +import { isModalOpenState, modalContentState } from "@/recoil/vote/alertModal"; import RegistrationSlide from "../../BottomFixedBtn/RegistrationSlide/RegistrationSlide"; import ReviewBottomSlide from "../../Contents/ReviewBottomSlide/ReviewBottomSlide"; @@ -21,7 +22,22 @@ const MeatballBottomSlide = ({ onClose, }: NavigationMeatballProps) => { const [isHeart, setIsHeart] = useRecoilState(IsHeartValued); + const setIsModalOpen = useSetRecoilState(isModalOpenState); + const setModalContent = useSetRecoilState(modalContentState); + const isLogin = useRecoilValue(IsLoginState); + const notLoginContent = { + title: "로그인이 필요한 기능입니다.", + subText: "로그인하고 모든 서비스를 이용해 보세요! ", + cancelText: "닫기", + actionButton: "로그인하기", + isSmallSize: true, + }; + + const showNotLoginModal = () => { + setIsModalOpen(true); + setModalContent({ ...notLoginContent }); + }; const showToast = CustomToast(); const handleHeartClick = () => { @@ -31,6 +47,7 @@ const MeatballBottomSlide = ({ setIsHeart(!isHeart); }; + return (
-
+
{ + setTabIndex(1); + window.scrollTo(0, tabPosition); + }} + > 리뷰 전체보기
diff --git a/src/recoil/detail/detail.ts b/src/recoil/detail/detail.ts index 2a2f8644..2447bbed 100644 --- a/src/recoil/detail/detail.ts +++ b/src/recoil/detail/detail.ts @@ -24,3 +24,13 @@ export const IsLoginState = atom({ key: "IsLoginState", default: true, }); + +export const TabIndexState = atom({ + key: "TabIndexState", + default: 0, +}); + +export const TabYPosition = atom({ + key: "TabYPosition", + default: 0, +}); From 32387d1637f1dbec3141a63cd21b26423cad0f34 Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Sun, 21 Jan 2024 20:00:59 +0900 Subject: [PATCH 10/15] Feat: main slide zoom modal --- src/chakra/modalCustom.ts | 11 ++ .../RegistrationModal/RegistrationModal.tsx | 2 +- .../Detail/Main/ImageSwiper/Swiper.tsx | 50 +++++--- .../ImageSwiper/SwiperButton/SwiperButton.tsx | 6 +- .../ImageSwiper/SwiperIndex/SwiperIndex.tsx | 2 +- .../Main/SlideModal/SlideModal.module.scss | 26 ++++ .../Detail/Main/SlideModal/SlideModal.tsx | 112 ++++++++++++++++++ 7 files changed, 186 insertions(+), 23 deletions(-) create mode 100644 src/components/Detail/Main/SlideModal/SlideModal.module.scss create mode 100644 src/components/Detail/Main/SlideModal/SlideModal.tsx diff --git a/src/chakra/modalCustom.ts b/src/chakra/modalCustom.ts index 389a5bcc..7a717e4d 100644 --- a/src/chakra/modalCustom.ts +++ b/src/chakra/modalCustom.ts @@ -59,5 +59,16 @@ export const modalTheme = defineMultiStyleConfig({ variants: { alertModal }, sizes: { addVote: { dialog: { w: "100%", maxW: "41rem", mx: "24px" } }, + imageModal: { + dialog: { + w: "100%", + maxW: "45rem", + height: "100%", + my: 0, + bg: "#0A0D14", + }, + body: {}, + footer: {}, + }, }, }); diff --git a/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationModal/RegistrationModal.tsx b/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationModal/RegistrationModal.tsx index b9c52de9..036b3693 100644 --- a/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationModal/RegistrationModal.tsx +++ b/src/components/Detail/BottomFixedBtn/RegistrationSlide/RegistrationModal/RegistrationModal.tsx @@ -32,7 +32,7 @@ const RegistrationModal = ({ isOpen, onClose }: RegistrationMoalProps) => { return ( - + (1); + const [imageIndex, setImageIndex] = useState(0); + const { isOpen, onOpen, onClose } = useDisclosure(); return ( - { - setImageIndex(swiper.activeIndex + 1); - }} - > - {images.map((data) => ( - - # - - ))} - + { + setImageIndex(swiperCore.activeIndex); + }} + > + {images.map((data) => ( + + # + + ))} + + + + - - + ); } diff --git a/src/components/Detail/Main/ImageSwiper/SwiperButton/SwiperButton.tsx b/src/components/Detail/Main/ImageSwiper/SwiperButton/SwiperButton.tsx index ca46db43..a0729423 100644 --- a/src/components/Detail/Main/ImageSwiper/SwiperButton/SwiperButton.tsx +++ b/src/components/Detail/Main/ImageSwiper/SwiperButton/SwiperButton.tsx @@ -15,7 +15,7 @@ function SwiperButton({ imageIndex, imageLength }: SwiperButtonPropsType) { onClick={() => { swiper.slidePrev(); }} - style={imageIndex <= 1 ? { display: "none" } : { display: "block" }} + style={imageIndex <= 0 ? { display: "none" } : { display: "block" }} > @@ -25,7 +25,9 @@ function SwiperButton({ imageIndex, imageLength }: SwiperButtonPropsType) { swiper.slideNext(); }} style={ - imageIndex >= imageLength ? { display: "none" } : { display: "block" } + imageIndex >= imageLength - 1 + ? { display: "none" } + : { display: "block" } } > diff --git a/src/components/Detail/Main/ImageSwiper/SwiperIndex/SwiperIndex.tsx b/src/components/Detail/Main/ImageSwiper/SwiperIndex/SwiperIndex.tsx index 107e4218..5e00e357 100644 --- a/src/components/Detail/Main/ImageSwiper/SwiperIndex/SwiperIndex.tsx +++ b/src/components/Detail/Main/ImageSwiper/SwiperIndex/SwiperIndex.tsx @@ -5,7 +5,7 @@ import { SwiperIndexPropsType } from "@/types/detail"; function SwiperIndex({ imageIndex, imageLength }: SwiperIndexPropsType) { return (
- {imageIndex} + {imageIndex + 1} / {imageLength}
diff --git a/src/components/Detail/Main/SlideModal/SlideModal.module.scss b/src/components/Detail/Main/SlideModal/SlideModal.module.scss new file mode 100644 index 00000000..53f69361 --- /dev/null +++ b/src/components/Detail/Main/SlideModal/SlideModal.module.scss @@ -0,0 +1,26 @@ +@use "@/sass" as *; + +.slideIndex { + @include typography(button); + color: $neutral0; + position: absolute; + top: 17px; + left: 50%; + transform: translateX(-50%); +} + +.mainSlideContainer { + position: absolute; + top: 50%; + transform: translateY(-50%); +} + +.bottomSlide { + .swiperSlide { + border: 1px solid $neutral0; + } + + .swiperSlideActive { + border: 1px solid $primary300; + } +} diff --git a/src/components/Detail/Main/SlideModal/SlideModal.tsx b/src/components/Detail/Main/SlideModal/SlideModal.tsx new file mode 100644 index 00000000..96a29621 --- /dev/null +++ b/src/components/Detail/Main/SlideModal/SlideModal.tsx @@ -0,0 +1,112 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, +} from "@chakra-ui/react"; +import { useEffect, useState } from "react"; +import { Thumbs } from "swiper/modules"; +import { Swiper, SwiperSlide } from "swiper/react"; + +// Import Swiper styles +// import "swiper/css"; +// import "swiper/css/thumbs"; +import styles from "./SlideModal.module.scss"; + +interface SlideModalProps { + isOpen: boolean; + onClose: () => void; + images: string[]; + imageIndex: number; + setImageIndex: React.Dispatch>; +} + +function SlideModal({ + isOpen, + onClose, + images, + imageIndex, + setImageIndex, +}: SlideModalProps) { + const [thumbsSwiper, setThumbsSwiper] = useState(); + const [swiperIndex, setSwiperIndex] = useState(0); + + useEffect(() => { + setSwiperIndex(imageIndex); + }); + + return ( + + + + + + + {swiperIndex + 1}/{images.length} + + + + console.log(swiper.activeIndex)} + modules={[Thumbs]} + className={styles.mainSlideContainer} + onActiveIndexChange={(swiperCore) => { + setSwiperIndex(swiperCore.activeIndex); + setImageIndex(swiperCore.activeIndex); + }} + > + {images && + images.map((image, i) => ( + + + + ))} + + + + + {images && + images.map((image, i) => ( + + + + ))} + + + + + ); +} + +export default SlideModal; From f98b0f42d48dbd9788158bc166a5318f4452a920 Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Mon, 22 Jan 2024 01:53:52 +0900 Subject: [PATCH 11/15] Feat: review slide zoom modal --- .../ReviewImageSlider/ReviewImageSlider.tsx | 21 ++++++++++++++++-- .../Main/SlideModal/SlideModal.module.scss | 22 ++++++++++++++++++- .../Detail/Main/SlideModal/SlideModal.tsx | 3 +-- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/components/Detail/Contents/Review/ReviewImageSlider/ReviewImageSlider.tsx b/src/components/Detail/Contents/Review/ReviewImageSlider/ReviewImageSlider.tsx index 6c8741d6..638652e9 100644 --- a/src/components/Detail/Contents/Review/ReviewImageSlider/ReviewImageSlider.tsx +++ b/src/components/Detail/Contents/Review/ReviewImageSlider/ReviewImageSlider.tsx @@ -1,15 +1,25 @@ +import { useDisclosure } from "@chakra-ui/react"; import { useState } from "react"; import styles from "./ReviewImageSlider.module.scss"; import useComponentSize from "@/hooks/useComponetSize"; +import SlideModal from "@/components/Detail/Main/SlideModal/SlideModal"; import SlideButton from "@/components/SlideButton/SlideButton"; function ReviewImageSlider({ images }: { images: string[] }) { const [slideLocation, setSlideLocation] = useState(0); const [componentRef, size] = useComponentSize(); + const [imageIndex, setImageIndex] = useState(0); + const { isOpen, onOpen, onClose } = useDisclosure(); + + const handleIsOpen = (index: number) => { + setImageIndex(index); + onOpen(); + }; + return (
{images && ( @@ -36,10 +46,17 @@ function ReviewImageSlider({ images }: { images: string[] }) { left: slideLocation + "px", }} > - {images.map((data) => ( - + {images.map((data, i) => ( + handleIsOpen(i)} /> ))}
+
); } diff --git a/src/components/Detail/Main/SlideModal/SlideModal.module.scss b/src/components/Detail/Main/SlideModal/SlideModal.module.scss index 53f69361..414cdef7 100644 --- a/src/components/Detail/Main/SlideModal/SlideModal.module.scss +++ b/src/components/Detail/Main/SlideModal/SlideModal.module.scss @@ -10,17 +10,37 @@ } .mainSlideContainer { - position: absolute; + position: fixed; top: 50%; transform: translateY(-50%); + + div { + position: relative; + height: 50rem; + img { + position: absolute; + top: 50%; + transform: translateY(-50%); + } + } } .bottomSlide { + width: 100%; .swiperSlide { border: 1px solid $neutral0; + width: 5.6rem; + height: 5.6rem; } .swiperSlideActive { border: 1px solid $primary300; + width: 5.6rem; + height: 5.6rem; + } + + img { + width: 100%; + height: 100%; } } diff --git a/src/components/Detail/Main/SlideModal/SlideModal.tsx b/src/components/Detail/Main/SlideModal/SlideModal.tsx index 96a29621..c855922a 100644 --- a/src/components/Detail/Main/SlideModal/SlideModal.tsx +++ b/src/components/Detail/Main/SlideModal/SlideModal.tsx @@ -59,7 +59,6 @@ function SlideModal({ Date: Mon, 22 Jan 2024 01:55:21 +0900 Subject: [PATCH 12/15] Fix: useEffect error in slide moal --- src/components/Detail/Main/SlideModal/SlideModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Detail/Main/SlideModal/SlideModal.tsx b/src/components/Detail/Main/SlideModal/SlideModal.tsx index c855922a..ca9f8438 100644 --- a/src/components/Detail/Main/SlideModal/SlideModal.tsx +++ b/src/components/Detail/Main/SlideModal/SlideModal.tsx @@ -38,7 +38,7 @@ function SlideModal({ useEffect(() => { setSwiperIndex(imageIndex); - }); + }, [imageIndex]); return ( From 5672e53b7844b08652aea541da0088287d8519c6 Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Mon, 22 Jan 2024 02:08:26 +0900 Subject: [PATCH 13/15] Feat: create init bottom slide feature --- .../BottomSlideDetail/BottomSlideDetail.tsx | 3 +++ src/pages/Detail/Detail.tsx | 18 +++++++++++++++--- src/types/detail.ts | 1 + 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/components/Detail/BottomSlideDetail/BottomSlideDetail.tsx b/src/components/Detail/BottomSlideDetail/BottomSlideDetail.tsx index 901601df..ed2468a2 100644 --- a/src/components/Detail/BottomSlideDetail/BottomSlideDetail.tsx +++ b/src/components/Detail/BottomSlideDetail/BottomSlideDetail.tsx @@ -12,6 +12,7 @@ function BottomSlideDetail({ onClose, children, isReviewModal, + setBottomSlideContent, }: BottomSlideDetailProps) { const setIsModalOpen = useSetRecoilState(isModalOpenState); const setModalContent = useSetRecoilState(modalContentState); @@ -23,6 +24,7 @@ function BottomSlideDetail({ actionButton: "나갈래요", isSmallSize: true, onClickAction: () => { + setBottomSlideContent(null); setIsModalOpen(false); onClose(); document.body.style.removeProperty("overflow"); @@ -45,6 +47,7 @@ function BottomSlideDetail({ if (isReviewModal) { showCheckBeforeExitModal(); } else { + setBottomSlideContent(null); onClose(); } document.body.style.removeProperty("overflow"); diff --git a/src/pages/Detail/Detail.tsx b/src/pages/Detail/Detail.tsx index 7a0a532c..a877af7f 100644 --- a/src/pages/Detail/Detail.tsx +++ b/src/pages/Detail/Detail.tsx @@ -30,6 +30,11 @@ function Detail() { document.body.style.overflow = "hidden"; }; + const handleSlideOnClose = () => { + setBottomSlideContent(null); + onClose(); + }; + return (
, false, ) @@ -46,12 +51,18 @@ function Detail() {
- onBottomSlideOpen(, true) + onBottomSlideOpen( + , + true, + ) } /> - onBottomSlideOpen(, false) + onBottomSlideOpen( + , + false, + ) } />
diff --git a/src/types/detail.ts b/src/types/detail.ts index bfeb50b0..40034893 100644 --- a/src/types/detail.ts +++ b/src/types/detail.ts @@ -98,4 +98,5 @@ export interface BottomSlideDetailProps { onClose: () => void; children: ReactNode; isReviewModal: boolean; + setBottomSlideContent: React.Dispatch>; } From ccc600b41d12185acc2ed80c3d4efed5bb03fd1a Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Mon, 22 Jan 2024 02:11:58 +0900 Subject: [PATCH 14/15] Feat: kakao map draggable, zoomable false --- .../Information/BasicInformation/MapInDetail/MapInDetail.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/Detail/Contents/Information/BasicInformation/MapInDetail/MapInDetail.tsx b/src/components/Detail/Contents/Information/BasicInformation/MapInDetail/MapInDetail.tsx index 7454438e..7a6bcd5a 100644 --- a/src/components/Detail/Contents/Information/BasicInformation/MapInDetail/MapInDetail.tsx +++ b/src/components/Detail/Contents/Information/BasicInformation/MapInDetail/MapInDetail.tsx @@ -36,6 +36,8 @@ function MapInDetail() { From 002363072a90fdd8389d7f7a669d0fa48b368942 Mon Sep 17 00:00:00 2001 From: JinJeongMin Date: Mon, 22 Jan 2024 03:25:33 +0900 Subject: [PATCH 15/15] Feat: create map drawer --- .../MapInDetail/MapInDetail.tsx | 42 +++++++--- .../MapModal/MapModal.module.scss | 83 +++++++++++++++++++ .../BasicInformation/MapModal/MapModal.tsx | 68 +++++++++++++++ ...Rviews.module.scss => Reviews.module.scss} | 0 .../Detail/Contents/Reviews/Reviews.tsx | 2 +- 5 files changed, 184 insertions(+), 11 deletions(-) create mode 100644 src/components/Detail/Contents/Information/BasicInformation/MapModal/MapModal.module.scss create mode 100644 src/components/Detail/Contents/Information/BasicInformation/MapModal/MapModal.tsx rename src/components/Detail/Contents/Reviews/{Rviews.module.scss => Reviews.module.scss} (100%) diff --git a/src/components/Detail/Contents/Information/BasicInformation/MapInDetail/MapInDetail.tsx b/src/components/Detail/Contents/Information/BasicInformation/MapInDetail/MapInDetail.tsx index 7a6bcd5a..b6fcfb1a 100644 --- a/src/components/Detail/Contents/Information/BasicInformation/MapInDetail/MapInDetail.tsx +++ b/src/components/Detail/Contents/Information/BasicInformation/MapInDetail/MapInDetail.tsx @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { useDisclosure } from "@chakra-ui/react"; import { useEffect, useState } from "react"; import { CustomOverlayMap, Map } from "react-kakao-maps-sdk"; @@ -7,6 +8,8 @@ import styles from "./MapInDetail.module.scss"; import BigHomeMarker from "@/assets/homeIcons/map/house_big.svg?react"; +import MapModal from "../MapModal/MapModal"; + interface Coordinate { lat: number; lng: number; @@ -18,6 +21,7 @@ function MapInDetail() { lat: 33.5563, lng: 126.79581, }); + const { isOpen, onOpen, onClose } = useDisclosure(); useEffect(() => { const geocoder = new kakao.maps.services.Geocoder(); @@ -32,17 +36,35 @@ function MapInDetail() { geocoder.addressSearch("경기도 양평군 양평읍 백안리 9", callback); }, []); + const handleMapDoubleClick = (event: any) => { + event.preventDefault(); + }; + return ( - - - - - + <> + + + + + + + ); } diff --git a/src/components/Detail/Contents/Information/BasicInformation/MapModal/MapModal.module.scss b/src/components/Detail/Contents/Information/BasicInformation/MapModal/MapModal.module.scss new file mode 100644 index 00000000..22c73749 --- /dev/null +++ b/src/components/Detail/Contents/Information/BasicInformation/MapModal/MapModal.module.scss @@ -0,0 +1,83 @@ +@use "@/sass" as *; + +.header { + position: fixed; + width: 100%; + + padding: 16px 20px; + background-color: $neutral0; + + display: flex; + align-items: center; + gap: 12px; + + @include typography(button); + color: $neutral900; + + z-index: 10; +} + +.body { + width: 100%; + + .map { + width: 100%; + height: 100%; + } +} + +.footer { + position: fixed; + width: 100%; + padding: 24px 20px; + bottom: 0; + + z-index: 10; + + .flexBox { + width: 100%; + display: flex; + } + + &__card { + width: 100%; + height: 12rem; + background-color: $neutral0; + border-radius: 16px; + + display: flex; + align-items: center; + gap: 12px; + + max-width: 41rem; + + position: relative; + + img { + width: 9.6rem; + height: 9.6rem; + } + + &__textWrapper { + display: flex; + flex-direction: column; + gap: 4px; + justify-content: center; + + &__name { + @include typography(titleSmall); + color: $neutral900; + } + &__category { + @include typography(captionSmall); + color: $neutral400; + } + } + + &__icon { + position: absolute; + top: 16px; + right: 16px; + } + } +} diff --git a/src/components/Detail/Contents/Information/BasicInformation/MapModal/MapModal.tsx b/src/components/Detail/Contents/Information/BasicInformation/MapModal/MapModal.tsx new file mode 100644 index 00000000..43a55c1a --- /dev/null +++ b/src/components/Detail/Contents/Information/BasicInformation/MapModal/MapModal.tsx @@ -0,0 +1,68 @@ +import { + Drawer, + DrawerBody, + DrawerContent, + DrawerFooter, + DrawerHeader, +} from "@chakra-ui/react"; +import { AiOutlineLeft } from "react-icons/ai"; +import { FaRegHeart } from "react-icons/fa"; +import { CustomOverlayMap, Map } from "react-kakao-maps-sdk"; + +import styles from "./MapModal.module.scss"; + +import BigHomeMarker from "@/assets/homeIcons/map/house_big.svg?react"; + +interface MapModalProps { + isOpen: boolean; + onClose: () => void; + lat: number; + lng: number; + name: string; +} + +function MapModal({ isOpen, onClose, lat, lng, name }: MapModalProps) { + return ( + + + + + {name} + + + + + + + + + + + +
+
+ +
+

{name}

+

+ 숙소 서울 +

+
+ {" "} +
+
+
+
+
+ ); +} + +export default MapModal; diff --git a/src/components/Detail/Contents/Reviews/Rviews.module.scss b/src/components/Detail/Contents/Reviews/Reviews.module.scss similarity index 100% rename from src/components/Detail/Contents/Reviews/Rviews.module.scss rename to src/components/Detail/Contents/Reviews/Reviews.module.scss diff --git a/src/components/Detail/Contents/Reviews/Reviews.tsx b/src/components/Detail/Contents/Reviews/Reviews.tsx index bf48dbd9..c6af09e3 100644 --- a/src/components/Detail/Contents/Reviews/Reviews.tsx +++ b/src/components/Detail/Contents/Reviews/Reviews.tsx @@ -2,7 +2,7 @@ import { CiEdit } from "react-icons/ci"; import { GoStarFill } from "react-icons/go"; import { useRecoilValue, useSetRecoilState } from "recoil"; -import styles from "./Rviews.module.scss"; +import styles from "./Reviews.module.scss"; import Review from "@/components/Detail/Contents/Review/Review";