Skip to content

Commit 5207cfe

Browse files
committed
체험 상세페이지 전체 레이아웃 1차완성/태블릿화면 팝업추가
1 parent b01d043 commit 5207cfe

File tree

10 files changed

+208
-109
lines changed

10 files changed

+208
-109
lines changed

public/assets/svg/star.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
3+
const Star = ({ size = 20, color = '#fff', ...props }) => (
4+
<svg
5+
xmlns='http://www.w3.org/2000/svg'
6+
width={size}
7+
height={size}
8+
viewBox='0 0 20 20'
9+
fill={color}
10+
{...props}
11+
>
12+
<path
13+
d='M12.3122 15.0005C12.2069 15.0009 12.1042 14.9681 12.0187 14.9067L7.99966 11.993L3.9806 14.9067C3.89474 14.969 3.79129 15.0024 3.68522 15.002C3.57915 15.0016 3.47595 14.9675 3.39054 14.9046C3.30513 14.8417 3.24193 14.7532 3.21009 14.6521C3.17825 14.5509 3.17942 14.4422 3.21341 14.3417L4.78091 9.69891L0.718413 6.91298C0.630416 6.8527 0.564002 6.76586 0.528872 6.66515C0.493743 6.56444 0.491741 6.45513 0.523158 6.3532C0.554575 6.25127 0.617764 6.16206 0.703494 6.0986C0.789224 6.03514 0.893001 6.00076 0.999663 6.00048H6.01154L7.52404 1.34579C7.55662 1.2453 7.6202 1.15771 7.70564 1.09558C7.79109 1.03346 7.89402 1 7.99966 1C8.10531 1 8.20823 1.03346 8.29368 1.09558C8.37913 1.15771 8.44271 1.2453 8.47529 1.34579L9.98779 6.00204H14.9997C15.1065 6.00199 15.2105 6.03613 15.2964 6.09947C15.3824 6.16281 15.4459 6.25201 15.4775 6.35402C15.5091 6.45603 15.5072 6.56548 15.4721 6.66634C15.437 6.76721 15.3706 6.85419 15.2825 6.91454L11.2184 9.69891L12.785 14.3405C12.8104 14.4156 12.8175 14.4957 12.8058 14.5742C12.7941 14.6526 12.7639 14.7272 12.7177 14.7917C12.6715 14.8561 12.6107 14.9087 12.5401 14.945C12.4696 14.9813 12.3915 15.0003 12.3122 15.0005Z'
14+
fill='#FFC23D'
15+
/>
16+
</svg>
17+
);
18+
19+
export default Star;

