Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

투표 취소 기능 / ScrollToTop 버튼 추가 #253

Merged
merged 11 commits into from
Jan 24, 2024
Merged
2 changes: 2 additions & 0 deletions src/components/Plan/PlanSectionTop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { visitDateState } from '@recoil/socket';
import { useState } from 'react';
import { getItem } from '@utils/localStorageFun';
import PlanSchedule from './PlanSchedule';
import ScrollTopButton from './ScrollTopButton';

const PlanSectionTop = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -101,6 +102,7 @@ const PlanSectionTop = () => {
<PlanItem key={date} date={date} day={DayArr[index]} />
))}
/>
<ScrollTopButton />
</div>
);
};
Expand Down
42 changes: 42 additions & 0 deletions src/components/Plan/ScrollTopButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { TopIcon } from '@components/common/icons/Icons';
import { useEffect, useState } from 'react';

const ScrollTopButton = () => {
const [visible, setVisible] = useState<boolean>(false);

const checkScrollTop = () => {
if (!visible && window.scrollY > 300) {
setVisible(true);
} else if (visible && window.scrollY <= 300) {
setVisible(false);
}
};

useEffect(() => {
window.addEventListener('scroll', checkScrollTop);
return () => {
window.removeEventListener('scroll', checkScrollTop);
};
}, [visible]);

const scrollToTop = () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
};

if (!visible) {
return null;
}

return (
<div
className="sticky bottom-[20px]
mt-[-50px] flex h-12 w-12 cursor-pointer items-center justify-center rounded-full bg-white shadow-md"
style={{ left: 'calc(100%)' }}>
<button onClick={scrollToTop}>
<TopIcon />
</button>
</div>
);
};

export default ScrollTopButton;
2 changes: 2 additions & 0 deletions src/components/Review/MyReview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ 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/Plan/ScrollTopButton';

export default function MyReview() {
const [reviewDataLength, setReviewDataLength] = useState<number>(0);
Expand Down Expand Up @@ -163,6 +164,7 @@ export default function MyReview() {
<MyAlert title="리뷰 삭제" content="리뷰를 삭제할까요?" />
)}
</Modal>
<ScrollTopButton />
</>
);
}
43 changes: 7 additions & 36 deletions src/components/Review/ReviewButton.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,17 @@
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 { 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);
Expand All @@ -41,28 +21,19 @@ const ReviewButton = (props: ButtonProps) => {
}, [rating]);

