Skip to content

[캠퍼스] 콜밴팟 로깅 추가 및 버그 수정#1211

Merged
dooohun merged 4 commits intodevelopfrom
feat/1183/callvan-logging
Mar 17, 2026
Merged

[캠퍼스] 콜밴팟 로깅 추가 및 버그 수정#1211
dooohun merged 4 commits intodevelopfrom
feat/1183/callvan-logging

Conversation

@dooohun
Copy link
Contributor

@dooohun dooohun commented Mar 17, 2026

What is this PR? 🔍

Changes 📝

  • 콜밴팟 로깅 추가
  • 콜밴팟 UI 에러 해결
    • 잘못된 svg 수정

Precaution

N/A

✔️ Please check if the PR fulfills these requirements

  • It's submitted to the correct branch, not the develop branch unconditionally?
  • If on a hotfix branch, ensure it targets main?
  • There are no warning message when you run yarn lint

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 전화하기 버튼 클릭 시 쇼핑 카테고리 페이지로 이동 기능 추가
    • 글 작성, 시간 선택, 필터 적용, 검색, 채팅 등 주요 상호작용에 대한 분석(로그) 추적 추가
  • 스타일

    • 채팅방 이미지 버튼 스타일 개선 (32px, 둥근 모서리)
    • 검색 입력 필드의 포커스 스타일 제거
  • 버그 수정

    • 접근성 레이블 관련 문제 수정

@dooohun dooohun self-assigned this Mar 17, 2026
@dooohun dooohun added the 📊DA 데이터 분석 label Mar 17, 2026
@github-actions github-actions bot requested review from ff1451 and hyejun0228 March 17, 2026 12:03
@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 693a8955-cb6e-4e7e-8a44-01c22bca85b0

📥 Commits

Reviewing files that changed from the base of the PR and between 431a8d6 and f49f791.

📒 Files selected for processing (1)
  • src/components/Callvan/components/CallvanPageLayout/index.tsx

Walkthrough

Callvan UI 전반에 useLogger 기반 분석 로깅을 추가합니다. 양식 제출, 필터 적용, 검색, 채팅, 통화 및 네비게이션 관련 사용자 상호작용에서 이벤트를 전송하며 일부 스타일 및 라우팅 키가 조정됩니다.

Changes

Cohort / File(s) Summary
양식/시간/위치 로깅
src/components/Callvan/components/AddPostForm/index.tsx, src/components/Callvan/components/TimeDropdown/index.tsx, src/components/Callvan/components/LocationBottomSheet/index.tsx
useLogger 도입 및 제출/시간확정/위치확인 시 분석 이벤트 전송; AddPostForm의 handleSubmit을 useCallback → 일반 함수로 변경.
카드·목록 상호작용 로그 및 네비게이션
src/components/Callvan/components/CallvanCard/index.tsx, src/components/Callvan/components/ParticipantsList/index.tsx
참여/취소/채팅/통화 클릭에 로그 추가, CALLVAN 카테고리용 ORDER_BASE_URL 사용해 통화 클릭 시 네비게이션 추가; 일부 aria-label 변경 포인트 존재.
채팅·레이아웃·필터 로그
src/components/Callvan/components/CallvanChatRoom/index.tsx, src/components/Callvan/components/CallvanFilterPanel/index.tsx, src/components/Callvan/components/CallvanPageLayout/index.tsx
메시지 전송, 필터 적용, 검색 클릭, 뒤로가기 및 모집하기 액션에 로깅 추가(로그 훅 인스턴스화 및 actionEventClick 호출).
스타일 조정
src/components/Callvan/components/CallvanChatRoom/CallvanChatRoom.module.scss, src/components/Callvan/components/CallvanPageLayout/CallvanPageLayout.module.scss
채팅룸의 이미지 버튼 크기/배경 조정 및 검색 필드의 focus-visible 스타일 제거.
인덱스 링크 키 변경
src/components/IndexComponents/IndexCallvan/index.tsx
CALLVAN_LINKS 키값 변경: findview, createwrite 및 클릭 이벤트의 event_label 값 일부 조정.

Sequence Diagram(s)

sequenceDiagram
  participant User as User
  participant UI as AddPostForm
  participant Logger as AnalyticsLogger
  participant Router as Router

  User->>UI: 작성 후 제출 클릭
  UI->>Logger: logger.actionEventClick(callvan_write_done...)
  UI->>Router: navigate to target (e.g., list)
  Router-->>User: 화면 전환
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Suggested labels

✨ Feature

Suggested reviewers

  • ff1451
  • JeongWon-CHO
  • ParkSungju01
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: adding logging to Callvan components and fixing UI/SVG bugs.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/1183/callvan-logging
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@ff1451 ff1451 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/components/Callvan/components/AddPostForm/index.tsx (1)

80-103: ⚠️ Potential issue | 🟠 Major