src/app/(with-header)/activities/[activitiesId]/components/ReviewCard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ export default function ReviewCard({
1414
avatarSrc,
1515
}: UserReviewProps) {
1616
return (
17-
<div className='mx-auto flex max-w-md items-start gap-6 p-6 text-black md:max-w-2xl'>
17+
<div className='flex max-w-md justify-start gap-6 p-6 text-black md:max-w-2xl'>
1818
<Avatar src={avatarSrc} size='sm' />
1919
<div className='grid flex-1 gap-6'>
20-
<div className='flex items-center gap-10 text-sm md:text-lg'>
20+
<div className='flex gap-10 text-sm md:text-lg'>
2121
<p className='font-bold'>{userName}</p>
2222
<p className='text-black'>|</p>
2323
<p className='text-gray-600'>{date}</p>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Star from '@assets/svg/star';
2+
3+
export default function ReviewTitle() {
4+
return (
5+
<div className='mt-10 mb-10 flex flex-col'>
6+
<h2 className='text-2xl font-bold'>후기</h2>
7+
8+
<div className='mt-15 flex items-center gap-15'>
9+
<h2 className='text-4xl font-bold'>4.2</h2>
10+
<div className='flex flex-col gap-10'>
11+
<p>매우 만족</p>
12+
<div className='flex items-center'>
13+
<Star />
14+
<p>1300개 후기</p>
15+
</div>
16+
</div>
17+
</div>
18+
</div>
19+
);
20+
}

src/app/(with-header)/activities/[activitiesId]/components/Title.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import IconDropdown from '@assets/svg/dropdown';
3+
import Star from '@assets/svg/star';
34

45
interface TitleProps {
56
title: string;
@@ -25,9 +26,9 @@ export default function Title({
2526
<h1 className='mb-2 text-2xl font-bold text-black md:text-3xl'>
2627
{title}
2728
</h1>
28-
<div className='flex items-center gap-4 text-sm text-gray-600'>
29+
<div className='flex items-center gap-10 text-sm text-gray-600'>
2930
<div className='flex items-center gap-1'>
30-
<span className='text-yellow-500'></span>
31+
<Star />
3132
<span className='font-medium'>
3233
{rating.toFixed(1)} ({reviewCount}명)
3334
</span>
@@ -37,7 +38,7 @@ export default function Title({
3738
</div>
3839

3940
{isDropDown && (
40-
<div className='mt-30 flex items-center gap-2'>
41+
<div className='mt-30 flex items-center gap-1'>
4142
<IconDropdown />
4243
</div>
4344
)}

src/app/(with-header)/activities/[activitiesId]/page.tsx

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { mockActivity } from './mock/mock';
44
import Title from './components/Title';
55
import ImageGrid from './components/ImageGrid';
66
import ReviewCard from './components/ReviewCard';
7+
import BookingInterface from '@/components/FloatingBox/BookingInterface';
8+
import LocationMap from '@/components/LocationMap';
9+
import ReviewTitle from './components/ReviewTitle';
710

811
export default function ActivityDetailPage() {
912
const {
@@ -31,18 +34,46 @@ export default function ActivityDetailPage() {
3134
/>
3235
<ImageGrid mainImage={bannerImageUrl} subImages={subImageUrls} />
3336

34-
<div className='mt-8 grid grid-cols-1 gap-8 md:grid-cols-3'>
37+
<div className='mt-86 grid grid-cols-1 gap-15 md:grid-cols-3'>
3538
<div className='md:col-span-2'>
36-
<h2 className='mb-4 border-b pb-2 text-2xl font-bold'>체험 설명</h2>
37-
<p>{description}</p>
39+
<h2 className='mb-4 pb-2 text-2xl font-bold'>체험 설명</h2>
40+
<p className='whitespace-pre-line'>{description}</p>
41+
</div>
42+
<div className='md:row-span-2'>
43+
<BookingInterface />
44+
</div>
45+
46+
<div className='md:col-span-2'>
47+
<h2 className='mb-4 pb-2 text-2xl font-bold'>체험 장소</h2>
48+
<LocationMap address='서울특별시 강남구' />
49+
<ReviewTitle />
50+
<ReviewCard
51+
userName='강지현'
52+
date='2023. 2. 4'
53+
reviewText='전문가가 직접 강사로 참여하기 때문에 어떤 수준의 춤추는 사람도 쉽게 이해할 수 있었습니다. 이번 체험을 거쳐 저의 춤추기 실력은 더욱 향상되었어요.'
54+
avatarSrc='/test/image1.png'
55+
/>
56+
<ReviewCard
57+
userName='강지현'
58+
date='2023. 2. 4'
59+
reviewText='전문가가 직접 강사로 참여하기 때문에 어떤 수준의 춤추는 사람도 쉽게 이해할 수 있었습니다. 이번 체험을 거쳐 저의 춤추기 실력은 더욱 향상되었어요.'
60+
avatarSrc='/test/image1.png'
61+
/>
62+
63+
<ReviewCard
64+
userName='강지현'
65+
date='2023. 2. 4'
66+
reviewText='전문가가 직접 강사로 참여하기 때문에 어떤 수준의 춤추는 사람도 쉽게 이해할 수 있었습니다. 이번 체험을 거쳐 저의 춤추기 실력은 더욱 향상되었어요.'
67+
avatarSrc='/test/image1.png'
68+
/>
69+
<ReviewCard
70+
userName='강지현'
71+
date='2023. 2. 4'
72+
reviewText='전문가가 직접 강사로 참여하기 때문에 어떤 수준의 춤추는 사람도 쉽게 이해할 수 있었습니다. 이번 체험을 거쳐 저의 춤추기 실력은 더욱 향상되었어요.'
73+
avatarSrc='/test/image1.png'
74+
/>
3875
</div>
3976
</div>
40-
<ReviewCard
41-
userName='강지현'
42-
date='2023. 2. 4'
43-
reviewText='전문가가 직접 강사로 참여하기 때문에 어떤 수준의 춤추는 사람도 쉽게 이해할 수 있었습니다. 이번 체험을 거쳐 저의 춤추기 실력은 더욱 향상되었어요.'
44-
avatarSrc='/test/image1.png'
45-
/>
4677
</div>
4778
);
4879
}

src/components/DatePicker/DatePicker.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export default function DatePicker() {
5454
const highlightDates = availableDates.map((item) => dayjs(item.date));
5555

5656
return (
57-
<div className='w-full max-w-md rounded-2xl bg-white p-6'>
57+
<div className='max-h-[746px] w-full max-w-md rounded-2xl bg-white p-6'>
5858
<CalendarHeader viewDate={viewDate} onMonthChange={changeMonth} />
5959
<CalendarBody
6060
viewDate={viewDate}

src/components/FloatingBox/BookingInterface.tsx

Lines changed: 67 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import BookingModal from '@/ui/BookingModal';
1010
import { useState } from 'react';
1111
import TabletPopup from './TabletPopup';
1212
import DatePicker from '../DatePicker/DatePicker';
13+
import Button from '../Button';
1314

1415
export default function BookingInterface() {
1516
const handleBooking = () => {
@@ -20,86 +21,82 @@ export default function BookingInterface() {
2021
const [openTablet, setOpenTablet] = useState(false);
2122

2223
return (
23-
<div className='flex min-h-screen items-center justify-center bg-gray-50 p-4'>
24-
<div className='w-full max-w-sm'>
25-
{/* PC */}
26-
<div className='hidden rounded-lg border border-gray-800 bg-white p-6 lg:block'>
27-
<div className='flex flex-col gap-10 px-20'>
24+
<div className='w-full max-w-sm'>
25+
{/* PC */}
26+
<div className='hidden rounded-lg border border-gray-800 bg-white p-6 lg:block'>
27+
<div className='flex flex-col gap-10 px-20'>
28+
<PriceDisplay />
29+
<div className='flex justify-center'>
30+
<DatePicker />
31+
</div>
32+
<TimeSelector />
33+
<ParticipantsSelector />
34+
<BookingButton onClick={handleBooking}>예약하기</BookingButton>
35+
<TotalPriceDisplay />
36+
</div>
37+
</div>
38+
39+
{/* 태블릿 */}
40+
<div className='relative hidden w-full max-w-sm rounded-lg border border-gray-800 bg-white p-6 md:block lg:hidden'>
41+
<div className='flex flex-col gap-20 px-18'>
42+
<div className='mb-6'>
2843
<PriceDisplay />
29-
<div className='flex justify-center'>
30-
<DatePicker />
31-
</div>
32-
<TimeSelector />
44+
<h3 className='mb-4 text-lg font-semibold text-gray-900'>날짜</h3>
45+
<button
46+
onClick={() => setIsOpen(true)}
47+
className='w-full rounded-lg border border-gray-300 p-3 py-8 text-left text-black hover:bg-gray-50'
48+
>
49+
{selectedDate && selectedTime ? (
50+
<h2>
51+
{selectedDate instanceof Date
52+
? selectedDate.toLocaleDateString()
53+
: selectedDate}
54+
/{selectedTime}
55+
</h2>
56+
) : (
57+
'날짜선택하기'
58+
)}
59+
</button>
60+
</div>
61+
<div className='flex flex-col items-center justify-center gap-20 px-10'>
3362
<ParticipantsSelector />
63+
<BookingModal />
64+
3465
<BookingButton onClick={handleBooking}>예약하기</BookingButton>
3566
<TotalPriceDisplay />
3667
</div>
3768
</div>
69+
</div>
3870

39-
{/* 태블릿 */}
40-
<div className='relative hidden min-h-420 max-w-250 rounded-lg border border-gray-800 bg-white p-6 md:block lg:hidden'>
41-
<div className='flex flex-col gap-20 px-18'>
42-
<div className='mb-6'>
43-
<PriceDisplay />
44-
<h3 className='mb-4 text-lg font-semibold text-gray-900'>날짜</h3>
45-
<button
46-
onClick={() => setOpenTablet(true)}
47-
className='w-full rounded-lg border border-gray-300 p-3 py-8 text-left text-black hover:bg-gray-50'
48-
>
49-
{selectedDate && selectedTime ? (
50-
<h2>
51-
{selectedDate instanceof Date
52-
? selectedDate.toLocaleDateString()
53-
: selectedDate}
54-
/{selectedTime}
55-
</h2>
56-
) : (
57-
'날짜선택하기'
58-
)}
59-
</button>
71+
{/* 모바일 */}
72+
<div className='fixed bottom-0 left-0 right-0 z-100 block border border-gray-200 bg-white p-6 md:hidden'>
73+
<div className='mb-6 flex items-start justify-between'>
74+
<div className='flex-1'>
75+
<div className='mb-1 text-xl font-bold text-gray-900'>
76+
₩ 10,000{' '}
77+
<span className='text-sm font-normal text-gray-600'>
78+
/ 총 {participants}
79+
</span>
6080
</div>
61-
<div className='flex flex-col items-center justify-center gap-20 px-10'>
62-
<ParticipantsSelector />
63-
<BookingModal />
64-
{openTablet && (
65-
<div className='absolute top-0 left-0 z-50 mt-2 w-full rounded border bg-white shadow-lg'>
66-
<TabletPopup />
67-
</div>
81+
<div
82+
onClick={() => setIsOpen(true)}
83+
className='mb-4 text-sm text-gray-600'
84+
>
85+
{selectedDate && selectedTime ? (
86+
<h2>
87+
{selectedDate instanceof Date
88+
? selectedDate.toLocaleDateString()
89+
: selectedDate}
90+
/{selectedTime}
91+
</h2>
92+
) : (
93+
'날짜 선택하기'
6894
)}
69-
<BookingButton onClick={handleBooking}>예약하기</BookingButton>
70-
<TotalPriceDisplay />
71-
</div>
72-
</div>
73-
</div>
74-
75-
{/* 모바일 */}
76-
<div className='fixed bottom-0 block w-full rounded-lg border border-gray-200 bg-white p-6 md:hidden'>
77-
<div className='mb-6 flex items-start justify-between'>
78-
<div className='flex-1'>
79-
<div className='mb-1 text-xl font-bold text-gray-900'>
80-
₩ 10,000{' '}
81-
<span className='text-sm font-normal text-gray-600'>
82-
/ 총 {participants}
83-
</span>
84-
</div>
85-
<div
86-
onClick={() => setIsOpen(true)}
87-
className='mb-4 text-sm text-gray-600'
88-
>
89-
{selectedDate && selectedTime ? (
90-
<h2>
91-
{selectedDate instanceof Date
92-
? selectedDate.toLocaleDateString()
93-
: selectedDate}
94-
/{selectedTime}
95-
</h2>
96-
) : (
97-
'날짜 선택하기'
98-
)}
99-
</div>
100-
<BookingModal />
101-
<BookingButton onClick={handleBooking}>예약하기</BookingButton>
10295
</div>
96+
<BookingModal />
97+
<Button variant='primary' className='py-20' onClick={handleBooking}>
98+
예약하기
99+
</Button>
103100
</div>
104101
</div>
105102
</div>
Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
1+
'use client';
2+
3+
import useBookingStore from '@/stores/Booking/useBookingStore';
4+
import IconClose from '@assets/svg/close';
15
import DatePicker from '../DatePicker/DatePicker';
6+
import TimeSelector from './TimeSelector';
7+
8+
export default function TabletPopup({}) {
9+
const isOpen = useBookingStore((state) => state.isOpen);
10+
const setIsOpen = useBookingStore((state) => state.setIsOpen);
11+
12+
if (!isOpen) return null;
213

3-
export default function TabletPopup() {
414
return (
5-
<div className='flex items-center justify-center'>
6-
<div
7-
className={
8-
'relative m-auto flex h-fit max-h-[85%] w-screen min-w-[375] flex-col bg-white p-8 px-10 shadow-2xl inset-shadow-sm inset-shadow-gray-300 md:h-fit md:w-[50%] md:max-w-600'
9-
}
10-
>
11-
<DatePicker />
15+
<div className='absolute z-50 flex flex-col items-center justify-center'>
16+
<div className='flex justify-between'>
17+
<h2>날짜</h2>
18+
<button onClick={() => setIsOpen(false)}>
19+
<IconClose />
20+
</button>
1221
</div>
22+
23+
<DatePicker />
24+
25+
<TimeSelector />
1326
</div>
1427
);
1528
}

src/components/LocationMap.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const LocationMap = ({ address }: LocationMapProps) => {
6666

6767
return (
6868
<>
69-
<div className='h-[480px] w-full max-w-[327px] overflow-hidden rounded-lg shadow-md md:max-w-[430px] lg:max-w-[800px]'>
69+
<div className='flex h-[480px] w-full flex-col overflow-hidden rounded-lg shadow-md lg:max-w-[800px]'>
7070
{/* 지도 */}
7171
<Map
7272
center={coords}

0 commit comments

Comments
 (0)