Skip to content

Commit

Permalink
Merge pull request #31 from ssumai-kr/Feature-박수민
Browse files Browse the repository at this point in the history
메인 화면 API 모두 적용, 페이지네이션 적용
  • Loading branch information
ssumai-kr authored Jul 15, 2024
2 parents 9dd3898 + f07ada0 commit 71eea91
Show file tree
Hide file tree
Showing 14 changed files with 662 additions and 62 deletions.
168 changes: 145 additions & 23 deletions components/Lander/AllActivities.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,62 @@ import Image from 'next/image';
import StarImg from '@/public/icon/Star.svg';
import CatergoryBtn from '../CatergoryBtn/CatergoryBtn';
import PriceFilterBtn from '../PriceFilterBtn/PriceFilterBtn';
import { useState, useEffect } from 'react';
import { AllActivityProps } from './AllActivities.type';
import { getActivityList } from '@/pages/api/activities/apiactivities';
import { getActivityListResponse } from '@/pages/api/activities/apiactivities.types';
import { getActivityListParams } from '@/pages/api/activities/apiactivities.types';
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import Pagination from '../Pagination/Pagination';
import { useRecoilState, useRecoilValue } from 'recoil';
import { mainPageState } from '@/states/mainPageState';

const Kategories = ['문화 예술', '식음료', '스포츠', '투어', '관광', '웰빙'];