성공/실패 분기 없이 로깅되어 분석 지표가 왜곡됩니다

Line 102의 logger.actionEventClick() 호출이 mutate() 외부(직후)에 위치하여, API 요청 실패 시에도 callvan_write_done 이벤트가 기록됩니다. 성공/실패를 구분하지 않고 항상 로그가 전송되므로 분석 데이터의 신뢰성이 떨어집니다.

수정 제안
   mutate(
     {
       departure_type: form.departureType,
       departure_custom_name: form.departureType === 'CUSTOM' ? form.departureCustomName : null,
       arrival_type: form.arrivalType,
       arrival_custom_name: form.arrivalType === 'CUSTOM' ? form.arrivalCustomName : null,
       departure_date: formatDateParam(form.departureDate),
       departure_time: departureTime,
       max_participants: form.maxParticipants,
     },
     {
       onSuccess: () => {
         openToast('작성되었습니다.');
+        logger.actionEventClick({ event_label: 'callvan_write_done', team: 'CAMPUS', value: '' });
         router.replace({ pathname: ROUTES.Callvan(), query: { created: '1' } });
       },
+      onError: () => {
+        logger.actionEventClick({ event_label: 'callvan_write_fail', team: 'CAMPUS', value: '' });
+      },
     },
   );
-  logger.actionEventClick({ event_label: 'callvan_write_done', team: 'CAMPUS', value: '' });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Callvan/components/AddPostForm/index.tsx` around lines 80 -
103, The logger.actionEventClick call for 'callvan_write_done' is executed
immediately after mutate(), so failures still record a success event; move this
logging into the mutate onSuccess callback (inside the existing onSuccess in
handleSubmit) so it only fires on successful API response, and optionally add a
logger.actionEventClick or logger.actionEventError call in the mutate onError
callback to record failures; update references in handleSubmit, mutate, and the
onSuccess/onError callbacks accordingly.
src/components/Callvan/components/CallvanChatRoom/index.tsx (1)

78-94: ⚠️ Potential issue | 🟡 Minor

로깅 호출 위치가 적절하지 않습니다.

logger.actionEventClicksendMessageonSuccess 콜백 외부에서 호출되고 있습니다. 이렇게 되면 메시지 전송이 실패하더라도 로그가 기록되어 분석 데이터의 정확성이 떨어질 수 있습니다.

🔧 제안하는 수정 사항
  sendMessage(
    { is_image: false, content },
    {
      onSuccess: () => {
        setInputValue('');
        if (textareaRef.current) {
          textareaRef.current.style.height = 'auto';
        }
+       logger.actionEventClick({ event_label: 'callvan_chat_send', team: 'CAMPUS', value: '' });
      },
    },
  );
-  logger.actionEventClick({ event_label: 'callvan_chat_send', team: 'CAMPUS', value: '' });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Callvan/components/CallvanChatRoom/index.tsx` around lines 78
- 94, The logger.actionEventClick call is currently outside sendMessage's
onSuccess so it logs even on failures; move the logger.actionEventClick
invocation inside the onSuccess callback of sendMessage (in the same block that
calls setInputValue('') and resets textareaRef.style.height) so the event is
recorded only after a successful send; keep the existing payload ({ event_label:
'callvan_chat_send', team: 'CAMPUS', value: '' }) and placement order (reset
input then log) in the handleSend function.
🧹 Nitpick comments (7)
src/components/Callvan/components/CallvanChatRoom/CallvanChatRoom.module.scss (2)

298-311: 키보드 포커스 스타일을 명시해 접근성을 보강해주세요.

현재 버튼은 포커스 상태를 커스텀하지 않아 브라우저 기본 스타일에 의존합니다. :focus-visible을 명시하면 키보드 사용자에게 더 일관된 포커스 피드백을 줄 수 있습니다.

예시 diff
   &__image-button {
     display: flex;
     align-items: center;
     justify-content: center;
     width: 32px;
     height: 32px;
     background: none;
     border: none;
     border-radius: 12px;
     cursor: pointer;
     padding: 0;
     background-color: `#fff`;
     flex-shrink: 0;
+
+    &:focus-visible {
+      outline: 2px solid `#980ac9`;
+      outline-offset: 2px;
+    }
   }

