Skip to content

Commit 71c9fe0

Browse files
authored
Merge pull request #85 from geulDa/feat/#84/eventdeatail
✨Feat : 상세 행사 페이지
2 parents 545958d + e97c246 commit 71c9fe0

File tree

5 files changed

+177
-14
lines changed

5 files changed

+177
-14
lines changed

src/pages/events/[id].tsx

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { Header, EventCard } from '@/shared/components';
2+
import DateTag from '@/pages/events/components/DateTag';
3+
import { cn } from '@/shared/lib';
4+
import { eventData } from '@/shared/constants/events/eventsData';
5+
import Image from 'next/image';
6+
import { useRouter } from 'next/router';
7+
8+
const EventDetailPage = () => {
9+
const router = useRouter();
10+
const { id } = router.query;
11+
12+
const event = eventData.find((e) => e.id === Number(id));
13+
if (!event) return null;
14+
15+
const { name, address, description, startDate, endDate, imageSrc } = event;
16+
17+
return (
18+
<div
19+
className={cn(
20+
'relative w-full min-h-[100vh] overflow-auto',
21+
)}
22+
>
23+
<Header
24+
title='행사명'
25+
onClick={() => router.back()}
26+
className={cn('fixed top-0 left-0 right-0 z-50')}
27+
/>
28+
29+
<main
30+
className={cn(
31+
'flex flex-col items-center justify-start',
32+
'px-[2.4rem] pt-[calc(10rem+1.4rem)]'
33+
)}
34+
>
35+
{/* 행사 기간 */}
36+
<div className={cn('flex justify-center w-[18.4rem] mt-[1.3rem]')}>
37+
<DateTag startDate={startDate} endDate={endDate} />
38+
</div>
39+
40+
{/* 대표 이미지 */}
41+
<section
42+
className={cn(
43+
'relative w-full flex justify-center max-w-[35.4rem]',
44+
'mt-[1rem]'
45+
)}
46+
>
47+
{imageSrc ? (
48+
<Image
49+
src={imageSrc}
50+
alt={`${name} 이미지`}
51+
width={354}
52+
height={430}
53+
className={cn('w-full h-auto object-cover rounded-[2rem]')}
54+
/>
55+
) : (
56+
<div
57+
className={cn('w-full h-[43.6rem] bg-gray-200 rounded-[2rem]')}
58+
/>
59+
)}
60+
</section>
61+
62+
{/* 행사 카드 */}
63+
<div
64+
className={cn(
65+
'flex flex-col items-center w-full gap-[0.8rem]',
66+
'mt-[0.8rem]'
67+
)}
68+
>
69+
<EventCard
70+
name={name}
71+
address={address}
72+
description={description}
73+
variant='gray'
74+
size='large'
75+
/>
76+
77+
{/* 관련 행사 */}
78+
<div
79+
className={cn(
80+
'grid grid-cols-2 gap-[1.2rem] justify-items-center w-full max-w-[35.4rem]'
81+
)}
82+
>
83+
<div className={cn('w-[17rem]')}>
84+
<EventCard
85+
name='관련 행사'
86+
address=''
87+
description=''
88+
variant='gray'
89+
size='small'
90+
/>
91+
</div>
92+
<div className={cn('w-[17rem]')}>
93+
<EventCard
94+
name='관련 행사'
95+
address=''
96+
description=''
97+
variant='gray'
98+
size='small'
99+
/>
100+
</div>
101+
</div>
102+
</div>
103+
</main>
104+
</div>
105+
);
106+
};
107+
108+
export default EventDetailPage;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use client';
2+
3+
import { cva, type VariantProps } from 'class-variance-authority';
4+
import { cn } from '@/shared/lib';
5+
6+
interface DateTagProps extends VariantProps<typeof dateTagStyle> {
7+
startDate?: string;
8+
endDate?: string;
9+
className?: string;
10+
}
11+
12+
const dateTagStyle = cva(
13+
`
14+
inline-flex justify-center items-center whitespace-nowrap
15+
w-full h-[4.5rem]
16+
px-[1.3rem] py-[1.2rem]
17+
rounded-[2rem]
18+
border border-pink-100
19+
bg-pink-50
20+
text-pink-300 text-label-lg
21+
`,
22+
);
23+
24+
export default function DateTag({
25+
startDate,
26+
endDate,
27+
className,
28+
}: DateTagProps) {
29+
const formatDate = (date?: string) => {
30+
if (!date) return '';
31+
return date.replace(/-/g, '.');
32+
};
33+
34+
if (!startDate && !endDate) return null;
35+
36+
return (
37+
<div className={cn(dateTagStyle(), className)}>
38+
{formatDate(startDate)} ~ {formatDate(endDate)}
39+
</div>
40+
);
41+
}

src/pages/events/index.tsx

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,17 @@ import {
1111
EventCard,
1212
} from '@/shared/components';
1313
import { eventData } from '@/shared/constants/events/eventsData';
14+
import { formatDateToISO, isDateWithinRange } from '@/shared/utils/date';
1415

1516
export default function EventPage() {
1617
const router = useRouter();
1718
const [date, setDate] = useState<Date>();
1819

19-
const selectedDate = date
20-
? new Date(date.getTime() - date.getTimezoneOffset() * 60000)
21-
.toISOString()
22-
.split('T')[0]
23-
: undefined;
20+
const selectedDate = formatDateToISO(date);
2421

25-
const filteredEvents = eventData.filter((event) => {
26-
if (!selectedDate) return false;
27-
const start = new Date(event.startDate);
28-
const end = new Date(event.endDate);
29-
const selected = new Date(selectedDate);
30-
return selected >= start && selected <= end;
31-
});
22+
const filteredEvents = eventData.filter((event) =>
23+
isDateWithinRange(selectedDate, event.startDate, event.endDate),
24+
);
3225

3326
const handleCardClick = (id: number) => {
3427
router.push(`/events/${id}`);

src/shared/constants/events/eventsData.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ export interface EventData {
33
name: string;
44
address: string;
55
description: string;
6-
startDate: string;
7-
endDate: string;
6+
startDate: string;
7+
endDate: string;
88
imageSrc?: string;
99
}
1010

src/shared/utils/date.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export const formatDateToISO = (date?: Date): string | undefined => {
2+
if (!date) return undefined;
3+
return new Date(date.getTime() - date.getTimezoneOffset() * 60000)
4+
.toISOString()
5+
.split('T')[0];
6+
};
7+
8+
9+
export const isDateWithinRange = (
10+
selectedDate: string | undefined,
11+
startDate: string,
12+
endDate: string,
13+
): boolean => {
14+
if (!selectedDate) return false;
15+
16+
const start = new Date(startDate);
17+
const end = new Date(endDate);
18+
const selected = new Date(selectedDate);
19+
20+
return selected >= start && selected <= end;
21+
};

0 commit comments

Comments
 (0)