diff --git a/src/components/CourseRegister/StartButton.tsx b/src/components/CourseRegister/StartButton.tsx index 726e3e0..5503cd3 100644 --- a/src/components/CourseRegister/StartButton.tsx +++ b/src/components/CourseRegister/StartButton.tsx @@ -5,6 +5,7 @@ import {deleteAllRegistrations} from '@apis/api/course.ts'; import {setEndCount} from '@/store/modules/courseRegisteredSlice'; import {useAppSelector} from '@/store/hooks'; import Timeout from './Timeout'; +import ReactGA from 'react-ga4'; interface StartBtnProps { onClick: () => void; @@ -37,6 +38,12 @@ function StartButton({onClick}: StartBtnProps) { const handleClick = async () => { if (!confirm('수강신청 연습 시작하시겠습니까?')) return; + ReactGA.event({ + category: 'Course Registration', + action: isRunning ? 'Restart Practice Button' : 'Start Practice Button', + label: isRunning ? 'PracticeButton_Restart' : 'PracticeButton_Start', + }); + //카운트다운 중에 재시작 if (isRunning) { setTimeLeft(time); diff --git a/src/components/LoginForm/index.tsx b/src/components/LoginForm/index.tsx index 8b0c74f..161dca1 100644 --- a/src/components/LoginForm/index.tsx +++ b/src/components/LoginForm/index.tsx @@ -12,6 +12,7 @@ import {generateRandomStudentId} from '@/utils/randomUtils.ts'; import copyIcon from '@/assets/img/file-copy-line.png'; import reloadIcon from '@/assets/img/refresh-line.png'; import {resetTab} from '@/store/modules/tabSlice'; +import ReactGA from 'react-ga4'; export type setType = string | number | undefined; @@ -40,6 +41,13 @@ function LoginForm({isTermsCheck}: {isTermsCheck: boolean}) { }); }; const handleLogin = async () => { + + ReactGA.event({ + category: 'User', + action: 'Login Attempt', + label: 'Login Page', + }); + if (!id || !password) { setError('학번과 비밀번호를 모두 입력해주세요.'); return; @@ -65,8 +73,15 @@ function LoginForm({isTermsCheck}: {isTermsCheck: boolean}) { studentId: id.toString(), password: password.toString(), }); + console.log('Login successful'); + ReactGA.event({ + category: 'User', + action: 'Login Success', + label: 'Login Page', + }); + Cookies.set('accessToken', response.accessToken, {expires: 0.5 / 24}); baseAPI.defaults.headers.common['Authorization'] = `Bearer ${response.accessToken}`; @@ -83,6 +98,13 @@ function LoginForm({isTermsCheck}: {isTermsCheck: boolean}) { navigate('/'); } catch (error) { console.error('Login failed', error); + + ReactGA.event({ + category: 'User', + action: 'Login Failed', + label: 'Login Page', + }); + setError('로그인에 실패했습니다. 다시 시도해주세요.'); } }; diff --git a/src/components/Wishlist/index.tsx b/src/components/Wishlist/index.tsx index b0f4b5e..f8ecf7c 100644 --- a/src/components/Wishlist/index.tsx +++ b/src/components/Wishlist/index.tsx @@ -13,6 +13,7 @@ import {useSelector} from 'react-redux'; import {TableTitle, TableTitleWrap} from '../LectureList'; import {openModalHandler} from '../common/Modal/handlers/handler'; import {useAppDispatch} from '@/store/hooks'; +import ReactGA from 'react-ga4'; const searchResultColData = [ {name: 'action', value: '신청', initialWidth: 50, enableFilters: false}, @@ -81,6 +82,11 @@ function Wishlist() { ) => { if (action === '신청' && scheduleId) { try { + ReactGA.event({ + category: 'Wishlist', + action: 'Add to Wishlist', + label: 'Click_WishlistButton', + }); await saveWishlistItem(username, scheduleId); console.log('관심과목 담기 성공'); fetchWishlist(); @@ -99,6 +105,12 @@ function Wishlist() { }; const handleClickTimetable = () => { + ReactGA.event({ + category: 'Timetable', + action: 'View Timetable', + label: 'Click_ViewTimetableButton', + }); + openModalHandler(dispatch, 'timetable'); if (wishlistData.length !== 0) { document.body.style.overflow = 'hidden';