As per coding guidelines src/components/**: 4. 접근성(a11y) 관련 속성이 적절히 사용되고 있는지 확인해주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/components/Callvan/components/CallvanChatRoom/CallvanChatRoom.module.scss`
around lines 298 - 311, The .__image-button currently relies on browser default
focus styles; add explicit keyboard focus styles using the :focus-visible
pseudo-class on the &__image-button selector (and optionally a subtle :focus
fallback) to provide consistent visible focus for keyboard users—e.g., set a
visible outline or box-shadow color with outline-offset and preserve
border-radius, ensure high contrast (meets contrast requirements), and avoid
removing focus for mouse users by targeting :focus-visible rather than :focus.

304-309: 배경 속성 선언을 하나로 정리해 가독성을 높여주세요.

Line [304]의 background: none;은 Line [309]의 background-color: #fff;로 바로 덮여 실질 효과가 없습니다. 하나로 정리하면 의도가 더 명확해집니다.

예시 diff
-    background: none;
+    background-color: `#fff`;
     border: none;
     border-radius: 12px;
     cursor: pointer;
     padding: 0;
-    background-color: `#fff`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/components/Callvan/components/CallvanChatRoom/CallvanChatRoom.module.scss`
around lines 304 - 309, 현재 스타일블록에 background: none; 와 background-color: `#fff`; 가
중복되어 의도가 불명확하므로 background 선언을 하나로 정리하세요 — CallvanChatRoom.module.scss에서
background: none; 을 제거하고 background-color: `#fff`; 만 남기거나, 의도대로라면 background:
`#fff`; 같은 단일 background 속성으로 통합하여 가독성과 명확성을 확보하세요 (참조: 기존 background: none; 및
background-color: `#fff`;).
src/components/IndexComponents/IndexCallvan/index.tsx (1)

36-36: Line 36 인라인 핸들러/객체 생성은 분리하는 편이 좋습니다.

렌더마다 함수와 payload 객체가 새로 만들어집니다. 현재는 영향이 작지만, 카드 수가 늘면 추적/최적화가 어려워질 수 있습니다.
장점: 렌더 안정성/테스트 용이성 향상, 단점: 코드가 약간 늘어남.

♻️ 제안 코드
+import { useMemo } from 'react';
 import Link from 'next/link';
 import ChevronRight from 'assets/svg/IndexPage/Bus/chevron-right.svg';
 import ROUTES from 'static/routes';
 import useLogger from 'utils/hooks/analytics/useLogger';
 import styles from './IndexCallvan.module.scss';
@@
 function IndexCallvan() {
   const logger = useLogger();
+  const linksWithHandler = useMemo(
+    () =>
+      CALLVAN_LINKS.map((item) => ({
+        ...item,
+        onClick: () =>
+          logger.actionEventClick({
+            team: 'CAMPUS',
+            event_label: `main_callvan_${item.key}`,
+            value: '',
+          }),
+      })),
+    [logger],
+  );
 
   return (
@@
-        {CALLVAN_LINKS.map(({ key, title, subtitle, link }) => (
+        {linksWithHandler.map(({ key, title, subtitle, link, onClick }) => (
           <Link
             href={link}
             key={key}
             className={styles.card}
-            onClick={() => logger.actionEventClick({ team: 'CAMPUS', event_label: `main_callvan_${key}`, value: '' })}
+            onClick={onClick}
           >

As per coding guidelines, src/components/**: "3. 불필요한 리렌더링을 유발하는 패턴(인라인 함수, 객체 리터럴 등)이 있는지 확인해주세요."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/IndexComponents/IndexCallvan/index.tsx` at line 36, Extract
the inline onClick payload into a stable handler: create a memoized factory like
getCallvanClick using useCallback (e.g., const getCallvanClick =
useCallback((itemKey) => () => logger.actionEventClick({ team: 'CAMPUS',
event_label: `main_callvan_${itemKey}`, value: '' }), [logger]) ) and replace
the inline onClick with onClick={getCallvanClick(key)} so the
logger.actionEventClick payload creation is no longer done inline on each
render.
src/components/Callvan/components/LocationBottomSheet/index.tsx (1)

52-56: title 문자열 비교로 event_label을 결정하는 방식은 취약합니다.

title prop의 문자열 값에 의존하여 이벤트 레이블을 결정하면, 추후 title 텍스트가 변경되거나 다국어 지원 시 로깅이 깨질 수 있습니다. 또한 템플릿 리터럴 내 불필요한 백틱이 있습니다.

♻️ Props로 eventLabel을 전달하거나 타입으로 구분하는 방식 제안
 interface LocationBottomSheetProps {
   isOpen: boolean;
   title: string;
+  locationType: 'departure' | 'arrival';
   initialType: CallvanPostLocationType | null;
   initialCustomName: string;
   onClose: () => void;
   onConfirm: (type: CallvanPostLocationType, customName: string) => void;
 }
-    logger.actionEventClick({
-      event_label: `${title === '출발지가 어디인가요?' ? 'callvan_write_departure' : 'callvan_write_arrival'}`,
-      team: 'CAMPUS',
-      value: selectedType,
-    });
+    logger.actionEventClick({
+      event_label: locationType === 'departure' ? 'callvan_write_departure' : 'callvan_write_arrival',
+      team: 'CAMPUS',
+      value: selectedType,
+    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Callvan/components/LocationBottomSheet/index.tsx` around lines
52 - 56, The event_label decision using the title string is fragile; update the
component to accept an explicit prop (e.g., eventLabel) or a typed discriminator
(e.g., sheetType or locationType) and use that instead of comparing title, then
call logger.actionEventClick with a plain string (remove the unnecessary
template literal/backticks) for event_label and pass selectedType unchanged;
locate the logger.actionEventClick call and replace its event_label expression
to use the new prop (or switch on the typed discriminator) so labels remain
stable across text changes and i18n.
src/components/Callvan/components/CallvanCard/index.tsx (1)

89-89: 로깅 value에 버튼 레이블 대신 의미 있는 값을 사용하세요.

value: '예, 아니요'는 모달의 버튼 레이블이지 사용자 행동의 의미 있는 값이 아닙니다. 분석 목적으로는 post.id나 참여자 수 같은 컨텍스트 정보가 더 유용할 수 있습니다.

♻️ 의미 있는 value 사용 제안
- logger.actionEventClick({ event_label: 'callvan_join', team: 'CAMPUS', value: '예, 아니요' });
+ logger.actionEventClick({ event_label: 'callvan_join', team: 'CAMPUS', value: String(post.id) });

Also applies to: 95-95

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Callvan/components/CallvanCard/index.tsx` at line 89, The call
to logger.actionEventClick currently sends the UI button labels as value
(logger.actionEventClick({ event_label: 'callvan_join', team: 'CAMPUS', value:
'예, 아니요' })), so change both occurrences of logger.actionEventClick in this
component to send meaningful context (e.g., post.id, participantCount, or a
boolean like joined: true/false) instead of the button text; locate the calls to
logger.actionEventClick inside CallvanCard (the join modal confirm/cancel
handlers) and replace value with a descriptive field such as value: post.id or
value: `${post.id}:${participantCount}` or add a separate property like
metadata: { postId: post.id, participantCount } to preserve richer analytics
context.
src/components/Callvan/components/TimeDropdown/index.tsx (1)

214-218: 로깅 시 시간 값 포맷이 일관성 없습니다.

value에 기록되는 시간 포맷이 ${tempHour}:${tempMinute}로 되어 있어 "9:05"와 같이 시(hour)가 패딩되지 않습니다. Line 181-183의 formatTriggerTime 함수를 재사용하면 "09:05"와 같이 일관된 포맷을 유지할 수 있습니다.

♻️ formatTriggerTime 재사용 제안
  const handleConfirm = () => {
    onChange({ hour: tempHour, minute: tempMinute, isPM: tempIsPM });
-   logger.actionEventClick({ event_label: 'callvan_write_time', team: 'CAMPUS', value: `${tempHour}:${tempMinute}` });
+   logger.actionEventClick({ event_label: 'callvan_write_time', team: 'CAMPUS', value: formatTriggerTime(tempHour, tempMinute) });
    close();
  };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Callvan/components/TimeDropdown/index.tsx` around lines 214 -
218, The logger in handleConfirm uses `${tempHour}:${tempMinute}` which yields
inconsistent padding; replace that inline format with the existing
formatTriggerTime(...) helper to produce a consistent "HH:MM" string when
calling logger.actionEventClick. Update the call in handleConfirm (where
onChange, logger.actionEventClick and close are invoked) to compute the
formatted time via formatTriggerTime(tempHour, tempMinute, tempIsPM) and pass
that result as the value argument.
src/components/Callvan/components/CallvanPageLayout/index.tsx (1)

110-110: 검색 인풋 클릭 시마다 로깅이 발생합니다.

onClick에서 로깅하면 사용자가 인풋을 클릭할 때마다 이벤트가 기록됩니다. 검색 의도를 추적하려면 실제 검색 실행 시(handleSearch) 로깅하는 것이 더 정확한 분석 데이터를 제공할 수 있습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Callvan/components/CallvanPageLayout/index.tsx` at line 110,
The click handler currently logs every input click; move the logging into the
actual search execution (handleSearch) so only real searches are recorded:
remove the logger.actionEventClick call from the onClick prop and add a
logger.actionEventClick invocation inside handleSearch (use the same payload
keys: event_label: 'callvan_search', team: 'CAMPUS' and set value to the search
term or '' if empty). Ensure handleSearch is the single place that logs searches
(including submissions or programmatic triggers) so duplicate logs from onClick
are eliminated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/Callvan/components/CallvanCard/index.tsx`:
- Around line 113-116: The phone button currently rendered with <button
className={styles.card__phone} onClick={handleCallClick}> lacks accessibility
attributes; update the CallvanCard button (the element using styles.card__phone,
onClick handler handleCallClick, and child PhoneCallingIcon) to include
type="button" to prevent implicit form submission and add an appropriate
aria-label (e.g., aria-label="Call" or a localized string) so screen readers
convey the button's purpose.
- Line 224: In CallvanCard (component CallvanCard in index.tsx) remove the empty
aria-label="" on the button used for "참여취소" or replace it with an appropriate
label (e.g., aria-label="참여취소") so screen readers can announce the button
purpose; locate the button element in CallvanCard that currently has
aria-label="" and either delete that attribute (since visible text exists) or
set a meaningful value.
- Line 27: In the CallvanCard component, update the empty aria-label on the
cancel button to match its visible text (set aria-label="참여취소") so accessibility
labels are consistent with other buttons (e.g., the chat button and 참여하기
button); also remove the magic literal in CALLVAN_CATEGORY (currently '11') by
extracting it to a well-named constant or config entry (e.g.,
DEFAULT_CALLVAN_CATEGORY or from a settings/shopCategories source) in the same
module or a central constants/config file, add a brief comment explaining why
that specific category ID is required, and if feasible replace the hardcoded ID
with the dynamic lookup from shop_categories API used elsewhere.

In `@src/components/Callvan/components/CallvanPageLayout/index.tsx`:
- Around line 43-46: The event_label construction in handleBack currently uses
&& which produces unwanted strings like "false false"; update handleBack (the
logger.actionEventClick call) to compute a proper label before logging—e.g.,
determine label via a conditional/ternary or a small helper (check
router.pathname against ROUTES.Callvan() and ROUTES.CallvanAdd()) and pass
either "callvan_back", "callvan_write_back", or an empty string (not boolean
values) to event_label so the log receives a single correct string.

---

Outside diff comments:
In `@src/components/Callvan/components/AddPostForm/index.tsx`:
- Around line 80-103: The logger.actionEventClick call for 'callvan_write_done'
is executed immediately after mutate(), so failures still record a success
event; move this logging into the mutate onSuccess callback (inside the existing
onSuccess in handleSubmit) so it only fires on successful API response, and
optionally add a logger.actionEventClick or logger.actionEventError call in the
mutate onError callback to record failures; update references in handleSubmit,
mutate, and the onSuccess/onError callbacks accordingly.

In `@src/components/Callvan/components/CallvanChatRoom/index.tsx`:
- Around line 78-94: The logger.actionEventClick call is currently outside
sendMessage's onSuccess so it logs even on failures; move the
logger.actionEventClick invocation inside the onSuccess callback of sendMessage
(in the same block that calls setInputValue('') and resets
textareaRef.style.height) so the event is recorded only after a successful send;
keep the existing payload ({ event_label: 'callvan_chat_send', team: 'CAMPUS',
value: '' }) and placement order (reset input then log) in the handleSend
function.

---

Nitpick comments:
In `@src/components/Callvan/components/CallvanCard/index.tsx`:
- Line 89: The call to logger.actionEventClick currently sends the UI button
labels as value (logger.actionEventClick({ event_label: 'callvan_join', team:
'CAMPUS', value: '예, 아니요' })), so change both occurrences of
logger.actionEventClick in this component to send meaningful context (e.g.,
post.id, participantCount, or a boolean like joined: true/false) instead of the
button text; locate the calls to logger.actionEventClick inside CallvanCard (the
join modal confirm/cancel handlers) and replace value with a descriptive field
such as value: post.id or value: `${post.id}:${participantCount}` or add a
separate property like metadata: { postId: post.id, participantCount } to
preserve richer analytics context.

In
`@src/components/Callvan/components/CallvanChatRoom/CallvanChatRoom.module.scss`:
- Around line 298-311: The .__image-button currently relies on browser default
focus styles; add explicit keyboard focus styles using the :focus-visible
pseudo-class on the &__image-button selector (and optionally a subtle :focus
fallback) to provide consistent visible focus for keyboard users—e.g., set a
visible outline or box-shadow color with outline-offset and preserve
border-radius, ensure high contrast (meets contrast requirements), and avoid
removing focus for mouse users by targeting :focus-visible rather than :focus.
- Around line 304-309: 현재 스타일블록에 background: none; 와 background-color: `#fff`; 가
중복되어 의도가 불명확하므로 background 선언을 하나로 정리하세요 — CallvanChatRoom.module.scss에서
background: none; 을 제거하고 background-color: `#fff`; 만 남기거나, 의도대로라면 background:
`#fff`; 같은 단일 background 속성으로 통합하여 가독성과 명확성을 확보하세요 (참조: 기존 background: none; 및
background-color: `#fff`;).

In `@src/components/Callvan/components/CallvanPageLayout/index.tsx`:
- Line 110: The click handler currently logs every input click; move the logging
into the actual search execution (handleSearch) so only real searches are
recorded: remove the logger.actionEventClick call from the onClick prop and add
a logger.actionEventClick invocation inside handleSearch (use the same payload
keys: event_label: 'callvan_search', team: 'CAMPUS' and set value to the search
term or '' if empty). Ensure handleSearch is the single place that logs searches
(including submissions or programmatic triggers) so duplicate logs from onClick
are eliminated.

In `@src/components/Callvan/components/LocationBottomSheet/index.tsx`:
- Around line 52-56: The event_label decision using the title string is fragile;
update the component to accept an explicit prop (e.g., eventLabel) or a typed
discriminator (e.g., sheetType or locationType) and use that instead of
comparing title, then call logger.actionEventClick with a plain string (remove
the unnecessary template literal/backticks) for event_label and pass
selectedType unchanged; locate the logger.actionEventClick call and replace its
event_label expression to use the new prop (or switch on the typed
discriminator) so labels remain stable across text changes and i18n.

In `@src/components/Callvan/components/TimeDropdown/index.tsx`:
- Around line 214-218: The logger in handleConfirm uses
`${tempHour}:${tempMinute}` which yields inconsistent padding; replace that
inline format with the existing formatTriggerTime(...) helper to produce a
consistent "HH:MM" string when calling logger.actionEventClick. Update the call
in handleConfirm (where onChange, logger.actionEventClick and close are invoked)
to compute the formatted time via formatTriggerTime(tempHour, tempMinute,
tempIsPM) and pass that result as the value argument.

In `@src/components/IndexComponents/IndexCallvan/index.tsx`:
- Line 36: Extract the inline onClick payload into a stable handler: create a
memoized factory like getCallvanClick using useCallback (e.g., const
getCallvanClick = useCallback((itemKey) => () => logger.actionEventClick({ team:
'CAMPUS', event_label: `main_callvan_${itemKey}`, value: '' }), [logger]) ) and
replace the inline onClick with onClick={getCallvanClick(key)} so the
logger.actionEventClick payload creation is no longer done inline on each
render.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9fb0f42e-5153-4009-ae75-2e888717daff

📥 Commits

Reviewing files that changed from the base of the PR and between 47d8f4a and 431a8d6.

⛔ Files ignored due to path filters (1)
  • src/assets/svg/Callvan/image-upload.svg is excluded by !**/*.svg and included by **
