Skip to content
Open
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
27 changes: 27 additions & 0 deletions apps/web/src/app-pages/calendar/ui/CalendarPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import { useRouter } from 'next/navigation';
import { useSearchParams } from 'next/navigation';
import { useState } from 'react';
import { useAuthStore } from '@/features/auth/model/useAuthStore';
import { trackCalendarEvent } from '@/features/calendar/lib/trackCalendarEvent';
import { CALENDAR_EVENTS } from '@/features/calendar/model/constants';
import { useGetCalendarSchedule } from '@/features/calendar/model/useGetCalendarSchedule';
import { usePageName } from '@/shared/analytics/lib/getPageName';
import { PAGE_ROUTES } from '@/shared/config/path';
import { Calendar } from '@/widgets/calendar/ui/Calendar';

Expand All @@ -27,6 +30,28 @@ export const CalendarPage = () => {
month.getMonth() + 1,
);

const trackRef = useRef(false);
const pageName = usePageName();

useEffect(() => {
if (trackRef.current) return;
trackRef.current = true;
trackCalendarEvent(CALENDAR_EVENTS.PAGE_VIEW, { page_name: pageName });
}, [pageName]);

const handleDateClick = (date: Date) => {
trackCalendarEvent(CALENDAR_EVENTS.CALENDAR_DATE_CLICK, {
selected_date: format(date, 'yyyy-MM-dd'),
});
};

const handleEventClick = (scheduleId: number, postId?: number) => {
trackCalendarEvent(CALENDAR_EVENTS.EVENT_CARD_CLICK, {
event_id: scheduleId,
...(postId && { post_id: postId }),
});
};

