Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions apps/what-today/src/components/activities/ActivitiesReview.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { StarIcon } from '@what-today/design-system';
import { motion } from 'motion/react';

import { type ActivityReview } from '@/schemas/activityReview';
interface ActivitiesReviewProps {
Expand All @@ -20,16 +21,24 @@ export default function ActivitiesReview({ review }: ActivitiesReviewProps) {
});

return (
<div className='mb-20 rounded-xl border border-gray-50 px-20 py-20'>
<div className='mb-4 flex items-center gap-8'>
<div className='body-text font-bold'>{user.nickname}</div>
<div className='caption-text text-gray-400'>{formattedDate}</div>
<motion.div
key={review.id}
initial={{ opacity: 0, y: 80 }}
transition={{ duration: 1 }}
viewport={{ once: true, amount: 0.1 }}
whileInView={{ opacity: 1, y: 0 }}
>
<div className='mb-20 rounded-xl border border-gray-50 px-20 py-20'>
<div className='mb-4 flex items-center gap-8'>
<div className='body-text font-bold'>{user.nickname}</div>
<div className='caption-text text-gray-400'>{formattedDate}</div>
</div>
<div className='mb-12'>
<RatingStars rating={rating} />
</div>
<p className='body-text whitespace-pre-wrap'>{content}</p>
</div>
<div className='mb-12'>
<RatingStars rating={rating} />
</div>
<p className='body-text whitespace-pre-wrap'>{content}</p>
</div>
</motion.div>
);
}

Expand Down
61 changes: 39 additions & 22 deletions apps/what-today/src/pages/main/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
TourIcon,
WellbeingIcon,
} from '@what-today/design-system';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { motion } from 'motion/react';
import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';
import React from 'react';
import { useNavigate } from 'react-router-dom';