📒 Files selected for processing (11)
  • src/components/Callvan/components/AddPostForm/index.tsx
  • src/components/Callvan/components/CallvanCard/index.tsx
  • src/components/Callvan/components/CallvanChatRoom/CallvanChatRoom.module.scss
  • src/components/Callvan/components/CallvanChatRoom/index.tsx
  • src/components/Callvan/components/CallvanFilterPanel/index.tsx
  • src/components/Callvan/components/CallvanPageLayout/CallvanPageLayout.module.scss
  • src/components/Callvan/components/CallvanPageLayout/index.tsx
  • src/components/Callvan/components/LocationBottomSheet/index.tsx
  • src/components/Callvan/components/ParticipantsList/index.tsx
  • src/components/Callvan/components/TimeDropdown/index.tsx
  • src/components/IndexComponents/IndexCallvan/index.tsx
💤 Files with no reviewable changes (1)
  • src/components/Callvan/components/CallvanPageLayout/CallvanPageLayout.module.scss

import { redirectToLogin } from 'utils/ts/auth';
import styles from './CallvanCard.module.scss';

const CALLVAN_CATEGORY = '11';
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Search for category ID usage and definition in the codebase

# Find where category IDs are defined or used
rg -n "category.*11|CALLVAN.*CATEGORY" --type=ts --type=tsx -g '!node_modules'