const handleCreateSchedule = () => {
router.push(PAGE_ROUTES.CALENDAR.CREATE);
};
Expand All @@ -39,6 +64,8 @@ export const CalendarPage = () => {
onMonthChange={setMonth}
schedules={schedules}
initialSelectedDate={targetDate}
onDateClick={handleDateClick}
onEventClick={handleEventClick}
/>
</div>

Expand Down
4 changes: 4 additions & 0 deletions apps/web/src/features/calendar/lib/trackCalendarEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { createDomainTracker } from '@/shared/lib/createDomainTracker';
import { CalendarEventPropsMap } from '../model/constants';

export const trackCalendarEvent = createDomainTracker<CalendarEventPropsMap>();
17 changes: 17 additions & 0 deletions apps/web/src/features/calendar/model/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* 캘린더 관련 트래킹 이벤트
*/
export const CALENDAR_EVENTS = {
PAGE_VIEW: 'page_view',
CALENDAR_DATE_CLICK: 'calendar_date_click',
EVENT_CARD_CLICK: 'event_card_click',
} as const;
Comment on lines +4 to +8
Copy link
Copy Markdown

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:

# Search for PAGE_VIEW and page_view patterns
rg -n "PAGE_VIEW|page_view" --type ts --type tsx apps/web/src | head -30

Repository: Tave-Makers/SURF-FE

Length of output: 90


🏁 Script executed:

# Look for other event constants similar to CALENDAR_EVENTS
rg -n "EVENTS\s*=\s*\{" --type ts --type tsx apps/web/src | head -20

Repository: Tave-Makers/SURF-FE

Length of output: 90


🏁 Script executed:

# Check for event tracking/analytics patterns
rg -n "event.*page|page.*event" --type ts --type tsx apps/web/src -i | head -20

Repository: Tave-Makers/SURF-FE

Length of output: 90


🏁 Script executed:

# Look for naming convention documentation
fd -t f -e md -e txt . apps/web/src | xargs rg -l "event|naming|convention" 2>/dev/null | head -10

Repository: Tave-Makers/SURF-FE

Length of output: 515


🏁 Script executed:

# Search for PAGE_VIEW and page_view patterns
rg -n "PAGE_VIEW|page_view" apps/web/src | head -40

Repository: Tave-Makers/SURF-FE

Length of output: 474


🏁 Script executed:

# Look for other event constants similar to CALENDAR_EVENTS
rg -n "EVENTS\s*=\s*\{" apps/web/src | head -20

Repository: Tave-Makers/SURF-FE

Length of output: 954


🏁 Script executed:

# Check for any existing event tracking/analytics documentation
find apps/web -name "*.md" -o -name "*event*" -o -name "*analytics*" | grep -v node_modules | head -20

Repository: Tave-Makers/SURF-FE

Length of output: 191


🏁 Script executed:

# Examine the calendar model directory structure
ls -la apps/web/src/features/calendar/model/ 2>/dev/null || echo "Directory not found"

Repository: Tave-Makers/SURF-FE

Length of output: 370


🏁 Script executed:

# Look for how CALENDAR_EVENTS is being used
rg -n "CALENDAR_EVENTS" apps/web/src

Repository: Tave-Makers/SURF-FE

Length of output: 994


🏁 Script executed:

# Check COMMON_EVENTS definition
cat -n apps/web/src/shared/analytics/model/types.ts

Repository: Tave-Makers/SURF-FE

Length of output: 1403


🏁 Script executed:

# Check ONBOARDING_EVENTS to see the naming pattern
rg -A 10 "export const ONBOARDING_EVENTS" apps/web/src

Repository: Tave-Makers/SURF-FE

Length of output: 889


🏁 Script executed:

# Check other domain event definitions to confirm the pattern
rg -A 5 "export const.*_EVENTS\s*=" apps/web/src | head -50

Repository: Tave-Makers/SURF-FE

Length of output: 3112


🏁 Script executed:

# Check how calendar page view event is actually being tracked
cat -n apps/web/src/app-pages/calendar/ui/CalendarPage.tsx | sed -n '35,55p'

Repository: Tave-Makers/SURF-FE

Length of output: 804


🏁 Script executed:

# Verify the analytics tracking setup to see if page_view causes conflicts
rg -B 3 -A 3 "trackCalendarEvent|page_view" apps/web/src/app-pages/calendar/ui/CalendarPage.tsx

Repository: Tave-Makers/SURF-FE

Length of output: 1111


🏁 Script executed:

# Double-check if there are any other page_view events in the project
rg -n "page_view|PAGE_VIEW" apps/web/src --type ts | grep -v "page_name"

Repository: Tave-Makers/SURF-FE

Length of output: 236


🏁 Script executed:

# Look at the analytics library to understand how tracking works
ls -la apps/web/src/shared/analytics/

Repository: Tave-Makers/SURF-FE

Length of output: 340


🏁 Script executed:

# Check trackCalendarEvent implementation
find apps/web/src/features/calendar -name "*.ts" | xargs cat -n 2>/dev/null

Repository: Tave-Makers/SURF-FE

Length of output: 6372


🏁 Script executed:

# Check the onboarding comment mentioned in the results
cat -n apps/web/src/widgets/onboarding/ui/OnBoardingForm.tsx | sed -n '90,100p'

Repository: Tave-Makers/SURF-FE

Length of output: 486


🏁 Script executed:

# Look at createDomainTracker to understand how event tracking works
find apps/web/src/shared/lib -name "*tracker*" -o -name "*analytics*" | xargs cat -n 2>/dev/null | head -50

Repository: Tave-Makers/SURF-FE

Length of output: 45


🏁 Script executed:

# Let's check if there's any documentation on event naming conventions
find apps/web -name "*.md" -type f | xargs grep -l "event\|analytics\|tracking" 2>/dev/null

Repository: Tave-Makers/SURF-FE

Length of output: 47


🏁 Script executed:

# Check the createDomainTracker more carefully
ls -la apps/web/src/shared/lib/

Repository: Tave-Makers/SURF-FE

Length of output: 882


🏁 Script executed:

# Check createDomainTracker implementation
cat -n apps/web/src/shared/lib/createDomainTracker.ts

Repository: Tave-Makers/SURF-FE

Length of output: 635


🏁 Script executed:

# Check trackEvent implementation
cat -n apps/web/src/shared/lib/trackEvent.ts

Repository: Tave-Makers/SURF-FE

Length of output: 512


🏁 Script executed:

# Check the types
cat -n apps/web/src/shared/lib/types.ts

Repository: Tave-Makers/SURF-FE

Length of output: 442


도메인별 이벤트 네이밍 컨벤션 일관성 유지 필요

PAGE_VIEW: 'page_view'는 다른 모든 도메인 이벤트와 달리 도메인 구분이 없어 컨벤션 위반입니다.

프로젝트 내 다른 도메인들은 일관된 패턴을 따르고 있습니다:

  • Onboarding: VIEW_SIGNUP_PAGE: 'view_signup_page'
  • Profile: VIEW_PROFILE: 'view_profile'
  • Post: VIEW_MY_POSTS_PAGE: 'view_post_list'
  • Activity Score: VIEW_ACTIVITY: 'view_activity'

Calendar도 이 패턴을 따라 VIEW_CALENDAR_PAGE: 'view_calendar_page'로 변경하세요. page_name 속성으로 페이지를 구분할 수 있지만, 이벤트 이름 자체도 도메인별로 구분하면:

  1. Amplitude 대시보드에서 필터링/세분화가 명확함
  2. 향후 다른 도메인과의 충돌 위험 제거
  3. 전체 코드베이스에서 일관된 네이밍 규칙 유지
🤖 Prompt for AI Agents
In `@apps/web/src/features/calendar/model/constants.ts` around lines 4 - 8, The
CALENDAR_EVENTS constant uses PAGE_VIEW: 'page_view' which breaks the
domain-specific naming convention; update the key and value to
VIEW_CALENDAR_PAGE: 'view_calendar_page' in the CALENDAR_EVENTS export and then
update all usages (event dispatches, telemetry callers, tests, and any
types/interfaces) that reference CALENDAR_EVENTS.PAGE_VIEW to use
CALENDAR_EVENTS.VIEW_CALENDAR_PAGE so the telemetry name and code references
remain consistent.


/**
* 캘린더 이벤트별 속성 타입 매핑
*/
export type CalendarEventPropsMap = {
[CALENDAR_EVENTS.PAGE_VIEW]: { page_name: string };
[CALENDAR_EVENTS.CALENDAR_DATE_CLICK]: { selected_date: string };
[CALENDAR_EVENTS.EVENT_CARD_CLICK]: { event_id: number; post_id?: number };
};
8 changes: 7 additions & 1 deletion apps/web/src/widgets/calendar/ui/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,17 @@ type CalendarProps = {
onMonthChange: (date: Date) => void;
schedules: ActivityMap;
initialSelectedDate?: Date;
onDateClick?: (date: Date) => void;
onEventClick?: (scheduleId: number, postId?: number) => void;
};

export const Calendar = ({
month,
onMonthChange,
schedules,
initialSelectedDate,
onDateClick,
onEventClick,
}: CalendarProps) => {
const router = useRouter();
const [selectedDay, setSelectedDay] = useState<Date>(initialSelectedDate || new Date());
Expand All @@ -71,8 +75,9 @@ export const Calendar = ({
if (!date) return;
setSelectedDay(date);
onMonthChange(date);
onDateClick?.(date);
},
[onMonthChange],
[onMonthChange, onDateClick],
);

// DayPicker의 DayButton 커스텀 컴포넌트
Expand Down Expand Up @@ -146,6 +151,7 @@ export const Calendar = ({
postId={_ev.postId}
isAdmin={memberRole !== 'member'}
onClickCard={() => {
onEventClick?.(_ev.id, _ev.postId);
if (!_ev.postId) return;
router.push(PAGE_ROUTES.BOARD.POST_DETAIL(1, _ev.postId));
}}
Expand Down