Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useQuery } from '@tanstack/react-query';
import { privateInstance } from '@/apis/privateInstance';
import ReviewTitle from './ReviewTitle';
import useUserStore from '@/stores/authStore';
import cn from '@/lib/cn';

import ReviewCardSkeleton from './Skeletons/ReviewCardSkeleton';

Expand Down Expand Up @@ -58,11 +59,7 @@ function ReviewSection({
key={review.id}
userName={review.user.nickname}
avatarSrc={review.user.profileImageUrl}
date={new Date(review.createdAt).toLocaleDateString('ko-KR', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
})}
date={review.createdAt.slice(0, 10).replace(/-/g, '.')}
reviewText={review.content}
Comment on lines +62 to 63
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

날짜 포맷팅 방식 견고성 부족

slice(0, 10).replace(/-/g, '.') 는 ISO-8601 형식이 아닐 경우 깨질 수 있습니다.
dayjs, date-fns 등의 라이브러리 사용을 권장합니다.

- date={review.createdAt.slice(0, 10).replace(/-/g, '.')}
+ import dayjs from 'dayjs';
+ ...
+ date={dayjs(review.createdAt).format('YYYY.MM.DD')}
🤖 Prompt for AI Agents
In src/app/(with-header)/activities/[id]/components/ReviewSection.tsx around
lines 62 to 63, the current date formatting uses slice and replace on
review.createdAt, which is fragile if the date is not in ISO-8601 format.
Replace this manual string manipulation with a robust date formatting method by
importing and using a library like dayjs or date-fns to parse and format the
date safely.

/>
));
Expand All @@ -71,7 +68,7 @@ function ReviewSection({
if (isLoading) {
return (
<div className='mt-10 flex flex-col space-y-8'>
<div className='relative min-h-350 flex-col'>
<div className='relative min-h-300 flex-col'>
<ReviewTitle reviewCount={reviewCount} rating={rating} />
{[...Array(3)].map((_, index) => (
<ReviewCardSkeleton key={index} />
Expand All @@ -84,7 +81,7 @@ function ReviewSection({
if (!reviewData || reviewData.reviews.length === 0) {
return (
<div className='mt-10 flex flex-col space-y-8'>
<div className='relative min-h-350'>
<div className='relative min-h-300'>
<ReviewTitle reviewCount={reviewCount} rating={rating} />

<div className='pointer-events-none absolute inset-0 z-10 flex h-full items-center justify-center select-none'>
Expand All @@ -107,8 +104,10 @@ function ReviewSection({
<div className='mt-10 flex flex-col space-y-8'>
<ReviewTitle reviewCount={reviewCount} rating={rating} />

<div className='pointer-events-none relative min-h-350 select-none'>
<div className={user ? '' : 'blur-sm'}>{ReviewComponent()}</div>
<div className='pointer-events-none relative min-h-300 select-none'>
<div className={cn(user ? '' : 'blur-sm', 'mt-10')}>
{ReviewComponent()}
</div>
Comment on lines +107 to +110
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

pointer-events-none 무조건 적용으로 상호작용 차단

pointer-events-none 가 로그인 여부와 무관하게 적용되어 리뷰 영역 내 링크·텍스트 선택이 모두 비활성화됩니다.
로그인한 사용자는 정상적으로 상호작용할 수 있도록 조건부로 적용해 주세요.

- <div className='pointer-events-none relative min-h-300 select-none'>
+ <div
+   className={cn(!user && 'pointer-events-none select-none', 'relative min-h-300')}
+ >
📝 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
<div className='pointer-events-none relative min-h-300 select-none'>
<div className={cn(user ? '' : 'blur-sm', 'mt-10')}>
{ReviewComponent()}
</div>
<div
className={cn(!user && 'pointer-events-none select-none', 'relative min-h-300')}
>
<div className={cn(user ? '' : 'blur-sm', 'mt-10')}>
{ReviewComponent()}
</div>
🤖 Prompt for AI Agents
In src/app/(with-header)/activities/[id]/components/ReviewSection.tsx around
lines 107 to 110, the class 'pointer-events-none' is applied unconditionally,
blocking all interactions in the review area regardless of login status. Modify
the code to apply 'pointer-events-none' only when the user is not logged in,
allowing logged-in users to interact normally with links and text selection.


{!user && (
<div className='pointer-events-none absolute inset-0 z-10 flex h-full items-center justify-center select-none'>
Expand Down
23 changes: 21 additions & 2 deletions src/app/(with-header)/myactivity/[id]/hooks/useEditActivityForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,29 @@ export const useEditActivityForm = () => {
}

const newSchedules = dates.filter((d) => !d.id);

const scheduleIdsToRemove = originalSchedules
.filter((orig) => !dates.some((d) => d.id === orig.id))
.map((d) => d.id)
.filter((id): id is number => id !== undefined);
.map((d) => d.id!)
.filter(Boolean);
Comment on lines +147 to +148
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

타입 안전성 개선 제안

d.id!의 non-null assertion 사용은 런타임 에러 위험이 있습니다. 더 안전한 타입 가드를 사용하는 것을 권장합니다.

다음과 같이 수정하세요:

-        .map((d) => d.id!)
-        .filter(Boolean);
+        .map((d) => d.id)
+        .filter((id): id is number => id !== undefined);
📝 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
.map((d) => d.id!)
.filter(Boolean);
.map((d) => d.id)
.filter((id): id is number => id !== undefined);
🤖 Prompt for AI Agents
In src/app/(with-header)/myactivity/[id]/hooks/useEditActivityForm.ts at lines
147-148, the use of non-null assertion `d.id!` can cause runtime errors if `id`
is null or undefined. Replace the non-null assertion with a type-safe guard by
filtering out items where `d.id` is falsy before mapping, or use a conditional
check within the map to ensure only defined `id`s are processed. This will
improve type safety and prevent potential runtime exceptions.


originalSchedules.forEach((orig) => {
const matched = dates.find((d) => d.id === orig.id);
if (
matched &&
(matched.date !== orig.date ||
matched.startTime !== orig.startTime ||
matched.endTime !== orig.endTime)
) {
newSchedules.push({
date: matched.date,
startTime: matched.startTime,
endTime: matched.endTime,
});

scheduleIdsToRemove.push(orig.id!);
}
});

const parsedPrice = parseInt(price, 10);
if (isNaN(parsedPrice) || parsedPrice <= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function InfoSection({
placeholder='제목'
className='w-full'
value={title}
maxLength={20}
onChange={(e) => onTitleChange(e.target.value)}
Comment on lines +42 to 43
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

글자 수 제한 UX 보완 제안

maxLength={20} 설정으로 입력이 조용히 차단됩니다.
남은 글자 수 표시(예: “12/20”) 또는 경고 메시지를 추가하면 사용자 경험이 향상됩니다. 또한 백엔드에서도 동일한 제한이 적용되는지 확인해 주세요.


글자 수 제한 UX 보완 필요

InfoSection.tsx (src/app/(with-header)/myactivity/components/InfoSection.tsx) 42–43행에서

  maxLength={20}
  onChange={(e) => onTitleChange(e.target.value)}

현재 입력이 20자를 넘으면 조용히 막히기만 하므로, 아래를 검토해 주세요:

  • 남은 글자 수 표시 추가 (예: “12/20”)
  • 초과 입력 시 경고 또는 비활성화 상태 안내
  • 백엔드에서도 동일한 20자 제한이 정상적으로 적용되는지 확인
🤖 Prompt for AI Agents
In src/app/(with-header)/myactivity/components/InfoSection.tsx around lines
42-43, the input field limits text to 20 characters silently without user
feedback. Enhance the UX by adding a visible character count display (e.g.,
"12/20") near the input, provide a warning or disable further input when the
limit is exceeded, and verify that the backend enforces the same 20-character
limit to maintain consistency.

/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default function Button({
)}
{...props}
>
{isLoading ? <span className='animate-pulse'>로딩중...</span> : children}
{isLoading ? <span className='animate-pulse'>...</span> : children}
</button>
Comment on lines +48 to 49
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

로딩 텍스트 접근성 개선 필요

'...' 만으로는 스크린리더가 의미 있는 읽기를 하지 못합니다.
aria-label 또는 visually-hidden span 으로 “로딩 중” 과 같은 문구를 추가하여 접근성을 보완해 주세요.

- {isLoading ? <span className='animate-pulse'>...</span> : children}
+ {isLoading ? (
+   <span
+     className='animate-pulse'
+     aria-label='로딩 중'
+     role='status'
+   >
+     ...
+     <span className='sr-only'>로딩 중</span>
+   </span>
+ ) : (
+   children
+ )}
📝 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
{isLoading ? <span className='animate-pulse'>...</span> : children}
</button>
{isLoading ? (
<span
className='animate-pulse'
aria-label='로딩 중'
role='status'
>
...
<span className='sr-only'>로딩 중</span>
</span>
) : (
children
)}
</button>
🤖 Prompt for AI Agents
In src/components/Button.tsx around lines 48 to 49, the loading indicator
currently uses only '...' which is not accessible for screen readers. To improve
accessibility, add an aria-label with a descriptive text like "Loading" to the
span or include a visually hidden span containing the text "로딩 중" alongside the
dots. This will ensure screen readers convey meaningful information during
loading states.

);
}
2 changes: 1 addition & 1 deletion src/components/FloatingBox/BookingButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default function BookingButton({
{onBooking ? (
<div className='flex items-center justify-center gap-2'>
<span className='h-10 w-10 animate-spin rounded-full border-2 border-white border-t-transparent' />
<p>...</p>
<p>요청전송중...</p>
</div>
Comment on lines 31 to 35
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

로딩 문구 일관성 유지 검토

요청전송중...Button 컴포넌트의 '...' 가 불일치합니다.
사용자에게 동일한 로딩 경험을 제공하기 위해 메시지·스타일을 공통 util 로 추출하거나 최소한 문구를 통일하는 방안을 고려해 주세요.

🤖 Prompt for AI Agents
In src/components/FloatingBox/BookingButton.tsx around lines 31 to 35, the
loading text "요청전송중..." inside the div is inconsistent with the ellipsis style
used in the Button component. To fix this, unify the loading message and style
by either extracting the loading text and animation into a shared utility or
constant used by both places, or at minimum, make sure the ellipsis and wording
match exactly to provide a consistent user experience.

) : (
children
Expand Down