Expand Down Expand Up @@ -55,6 +56,17 @@ export default function MainPage() {
const [selectedCategory, setSelectedCategory] = useState<string | number>('');
const navigate = useNavigate();

useLayoutEffect(() => {
if ('scrollRestoration' in window.history) {
window.history.scrollRestoration = 'manual';
}
}, []);

// 페이지 마운트 시 무조건 맨 위로
useLayoutEffect(() => {
window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
}, []);

// 반응형 카드 수
const handleResize = useCallback(() => {
setItemsPerPage(getCount());
Expand Down Expand Up @@ -124,7 +136,9 @@ export default function MainPage() {
// 이벤트 핸들러
const handlePageChange = useCallback(
(page: number) => {
if (page !== currentPage) setCurrentPage(page);
if (page !== currentPage) {
setCurrentPage(page);
}
},
[currentPage],
);
Expand All @@ -148,28 +162,10 @@ export default function MainPage() {
setCurrentPage(1);
}, []);

// 카드 렌더링 최적화
const renderCards = useCallback(() => {
return pagedItems.map((item, idx) => (
<MemoizedMainCard
key={`${item.id}-${currentPage}-${idx}`}
bannerImageUrl={item.bannerImageUrl}
category={item.category}
price={item.price}
rating={item.rating}
reviewCount={item.reviewCount}
title={item.title}
onClick={() => navigate(`/activities/${item.id}`)}
>
<MainCard.Image />
<MainCard.Content />
</MemoizedMainCard>
));
}, [pagedItems, currentPage, navigate]);

return (
<>
<div className='to-primary-500/40 absolute top-0 left-0 h-1/2 w-full bg-gradient-to-t from-transparent' />

<div className='relative z-10 flex h-auto flex-col gap-60'>
<MainBanner />

Expand Down Expand Up @@ -252,7 +248,28 @@ export default function MainPage() {
<NoResult />
</div>
) : (
renderCards()
pagedItems.map((item, idx) => (
<motion.div
key={`${item.id}-${currentPage}-${idx}`}
initial={{ opacity: 0, y: 100 }}
transition={{ duration: 1 }}
viewport={{ once: true, amount: 0.1 }}
whileInView={{ opacity: 1, y: 0 }}
>
<MemoizedMainCard
bannerImageUrl={item.bannerImageUrl}
category={item.category}
price={item.price}
rating={item.rating}
reviewCount={item.reviewCount}
title={item.title}
onClick={() => navigate(`/activities/${item.id}`)}
>
<MainCard.Image />
<MainCard.Content />
</MemoizedMainCard>
</motion.div>
))
)}
</div>

Expand Down
34 changes: 21 additions & 13 deletions apps/what-today/src/pages/mypage/manage-activities/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
useToast,
WarningLogo,
} from '@what-today/design-system';
import { motion } from 'motion/react';
import { useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';

Expand Down Expand Up @@ -88,20 +89,27 @@ export default function ManageActivitiesPage() {
content = (
<>
{allActivities.map(({ id, title, price, bannerImageUrl, rating, reviewCount }) => (
<ExperienceCard
<motion.div
key={id}
bannerImageUrl={bannerImageUrl}
price={price}
rating={rating}
reviewCount={reviewCount}
title={title}
onDelete={() => {
setDeleteTargetId(id);
setIsDeleteOpen(true);
}}
onEdit={() => navigate(`/experiences/create/${id}`)}
onNavigate={() => navigate(`/activities/${id}`)}
/>
initial={{ opacity: 0, y: 80 }}
transition={{ duration: 1 }}
viewport={{ once: true, amount: 0.2 }}
whileInView={{ opacity: 1, y: 0 }}
>
<ExperienceCard
bannerImageUrl={bannerImageUrl}
price={price}
rating={rating}
reviewCount={reviewCount}
title={title}
onDelete={() => {
setDeleteTargetId(id);
setIsDeleteOpen(true);
}}
onEdit={() => navigate(`/experiences/create/${id}`)}
onNavigate={() => navigate(`/activities/${id}`)}
/>
</motion.div>
))}
<div ref={observerRef} />
{isFetchingNextPage && <div className='text-center text-gray-400'>체험목록 불러오는 중...</div>}
Expand Down
12 changes: 10 additions & 2 deletions apps/what-today/src/pages/mypage/reservations-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from '@what-today/design-system';
import { WarningLogo } from '@what-today/design-system';
import { useToast } from '@what-today/design-system';
import { motion } from 'motion/react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { twJoin } from 'tailwind-merge';
Expand Down Expand Up @@ -207,7 +208,14 @@ export default function ReservationsListPage() {

// 🎯 날짜별 그룹핑만 하고 정렬 제거 (자연스러운 순서 유지)
return Object.entries(grouped).map(([date, group], index) => (
<section key={date} className={twJoin('space-y-12 pt-20 pb-30', index !== 0 && 'border-t border-gray-50')}>
<motion.section
key={date}
className={twJoin('space-y-12 pt-20 pb-30', index !== 0 && 'border-t border-gray-50')}
initial={{ opacity: 0, y: 80 }}
transition={{ duration: 1, ease: 'easeOut' }}
viewport={{ once: true, amount: 0.2 }}
whileInView={{ opacity: 1, y: 0 }}
>
<h3 className='section-text'>{date}</h3>
<ul>
{group.map((res) => {
Expand Down Expand Up @@ -261,7 +269,7 @@ export default function ReservationsListPage() {
);
})}
</ul>
</section>
</motion.section>
));
};

Expand Down
2 changes: 1 addition & 1 deletion packages/design-system/src/components/skeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { default as ExperienceCardSkeleton } from './ExperienceCardSkeleton';
export { default as NotificationCardSkeleton } from './NotificationCardSkeleton';
export { default as OngoingExperienceCardSkeleton } from './OngoingExperienceCardSkeleton';
export { default as UpcomingScheduleItemSkeleton } from './UpcomingScheduleItemSkeleton';
export { default as NotificationCardSkeleton } from './NotificationCardSkeleton';
6 changes: 3 additions & 3 deletions packages/design-system/src/pages/OngoingExperienceCardDoc.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import OngoingExperienceCard from '../components/OngoingExperienceCard';
// import OngoingExperienceCard from '../components/OngoingExperienceCard';
import DocTemplate, { DocCode } from '../layouts/DocTemplate';

/* Playground는 편집 가능한 코드 블록입니다. */
Expand Down Expand Up @@ -26,9 +26,9 @@ export default function OngoingExperienceCardDoc() {
<DocCode code={`<OngoingExperienceCard variant="primary">Click me</OngoingExperienceCard>`} />

<div className='flex gap-12'>
{/* <OngoingExperienceCard activities={[]} onClick={() => {}} onClickActivity={() => {}} />
<OngoingExperienceCard activities={[]} onClick={() => {}} onClickActivity={() => {}} />
<OngoingExperienceCard activities={[]} onClick={() => {}} onClickActivity={() => {}} />
<OngoingExperienceCard activities={[]} onClick={() => {}} onClickActivity={() => {}} />
<OngoingExperienceCard activities={[]} onClick={() => {}} onClickActivity={() => {}} /> */}
</div>
</>
);
Expand Down
4 changes: 2 additions & 2 deletions packages/design-system/src/pages/UpcomingScheduleDoc.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import UpcomingSchedule from '@/components/UpcomingSchedule';
// import UpcomingSchedule from '@/components/UpcomingSchedule';

import DocTemplate, { DocCode } from '../layouts/DocTemplate';

Expand Down Expand Up @@ -26,7 +26,7 @@ export default function UpcomingScheduleDoc() {
{/* 예시 코드 */}
<DocCode code={`<UpcomingSchedule variant="primary">Click me</UpcomingSchedule>`} />

<UpcomingSchedule reservation={[]} onClickReservation={() => {}} />
{/* <UpcomingSchedule reservation={[]} onClickReservation={() => {}} /> */}
</>
);
}