function AllActivity() {
function AllActivity({
title,
backgroundImage,
price,
rating,
reviewCount,
id,
}: AllActivityProps) {
const router = useRouter();

const handleClick = () => {
router.push(`/activity-details/${id}`);
};

return (
<div>
<div onClick={handleClick} className="cursor-pointer">
<div
className="w-[286px] t:w-[223px] m:w-[170px] h-[286px] t:h-[223px] m:h-[170px] rounded-xl bg-[url('/image/Testimage.jpg')]"
style={{
backgroundImage:
'linear-gradient(180deg, rgba(0, 0, 0, 0.10) 20.33%, rgba(0, 0, 0, 0.60) 100%), url("/image/Testimage.jpg")',
backgroundImage: `linear-gradient(180deg, rgba(0, 0, 0, 0.10) 20.33%, rgba(0, 0, 0, 0.60) 100%),url(${backgroundImage})`,
}}
></div>
<div>
<div className='hover:bg-gray-200 rounded px-[4px]'>
<div className="flex items-center mt-[16.5px]">
<Image src={StarImg} alt="별점 표시 이미지" width={20} height={20} />
<Image
src={StarImg}
alt="별점 표시 이미지"
width={20}
height={20}
></Image>
<div className="font-sans text-[16px] font-[500] ml-[5px]">
별 점{' '}
<span className="font-sans text-[16px] text-[#A1A1A1] font-[500]">
(리뷰 수)
{rating ? rating.toFixed(1) : 0}{' '}
<span className="font-sans text-[16px] text-[#A1A1A1] font-[500] ">
({reviewCount ? reviewCount : 0})
</span>
</div>
</div>
<div className="font-sans text-[24px] m:text-[18px] font-[600] mt-[10px]">
체험 제목
<div className="h-[70px] t:h-[50px] m:h-[30px] m:w-[160px] font-sans text-[24px] m:text-[18px] font-[600] mt-[10px]">
{title}
</div>
<div className="font-sans text-[28px] m:text-[20px] font-[700] mt-[15px]">
가격{' '}
<span className="font-sans text-[20px] m:text-[16px] font-[400]">
<div className="font-sans text-[28px] text-[20px] font-[700] p:mt-[0px] mt-[15px]">
{price}{' '}
<span className="font-sans text-[20px] text-[16px] font-[400]">
/ 인
</span>
</div>
Expand All @@ -40,6 +67,91 @@ function AllActivity() {
}

function AllActivities() {
const router = useRouter();
// const [currentPage, setCurrentPage] = useState<number>(
// router.query.page ? parseInt(router.query.page as string, 10) : 1
// );
const [MainPageState, setMainPageState] = useRecoilState(mainPageState);

const {
itemsPerPage: items_per_page,
selectedSorted,
currentPage,
} = useRecoilValue(mainPageState);

const setItemsPerPage = () => {
if (typeof window !== 'undefined') {
// 브라우저 환경에서만 실행
const width = window.innerWidth;

let itemsPerPage;
if (width >= 1281) {
itemsPerPage = 8;
} else if (width > 744) {
itemsPerPage = 9;
} else {
itemsPerPage = 6;
}

setMainPageState((prevState) => ({
...prevState,
itemsPerPage,
}));
}
};

const params: getActivityListParams = {
method: 'offset',
cursorId: null,
category: null,
keyword: null,
sort: selectedSorted,
page: currentPage,
size: items_per_page,
};

const {
data: allActivitiesData,
error,
isLoading,
} = useQuery<getActivityListResponse>({
queryKey: ['AllActivities', params],
queryFn: () => getActivityList(params),
});

const handlePageChange = (page: number) => {
//setCurrentPage(page);
setMainPageState((prevState) => ({
...prevState,
currentPage: page,
}));
//router.push(`/?page=${page}`);
};

useEffect(() => {
setItemsPerPage();
if (typeof window !== 'undefined') {
window.addEventListener('resize', setItemsPerPage);
}
return () => {
if (typeof window !== 'undefined') {
window.removeEventListener('resize', setItemsPerPage);
}
};
}, []);

useEffect(() => {
const params: getActivityListParams = {
method: 'offset',
cursorId: null,
category: null,
keyword: null,
sort: selectedSorted,
page: currentPage,
size: items_per_page,
};
}, [currentPage, items_per_page, selectedSorted]);

return (
<div>
<div className="flex justify-between">
Expand All @@ -57,17 +169,27 @@ function AllActivities() {
🛼 모든 체험
</div>
<div className="grid grid-cols-4 t:grid-cols-3 m:grid-cols-2 grid-rows-2 gap-[20px] t:gap-[14px] m:gap-[6px] gap-y-[48px] mb-[40px] overflow-auto scrollbar-hide">
<AllActivity />
<AllActivity />
<AllActivity />
<AllActivity />
<AllActivity />
<AllActivity />
<AllActivity />
<AllActivity />
{allActivitiesData?.activities.map((data) => (
<AllActivity
key={data.id}
title={data.title}
backgroundImage={data.bannerImageUrl}
price={data.price}
rating={data.rating}
reviewCount={data.reviewCount}
id={data.id}
/>
))}
</div>
<div className="text-[30px] font-[700] flex justify-center mb-[342px] mt-[70px]">
페이지네이션 버튼
{allActivitiesData && allActivitiesData.totalCount > 0 && (
<Pagination
totalItems={allActivitiesData?.totalCount}
itemsPerPage={items_per_page}
currentPage={currentPage}
onPageChange={handlePageChange}
/>
)}
</div>
</div>
);
Expand Down
8 changes: 8 additions & 0 deletions components/Lander/AllActivities.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface AllActivityProps {
title: string;
backgroundImage: string;
price: number;
rating: number;
reviewCount: number;
id: number;
}
145 changes: 132 additions & 13 deletions components/Lander/BestActivities.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
import Image from 'next/image';
import { PaginationArrowButton } from '../Button/Button';
import StarImg from '@/public/icon/Star.svg';
import { useEffect, useState } from 'react';
import { ActivityDetail, BestActivityProps } from './BestActivities.type';
import usePagination from '@/hooks/usePagination';
import {
getActivityListParams,
getActivityListResponse,
} from '@/pages/api/activities/apiactivities.types';
import { useQuery } from '@tanstack/react-query';
import { getActivityList } from '@/pages/api/activities/apiactivities';
import { useRouter } from 'next/router';
import { useRecoilState } from 'recoil';

function BestActivity({
title,
price,
rating,
reviewCount,
bannerImageUrl,
id,
}: BestActivityProps) {
const router = useRouter();

const handleClick = () => {
router.push(`/activity-details/${id}`);
};

function BestActivity() {
return (
<div
onClick={handleClick}
className="relative w-[384px] m:w-[186px] h-[384px] m:h-[186px] rounded-3xl border bg-gray-300 flex flex-col justify-center bg-[url('/image/Testimage.jpg')] cursor-pointer shrink-0 bg-cover bg-center"
style={{
backgroundImage:
'linear-gradient(180deg, rgba(0, 0, 0, 0.00) 33.33%, rgba(0, 0, 0, 0.80) 91.67%), url("/image/Testimage.jpg")',
backgroundImage: `linear-gradient(180deg, rgba(0, 0, 0, 0.00) 33.33%, rgba(0, 0, 0, 0.80) 91.67%), url(${bannerImageUrl})`,
}}
>
<div className="flex gap-[5px] absolute left-[20px] bottom-[166px] m:bottom-[98px]">
Expand All @@ -19,35 +43,130 @@ function BestActivity() {
height={18}
></Image>
<span className="font-sans text-[14px] font-[600] text-white">
별점 (리뷰 수)
{rating.toFixed(1)} ({reviewCount})
</span>
</div>
<div className="font-sans text-[30px] m:text-[18px] font-[700] absolute left-[20px] bottom-[74px] m:bottom-[50px] text-white">
체험 제목 체험 제목
{title}
</div>
<div className="font-sans text-[20px] m:text-[16px] font-[700] absolute left-[20px] bottom-[39px] m:bottom-[24px] text-white">
가격 / 인
{price} / 인
</div>
</div>
);
}

function BestActivities() {
const [bestCurrentPage, setBestCurrentPage] = useState(1);

const params: getActivityListParams = {
method: 'offset',
cursorId: null,
category: null,
keyword: null,
sort: 'most_reviewed',
page: bestCurrentPage,
size: 3,
};

const paramsNotPc: getActivityListParams = {
method: 'offset',
cursorId: null,
category: null,
keyword: null,
sort: 'most_reviewed',
page: 1,
size: 9,
};

const {
data: bestActivitiesData,
error,
isLoading,
} = useQuery<getActivityListResponse>({
queryKey: ['BestActivities', params],
queryFn: () => getActivityList(params),
});

const {
data: bestActivitiesDataNotPc,
error: errorNotPc,
isLoading: isLoadingNotPc,
} = useQuery<getActivityListResponse>({
queryKey: ['BestActivitiesNotPc', paramsNotPc],
queryFn: () => getActivityList(paramsNotPc),
});

const {
items,
currentPage,
isFirstPage,
isLastPage,
handlePrevClick,
handleNextClick,
} = usePagination({
data: bestActivitiesData,
itemsPerPage: 3,
});

useEffect(() => {
setBestCurrentPage(currentPage);
}, [currentPage]);

return (
<div>
<div className="flex justify-between items-center">
<span className="text-[36px] m:text-[18px] font-[700]">
🔥 인기 체험
</span>
<div className="t:hidden m:hidden">
{/* <PaginationArrowButton></PaginationArrowButton> */}
<div className="t:hidden m:hidden flex gap-[10px]">
<PaginationArrowButton
onClick={handlePrevClick}
direction="prev"
disabled={isFirstPage}
/>
<PaginationArrowButton
onClick={handleNextClick}
direction="next"
disabled={isLastPage}
/>
</div>
</div>
<div className="flex gap-[32px] m:gap-[16px] mt-[34px] overflow-auto scrollbar-hide">
<BestActivity></BestActivity>
<BestActivity></BestActivity>
<BestActivity></BestActivity>
</div>
{items && items.length > 0 ? (
<div className="flex gap-[32px] m:gap-[16px] mt-[34px] overflow-auto scrollbar-hide t:hidden m:hidden">
{items.map((item: ActivityDetail) => (
<BestActivity
key={item.id}
title={item.title}
price={item.price}
rating={item.rating}
reviewCount={item.reviewCount}
id={item.id}
bannerImageUrl={item.bannerImageUrl}
/>
))}
</div>
) : (
<div>No activities found</div>
)}
{bestActivitiesDataNotPc?.activities &&
bestActivitiesDataNotPc.activities.length > 0 ? (
<div className="flex gap-[32px] m:gap-[16px] mt-[34px] overflow-auto scrollbar-hide p:hidden">
{bestActivitiesDataNotPc.activities.map((item: ActivityDetail) => (
<BestActivity
key={item.id}
title={item.title}
price={item.price}
rating={item.rating}
reviewCount={item.reviewCount}
id={item.id}
bannerImageUrl={item.bannerImageUrl}
/>
))}
</div>
) : (
<div>No activities found</div>
)}
</div>
);
}
Expand Down
Loading

0 comments on commit 71eea91

Please sign in to comment.