diff --git a/index.html b/index.html index a39119f2..c3bd5b82 100644 --- a/index.html +++ b/index.html @@ -1,16 +1,29 @@ + + + + + 위플플 | 여정 공유 플랫폼 + + + + - -
- - - - \ No newline at end of file + +
+ + + diff --git a/src/@types/detail.types.ts b/src/@types/detail.types.ts index bfb4bca8..71827919 100644 --- a/src/@types/detail.types.ts +++ b/src/@types/detail.types.ts @@ -1,5 +1,6 @@ interface tourDetail { id: number; + contentTypeId: number; title: string; liked: boolean; fullAddress: string; diff --git a/src/@types/review.types.ts b/src/@types/review.types.ts index 851b017b..6f6cf219 100644 --- a/src/@types/review.types.ts +++ b/src/@types/review.types.ts @@ -1,11 +1,34 @@ -interface ReviewRequest { - tourItemId: number; +interface Keyword { + keywordId: number; + content: string; + type?: string; +} + +interface CommentItemProps { + commentId: number; + authorNickname: string; + authorProfileImageUrl: string; + createdTime: string; + content: string; + onClick?: () => void; + isAuthor: boolean; +} + +interface MyReviewContent { + reviewId: number; + authorNickname: string; + authorProfileImageUrl: string; rating: number; - keywords: Keyword[]; + createdTime: string; content: string; + keywords: Keyword[]; + commentCount: number; + isAuthor?: boolean; } -interface Keyword { - keywordId: number; +interface ReviewRequest { + tourItemId: number; + rating: number; + keywords: Keyword[]; content: string; } diff --git a/src/@types/tours.types.ts b/src/@types/tours.types.ts index ccd95671..52776135 100644 --- a/src/@types/tours.types.ts +++ b/src/@types/tours.types.ts @@ -1,30 +1,30 @@ -export type TourKeywordInfo = { +interface TourKeywordInfo { keywordId: number; content: string; type: string; keywordCount: number; -}; +} -export interface RegionTypes { +interface RegionTypes { areaCode?: number; subAreaCode?: number; name: string; } -export interface ToursCategoryItemProps extends RegionTypes { +interface ToursCategoryItemProps extends RegionTypes { isSelected: boolean; onSelect: (name: string) => void; } -export interface ToursListProps { +interface ToursListProps { selectedRegion: string; } -export interface ToursCategoryProps extends ToursListProps { +interface ToursCategoryProps extends ToursListProps { setSelectedRegion: (region: string) => void; } -export interface TourType { +interface TourType { contentTypeId?: number; id: number; title: string; @@ -38,7 +38,7 @@ export interface TourType { latitude?: string; } -export interface LikedListType { +interface LikedListType { tripLikedItemId: number; tourItemId: number; contentTypeId: number; @@ -52,3 +52,25 @@ export interface LikedListType { preferTotalCount: number; notPreferTotalCount: number; } + +interface ReviewInfoItemProps { + reviewId: number; + authorNickname: string; + authorProfileImageUrl: string; + rating: number; + createdTime: string; + content: string; + keywords: Keyword[]; // keywordId, content, type + commentCount: number; + onClick?: () => void; + tourItemId?: number; + contentTypeId?: number; + canTextOverflow: boolean; + isAuthor?: boolean; +} + +interface Keyword { + keywordId: number; + content: string; + type?: string; +} diff --git a/src/@types/trips.types.ts b/src/@types/trips.types.ts index e2ebbb0c..71ab6a4f 100644 --- a/src/@types/trips.types.ts +++ b/src/@types/trips.types.ts @@ -51,3 +51,25 @@ interface AuthorityType { tripId: string; }; } +interface TripSurveySetMemberInfo { + memberId: number; + nickname: string; + thumbnail: string; +} + +interface TripMemeberInfo { + nickname: string; + profileImageUrl: string; +} + +interface Participant { + memberId: number; + nickname: string; + thumbnail: string; +} + +interface Participants { + tripSurveyMemberCount: number; + tripSurveySetMemberInfos: Participant[]; + nonTripSurveySetMemberInfos: Participant[]; +} diff --git a/src/App.tsx b/src/App.tsx index 909f6bac..030880f3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,3 @@ -import { ThemeProvider } from 'styled-components'; -import { GlobalStyle } from '@styles/globalStyles'; -import { theme } from '@styles/theme'; import { RecoilRoot } from 'recoil'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; @@ -17,11 +14,8 @@ const App = () => { - - - - - + + diff --git a/src/api/review.ts b/src/api/review.ts index 9c5e46df..33c11ba8 100644 --- a/src/api/review.ts +++ b/src/api/review.ts @@ -1,6 +1,5 @@ import client from './client'; import authClient from './authClient'; - // 리뷰 관련 API // 리뷰수정 diff --git a/src/api/socket.ts b/src/api/socket.ts index 2f22446e..978ae336 100644 --- a/src/api/socket.ts +++ b/src/api/socket.ts @@ -125,6 +125,7 @@ export const pubUpdateTransportation = ( destination: `/pub/trips/${tripId}/updateTransportation`, body: JSON.stringify(pubUpdateTransportation), }); + console.log('펍실행'); }; // 여행 아이템 방문 날짜 변경 이벤트 발생시 diff --git a/src/components/DetailSectionBottom/DetailReviews.tsx b/src/components/DetailSectionBottom/DetailReviews.tsx index 8d526846..ddb3161c 100644 --- a/src/components/DetailSectionBottom/DetailReviews.tsx +++ b/src/components/DetailSectionBottom/DetailReviews.tsx @@ -27,11 +27,11 @@ import EditDelete from '@components/common/modal/children/EditDelete'; import MyAlert from '@components/common/modal/children/MyAlert'; import { alertTypeState } from '@recoil/modal'; -interface reviewProps { - reviewData: any; -} - -export default function DetailReviews({ reviewData }: reviewProps) { +export default function DetailReviews({ + reviewData, +}: { + reviewData: tourDetail; +}) { const [reviewDataLength, setReviewDataLength] = useState(0); const { title, contentTypeId } = reviewData; const params = useParams(); @@ -73,7 +73,7 @@ export default function DetailReviews({ reviewData }: reviewProps) { return
데이터를 불러오는 중 오류가 발생했습니다.
; } - const handleReviewClick = (item: any) => { + const handleReviewClick = (item: ReviewInfoItemProps) => { const reviewId = item.reviewId; navigate(`/reviewComment/${reviewId}`, { state: { item, tourItemId } }); }; @@ -155,24 +155,26 @@ export default function DetailReviews({ reviewData }: reviewProps) { { return ( - {group?.data.data.reviewInfos.content.map((item: any) => ( - handleReviewClick(item)} - tourItemId={tourItemId} - contentTypeId={contentTypeId} - canTextOverflow={true} - isAuthor={item.isAuthor} - /> - ))} + {group?.data.data.reviewInfos.content.map( + (item: ReviewInfoItemProps) => ( + handleReviewClick(item)} + tourItemId={tourItemId} + contentTypeId={contentTypeId} + canTextOverflow={true} + isAuthor={item.isAuthor} + /> + ), + )} ); } @@ -187,7 +189,7 @@ export default function DetailReviews({ reviewData }: reviewProps) { {modalChildren === 'MyAlert' && alertType === 'LoginReview' && ( )} diff --git a/src/components/DetailSectionBottom/ReviewItem.tsx b/src/components/DetailSectionBottom/ReviewItem.tsx index 57a89c8c..c11e040e 100644 --- a/src/components/DetailSectionBottom/ReviewItem.tsx +++ b/src/components/DetailSectionBottom/ReviewItem.tsx @@ -22,29 +22,7 @@ import { MouseEvent, useState } from 'react'; import { getEmoji } from '@utils/utils'; import { getStarFill } from '@utils/getStarFill'; -interface Keyword { - keywordId: number; - content: string; - type: string; -} - -interface ItemProps { - reviewId: number; - authorNickname: string; - authorProfileImageUrl: string; - rating: number; - createdTime: any; - content: string; - keywords: Keyword[]; // keywordId, content, type - commentCount: number; - onClick?: () => void; - tourItemId?: number; - contentTypeId?: number; - canTextOverflow: boolean; - isAuthor?: boolean; -} - -const Item: React.FC = (props: ItemProps) => { +const Item: React.FC = (props: ReviewInfoItemProps) => { const { reviewId, authorNickname, @@ -206,7 +184,7 @@ const Item: React.FC = (props: ItemProps) => { .map((keyword, idx) => (
+ className="rounded-md bg-gray1 px-2 py-1 text-xs text-gray6"> {getEmoji(keyword.content)} {keyword.content}
))} diff --git a/src/components/DetailSectionTop/DetailAddSchedule.tsx b/src/components/DetailSectionTop/DetailAddSchedule.tsx index fbbc8361..0b39bba6 100644 --- a/src/components/DetailSectionTop/DetailAddSchedule.tsx +++ b/src/components/DetailSectionTop/DetailAddSchedule.tsx @@ -11,6 +11,7 @@ import { useState, useEffect } from 'react'; import { postTripsItem } from '@api/trips'; import { useParams } from 'react-router-dom'; import { Swiper, SwiperSlide } from 'swiper/react'; +import ToastPopUp from '@components/common/toastpopup/ToastPopUp'; const DetailAddSchedule = () => { const token = localStorage.getItem('accessToken'); @@ -30,6 +31,12 @@ const DetailAddSchedule = () => { (trip) => trip.tripStatus !== '여행완료', ); + const [toastPopUp, setToastPopUp] = useState({ + isPopUp: false, + noun: '', + verb: '', + }); + const handleNavigate = (url: string) => { navigate(url); }; @@ -63,6 +70,11 @@ const DetailAddSchedule = () => { } catch (error) { console.error('요청 실패:', error); } finally { + setToastPopUp(() => ({ + isPopUp: true, + noun: '일정', + verb: '추가', + })); setIsProcessing(false); } } @@ -79,14 +91,30 @@ const DetailAddSchedule = () => { } }, [isOpen]); + useEffect(() => { + if (toastPopUp.isPopUp) { + const timer = setTimeout(() => { + setToastPopUp(() => ({ + isPopUp: false, + noun: '', + verb: '', + })); + }, 2000); + return () => clearTimeout(timer); + } + }, [toastPopUp]); + return ( <> + {toastPopUp.isPopUp && ( + + )} {token ? ( @@ -202,7 +230,7 @@ const DetailAddSchedule = () => {

- 등록된 여행이 없습니다. + 참여하고 있는 여정이 없어요.

@@ -244,8 +272,8 @@ const DetailAddSchedule = () => { } onConfirm={() => handleNavigate('/login')}> )} diff --git a/src/components/DetailSectionTop/DetailToursButtons.tsx b/src/components/DetailSectionTop/DetailToursButtons.tsx index 8c9e01a6..d25e517d 100644 --- a/src/components/DetailSectionTop/DetailToursButtons.tsx +++ b/src/components/DetailSectionTop/DetailToursButtons.tsx @@ -10,11 +10,11 @@ import { useNavigate, useParams } from 'react-router-dom'; import { useSetRecoilState } from 'recoil'; import { getMember } from '@api/member'; -interface reviewProps { - reviewData: any; -} - -export default function DetailTourButtons({ reviewData }: reviewProps) { +export default function DetailTourButtons({ + reviewData, +}: { + reviewData: tourDetail; +}) { const { title, contentTypeId } = reviewData; const params = useParams(); const tourItemId = Number(params.id); @@ -48,8 +48,8 @@ export default function DetailTourButtons({ reviewData }: reviewProps) { diff --git a/src/components/DetailSectionTop/DetailToursInfo.tsx b/src/components/DetailSectionTop/DetailToursInfo.tsx index 8af2a5ee..7b3eaba3 100644 --- a/src/components/DetailSectionTop/DetailToursInfo.tsx +++ b/src/components/DetailSectionTop/DetailToursInfo.tsx @@ -9,7 +9,7 @@ export default function DetailToursInfo({ infoData }: DetailToursInfoProps) { return ( <> -
+
tour-image
-

- {title} -

+

{title}

diff --git a/src/components/DetailSectionTop/DetailToursMap.tsx b/src/components/DetailSectionTop/DetailToursMap.tsx index 07871ac0..7bec6bc9 100644 --- a/src/components/DetailSectionTop/DetailToursMap.tsx +++ b/src/components/DetailSectionTop/DetailToursMap.tsx @@ -17,7 +17,7 @@ export default function DetailToursMap({ mapData }: DetailToursMapProps) { const MapStyle = { width: '100%', - height: '180px', + height: '160px', marginTop: '5px', marginBottom: '15px', }; @@ -42,7 +42,7 @@ export default function DetailToursMap({ mapData }: DetailToursMapProps) {
-

+

{fullAddress}

diff --git a/src/components/DetailSectionTop/DetailToursRating.tsx b/src/components/DetailSectionTop/DetailToursRating.tsx index d92303d2..4f10b83d 100644 --- a/src/components/DetailSectionTop/DetailToursRating.tsx +++ b/src/components/DetailSectionTop/DetailToursRating.tsx @@ -44,7 +44,7 @@ export default function DetailToursRating({
{STAR_IDX_ARR.map((item, idx) => { return ( - + ); })} -
-

+

+

({reviewTotalCount})

diff --git a/src/components/MyTrip/MyTrip.tsx b/src/components/MyTrip/MyTrip.tsx index ae8ed92e..c80f12fc 100644 --- a/src/components/MyTrip/MyTrip.tsx +++ b/src/components/MyTrip/MyTrip.tsx @@ -32,7 +32,7 @@ const MyTrip = () => { return (
-

나의 여정

+

나의 여정

{data.length > 0 ? ( <> @@ -42,7 +42,7 @@ const MyTrip = () => { ) : ( } /> diff --git a/src/components/MyTrip/MyTripAfterList.tsx b/src/components/MyTrip/MyTripAfterList.tsx index ec33c2de..c5d65cb4 100644 --- a/src/components/MyTrip/MyTripAfterList.tsx +++ b/src/components/MyTrip/MyTripAfterList.tsx @@ -17,18 +17,22 @@ const MyTripAfterList: React.FC = ({ myTripsData }) => { new Date(a.startDate).getTime() - new Date(b.startDate).getTime(), ); - return ( - <> -
-

지난 여행

-
-
- {sortedTrips.map((myTripList: MyTripType) => ( - - ))} -
- - ); + if (sortedTrips.length > 0) { + return ( + <> +
+

지난 여행

+
+
+ {sortedTrips.map((myTripList: MyTripType) => ( + + ))} +
+ + ); + } else { + return null; + } }; export default MyTripAfterList; diff --git a/src/components/MyTrip/MyTripBeforeList.tsx b/src/components/MyTrip/MyTripBeforeList.tsx index e4d27037..88dc770f 100644 --- a/src/components/MyTrip/MyTripBeforeList.tsx +++ b/src/components/MyTrip/MyTripBeforeList.tsx @@ -14,8 +14,8 @@ const MyTripBeforeList: React.FC = ({ myTripsData }) => { return ( <> -
-

다가오는 여행

+
+

다가오는 여행

{myTripsData.map((myTripList: MyTripType) => ( diff --git a/src/components/MyTrip/MyTripIngItem.tsx b/src/components/MyTrip/MyTripIngItem.tsx index ca0d08d4..e054b93f 100644 --- a/src/components/MyTrip/MyTripIngItem.tsx +++ b/src/components/MyTrip/MyTripIngItem.tsx @@ -19,7 +19,7 @@ const MyTripIngItem: React.FC = ({ myTripList }) => {
여행지 이미지 @@ -30,13 +30,13 @@ const MyTripIngItem: React.FC = ({ myTripList }) => {
-
-
+
+
{tripName}
-
- {startDate.replace(/-/g, '.')} ~{' '} +
+ {startDate.replace(/-/g, '.')} -{' '} {endDate.replace(/-/g, '.').split('2024.')}{' '} {tripDuration === '0박 1일' ? null : ` (${tripDuration})`}
diff --git a/src/components/MyTrip/MyTripItem.tsx b/src/components/MyTrip/MyTripItem.tsx index 72375a66..7776541d 100644 --- a/src/components/MyTrip/MyTripItem.tsx +++ b/src/components/MyTrip/MyTripItem.tsx @@ -66,10 +66,10 @@ const MyTripItem: React.FC = ({ myTripList }) => {
-
+
{tripName}
-
+
{startDate.replace(/-/g, '.')} -{' '} {endDate.replace(/-/g, '.').split('2024.')} {tripDuration === '0박 1일' ? null : ` (${tripDuration})`} diff --git a/src/components/Mypage/LogoutButton.tsx b/src/components/Mypage/LogoutButton.tsx index 0e6666d7..c66aa282 100644 --- a/src/components/Mypage/LogoutButton.tsx +++ b/src/components/Mypage/LogoutButton.tsx @@ -34,7 +34,7 @@ const LogoutButton = () => { return (
-
+
img -
+
{item.name.length > 17 ? item.name.slice(0, 17) + '...' : item.name}
-
- {item.category} +
+
+ {item.category} +
-
+
{item.price} 원
@@ -171,7 +166,7 @@ const PlanEditItemBox = ({
선택한 장소를 삭제하시겠습니까?} + message={<>여정에서 이 장소를 삭제할까요?} onConfirm={handleConfirm} closeOnConfirm={true} isCheck={selectedItemId}> diff --git a/src/components/Plan/PlanItem.tsx b/src/components/Plan/PlanItem.tsx index 5ce5b3bb..ebe35ae5 100644 --- a/src/components/Plan/PlanItem.tsx +++ b/src/components/Plan/PlanItem.tsx @@ -4,13 +4,14 @@ import { useNavigate } from 'react-router-dom'; import TripMap from './TripMap'; import PlanItemBox from './PlanItemBox'; import PlanEditItemBox from './PlanEditItemBox'; -import { useContext, useEffect } from 'react'; +import { useContext, useEffect, useCallback } from 'react'; import { socketContext } from '@hooks/useSocket'; import { useRecoilState, useRecoilValue } from 'recoil'; import { visitDateState, isEditState } from '@recoil/socket'; import { pubGetPathAndItems, pubUpdateTransportation } from '@api/socket'; import { tapState } from '@recoil/plan'; import { useGetTripsAuthority } from '@hooks/useGetTripsAuthority'; +import { debounce } from 'lodash'; type PlanItemProps = { date: string; @@ -40,24 +41,23 @@ const PlanItem: React.FC = ({ date, day }) => { setIsEdit((prev) => !prev); }; - const handleTranspo = ( - transportation: 'CAR' | 'PUBLIC_TRANSPORTATION', - date: string, - tripId: string, - ) => { - if (transportation !== transpo) { - pubUpdateTransportation( - { - visitDate: date, - transportation: transportation, - }, - tripId, - ); - } - }; - const transpo = tripItem?.data?.transportation || ''; + const debouncedHandleTranspo = useCallback( + debounce((transportation, date, tripId) => { + if (transportation !== transpo) { + pubUpdateTransportation( + { + visitDate: date, + transportation: transportation, + }, + tripId, + ); + } + }, 1000), + [transpo], + ); + return ( <> {tripPath && } @@ -67,7 +67,9 @@ const PlanItem: React.FC = ({ date, day }) => { ) : (
handleTranspo('CAR', date || '', tripId || '')} + onClick={() => + debouncedHandleTranspo('CAR', date || '', tripId || '') + } className="flex h-[32px] w-[32px] cursor-pointer items-center justify-center rounded-l-md border border-solid border-gray3"> = ({ date, day }) => {
- handleTranspo('PUBLIC_TRANSPORTATION', date || '', tripId || '') + debouncedHandleTranspo( + 'PUBLIC_TRANSPORTATION', + date || '', + tripId || '', + ) } className="pointer-cursor -ml-[1px] flex h-[32px] w-[32px] cursor-pointer items-center justify-center rounded-r-md border border-solid border-gray3"> { + const hours = Math.floor(totalMinutes / 60); + const minutes = totalMinutes % 60; + if (hours === 0) { + return `${minutes}분`; + } + return `${hours}시간 ${minutes}분`; + }; + return ( <>
-
{day}
+
{day}
{item.map((item, index) => (
@@ -67,22 +76,24 @@ const PlanItemBox = ({
-
+
img -
+
{item.name.length > 19 ? item.name.slice(0, 19) + '...' : item.name}
-
- {item.category} +
+
+ {item.category} +
-
+
{item.price.toLocaleString()} 원 {tripAuthority == 'WRITE' && (
diff --git a/src/components/Plan/PlanSectionTop.tsx b/src/components/Plan/PlanSectionTop.tsx index 0c84359f..00abda5b 100644 --- a/src/components/Plan/PlanSectionTop.tsx +++ b/src/components/Plan/PlanSectionTop.tsx @@ -22,6 +22,7 @@ import { getItem } from '@utils/localStorageFun'; import PlanSchedule from './PlanSchedule'; import PlanCursor from './PlanCursor'; import PlanOtherCursor from './PlanOtherCursor'; +import ScrollTopButton from '@components/common/scrollTopButton/ScrollTopButton'; import { isMobile } from 'react-device-detect'; const PlanSectionTop = () => { @@ -107,6 +108,7 @@ const PlanSectionTop = () => { ))} /> +
); }; diff --git a/src/components/Review/CommentItem.tsx b/src/components/Review/CommentItem.tsx index 6c1b907e..c74ff1c5 100644 --- a/src/components/Review/CommentItem.tsx +++ b/src/components/Review/CommentItem.tsx @@ -6,17 +6,8 @@ import { } from '@recoil/modal'; import { commentState, targetCommentIdState } from '@recoil/review'; import { useRecoilState, useSetRecoilState } from 'recoil'; -interface ItemProps { - commentId: number; - authorNickname: string; - authorProfileImageUrl: string; - createdTime: any; - content: string; - onClick?: () => void; - isAuthor: boolean; -} -const CommentItem: React.FC = (props: ItemProps) => { +const CommentItem: React.FC = (props: CommentItemProps) => { const { commentId, authorNickname, diff --git a/src/components/Review/MyReview.tsx b/src/components/Review/MyReview.tsx index 1db45243..1f93e8bf 100644 --- a/src/components/Review/MyReview.tsx +++ b/src/components/Review/MyReview.tsx @@ -21,6 +21,8 @@ import EditDelete from '@components/common/modal/children/EditDelete'; import MyAlert from '@components/common/modal/children/MyAlert'; import { alertTypeState } from '@recoil/modal'; import { PenIcon } from '@components/common/icons/Icons'; +import ScrollTopButton from '@components/common/scrollTopButton/ScrollTopButton'; + export default function MyReview() { const [reviewDataLength, setReviewDataLength] = useState(0); @@ -59,7 +61,7 @@ export default function MyReview() { return
데이터를 불러오는 중 오류가 발생했습니다.
; } - const handleReviewClick = (item: any) => { + const handleReviewClick = (item: MyReviewContent) => { const reviewId = item.reviewId; navigate(`/reviewComment/${reviewId}`, { state: { item } }); }; @@ -112,7 +114,7 @@ export default function MyReview() {
- 작성한 리뷰가 없습니다 + 내가 쓴 리뷰가 없어요
다녀온 여행지의 리뷰를 남겨보세요! @@ -133,7 +135,7 @@ export default function MyReview() { { return ( - {group?.data.data.content.map((item: any) => { + {group?.data.data.content.map((item: MyReviewContent) => { item.isAuthor = true; return ( )} + ); } diff --git a/src/components/Review/Review.tsx b/src/components/Review/Review.tsx index 8de24626..c60a1b28 100644 --- a/src/components/Review/Review.tsx +++ b/src/components/Review/Review.tsx @@ -15,9 +15,8 @@ import { isModalOpenState } from '@recoil/modal'; import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; import { useParams, useNavigate } from 'react-router-dom'; import { useMutation, useQueryClient } from '@tanstack/react-query'; - interface EditReviewMutationParams { - reviewData: any; + reviewData: ReviewRequest; targetReviewId: number; } diff --git a/src/components/Review/ReviewButton.tsx b/src/components/Review/ReviewButton.tsx index ca1209a5..634dd2c5 100644 --- a/src/components/Review/ReviewButton.tsx +++ b/src/components/Review/ReviewButton.tsx @@ -1,37 +1,13 @@ import { ButtonPrimary } from '@components/common/button/Button'; -import { useState, useEffect } from 'react'; -import { contentState, keywordsState, ratingState } from '@recoil/review'; -import { useRecoilState, useRecoilValue } from 'recoil'; +import { ratingState } from '@recoil/review'; +import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; -interface ButtonProps { - onClick: () => void; -} - -const ReviewButton = (props: ButtonProps) => { +const ReviewButton = (props: { onClick: () => void }) => { const { onClick } = props; - const [content] = useRecoilState(contentState); - const keywords = useRecoilValue(keywordsState); const rating = useRecoilValue(ratingState); - const [isContentValid, setIsContentValid] = useState(false); - const [isKeywordsValid, setIsKeywordsValid] = useState(false); const [isRatingValid, setIsRatingValid] = useState(false); - useEffect(() => { - if (content.length >= 10) { - setIsContentValid(true); - } else if (content.length < 10) { - setIsContentValid(false); - } - }, [content]); - - useEffect(() => { - if (keywords.length > 0) { - setIsKeywordsValid(true); - } else if (keywords.length <= 0) { - setIsKeywordsValid(false); - } - }, [keywords]); - useEffect(() => { if (rating > 0) { setIsRatingValid(true); @@ -41,28 +17,19 @@ const ReviewButton = (props: ButtonProps) => { }, [rating]); return ( -
- {isRatingValid === false && ( -
- 별점을 입력해주세요 -
- )} - - {isRatingValid === true && +
+ {/* {isRatingValid === true && isContentValid === false && isKeywordsValid === false && (
키워드를 선택하거나 텍스트를 10자 이상 입력해주세요
- )} + )} */} + disabled={isRatingValid === false}> 완료
diff --git a/src/components/Review/ReviewComments.tsx b/src/components/Review/ReviewComments.tsx index 16fc7a00..05dd0244 100644 --- a/src/components/Review/ReviewComments.tsx +++ b/src/components/Review/ReviewComments.tsx @@ -88,8 +88,8 @@ export default function ReviewComments() {
{commentDataLength == 0 && ( -
-
댓글이 없습니다.
+
+
아직 댓글이 없어요.
첫 댓글을 작성해보세요!
)} @@ -107,17 +107,19 @@ export default function ReviewComments() { { return ( - {group?.data.data.comments.content.map((item: any) => ( - - ))} + {group?.data.data.comments.content.map( + (item: CommentItemProps) => ( + + ), + )} ); } diff --git a/src/components/Review/ReviewKeyword.tsx b/src/components/Review/ReviewKeyword.tsx index 1d9d7ad3..d6c24780 100644 --- a/src/components/Review/ReviewKeyword.tsx +++ b/src/components/Review/ReviewKeyword.tsx @@ -5,11 +5,6 @@ import { useQuery } from '@tanstack/react-query'; import { useRecoilState } from 'recoil'; import { keywordsState } from '@recoil/review'; -interface Keyword { - keywordId: number; - content: string; -} - export default function ReviewKeyword() { const location = useLocation(); const { state } = location; @@ -59,7 +54,7 @@ export default function ReviewKeyword() {
어떤 점이 좋았나요?
{reviewKeywords?.data?.data?.keywords?.map( - (keyword: any, index: number) => { + (keyword: Keyword, index: number) => { const row = Math.floor(index / columns) + 1; const col = (index % columns) + 1; diff --git a/src/components/Review/ReviewPosting.tsx b/src/components/Review/ReviewPosting.tsx index e266e39d..215e164a 100644 --- a/src/components/Review/ReviewPosting.tsx +++ b/src/components/Review/ReviewPosting.tsx @@ -17,7 +17,7 @@ export default function ReviewPosting() {
리뷰를 작성해주세요