return (
<div className="pb-4">
{isRatingValid === false && (
<div className="mb-2 flex items-center justify-center text-xs text-[#FF0F00]">
별점을 입력해주세요
</div>
)}

{isRatingValid === true &&
<div className=" bottom-0 mt-auto flex w-full items-center justify-center pb-4">
{/* {isRatingValid === true &&
isContentValid === false &&
isKeywordsValid === false && (
<div className="mb-2 flex items-center justify-center text-xs text-[#FF0F00]">
키워드를 선택하거나 텍스트를 10자 이상 입력해주세요
</div>
)}
)} */}

<ButtonPrimary
onClick={onClick}
className="flex h-[56px] items-center justify-center"
disabled={
isRatingValid === false ||
(isContentValid === false && isKeywordsValid === false)
}>
disabled={isRatingValid === false}>
완료
</ButtonPrimary>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Review/ReviewPosting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function ReviewPosting() {
<div className="mb-5 text-lg font-bold">리뷰를 작성해주세요</div>
<div className="mb-1 ">
<textarea
className="h-[112px] w-full rounded-md border p-2 text-sm placeholder-gray3 "
className="h-[152px] w-full rounded-md border p-2 text-sm placeholder-gray3 "
placeholder="직접 경험한 솔직한 리뷰를 남겨주세요"
onChange={handleTextChange}
value={content}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Review/ReviewRating.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ const ReviewRating = () => {

return (
<div className="mb-6 flex flex-col items-center justify-center">
<div className="mb-1 text-xl font-bold">{title}</div>
<div className="mb-4 text-[20px] font-bold">{title}</div>
<button className="flex gap-1">
{Array.from({ length: 5 }, (_, index) => (
<StarIcon
key={index}
size={30}
size={40}
color="none"
fill={index < rating ? '#FFEC3E' : '#EDEDED'}
onClick={() => handleStarClick(index)}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Share/IsEditableModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const IsEditableModal = ({ isEditable, setIsEditable }: Props) => {
return (
<Dialog.Root open={isEditable} onOpenChange={setIsEditable} modal>
<Dialog.Portal>
<Dialog.Overlay className="data-[state=open]:animate-overlayShow fixed inset-0 z-10 bg-black opacity-70" />
<Dialog.Content className="data-[state=open]:animate-contentShow fixed bottom-0 left-[50%] z-10 flex w-full max-w-[412px] translate-x-[-50%] flex-col items-center rounded-t-2xl bg-white px-5 pb-8 pt-9">
<Dialog.Overlay className="data-[state=open]:animate-overlayShow fixed inset-0 z-[101] bg-black opacity-70" />
<Dialog.Content className="data-[state=open]:animate-contentShow fixed bottom-0 left-[50%] z-[101] flex w-full max-w-[412px] translate-x-[-50%] flex-col items-center rounded-t-2xl bg-white px-5 pb-8 pt-9">
<Dialog.Title className="title3 pb-2.5 text-center text-gray7">
편집 참여 코드를 입력하시면
<br />
Expand Down
4 changes: 2 additions & 2 deletions src/components/Trip/EditCodeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ const EditCodeModal = () => {
</Dialog.Trigger>
{isEditModal && (
<Dialog.Portal>
<Dialog.Overlay className="data-[state=open]:animate-overlayShow fixed inset-0 z-10 bg-black opacity-70" />
<Dialog.Content className="data-[state=open]:animate-contentShow fixed bottom-0 left-[50%] z-10 flex w-full max-w-[412px] translate-x-[-50%] flex-col items-center rounded-t-2xl bg-white px-5 pb-8 pt-9">
<Dialog.Overlay className="data-[state=open]:animate-overlayShow fixed inset-0 z-[100] bg-black opacity-70" />
<Dialog.Content className="data-[state=open]:animate-contentShow fixed bottom-0 left-[50%] z-[100] flex w-full max-w-[412px] translate-x-[-50%] flex-col items-center rounded-t-2xl bg-white px-5 pb-8 pt-9">
<Dialog.Title className="headline2 mr-auto pb-2.5 text-gray7">
나의 여정
</Dialog.Title>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Trip/LikedToursList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const LikedToursList = () => {
)}

{/* 우리의 관심 여행지 추가 버튼 => 검색 라우터 이동 */}
<div className="sticky bottom-5 left-1/2 z-[100] inline-flex h-10 w-[168px] -translate-x-1/2 transform items-center justify-center gap-1.5 rounded-3xl border border-solid border-cyan-400 bg-white px-3.5">
<div className="sticky bottom-[65px] left-1/2 z-[100] inline-flex h-10 w-[168px] -translate-x-1/2 transform items-center justify-center gap-1.5 rounded-3xl border border-solid border-cyan-400 bg-white px-3.5">
<button
onClick={() => navigate('add')}
className="flex items-center justify-between">
Expand Down
28 changes: 17 additions & 11 deletions src/components/Trip/LikedToursLists/LikedToursListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { postTripsLikeHate } from '@api/trips';
import {
ThumbsUp,
ThumbsDown,
ClickThumbsUp,
ClickThumbsDown,
StarIcon,
} from '@components/common/icons/Icons';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { postTripsLikeHate } from '@api/trips';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';

interface LikedToursListItemProps {
ourTripList: ourTripType;
Expand All @@ -34,11 +34,11 @@ const LikedToursListItem: React.FC<LikedToursListItemProps> = ({
const navigate = useNavigate();
const queryClient = useQueryClient();
const [thumbsState, setThumbsState] = useState({
prefer: false,
notPrefer: false,
prefer: prefer,
notPrefer: notPrefer,
});

const { mutate: thumbsUpMutate } = useMutation({
const { mutate: thumbsMutate } = useMutation({
mutationFn: () =>
postTripsLikeHate(
selectedTripId,
Expand All @@ -54,14 +54,20 @@ const LikedToursListItem: React.FC<LikedToursListItemProps> = ({

const onClickThumbsUpButton = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
setThumbsState({ prefer: true, notPrefer: false });
thumbsUpMutate();
setThumbsState((prev) => ({
prefer: !prev.prefer,
notPrefer: false,
}));
thumbsMutate();
};

const onClickThumbsDownButton = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
setThumbsState({ prefer: false, notPrefer: true });
thumbsUpMutate();
setThumbsState((prev) => ({
prefer: false,
notPrefer: !prev.notPrefer,
}));
thumbsMutate();
};

return (
Expand Down
12 changes: 10 additions & 2 deletions src/components/Trip/PlanTripButton.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { PlanColorIcon, RightIcon } from '@components/common/icons/Icons';
import { useNavigate } from 'react-router-dom';
import { getMember } from '@api/member';

const PlanTripButton = () => {
const navigate = useNavigate();

const handleButtonClick = () => {
navigate('plan');
const handleButtonClick = async () => {
try {
const res = await getMember();
if (res.data.status === 200) {
navigate('plan');
}
} catch (err) {
console.error(err);
}
};

return (
Expand Down
58 changes: 38 additions & 20 deletions src/components/Trip/TripPreference.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useSetRecoilState, useRecoilState } from 'recoil';
import { participantsState } from '@recoil/trip';
import { useGetTripsAuthority } from '@hooks/useGetTripsAuthority';
import { useNavigate } from 'react-router-dom';
import { getMember } from '@api/member';

interface RatioBarParams {
value: number;
Expand All @@ -30,29 +31,46 @@ interface PercentageParams {
const TripPreferenceButton: React.FC = () => {
const { tripAuthority } = useGetTripsAuthority();
const navigate = useNavigate();
const [res, setRes] = useState<any>(null);

const handleTrip = () => {
if (tripAuthority === 'WRITE') {
navigate('/mypage/survey');
}
navigate('/mypage/survey');
};

return (
<button
onClick={handleTrip}
className="mb-[17.5px] mt-[20px] flex w-[335px] items-center rounded-full bg-white px-6 py-4 text-sm">
<div className="flex items-center text-gray6">
<div>
<HeartIcon fill="#888888" color="#888888" size={20} />
useEffect(() => {
const fetchData = async () => {
try {
const temp = await getMember();
setRes(temp);
} catch (err) {
console.error(err);
}
};

fetchData();
}, []);

if (res?.data?.status === 200 && tripAuthority === 'WRITE') {
return (
<button
onClick={handleTrip}
className="mb-[17.5px] flex w-[335px] items-center rounded-full bg-white px-6 py-4 text-sm">
<div className="flex items-center text-gray6">
<div>
<HeartIcon fill="#888888" color="#888888" size={20} />
</div>
<p className="ml-1.5 text-[14px] text-main1">
내 여행 취향 설정하러 가기
</p>
</div>
<p className="ml-1.5 text-[14px] text-main1">
내 여행 취향 설정하러 가기
</p>
</div>
<div className="ml-auto">
<RightIcon fill="#5E5E5E" />
</div>
</button>
);
<div className="ml-auto">
<RightIcon fill="#5E5E5E" />
</div>
</button>
);
} else {
return null;
}
};

const RatioBar = ({ value, total, color, label1, label2 }: RatioBarParams) => {
Expand Down Expand Up @@ -189,7 +207,7 @@ const TripPreference: React.FC = () => {
};

return (
<div className=" m-[-20px] mt-0 flex flex-col items-center bg-gray1 pb-[20px] ">
<div className=" m-[-20px] mt-0 flex flex-col items-center bg-gray1 pb-[20px] pt-[20px] ">
<TripPreferenceButton />
<div
onClick={handleButtonClick}
Expand Down
3 changes: 3 additions & 0 deletions src/components/Trip/TripSectionTop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { LikedToursList } from './LikedToursList';
import { useGetTripsAuthority } from '@hooks/useGetTripsAuthority';
import { useEffect, useState } from 'react';
import IsEditableModal from '@components/Share/IsEditableModal';
import ScrollTopButton from '@components/Plan/ScrollTopButton';

const TripSectionTop = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -43,6 +44,8 @@ const TripSectionTop = () => {
lists={['우리의 여행취향', '우리의 관심목록']}
contents={[<TripPreference />, <LikedToursList />]}
/>
<ScrollTopButton />
<div className="sticky bottom-[40px] mb-5" />
</div>
);
};
Expand Down
Loading