# Check API entity files for category definitions
fd -e ts -e tsx entity | xargs rg -l "category" | head -10

Repository: BCSDLab/KOIN_WEB_RECODE

Length of output: 185


🏁 Script executed:

#!/bin/bash
# First, let's look at the CallvanCard component to see how CALLVAN_CATEGORY is used
echo "=== CallvanCard component usage of CALLVAN_CATEGORY ==="
rg -n "CALLVAN_CATEGORY" src/components/Callvan/components/CallvanCard/ -A 3 -B 3

echo -e "\n=== Checking entity files for category structure ==="
cat src/api/store/entity.ts | head -100

echo -e "\n=== Search for other category ID definitions/constants ==="
rg -n "const.*CATEGORY.*=.*['\"]" src/ --type=ts --type=tsx | head -20

echo -e "\n=== How shop_categories is used (from IndexStore) ==="
rg -n "shop_categories" src/components/IndexComponents/IndexStore/ -B 2 -A 2

Repository: BCSDLab/KOIN_WEB_RECODE

Length of output: 4608


🏁 Script executed:

#!/bin/bash
# Search for category definitions, enums, or mappings
echo "=== Search for category definitions or enums ==="
rg -n "category" src/api/ -B 1 -A 1 | grep -i "interface\|type\|enum\|export" | head -30

