Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
19 changes: 19 additions & 0 deletions public/assets/svg/star.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';

const Star = ({ size = 20, color = '#fff', ...props }) => (
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

color prop의 기본값과 실제 사용이 일치하지 않습니다.

color prop의 기본값은 #fff이지만 path 요소에서는 항상 #FFC23D가 사용됩니다. 이는 혼란을 야기할 수 있습니다.

다음 중 하나를 선택하여 수정하세요:

옵션 1: path에서 color prop 사용

    <path
      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'
-      fill='#FFC23D'
+      fill={color}
    />

옵션 2: color prop 기본값을 실제 사용 색상으로 변경

-const Star = ({ size = 20, color = '#fff', ...props }) => (
+const Star = ({ size = 20, color = '#FFC23D', ...props }) => (

Also applies to: 14-14

🤖 Prompt for AI Agents
In public/assets/svg/star.tsx at lines 3 and 14, the color prop default value is
'#fff' but the path element always uses '#FFC23D', causing inconsistency. Fix
this by either updating the path element to use the color prop value or changing
the color prop default to '#FFC23D' to match the path usage.

🛠️ Refactor suggestion

TypeScript 인터페이스를 추가해야 합니다.

props에 대한 타입 정의가 누락되어 타입 안전성이 보장되지 않습니다.

다음과 같이 인터페이스를 추가하세요:

+interface StarProps extends React.SVGProps<SVGSVGElement> {
+  size?: number;
+  color?: string;
+}
+
-const Star = ({ size = 20, color = '#fff', ...props }) => (
+const Star: React.FC<StarProps> = ({ size = 20, color = '#fff', ...props }) => (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const Star = ({ size = 20, color = '#fff', ...props }) => (
interface StarProps extends React.SVGProps<SVGSVGElement> {
size?: number;
color?: string;
}
const Star: React.FC<StarProps> = ({ size = 20, color = '#fff', ...props }) => (
<svg
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
fill="#FFC23D"
d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63
2 9.24l5.46 4.73L5.82 21z"
/>
</svg>
);
🤖 Prompt for AI Agents
In public/assets/svg/star.tsx at line 3, the Star component lacks a TypeScript
interface for its props, which reduces type safety. Define a TypeScript
interface specifying the types for size, color, and any additional props, then
apply this interface to the component's props parameter to ensure proper type
checking.

<svg
xmlns='http://www.w3.org/2000/svg'
width={size}
height={size}
viewBox='0 0 20 20'
fill={color}
{...props}
>
<path
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'
fill='#FFC23D'
/>
</svg>
);

export default Star;
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ export default function ReviewCard({
avatarSrc,
}: UserReviewProps) {
return (
<div className='mx-auto flex max-w-md items-start gap-6 p-6 text-black md:max-w-2xl'>
<div className='flex max-w-md justify-start gap-6 p-6 text-black md:max-w-2xl'>
<Avatar src={avatarSrc} size='sm' />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

파이프라인 오류를 수정해야 합니다.

Avatar 컴포넌트의 props 정렬을 수정해야 합니다.

-      <Avatar src={avatarSrc} size='sm' />
+      <Avatar size='sm' src={avatarSrc} />
🧰 Tools
🪛 GitHub Actions: CI

[warning] 18-18: Props should be sorted alphabetically (react/jsx-sort-props)

🤖 Prompt for AI Agents
In src/app/(with-header)/activities/[activitiesId]/components/ReviewCard.tsx at
line 18, the props passed to the Avatar component are not properly ordered,
causing a pipeline error. Reorder the props so that they follow a consistent and
logical sequence, typically placing size before src or following the project's
established prop order conventions.

<div className='grid flex-1 gap-6'>
<div className='flex items-center gap-10 text-sm md:text-lg'>
<div className='flex gap-10 text-sm md:text-lg'>
<p className='font-bold'>{userName}</p>
<p className='text-black'>|</p>
<p className='text-gray-600'>{date}</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Star from '@assets/svg/star';

export default function ReviewTitle() {
return (
<div className='mt-10 mb-10 flex flex-col'>
<h2 className='text-2xl font-bold'>후기</h2>

<div className='mt-15 flex items-center gap-15'>
<h2 className='text-4xl font-bold'>4.2</h2>
<div className='flex flex-col gap-10'>
<p>매우 만족</p>
<div className='flex items-center'>
<Star />
<p>1300개 후기</p>
</div>
</div>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import IconDropdown from '@assets/svg/dropdown';
import Star from '@assets/svg/star';

interface TitleProps {
title: string;
Expand All @@ -25,9 +26,9 @@ export default function Title({
<h1 className='mb-2 text-2xl font-bold text-black md:text-3xl'>
{title}
</h1>
<div className='flex items-center gap-4 text-sm text-gray-600'>
<div className='flex items-center gap-10 text-sm text-gray-600'>
<div className='flex items-center gap-1'>
<span className='text-yellow-500'>★</span>
<Star />
<span className='font-medium'>
{rating.toFixed(1)} ({reviewCount}명)
</span>
Expand All @@ -37,7 +38,7 @@ export default function Title({
</div>

{isDropDown && (
<div className='mt-30 flex items-center gap-2'>
<div className='mt-30 flex items-center gap-1'>
<IconDropdown />
</div>
)}
Expand Down
49 changes: 40 additions & 9 deletions src/app/(with-header)/activities/[activitiesId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { mockActivity } from './mock/mock';
import Title from './components/Title';
import ImageGrid from './components/ImageGrid';
import ReviewCard from './components/ReviewCard';
import BookingInterface from '@/components/FloatingBox/BookingInterface';
import LocationMap from '@/components/LocationMap';
import ReviewTitle from './components/ReviewTitle';

export default function ActivityDetailPage() {
const {
Expand Down Expand Up @@ -31,18 +34,46 @@ export default function ActivityDetailPage() {
/>
<ImageGrid mainImage={bannerImageUrl} subImages={subImageUrls} />

<div className='mt-8 grid grid-cols-1 gap-8 md:grid-cols-3'>
<div className='mt-86 grid grid-cols-1 gap-15 md:grid-cols-3'>
<div className='md:col-span-2'>
<h2 className='mb-4 border-b pb-2 text-2xl font-bold'>체험 설명</h2>
<p>{description}</p>
<h2 className='mb-4 pb-2 text-2xl font-bold'>체험 설명</h2>
<p className='whitespace-pre-line'>{description}</p>
</div>
<div className='md:row-span-2'>
<BookingInterface />
</div>

<div className='md:col-span-2'>
<h2 className='mb-4 pb-2 text-2xl font-bold'>체험 장소</h2>
<LocationMap address='서울특별시 강남구' />
<ReviewTitle />
<ReviewCard
userName='강지현'
date='2023. 2. 4'
reviewText='전문가가 직접 강사로 참여하기 때문에 어떤 수준의 춤추는 사람도 쉽게 이해할 수 있었습니다. 이번 체험을 거쳐 저의 춤추기 실력은 더욱 향상되었어요.'
avatarSrc='/test/image1.png'
/>
<ReviewCard
userName='강지현'
date='2023. 2. 4'
reviewText='전문가가 직접 강사로 참여하기 때문에 어떤 수준의 춤추는 사람도 쉽게 이해할 수 있었습니다. 이번 체험을 거쳐 저의 춤추기 실력은 더욱 향상되었어요.'
avatarSrc='/test/image1.png'
/>

<ReviewCard
userName='강지현'
date='2023. 2. 4'
reviewText='전문가가 직접 강사로 참여하기 때문에 어떤 수준의 춤추는 사람도 쉽게 이해할 수 있었습니다. 이번 체험을 거쳐 저의 춤추기 실력은 더욱 향상되었어요.'
avatarSrc='/test/image1.png'
/>
<ReviewCard
userName='강지현'
date='2023. 2. 4'
reviewText='전문가가 직접 강사로 참여하기 때문에 어떤 수준의 춤추는 사람도 쉽게 이해할 수 있었습니다. 이번 체험을 거쳐 저의 춤추기 실력은 더욱 향상되었어요.'
avatarSrc='/test/image1.png'
/>
</div>
</div>
<ReviewCard
userName='강지현'
date='2023. 2. 4'
reviewText='전문가가 직접 강사로 참여하기 때문에 어떤 수준의 춤추는 사람도 쉽게 이해할 수 있었습니다. 이번 체험을 거쳐 저의 춤추기 실력은 더욱 향상되었어요.'
avatarSrc='/test/image1.png'
/>
</div>
);
}
2 changes: 1 addition & 1 deletion src/components/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default function DatePicker() {
const highlightDates = availableDates.map((item) => dayjs(item.date));

return (
<div className='w-full max-w-md rounded-2xl bg-white p-6'>
<div className='max-h-[746px] w-full max-w-md rounded-2xl bg-white p-6'>
<CalendarHeader viewDate={viewDate} onMonthChange={changeMonth} />
<CalendarBody
viewDate={viewDate}
Expand Down
137 changes: 67 additions & 70 deletions src/components/FloatingBox/BookingInterface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import BookingModal from '@/ui/BookingModal';
import { useState } from 'react';
import TabletPopup from './TabletPopup';
import DatePicker from '../DatePicker/DatePicker';
import Button from '../Button';

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

return (
<div className='flex min-h-screen items-center justify-center bg-gray-50 p-4'>
<div className='w-full max-w-sm'>
{/* PC */}
<div className='hidden rounded-lg border border-gray-800 bg-white p-6 lg:block'>
<div className='flex flex-col gap-10 px-20'>
<div className='w-full max-w-sm'>
{/* PC */}
<div className='hidden rounded-lg border border-gray-800 bg-white p-6 lg:block'>
<div className='flex flex-col gap-10 px-20'>
<PriceDisplay />
<div className='flex justify-center'>
<DatePicker />
</div>
<TimeSelector />
<ParticipantsSelector />
<BookingButton onClick={handleBooking}>예약하기</BookingButton>
<TotalPriceDisplay />
</div>
</div>

{/* 태블릿 */}
<div className='relative hidden w-full max-w-sm rounded-lg border border-gray-800 bg-white p-6 md:block lg:hidden'>
<div className='flex flex-col gap-20 px-18'>
<div className='mb-6'>
<PriceDisplay />
<div className='flex justify-center'>
<DatePicker />
</div>
<TimeSelector />
<h3 className='mb-4 text-lg font-semibold text-gray-900'>날짜</h3>
<button
onClick={() => setIsOpen(true)}
className='w-full rounded-lg border border-gray-300 p-3 py-8 text-left text-black hover:bg-gray-50'
>
{selectedDate && selectedTime ? (
<h2>
{selectedDate instanceof Date
? selectedDate.toLocaleDateString()
: selectedDate}
/{selectedTime}
</h2>
) : (
'날짜선택하기'
)}
</button>
</div>
<div className='flex flex-col items-center justify-center gap-20 px-10'>
<ParticipantsSelector />
<BookingModal />

<BookingButton onClick={handleBooking}>예약하기</BookingButton>
<TotalPriceDisplay />
</div>
</div>
</div>

{/* 태블릿 */}
<div className='relative hidden min-h-420 max-w-250 rounded-lg border border-gray-800 bg-white p-6 md:block lg:hidden'>
<div className='flex flex-col gap-20 px-18'>
<div className='mb-6'>
<PriceDisplay />
<h3 className='mb-4 text-lg font-semibold text-gray-900'>날짜</h3>
<button
onClick={() => setOpenTablet(true)}
className='w-full rounded-lg border border-gray-300 p-3 py-8 text-left text-black hover:bg-gray-50'
>
{selectedDate && selectedTime ? (
<h2>
{selectedDate instanceof Date
? selectedDate.toLocaleDateString()
: selectedDate}
/{selectedTime}
</h2>
) : (
'날짜선택하기'
)}
</button>
{/* 모바일 */}
<div className='fixed bottom-0 left-0 right-0 z-100 block border border-gray-200 bg-white p-6 md:hidden'>
<div className='mb-6 flex items-start justify-between'>
<div className='flex-1'>
<div className='mb-1 text-xl font-bold text-gray-900'>
₩ 10,000{' '}
<span className='text-sm font-normal text-gray-600'>
/ 총 {participants}인
</span>
</div>
<div className='flex flex-col items-center justify-center gap-20 px-10'>
<ParticipantsSelector />
<BookingModal />
{openTablet && (
<div className='absolute top-0 left-0 z-50 mt-2 w-full rounded border bg-white shadow-lg'>
<TabletPopup />
</div>
<div
onClick={() => setIsOpen(true)}
className='mb-4 text-sm text-gray-600'
>
{selectedDate && selectedTime ? (
<h2>
{selectedDate instanceof Date
? selectedDate.toLocaleDateString()
: selectedDate}
/{selectedTime}
</h2>
) : (
'날짜 선택하기'
)}
<BookingButton onClick={handleBooking}>예약하기</BookingButton>
<TotalPriceDisplay />
</div>
</div>
</div>

{/* 모바일 */}
<div className='fixed bottom-0 block w-full rounded-lg border border-gray-200 bg-white p-6 md:hidden'>
<div className='mb-6 flex items-start justify-between'>
<div className='flex-1'>
<div className='mb-1 text-xl font-bold text-gray-900'>
₩ 10,000{' '}
<span className='text-sm font-normal text-gray-600'>
/ 총 {participants}인
</span>
</div>
<div
onClick={() => setIsOpen(true)}
className='mb-4 text-sm text-gray-600'
>
{selectedDate && selectedTime ? (
<h2>
{selectedDate instanceof Date
? selectedDate.toLocaleDateString()
: selectedDate}
/{selectedTime}
</h2>
) : (
'날짜 선택하기'
)}
</div>
<BookingModal />
<BookingButton onClick={handleBooking}>예약하기</BookingButton>
</div>
<BookingModal />
<Button variant='primary' className='py-20' onClick={handleBooking}>
예약하기
</Button>
</div>
</div>
</div>
Expand Down
29 changes: 21 additions & 8 deletions src/components/FloatingBox/TabletPopup.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
'use client';

import useBookingStore from '@/stores/Booking/useBookingStore';
import IconClose from '@assets/svg/close';
import DatePicker from '../DatePicker/DatePicker';
import TimeSelector from './TimeSelector';

export default function TabletPopup({}) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

불필요한 빈 객체 패턴을 제거하세요.

정적 분석 도구에서 빈 객체 패턴에 대한 오류가 발생했습니다. props가 필요하지 않다면 매개변수를 제거하세요.

-export default function TabletPopup({}) {
+export default function TabletPopup() {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export default function TabletPopup({}) {
-export default function TabletPopup({}) {
+export default function TabletPopup() {
🧰 Tools
🪛 Biome (1.9.4)

[error] 8-8: Unexpected empty object pattern.

(lint/correctness/noEmptyPattern)

🤖 Prompt for AI Agents
In src/components/FloatingBox/TabletPopup.tsx at line 8, the function
TabletPopup currently has an unnecessary empty object as its parameter. Remove
the empty object parameter entirely since no props are being used, changing the
function signature to have no parameters.

const isOpen = useBookingStore((state) => state.isOpen);
const setIsOpen = useBookingStore((state) => state.setIsOpen);

if (!isOpen) return null;

export default function TabletPopup() {
return (
<div className='flex items-center justify-center'>
<div
className={
'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'
}
>
<DatePicker />
<div className='absolute z-50 flex flex-col items-center justify-center'>
<div className='flex justify-between'>
<h2>날짜</h2>
<button onClick={() => setIsOpen(false)}>
<IconClose />
</button>
</div>

<DatePicker />

<TimeSelector />
</div>
);
}
2 changes: 1 addition & 1 deletion src/components/LocationMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const LocationMap = ({ address }: LocationMapProps) => {

return (
<>
<div className='h-[480px] w-full max-w-[327px] overflow-hidden rounded-lg shadow-md md:max-w-[430px] lg:max-w-[800px]'>
<div className='flex h-[480px] w-full flex-col overflow-hidden rounded-lg shadow-md lg:max-w-[800px]'>
{/* 지도 */}
<Map
center={coords}
Expand Down
Loading
Loading