diff --git a/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailContract.kt b/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailContract.kt index b7dc018d..6f5842eb 100644 --- a/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailContract.kt +++ b/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailContract.kt @@ -23,7 +23,8 @@ class CourseDetailContract { val currentImagePage: Int = 0, val usePointLoadState: LoadState = LoadState.Idle, val deleteLoadState: LoadState = LoadState.Idle, - var isWebViewOpened: Boolean = false + var isWebViewOpened: Boolean = false, + var hasPointReadDialogOpened: Boolean = false ) : UiState sealed interface CourseDetailSideEffect : UiSideEffect { diff --git a/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailScreen.kt b/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailScreen.kt index 351966d4..0f8026d9 100644 --- a/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailScreen.kt +++ b/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailScreen.kt @@ -45,8 +45,15 @@ import org.sopt.dateroad.presentation.ui.coursedetail.component.CourseDetailBasi import org.sopt.dateroad.presentation.ui.coursedetail.component.CourseDetailBottomBar import org.sopt.dateroad.presentation.ui.coursedetail.component.CourseDetailUnopenedDetail import org.sopt.dateroad.presentation.ui.coursedetail.component.courseDetailOpenedDetail +import org.sopt.dateroad.presentation.util.CourseDetailAmplitude.CLICK_COURSE_BACK +import org.sopt.dateroad.presentation.util.CourseDetailAmplitude.CLICK_COURSE_PURCHASE +import org.sopt.dateroad.presentation.util.CourseDetailAmplitude.COURSE_LIST_ID +import org.sopt.dateroad.presentation.util.CourseDetailAmplitude.COURSE_LIST_TITLE +import org.sopt.dateroad.presentation.util.CourseDetailAmplitude.PURCHASE_SUCCESS +import org.sopt.dateroad.presentation.util.CourseDetailAmplitude.VIEW_COURSE_DETAILS import org.sopt.dateroad.presentation.util.ViewPath.COURSE_DETAIL import org.sopt.dateroad.presentation.util.WebViewUrl.REPORT_URL +import org.sopt.dateroad.presentation.util.amplitude.AmplitudeUtils import org.sopt.dateroad.presentation.util.view.LoadState import org.sopt.dateroad.ui.theme.DATEROADTheme import org.sopt.dateroad.ui.theme.DateRoadTheme @@ -75,6 +82,20 @@ fun CourseDetailRoute( viewModel.fetchCourseDetail(courseId = courseId) } + LaunchedEffect(uiState.loadState, lifecycleOwner) { + if (uiState.loadState == LoadState.Success) { + with(uiState.courseDetail) { + AmplitudeUtils.trackEventWithProperties( + eventName = VIEW_COURSE_DETAILS, + mapOf( + COURSE_LIST_ID to courseId, + COURSE_LIST_TITLE to title + ) + ) + } + } + } + when (uiState.loadState) { LoadState.Idle -> DateRoadIdleView() @@ -111,7 +132,16 @@ fun CourseDetailRoute( onReportCourseBottomSheet = { viewModel.setEvent(CourseDetailContract.CourseDetailEvent.OnReportCourseBottomSheet) }, dismissReportCourseBottomSheet = { viewModel.setEvent(CourseDetailContract.CourseDetailEvent.DismissReportCourseBottomSheet) }, enrollSchedule = { viewModel.setSideEffect(CourseDetailContract.CourseDetailSideEffect.NavigateToEnroll(enrollType = EnrollType.TIMELINE, viewPath = COURSE_DETAIL, id = courseId)) }, - onTopBarIconClicked = { viewModel.setSideEffect(CourseDetailContract.CourseDetailSideEffect.PopBackStack) }, + onTopBarIconClicked = { + viewModel.setSideEffect(CourseDetailContract.CourseDetailSideEffect.PopBackStack) + AmplitudeUtils.trackEventWithProperties( + eventName = CLICK_COURSE_BACK, + properties = mapOf( + CLICK_COURSE_PURCHASE to uiState.hasPointReadDialogOpened, + PURCHASE_SUCCESS to uiState.courseDetail.isAccess + ) + ) + }, openCourseDetail = { viewModel.postUsePoint(courseId = courseId) }, onReportButtonClicked = { viewModel.setEvent(CourseDetailContract.CourseDetailEvent.OnReportWebViewClicked) diff --git a/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailViewModel.kt b/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailViewModel.kt index c21bf7b8..e672944c 100644 --- a/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailViewModel.kt +++ b/app/src/main/java/org/sopt/dateroad/presentation/ui/coursedetail/CourseDetailViewModel.kt @@ -10,6 +10,8 @@ import org.sopt.dateroad.domain.usecase.DeleteCourseUseCase import org.sopt.dateroad.domain.usecase.GetCourseDetailUseCase import org.sopt.dateroad.domain.usecase.PostCourseLikeUseCase import org.sopt.dateroad.domain.usecase.PostUsePointUseCase +import org.sopt.dateroad.presentation.util.CourseDetailAmplitude.CLICK_COURSE_LIKES +import org.sopt.dateroad.presentation.util.CourseDetailAmplitude.COURSE_LIST_LIKE import org.sopt.dateroad.presentation.util.Point import org.sopt.dateroad.presentation.util.UserPropertyAmplitude.USER_FREE_REMAINED import org.sopt.dateroad.presentation.util.UserPropertyAmplitude.USER_POINT @@ -38,7 +40,7 @@ class CourseDetailViewModel @Inject constructor( is CourseDetailContract.CourseDetailEvent.DismissDialogDeleteCourse -> setState { copy(isDeleteCourseDialogOpen = false) } is CourseDetailContract.CourseDetailEvent.OnDialogReportCourse -> setState { copy(isReportCourseDialogOpen = true) } is CourseDetailContract.CourseDetailEvent.DismissDialogReportCourse -> setState { copy(isReportCourseDialogOpen = false) } - is CourseDetailContract.CourseDetailEvent.OnDialogLookedByPoint -> setState { copy(isPointReadDialogOpen = true) } + is CourseDetailContract.CourseDetailEvent.OnDialogLookedByPoint -> setState { copy(isPointReadDialogOpen = true, hasPointReadDialogOpened = true) } is CourseDetailContract.CourseDetailEvent.DismissDialogLookedByPoint -> setState { copy(isPointReadDialogOpen = false) } is CourseDetailContract.CourseDetailEvent.OnLikeButtonClicked -> setState { copy(isLikedButtonChecked = !isLikedButtonChecked) } is CourseDetailContract.CourseDetailEvent.OnDeleteCourseBottomSheet -> setState { copy(isDeleteCourseBottomSheetOpen = true) } @@ -60,6 +62,7 @@ class CourseDetailViewModel @Inject constructor( setEvent(CourseDetailContract.CourseDetailEvent.DeleteCourseLike(courseDetail = currentState.courseDetail)) deleteCourseLikeUseCase(courseId = courseId).onSuccess { setEvent(CourseDetailContract.CourseDetailEvent.DeleteCourseLike(courseDetail = currentState.courseDetail.copy(isUserLiked = false, like = currentState.courseDetail.like - 1))) + AmplitudeUtils.trackEventWithProperty(eventName = CLICK_COURSE_LIKES, propertyName = COURSE_LIST_LIKE, propertyValue = currentState.courseDetail.isUserLiked) }.onFailure { setEvent(CourseDetailContract.CourseDetailEvent.DeleteCourseLike(courseDetail = currentState.courseDetail)) } @@ -84,6 +87,7 @@ class CourseDetailViewModel @Inject constructor( ) postCourseLikeUseCase(courseId = courseId).onSuccess { setEvent(CourseDetailContract.CourseDetailEvent.PostCourseLike(courseDetail = currentState.courseDetail.copy(isUserLiked = true, like = currentState.courseDetail.like + 1))) + AmplitudeUtils.trackEventWithProperty(eventName = CLICK_COURSE_LIKES, propertyName = COURSE_LIST_LIKE, propertyValue = currentState.courseDetail.isUserLiked) }.onFailure { setEvent(CourseDetailContract.CourseDetailEvent.PostCourseLike(courseDetail = currentState.courseDetail)) } diff --git a/app/src/main/java/org/sopt/dateroad/presentation/util/Constraints.kt b/app/src/main/java/org/sopt/dateroad/presentation/util/Constraints.kt index 4d987bdf..101b9962 100644 --- a/app/src/main/java/org/sopt/dateroad/presentation/util/Constraints.kt +++ b/app/src/main/java/org/sopt/dateroad/presentation/util/Constraints.kt @@ -49,6 +49,7 @@ object Token { object Time { const val TIME = " 시간" } + object LoadingView { const val LOTTIE = "loading.json" const val CLIPMIN = 0 @@ -60,6 +61,17 @@ object Pattern { val NICKNAME_REGEX = Regex(NICKNAME_PATTERN) } +object CourseDetailAmplitude { + const val VIEW_COURSE_DETAILS = "view_course_details" + const val CLICK_COURSE_BACK = "click_course_back" + const val CLICK_COURSE_LIKES = "click_course_likes" + const val COURSE_LIST_ID = "course_list_id" + const val COURSE_LIST_TITLE = "course_list_title" + const val CLICK_COURSE_PURCHASE = "click_course_purchase" + const val PURCHASE_SUCCESS = "purchase_success" + const val COURSE_LIST_LIKE = "course_list_like" +} + object HomeAmplitude { const val VIEW_MAIN = "view_main" const val USER_NAME = "user_name"