echo -e "\n=== Search for Callvan API or data fetching ==="
rg -n "Callvan\|callvan" src/api/ src/hooks/ -l

echo -e "\n=== Check if there's a types or constants file with category mappings ==="
fd -e ts -e tsx -e js -path "*/types/*" -o -path "*/constants/*" | xargs grep -l "category\|CATEGORY" 2>/dev/null | head -10

echo -e "\n=== Look at the entire CallvanCard file to understand context ==="
wc -l src/components/Callvan/components/CallvanCard/index.tsx

Repository: BCSDLab/KOIN_WEB_RECODE

Length of output: 998


🏁 Script executed:

#!/bin/bash
# Read the CallvanCard component
echo "=== CallvanCard component ==="
cat -n src/components/Callvan/components/CallvanCard/index.tsx | head -150

echo -e "\n=== Search for CallvanPost type/interface ==="
rg -n "interface CallvanPost|type CallvanPost" src/

echo -e "\n=== Search for where CallvanCard is used ==="
rg -n "CallvanCard" src/ -B 1 -A 1 | head -30

echo -e "\n=== Search for Callvan data/hooks ==="
rg -n "useCallvan|callvan" src/hooks/ src/api/ 2>/dev/null

Repository: BCSDLab/KOIN_WEB_RECODE

