Skip to content

Commit

Permalink
Merge pull request #153 from FinalDoubleTen/FE-83--feat/myTrip
Browse files Browse the repository at this point in the history
Feat: 나의 여정 마크업 및 API 연동 완료
  • Loading branch information
LeHiHo authored Jan 14, 2024
2 parents db35cc3 + 11a0afb commit 16ff768
Show file tree
Hide file tree
Showing 13 changed files with 344 additions and 14 deletions.
10 changes: 10 additions & 0 deletions src/@types/trips.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,13 @@ interface TripRequest {
area: string;
subarea: string;
}

interface MyTripType {
tripId: number;
tripName: string;
startDate: string;
endDate: string;
numberOfTripMembers: number;
tripStatus: string;
tripThumbnailUrl: string;
}
10 changes: 7 additions & 3 deletions src/api/member.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ export const deleteMember = async () => {
};

// 나의 여정 조회
export const getMemberTrips = async () => {
const res = await authClient.get(`member/trips`);
return res;
export const getMemberTrips = async (page?: number, size?: number) => {
try {
const res = await authClient.get(`trips?&page=${page}&size=${size}`);
return res.data;
} catch (e) {
console.error(e);
}
};

// 나의 관심 여행지 조회
Expand Down
9 changes: 9 additions & 0 deletions src/components/MyTrip/CreateMyTripButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const CreateMyTripButton = () => {
return (
<div className="sticky bottom-20 z-[100] ml-auto mr-2 flex h-12 w-[119px] items-center justify-center gap-2 rounded-[30px] bg-[#28d8ff] p-2 shadow-[2px_2px_5px_0_rgba(0,0,0,0.2)]">
<button className="headline1 pt-[2px] text-white">여행 계획하기</button>
</div>
);
};

export default CreateMyTripButton;
59 changes: 59 additions & 0 deletions src/components/MyTrip/MyTrip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import MyTripList from './MyTripList';
import NoDataMessage from '@components/common/noData/NoDataMessage';
import { getMemberTrips } from '@api/member';
import { PenIcon } from '@components/common/icons/Icons';

const MyTrip = () => {
const { fetchNextPage, hasNextPage, data, isLoading, error } =
useInfiniteQuery({
queryKey: ['wishList'],
queryFn: ({ pageParam = 0 }) => getMemberTrips(pageParam, 10),
initialPageParam: 0,
getNextPageParam: (lastPage) => {
if (
lastPage &&
lastPage.data &&
lastPage.data &&
lastPage.data.pageable
) {
const currentPage = lastPage.data.pageable.pageNumber;
const totalPages = lastPage.data.totalPages;

if (currentPage < totalPages - 1) {
return currentPage + 1;
}
}
return undefined;
},
});

if (error) {
return <div>데이터를 불러오는 중 오류가 발생했습니다.</div>;
}

return (
<div className="mt-3 min-h-[100vh] ">
<div className=" sticky top-0 z-[105] bg-white py-[15px]">
<h1 className="title2">나의 여정</h1>
</div>

{data?.pages[0].data.content.length > 0 ? (
<MyTripList
myTripsData={data || { pages: [] }}
fetchNextPage={fetchNextPage}
hasNextPage={hasNextPage}
isLoading={isLoading}
/>
) : (
<NoDataMessage
message1="저장된 관심 여행지가 없습니다."
message2="가고 싶은 장소를 저장해보세요!"
icon={<PenIcon size={44} fill="#EDEDED" color="#EDEDED" />}
/>
)}
</div>
);
};

export default MyTrip;
72 changes: 72 additions & 0 deletions src/components/MyTrip/MyTripItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { MoreIcon } from '@components/common/icons/Icons';

interface MyTripItemProps {
myTripList: MyTripType;
}

const MyTripItem: React.FC<MyTripItemProps> = ({ myTripList }) => {
const {
tripName,
startDate,
endDate,
numberOfTripMembers,
tripStatus,
tripThumbnailUrl,
} = myTripList;

const ACTIVE_TRIP = '여행 중';
const COMPLETED_TRIP = '여행 후';

return (
<div className="relative cursor-pointer pb-4">
<div className="flex min-h-[96px]">
<div>
<img
className="rounded-1 h-[96px] min-h-[96px] w-[96px] rounded-[16px] object-cover"
src={tripThumbnailUrl}
alt="여행지 이미지"
/>
<div className="absolute right-[0px] top-[0px] z-10 w-[24px]">
<MoreIcon size={20} fill="gray3" color="gray3" />
</div>
</div>
<div className="ml-[10px] flex flex-col items-start justify-between gap-[15px]">
<div className="max-w-[300px]">
<div
className={`inline-flex ${
tripStatus === ACTIVE_TRIP
? 'border-cyan-400 bg-cyan-400 '
: tripStatus === COMPLETED_TRIP
? 'border-none bg-gray-200'
: 'border-cyan-400 border-cyan-400 '
} h-[22px] items-center justify-center gap-[8px] rounded-2xl border border-solid px-[8px] py-[10px] pt-[11px]`}>
<span
className={`text-xs font-semibold ${
tripStatus === ACTIVE_TRIP
? 'text-white'
: tripStatus === COMPLETED_TRIP
? 'text-gray4'
: 'text-cyan-400'
}`}>
{tripStatus}
</span>
</div>
<div className="mt-[7.5px] w-56 truncate text-base font-bold text-black">
{tripName}
</div>
<div className="h-4 w-56 font-['Pretendard'] text-sm font-medium tracking-tight text-zinc-500">
{startDate} ~ {endDate}
</div>
<div className="mt-[7.5px] inline-flex h-4 w-56 items-start justify-start gap-2">
<div className=" text-xs font-normal text-zinc-500">
{numberOfTripMembers}명과 공유중
</div>
</div>
</div>
</div>
</div>
</div>
);
};

export default MyTripItem;
56 changes: 56 additions & 0 deletions src/components/MyTrip/MyTripList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import InfiniteScroll from 'react-infinite-scroller';
import { v4 as uuidv4 } from 'uuid';
import ToursItemSkeleton from '@components/Tours/ToursItemSkeleton';
import MyTripItem from './MyTripItem';

interface MyTripListProps {
myTripsData: { pages: Array<{ data: { content: MyTripType[] } }> };
fetchNextPage: () => void;
hasNextPage: boolean;
isLoading: boolean;
}

const MyTripList: React.FC<MyTripListProps> = ({
myTripsData,
fetchNextPage,
hasNextPage,
isLoading,
}) => {
if (!myTripsData || myTripsData.pages.length === 0) {
return <div>데이터를 불러오는 중 오류가 발생했습니다.</div>;
}

return (
<InfiniteScroll
pageStart={0}
loadMore={() => fetchNextPage()}
hasMore={hasNextPage}
loader={
<div key={uuidv4()} className="flex justify-center">
<div
className="z-[100] mx-auto h-8 w-8 animate-spin rounded-full border-[3px] border-solid border-current border-t-transparent pt-10 text-[blue-600] dark:text-[#28d8ff]"
role="status"
aria-label="loading">
<div className="sr-only">Loading...</div>
</div>
</div>
}>
<div className="no-scrollbar grid grid-cols-1 gap-[5px] overflow-y-scroll">
{isLoading
? Array.from({ length: 10 }, (_, index) => (
<ToursItemSkeleton key={index} />
))
: myTripsData.pages.map((group) => (
<React.Fragment key={uuidv4()}>
{group?.data.content.map((myTripList: MyTripType) => (
<MyTripItem key={uuidv4()} myTripList={myTripList} />
))}
</React.Fragment>
))}
</div>
</InfiniteScroll>
);
};

export default MyTripList;
2 changes: 1 addition & 1 deletion src/components/Mypage/MypageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import MypageItem from './MypageItem';
const MypageList = () => {
return (
<div>
<MypageItem link="/mytour">나의 여정</MypageItem>
<MypageItem link="/mytrip">나의 여정</MypageItem>
<MypageItem link="/wishlist">나의 관심 여행지</MypageItem>
<MypageItem link="/myPageReview">나의 리뷰</MypageItem>
<MypageItem link="/mypage/survey">나의 여행 취향 설정</MypageItem>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Wish/Wish.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState } from 'react';
import { useInfiniteQuery } from '@tanstack/react-query';
import { getMemberTours } from '@api/member';
import WishCategory from './WishCategory';
import WishList from './WishList';
import NoDataMessage from '@components/common/noData/NoDataMessage';
import { getMemberTours } from '@api/member';
import { HeartIcon } from '@components/common/icons/Icons';

const Wish = () => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/Wish/WishItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const WishItem: React.FC<WishItemProps> = ({ wishList }) => {
{(Math.ceil(ratingAverage * 100) / 100).toFixed(1)}
</span>
<span className="text-xs">
({reviewCount.toLocaleString()})
({reviewCount ? reviewCount.toLocaleString() : reviewCount})
</span>
</div>
</div>
Expand All @@ -66,7 +66,7 @@ const WishItem: React.FC<WishItemProps> = ({ wishList }) => {
<HeartIcon size={14} color="#FF2167" fill="#FF2167" />
</div>
<span className="ml-1 mt-[2.8px] text-xs">
{likedCount.toLocaleString()}
{likedCount ? likedCount.toLocaleString() : likedCount}
</span>
</div>
</div>
Expand Down
74 changes: 74 additions & 0 deletions src/components/common/icons/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,80 @@ export const CalendarIcon: React.FC<IconProps> = ({
);
};

export const CalendarIcon2: React.FC<IconProps> = ({ size = 25 }) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={size}
height={size}
viewBox="0 0 25 25"
fill="none">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M2.40913 7.61438H21.8252C21.4919 4.94249 19.2127 2.875 16.4505 2.875H7.78385C5.0217 2.875 2.74243 4.94249 2.40913 7.61438ZM21.8672 8.96849H2.36719V16.9585C2.36719 19.95 4.79231 22.3752 7.78385 22.3752H16.4505C19.4421 22.3752 21.8672 19.95 21.8672 16.9585V8.96849Z"
fill="#1E1E1E"
/>
<path
d="M6.15918 12.6195H7.24251"
stroke="white"
strokeWidth="1.35412"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M11.5752 12.6195H12.6585"
stroke="white"
strokeWidth="1.35412"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M16.9922 12.6195H18.0755"
stroke="white"
strokeWidth="1.35412"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M6.15918 16.9525H7.24251"
stroke="white"
strokeWidth="1.35412"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M11.5752 16.9525H12.6585"
stroke="white"
strokeWidth="1.35412"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M16.9922 16.9525H18.0755"
stroke="white"
strokeWidth="1.35412"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M16.5758 2.06055L16.5758 5.31058"
stroke="#1E1E1E"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M7.65885 2.06055L7.65885 5.31058"
stroke="#1E1E1E"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
};

export const HeartIcon: React.FC<IconProps> = ({
size = 25,
color = 'black',
Expand Down
Loading

0 comments on commit 16ff768

Please sign in to comment.