Length of output: 9528


🏁 Script executed:

#!/bin/bash
# Check if there's a config or constants file for category mappings
echo "=== Search for category IDs or shop categories elsewhere ==="
rg -n "category.*11|shop.*category|CATEGORY.*=" src/static/ src/config/ 2>/dev/null | head -20

echo -e "\n=== Check CallvanPost entity to see if it has category info ==="
cat src/api/callvan/entity.ts | head -100

echo -e "\n=== Check if ORDER_BASE_URL uses category for filtering ==="
rg -n "ORDER_BASE_URL\|category" src/static/url.ts

echo -e "\n=== Search for any documentation about category 11 ==="
rg -n "11.*callvan\|callvan.*11\|food.*delivery\|음식" src/ --type=ts -i | head -20

Repository: BCSDLab/KOIN_WEB_RECODE

Length of output: 2948


🏁 Script executed:

#!/bin/bash
# Check the category.ts file for category ID 11
echo "=== Full CATEGORY constant from static/category.ts ==="
cat src/static/category.ts

echo -e "\n=== Search for category 11 specifically ==="
rg -n "^.*11.*$" src/static/category.ts -A 2 -B 2

echo -e "\n=== Check filterOptions for more context ==="
cat src/static/filterOptions.ts | head -50

Repository: BCSDLab/KOIN_WEB_RECODE

Length of output: 3965


🏁 Script executed:

#!/bin/bash
# Check what ORDER_BASE_URL is
echo "=== ORDER_BASE_URL definition ==="
rg -n "ORDER_BASE_URL" src/static/ -B 2 -A 2

echo -e "\n=== Search for any category ID definitions or comments ==="
rg -n "category.*id|shop.*category" src/api/store/ -i | head -20

echo -e "\n=== Check if there are any other hardcoded category IDs elsewhere ==="
rg -n "category.*=" src/ -i | grep -E "'[0-9]+'" | head -20

echo -e "\n=== Search for documentation or README about shop categories ==="
find src -name "README*" -o -name "*.md" | xargs grep -l "category\|shop" 2>/dev/null

Repository: BCSDLab/KOIN_WEB_RECODE

Length of output: 823


🏁 Script executed:

#!/bin/bash
# Let's check if we can find what category 11 represents in the shop data
echo "=== Search for StoreCategory interface to understand the structure ==="
rg -n "interface StoreCategory|type StoreCategory" src/api/store/entity.ts -A 5

echo -e "\n=== Check if there are API calls that fetch categories ==="
rg -n "shop_categories\|StoreCategory" src/api/store/ -B 2 -A 2

echo -e "\n=== Search for any test files or mock data with category IDs ==="
find src -name "*.mock.ts" -o -name "*.test.ts" -o -name "*.spec.ts" | xargs grep -l "category" 2>/dev/null | head -5

echo -e "\n=== Check comment or commit history context around CALLVAN_CATEGORY ==="
git log -p --all -S "CALLVAN_CATEGORY" -- src/components/Callvan/components/CallvanCard/index.tsx 2>/dev/null | head -50

Repository: BCSDLab/KOIN_WEB_RECODE

Length of output: 447


🏁 Script executed:

#!/bin/bash
# Check the full CallvanCard file for aria-label issues around line 224
echo "=== CallvanCard file around line 220-230 ==="
sed -n '220,230p' src/components/Callvan/components/CallvanCard/index.tsx

echo -e "\n=== Search for all aria-label instances in CallvanCard ==="
rg -n "aria-label" src/components/Callvan/components/CallvanCard/index.tsx

echo -e "\n=== Check if category 11 is mentioned anywhere in documentation or comments ==="
rg -n "food\|delivery\|주문\|음식" src/api/store/entity.ts src/components/Callvan/ -i | grep -i "category\|11\|type" | head -10

Repository: BCSDLab/KOIN_WEB_RECODE

Length of output: 873


Line 224에서 버튼의 접근성 레이블이 비어있습니다.

aria-label=""로 설정되어 있으나, 버튼 텍스트가 "참여취소"이므로 aria-label="참여취소"로 설정해야 합니다. 같은 파일의 다른 버튼들(예: 120번 줄의 aria-label="채팅하기", 247번 줄의 aria-label="참여하기")처럼 일관되게 접근성 레이블을 제공해주세요.

라인 27의 하드코딩된 카테고리 ID '11'은 유지보수 관점에서 개선 필요합니다.

다른 컴포넌트들은 API 응답의 shop_categories에서 카테고리 정보를 동적으로 가져오는 반면, 이 코드는 카테고리 ID를 매직 넘버로 하드코딩하고 있습니다. 백엔드에서 카테고리 ID 체계가 변경되면 이 코드가 깨질 수 있습니다. 카테고리 ID를 상수로 분리하면서 왜 특정 값이 필요한지 주석을 추가하거나, 가능하면 설정에서 관리하는 것을 검토해주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Callvan/components/CallvanCard/index.tsx` at line 27, In the
CallvanCard component, update the empty aria-label on the cancel button to match
its visible text (set aria-label="참여취소") so accessibility labels are consistent
with other buttons (e.g., the chat button and 참여하기 button); also remove the
magic literal in CALLVAN_CATEGORY (currently '11') by extracting it to a
well-named constant or config entry (e.g., DEFAULT_CALLVAN_CATEGORY or from a
settings/shopCategories source) in the same module or a central constants/config
file, add a brief comment explaining why that specific category ID is required,
and if feasible replace the hardcoded ID with the dynamic lookup from
shop_categories API used elsewhere.

Comment on lines +113 to 116
<button className={styles.card__phone} onClick={handleCallClick}>
<PhoneCallingIcon />
</span>
</button>
);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

전화 버튼에 type 속성과 aria-label이 누락되었습니다.

버튼 요소에 type="button" 속성이 없으면 form 내에서 submit으로 동작할 수 있고, aria-label이 없으면 스크린 리더 사용자가 버튼의 목적을 알 수 없습니다. As per coding guidelines, 접근성(a11y) 관련 속성이 적절히 사용되어야 합니다.

🔧 수정 제안
-      <button className={styles.card__phone} onClick={handleCallClick}>
+      <button type="button" className={styles.card__phone} onClick={handleCallClick} aria-label="콜밴 업체 전화">
         <PhoneCallingIcon />
       </button>
📝 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
<button className={styles.card__phone} onClick={handleCallClick}>
<PhoneCallingIcon />
</span>
</button>
);
<button type="button" className={styles.card__phone} onClick={handleCallClick} aria-label="콜밴 업체 전화">
<PhoneCallingIcon />
</button>
);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Callvan/components/CallvanCard/index.tsx` around lines 113 -
116, The phone button currently rendered with <button
className={styles.card__phone} onClick={handleCallClick}> lacks accessibility
attributes; update the CallvanCard button (the element using styles.card__phone,
onClick handler handleCallClick, and child PhoneCallingIcon) to include
type="button" to prevent implicit form submission and add an appropriate
aria-label (e.g., aria-label="Call" or a localized string) so screen readers
convey the button's purpose.

}}
disabled={isCancelPending}
aria-label="참여취소"
aria-label=""
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

aria-label은 접근성 문제를 야기합니다.

aria-label=""은 스크린 리더가 버튼의 목적을 전달하지 못하게 합니다. 버튼 텍스트가 "참여취소"이므로, aria-label을 제거하거나 적절한 값으로 설정해야 합니다.

🔧 수정 제안
-         aria-label=""
+         aria-label="참여취소"

또는 버튼 내부에 텍스트가 있으므로 aria-label 속성을 완전히 제거할 수도 있습니다.

📝 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
aria-label=""
aria-label="참여취소"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Callvan/components/CallvanCard/index.tsx` at line 224, In
CallvanCard (component CallvanCard in index.tsx) remove the empty aria-label=""
on the button used for "참여취소" or replace it with an appropriate label (e.g.,
aria-label="참여취소") so screen readers can announce the button purpose; locate the
button element in CallvanCard that currently has aria-label="" and either delete
that attribute (since visible text exists) or set a meaningful value.

@dooohun dooohun merged commit fd763d1 into develop Mar 17, 2026
2 of 3 checks passed
@github-actions github-actions bot deleted the feat/1183/callvan-logging branch March 17, 2026 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📊DA 데이터 분석

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants