diff --git a/core/analytics/.gitignore b/core/analytics/.gitignore
new file mode 100644
index 000000000..42afabfd2
--- /dev/null
+++ b/core/analytics/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/core/analytics/build.gradle.kts b/core/analytics/build.gradle.kts
new file mode 100644
index 000000000..c3bfc5ad6
--- /dev/null
+++ b/core/analytics/build.gradle.kts
@@ -0,0 +1,29 @@
+plugins {
+ alias(libs.plugins.koin.library)
+}
+
+android {
+ namespace = "in.koreatech.koin.core.analytics"
+
+ buildTypes {
+ getByName("debug") {
+ buildConfigField("Boolean", "IS_DEBUG", "true")
+ }
+
+ getByName("release") {
+ buildConfigField("Boolean", "IS_DEBUG", "false")
+ }
+ }
+}
+
+dependencies {
+
+ implementation(libs.core.ktx)
+ implementation(libs.appcompat)
+ implementation(libs.material)
+ implementation(platform(libs.firebase.bom))
+ implementation(libs.firebase.analytics)
+ testImplementation(libs.junit)
+ androidTestImplementation(libs.ext.junit)
+ androidTestImplementation(libs.espresso.core)
+}
\ No newline at end of file
diff --git a/core/analytics/consumer-rules.pro b/core/analytics/consumer-rules.pro
new file mode 100644
index 000000000..e69de29bb
diff --git a/core/analytics/proguard-rules.pro b/core/analytics/proguard-rules.pro
new file mode 100644
index 000000000..481bb4348
--- /dev/null
+++ b/core/analytics/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/core/analytics/src/androidTest/java/in/koreatech/koin/core/analytics/ExampleInstrumentedTest.kt b/core/analytics/src/androidTest/java/in/koreatech/koin/core/analytics/ExampleInstrumentedTest.kt
new file mode 100644
index 000000000..4e5561bd9
--- /dev/null
+++ b/core/analytics/src/androidTest/java/in/koreatech/koin/core/analytics/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package `in`.koreatech.koin.core.analytics
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("in.koreatech.koin.core.analytics.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/core/analytics/src/main/AndroidManifest.xml b/core/analytics/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..a5918e68a
--- /dev/null
+++ b/core/analytics/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/core/src/main/java/in/koreatech/koin/core/constant/AnalyticsConstant.kt b/core/analytics/src/main/java/in/koreatech/koin/core/analytics/AnalyticsConstant.kt
similarity index 97%
rename from core/src/main/java/in/koreatech/koin/core/constant/AnalyticsConstant.kt
rename to core/analytics/src/main/java/in/koreatech/koin/core/analytics/AnalyticsConstant.kt
index 3ed94f8e3..9f65ee2b0 100644
--- a/core/src/main/java/in/koreatech/koin/core/constant/AnalyticsConstant.kt
+++ b/core/analytics/src/main/java/in/koreatech/koin/core/analytics/AnalyticsConstant.kt
@@ -1,4 +1,4 @@
-package `in`.koreatech.koin.core.constant
+package `in`.koreatech.koin.core.analytics
object AnalyticsConstant {
@@ -18,8 +18,8 @@ object AnalyticsConstant {
const val CAFETERIA_INFO = "cafeteria_info"
const val HAMBURGER = "hamburger"
const val HAMBURGER_SHOP = HAMBURGER
- const val HAMBURGER_DINING = "${HAMBURGER}"
- const val HAMBURGER_BUS = "${HAMBURGER}"
+ const val HAMBURGER_DINING = "$HAMBURGER"
+ const val HAMBURGER_BUS = "$HAMBURGER"
const val MAIN_MENU_MOVEDETAILVIEW = "main_menu_moveDetailView"
const val MAIN_MENU_CORNER = "main_menu_corner"
const val MENU_TIME = "menu_time"
diff --git a/core/src/main/java/in/koreatech/koin/core/analytics/EventLogger.kt b/core/analytics/src/main/java/in/koreatech/koin/core/analytics/EventLogger.kt
similarity index 62%
rename from core/src/main/java/in/koreatech/koin/core/analytics/EventLogger.kt
rename to core/analytics/src/main/java/in/koreatech/koin/core/analytics/EventLogger.kt
index 1df10adda..8b46e0aa9 100644
--- a/core/src/main/java/in/koreatech/koin/core/analytics/EventLogger.kt
+++ b/core/analytics/src/main/java/in/koreatech/koin/core/analytics/EventLogger.kt
@@ -1,11 +1,8 @@
package `in`.koreatech.koin.core.analytics
-import android.util.Log
-import com.google.firebase.analytics.ktx.analytics
-import com.google.firebase.analytics.ktx.logEvent
-import com.google.firebase.ktx.Firebase
-import `in`.koreatech.koin.core.BuildConfig
-import `in`.koreatech.koin.core.analytics.EventLogger.logEvent
+import com.google.firebase.analytics.analytics
+import com.google.firebase.analytics.logEvent
+import com.google.firebase.Firebase
object EventLogger {
@@ -15,23 +12,31 @@ object EventLogger {
/**
* 클릭 이벤트 로깅
- * @param action: 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
- * @param label: 이벤트 소분류
- * @param value: 이벤트 값
- * @param extras: 추가 이벤트 값
+ * @param action 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
+ * @param label 이벤트 소분류
+ * @param value 이벤트 값
+ * @param extras 추가 이벤트 값
*/
fun logClickEvent(action: EventAction, label: String, value: String, vararg extras: EventExtra) {
logEvent(action, EventCategory.CLICK, label, value, *extras)
}
-
+ /**
+ * CAPMUS 클릭 이벤트 로깅
+ * @param label 이벤트 소분류
+ * @param value 이벤트 값
+ * @param extras 추가 이벤트 값
+ */
+ fun logCampusClickEvent(label: String, value: String, vararg extras: EventExtra) {
+ logClickEvent(EventAction.CAMPUS, label, value, *extras)
+ }
/**
* 스크롤 이벤트 로깅
- * @param action: 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
- * @param label: 이벤트 소분류
- * @param value: 이벤트 값
- * @param extras: 추가 이벤트 값
+ * @param action 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
+ * @param label 이벤트 소분류
+ * @param value 이벤트 값
+ * @param extras 추가 이벤트 값
*/
fun logScrollEvent(action: EventAction, label: String, value: String, vararg extras: EventExtra) {
logEvent(action, EventCategory.SCROLL, label, value, *extras)
@@ -39,10 +44,10 @@ object EventLogger {
/**
* 하단 뒤로가기 이벤트 로깅
- * @param action: 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
- * @param label: 이벤트 소분류
- * @param value: 이벤트 값
- * @param extras: 추가 이벤트 값
+ * @param action 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
+ * @param label 이벤트 소분류
+ * @param value 이벤트 값
+ * @param extras 추가 이벤트 값
*/
fun logSwipeEvent(action: EventAction, label: String, value: String, vararg extras: EventExtra) {
logEvent(action, EventCategory.SWIPE, label, value, *extras)
@@ -50,10 +55,10 @@ object EventLogger {
/**
* 푸시알림 접속 이벤트 로깅
- * @param action: 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
- * @param label: 이벤트 소분류
- * @param value: 이벤트 값
- * @param extras: 추가 이벤트 값
+ * @param action 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
+ * @param label 이벤트 소분류
+ * @param value 이벤트 값
+ * @param extras 추가 이벤트 값
*/
fun logNotificationEvent(action: EventAction, label: String, value: String, vararg extras: EventExtra) {
logEvent(action, EventCategory.NOTIFICATION, label, value, *extras)
@@ -61,20 +66,23 @@ object EventLogger {
/**
* AB테스트 이벤트 로깅
- * @param category: 이벤트 종류
- * @param label: 이벤트 소분류
- * @param value: 이벤트 값
+ * @param category 이벤트 종류
+ * @param label 이벤트 소분류
+ * @param value 이벤트 값
*/
fun logABTestEvent(category: String, label: String, value: String) {
logCustomEvent(EventAction.ABTEST.value, category, label, value)
}
/**
- * @param action: 커스텀 이벤트 발생(EventAction 이외에 action)
- * @param category: 커스텀 이벤트 종류(EventCategory 이외에 category)
- * @param label: 이벤트 소분류
- * @param value: 이벤트 값
- * @sample logEvent("force_update", "page_view", "forced_update_page_view", "v4.0.0")
+ * @param action 커스텀 이벤트 발생(EventAction 이외에 action)
+ * @param category 커스텀 이벤트 종류(EventCategory 이외에 category)
+ * @param label 이벤트 소분류
+ * @param value 이벤트 값
+ *
+ * ```
+ * logEvent("force_update", "page_view", "forced_update_page_view", "v4.0.0")
+ * ```
*/
fun logCustomEvent(action: String, category: String, label: String, value: String) {
if (BuildConfig.IS_DEBUG) {
@@ -94,11 +102,15 @@ object EventLogger {
}
}
/**
- * @param action: 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
- * @param category: 이벤트 종류(click, scroll, ...)
- * @param label: 이벤트 소분류
- * @param value: 이벤트 값
- * @sample logEvent("BUSINESS", "click", "main_shop_categories", "전체보기")
+ * @param action 이벤트 발생 도메인(BUSINESS, CAMPUS, USER)
+ * @param category 이벤트 종류(click, scroll, ...)
+ * @param label 이벤트 소분류
+ * @param value 이벤트 값
+ * @param extras 추가 이벤트 값
+ *
+ * ```
+ * logEvent(EventAction.CAMPUS, EventCategory.CLICK, "main_shop_categories", "전체보기")
+ * ```
*/
private fun logEvent(action: EventAction, category: EventCategory, label: String, value: String, vararg extras: EventExtra) {
if (BuildConfig.IS_DEBUG) {
diff --git a/core/src/main/java/in/koreatech/koin/core/analytics/EventUtils.kt b/core/analytics/src/main/java/in/koreatech/koin/core/analytics/EventUtils.kt
similarity index 100%
rename from core/src/main/java/in/koreatech/koin/core/analytics/EventUtils.kt
rename to core/analytics/src/main/java/in/koreatech/koin/core/analytics/EventUtils.kt
diff --git a/core/analytics/src/test/java/in/koreatech/koin/core/analytics/ExampleUnitTest.kt b/core/analytics/src/test/java/in/koreatech/koin/core/analytics/ExampleUnitTest.kt
new file mode 100644
index 000000000..a08d16ef1
--- /dev/null
+++ b/core/analytics/src/test/java/in/koreatech/koin/core/analytics/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package `in`.koreatech.koin.core.analytics
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/core/src/main/java/in/koreatech/koin/core/appbar/AppBarBase.java b/core/src/main/java/in/koreatech/koin/core/appbar/AppBarBase.java
index f8ca0a312..8e0c82b21 100644
--- a/core/src/main/java/in/koreatech/koin/core/appbar/AppBarBase.java
+++ b/core/src/main/java/in/koreatech/koin/core/appbar/AppBarBase.java
@@ -12,17 +12,11 @@
import android.view.View;
import android.widget.TextView;
-
import android.util.AttributeSet;
-
import in.koreatech.koin.core.R;
-import in.koreatech.koin.core.analytics.EventAction;
-import in.koreatech.koin.core.analytics.EventLogger;
-import in.koreatech.koin.core.constant.AnalyticsConstant;
import in.koreatech.koin.core.util.FontManager;
-
public class AppBarBase extends AppBarLayout {
public AppBarLayout background;
public TextView leftButton;
diff --git a/feature/bus/build.gradle.kts b/feature/bus/build.gradle.kts
index d5666e895..117d2b1d5 100644
--- a/feature/bus/build.gradle.kts
+++ b/feature/bus/build.gradle.kts
@@ -23,6 +23,7 @@ dependencies {
implementation(project(":domain"))
implementation(project(":core:onboarding"))
implementation(project(":core:designsystem"))
+ implementation(project(":core:analytics"))
implementation(libs.core.ktx)
implementation(libs.appcompat)
diff --git a/feature/bus/src/main/java/in/koreatech/bus/component/WrongInformationText.kt b/feature/bus/src/main/java/in/koreatech/bus/component/WrongInformationText.kt
index bb8c7127d..cacc25486 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/component/WrongInformationText.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/component/WrongInformationText.kt
@@ -8,6 +8,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
+import `in`.koreatech.bus.type.BusType
+import `in`.koreatech.bus.util.LocalSelectedTimetableTab
+import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.designsystem.component.text.LeadingIconText
import `in`.koreatech.koin.core.designsystem.noRippleClickable
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
@@ -15,11 +18,17 @@ import `in`.koreatech.koin.feature.bus.R
@Composable
internal fun WrongInformationText(
- modifier: Modifier = Modifier
+ modifier: Modifier = Modifier,
+ loggingEventValue: String = ""
) {
val context = LocalContext.current
+
LeadingIconText(
modifier = modifier.noRippleClickable {
+ EventLogger.logCampusClickEvent(
+ "error_feedback_button",
+ loggingEventValue
+ )
val url = GOOGLE_FORM_URL
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
context.startActivity(intent)
diff --git a/feature/bus/src/main/java/in/koreatech/bus/navigation/BusSearchNavigation.kt b/feature/bus/src/main/java/in/koreatech/bus/navigation/BusSearchNavigation.kt
index abc8512bf..31d8c708f 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/navigation/BusSearchNavigation.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/navigation/BusSearchNavigation.kt
@@ -19,6 +19,7 @@ import `in`.koreatech.bus.screen.search.composable.BusSearchScreen
import `in`.koreatech.bus.screen.searchresult.composable.BusSearchResultScreen
import `in`.koreatech.bus.type.PlaceType
import `in`.koreatech.bus.util.findActivity
+import `in`.koreatech.koin.core.analytics.EventLogger
import kotlin.reflect.typeOf
@Composable
@@ -49,7 +50,9 @@ fun BusSearchNavigation(
)
) {
BusSearchScreen(
- modifier = Modifier.fillMaxSize().background(Color.White),
+ modifier = Modifier
+ .fillMaxSize()
+ .background(Color.White),
onNavigationIconClick = { context.findActivity()?.finish() },
onSearch = { departure, arrival ->
navController.navigate(Routes.BusSearchResult(departure, arrival))
@@ -59,8 +62,16 @@ fun BusSearchNavigation(
composable {
BusSearchResultScreen(
- modifier = Modifier.fillMaxSize().background(Color.White),
- onNavigationIconClick = navController::popBackStack
+ modifier = Modifier
+ .fillMaxSize()
+ .background(Color.White),
+ onNavigationIconClick = {
+ EventLogger.logCampusClickEvent(
+ "search_result_back",
+ "뒤로가기"
+ )
+ navController.popBackStack()
+ }
)
}
}
diff --git a/feature/bus/src/main/java/in/koreatech/bus/screen/search/composable/BusSearchScreenContent.kt b/feature/bus/src/main/java/in/koreatech/bus/screen/search/composable/BusSearchScreenContent.kt
index 22015bc23..10ec4850f 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/screen/search/composable/BusSearchScreenContent.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/screen/search/composable/BusSearchScreenContent.kt
@@ -13,6 +13,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -22,6 +23,7 @@ import `in`.koreatech.bus.screen.timetable.viewmodel.BusNoticeUiState
import `in`.koreatech.bus.state.BusNoticeState
import `in`.koreatech.bus.type.PlaceSelectMode
import `in`.koreatech.bus.type.PlaceType
+import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.designsystem.component.topbar.KoinTopAppBar
import `in`.koreatech.koin.feature.bus.R
@@ -41,7 +43,12 @@ internal fun BusSearchScreenContent(
onNoticeClick: (BusNoticeState) -> Unit = {}
) {
- val searchButtonEnabled by remember(departure, arrival) { derivedStateOf { departure != null && arrival != null } }
+ val context = LocalContext.current
+
+ val searchButtonEnabled by remember(
+ departure,
+ arrival
+ ) { derivedStateOf { departure != null && arrival != null } }
var placeSelectMode by rememberSaveable { mutableStateOf(PlaceSelectMode.NONE) }
val disabledArrival by remember(departure) {
@@ -64,8 +71,20 @@ internal fun BusSearchScreenContent(
NoticeItem(
modifier = Modifier.padding(horizontal = 24.dp),
notice = busNoticeUiState.notice,
- onCloseIconClick = onCloseNotice,
- onNoticeClick = onNoticeClick,
+ onCloseIconClick = {
+ onCloseNotice()
+ EventLogger.logCampusClickEvent(
+ "bus_announcement_close",
+ "교통편 조회하기"
+ )
+ },
+ onNoticeClick = {
+ onNoticeClick(busNoticeUiState.notice)
+ EventLogger.logCampusClickEvent(
+ "bus_announcement",
+ "교통편 조회하기"
+ )
+ },
noticeMaxLines = 2
)
}
@@ -78,10 +97,34 @@ internal fun BusSearchScreenContent(
departure = departure?.titleRes?.let { stringResource(it) } ?: "",
arrival = arrival?.titleRes?.let { stringResource(it) } ?: "",
searchButtonEnabled = searchButtonEnabled,
- onSwapIconClicked = onSwapIconClick,
- onSearchClicked = onSearchClick,
- onDepartureFieldClicked = { placeSelectMode = PlaceSelectMode.DEPARTURE },
- onArrivalFieldClicked = { placeSelectMode = PlaceSelectMode.ARRIVAL }
+ onSwapIconClicked = {
+ EventLogger.logCampusClickEvent(
+ "swap_destination",
+ "스왑 버튼"
+ )
+ onSwapIconClick()
+ },
+ onSearchClicked = {
+ EventLogger.logCampusClickEvent(
+ "search_bus",
+ "조회하기"
+ )
+ onSearchClick()
+ },
+ onDepartureFieldClicked = {
+ EventLogger.logCampusClickEvent(
+ "departure_box",
+ "출발지 선택"
+ )
+ placeSelectMode = PlaceSelectMode.DEPARTURE
+ },
+ onArrivalFieldClicked = {
+ EventLogger.logCampusClickEvent(
+ "arrival_box",
+ "목적지 선택"
+ )
+ placeSelectMode = PlaceSelectMode.ARRIVAL
+ }
)
}
@@ -91,11 +134,18 @@ internal fun BusSearchScreenContent(
selectMode = placeSelectMode,
onConfirmSelection = {
if (placeSelectMode == PlaceSelectMode.DEPARTURE) {
+ EventLogger.logCampusClickEvent(
+ "departure_location_confirm",
+ context.getString(it.titleRes)
+ )
placeSelectMode =
if (arrival == null) PlaceSelectMode.ARRIVAL else PlaceSelectMode.NONE
onDepartureSet(it)
- }
- else if(placeSelectMode == PlaceSelectMode.ARRIVAL) {
+ } else if (placeSelectMode == PlaceSelectMode.ARRIVAL) {
+ EventLogger.logCampusClickEvent(
+ "arrival_location_confirm",
+ context.getString(it.titleRes)
+ )
placeSelectMode =
if (departure == null) PlaceSelectMode.DEPARTURE else PlaceSelectMode.NONE
onArrivalSet(it)
@@ -129,6 +179,7 @@ private fun BusSearchScreen2Preview() {
busNoticeUiState = busNoticeUiStateMock
)
}
+
@Preview(showBackground = true)
@Composable
private fun BusSearchScreen3Preview() {
diff --git a/feature/bus/src/main/java/in/koreatech/bus/screen/searchresult/composable/BusSearchResultScreenContent.kt b/feature/bus/src/main/java/in/koreatech/bus/screen/searchresult/composable/BusSearchResultScreenContent.kt
index 34b2e8ddd..0f6edc245 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/screen/searchresult/composable/BusSearchResultScreenContent.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/screen/searchresult/composable/BusSearchResultScreenContent.kt
@@ -5,14 +5,12 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -25,7 +23,6 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -35,12 +32,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.LayoutDirection
@@ -58,6 +55,7 @@ import `in`.koreatech.bus.type.BusType
import `in`.koreatech.bus.type.PlaceType
import `in`.koreatech.bus.util.formatDateValue
import `in`.koreatech.bus.util.formatDepartureTime
+import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.designsystem.component.topbar.KoinTopAppBar
import `in`.koreatech.koin.core.designsystem.noRippleClickable
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
@@ -89,6 +87,7 @@ internal fun BusSearchResultScreenContent(
selectedBusType: BusType,
onBusTypeChange: (BusType) -> Unit = {}
) {
+ val context = LocalContext.current
var showSelectDialog by rememberSaveable { mutableStateOf(false) }
val departureTime by remember(
selectedDateIndex,
@@ -183,6 +182,10 @@ internal fun BusSearchResultScreenContent(
)
},
onClick = {
+ EventLogger.logCampusClickEvent(
+ "search_result_bus_type",
+ context.getString(busType.titleRes)
+ )
isDropdownExpanded = false
onBusTypeChange(busType)
}
@@ -194,6 +197,10 @@ internal fun BusSearchResultScreenContent(
Row(
modifier = Modifier.noRippleClickable {
+ EventLogger.logCampusClickEvent(
+ "search_result_departure_time",
+ "출발 시각 설정"
+ )
showSelectDialog = true
}, verticalAlignment = Alignment.CenterVertically
) {
@@ -278,10 +285,23 @@ internal fun BusSearchResultScreenContent(
),
onDismissRequest = { showSelectDialog = false },
onDepartureNow = {
+ EventLogger.logCampusClickEvent(
+ "departure_now",
+ "지금 출발"
+ )
onMinDepartureTimeSetToNow()
showSelectDialog = false
},
onComplete = { date, daytime, hour, minute ->
+ EventLogger.logCampusClickEvent(
+ "departure_time_setting_done",
+ "시간설정: " + if (selectedDateIndex == date
+ && selectedDaytimeIndex == daytime
+ && selectedHourIndex == hour
+ && selectedMinuteIndex == minute
+ )
+ "N" else "Y"
+ )
onCompleteMinDepartureTime(date, daytime, hour, minute)
showSelectDialog = false
}, dateList = dateList,
diff --git a/feature/bus/src/main/java/in/koreatech/bus/screen/shuttle_timetable/composable/ShuttleTimetableScreenContent.kt b/feature/bus/src/main/java/in/koreatech/bus/screen/shuttle_timetable/composable/ShuttleTimetableScreenContent.kt
index da503f4b5..f77ec3530 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/screen/shuttle_timetable/composable/ShuttleTimetableScreenContent.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/screen/shuttle_timetable/composable/ShuttleTimetableScreenContent.kt
@@ -22,19 +22,23 @@ import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import `in`.koreatech.bus.component.CommonFailureView
import `in`.koreatech.bus.component.ShuttleBusOperationChip
+import `in`.koreatech.bus.component.WrongInformationText
import `in`.koreatech.bus.mock.shuttleTimetableUiStateMock1
import `in`.koreatech.bus.mock.shuttleTimetableUiStateMock2
import `in`.koreatech.bus.screen.shuttle_timetable.composable.loading.ShuttleTimetableLoading
import `in`.koreatech.bus.screen.shuttle_timetable.viewmodel.ShuttleTimetableUiState
+import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.designsystem.component.tab.KoinSurface
import `in`.koreatech.koin.core.designsystem.component.tab.KoinTabRow
import `in`.koreatech.koin.core.designsystem.component.topbar.KoinTopAppBar
@@ -58,6 +62,7 @@ fun ShuttleTimetableScreenContent(
val pagerState = rememberPagerState { 2 }
val scope = rememberCoroutineScope()
+ val context = LocalContext.current
KoinSurface(
modifier = modifier
) {
@@ -72,11 +77,10 @@ fun ShuttleTimetableScreenContent(
Column(
modifier = Modifier
.fillMaxSize()
- .verticalScroll(rememberScrollState())
) {
-
when (timetableUiState) {
is ShuttleTimetableUiState.Success -> {
+ val eventValue = "${stringResource(timetableUiState.timetable.routeType.simpleTitleRes)}_${timetableUiState.timetable.routeName}"
Column(
modifier = Modifier
.padding(horizontal = 24.dp, vertical = 16.dp)
@@ -116,6 +120,7 @@ fun ShuttleTimetableScreenContent(
) { page ->
Column(
modifier = Modifier.fillMaxSize()
+ .verticalScroll(rememberScrollState())
) {
Box(
modifier = Modifier
@@ -161,58 +166,82 @@ fun ShuttleTimetableScreenContent(
)
}
}
+ WrongInformationText(
+ modifier = Modifier.padding(top = 16.dp, start = 24.dp),
+ loggingEventValue = eventValue
+ )
Spacer(modifier = Modifier.height(120.dp))
}
}
- } else {
- HorizontalDivider(
- color = KoinTheme.colors.neutral400
- )
- Box(
- modifier = Modifier
- .fillMaxWidth()
- .height(14.dp)
- .background(color = KoinTheme.colors.neutral100)
- )
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .height(IntrinsicSize.Min),
- ) {
- ShuttleTimetableNodeItem(
- nodeItemHeightDp = nodeItemHeightDp,
- nodes = timetableUiState.timetable.nodeInfo.toPersistentList()
+ LaunchedEffect(pagerState.currentPage) {
+ EventLogger.logCampusClickEvent(
+ when(pagerState.currentPage) {
+ 0 -> "go_to_school"
+ 1 -> "go_home"
+ else -> "unknown"
+ },
+ eventValue
)
+ }
- VerticalDivider(
- modifier = Modifier.fillMaxHeight(),
- color = KoinTheme.colors.neutral300
+ } else {
+ Column(
+ modifier = Modifier.fillMaxSize()
+ .verticalScroll(rememberScrollState())
+ ) {
+ HorizontalDivider(
+ color = KoinTheme.colors.neutral400
)
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(14.dp)
+ .background(color = KoinTheme.colors.neutral100)
+ )
Row(
modifier = Modifier
.fillMaxWidth()
- .horizontalScroll(rememberScrollState())
+ .height(IntrinsicSize.Min),
) {
- timetableUiState.timetable.routeInfo.fastForEach { route ->
- ShuttleTimetableRouteItem(
- route = route,
- nodeItemHeightDp = nodeItemHeightDp,
- )
- }
+ ShuttleTimetableNodeItem(
+ nodeItemHeightDp = nodeItemHeightDp,
+ nodes = timetableUiState.timetable.nodeInfo.toPersistentList()
+ )
- /** 시간표가 화면을 못 채울 때, 상단의 회색 배경을 채우기 위함 (프리뷰 참조)
- * 더 좋은 방법을 모르겠음... */
- Spacer(
- modifier = Modifier.weight(1f).height(
- KoinTheme.typography.regular14.getMeasuredKoreanHeightDp() + 16.dp
- ).background(KoinTheme.colors.neutral100)
+ VerticalDivider(
+ modifier = Modifier.fillMaxHeight(),
+ color = KoinTheme.colors.neutral300
)
+
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .horizontalScroll(rememberScrollState())
+ ) {
+ timetableUiState.timetable.routeInfo.fastForEach { route ->
+ ShuttleTimetableRouteItem(
+ route = route,
+ nodeItemHeightDp = nodeItemHeightDp,
+ )
+ }
+
+ /** 시간표가 화면을 못 채울 때, 상단의 회색 배경을 채우기 위함 (프리뷰 참조)
+ * 더 좋은 방법을 모르겠음... */
+ Spacer(
+ modifier = Modifier.weight(1f).height(
+ KoinTheme.typography.regular14.getMeasuredKoreanHeightDp() + 16.dp
+ ).background(KoinTheme.colors.neutral100)
+ )
+ }
}
+ WrongInformationText(
+ modifier = Modifier.padding(top = 16.dp, start = 24.dp),
+ loggingEventValue = eventValue
+ )
+ Spacer(modifier = Modifier.height(120.dp))
}
-
- Spacer(modifier = Modifier.height(120.dp))
}
}
diff --git a/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/BusTimetableScreenContent.kt b/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/BusTimetableScreenContent.kt
index 38dbf5e1b..b598caaa0 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/BusTimetableScreenContent.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/BusTimetableScreenContent.kt
@@ -16,6 +16,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -46,6 +47,8 @@ import `in`.koreatech.bus.state.ShuttleCourseRouteState
import `in`.koreatech.bus.type.BusType
import `in`.koreatech.bus.type.CityBusNumberType
import `in`.koreatech.bus.type.CommonDirectionType
+import `in`.koreatech.bus.util.LocalSelectedTimetableTab
+import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.designsystem.component.tab.KoinTabRow
import `in`.koreatech.koin.core.designsystem.component.topbar.KoinTopAppBar
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
@@ -129,10 +132,23 @@ internal fun BusTimetableScreenContent(
}
Spacer(modifier = Modifier.height(8.dp))
if (busNoticeUiState is BusNoticeUiState.Show) {
+ val eventValue = selectedTimetableTypeTab.getEventValue()
NoticeItem(
notice = busNoticeUiState.notice,
- onCloseIconClick = onCloseNotice,
- onNoticeClick = onNoticeClick
+ onCloseIconClick = {
+ onCloseNotice()
+ EventLogger.logCampusClickEvent(
+ "bus_announcement_close",
+ eventValue
+ )
+ },
+ onNoticeClick = {
+ EventLogger.logCampusClickEvent(
+ "bus_announcement",
+ eventValue
+ )
+ onNoticeClick(busNoticeUiState.notice)
+ }
)
}
}
@@ -164,41 +180,47 @@ internal fun BusTimetableScreenContent(
is BusTimetableUiState.Success -> {
when (page + 1) { // BusType.ALL 때문에 +1
BusType.SHUTTLE.ordinal -> {
- ShuttleCoursesScreenContent(
- modifier = Modifier
- .background(KoinTheme.colors.neutral100)
- .verticalScroll(rememberScrollState()),
- shuttleCourses = busTimetableUiState.shuttleCourses,
- onItemClicked = onShuttleCourseRouteClick,
- )
+ CompositionLocalProvider(LocalSelectedTimetableTab provides BusType.SHUTTLE) {
+ ShuttleCoursesScreenContent(
+ modifier = Modifier
+ .background(KoinTheme.colors.neutral100)
+ .verticalScroll(rememberScrollState()),
+ shuttleCourses = busTimetableUiState.shuttleCourses,
+ onItemClicked = onShuttleCourseRouteClick,
+ )
+ }
}
BusType.EXPRESS.ordinal -> {
- ExpressTimetableScreenContent(
- modifier = Modifier
- .background(KoinTheme.colors.neutral100)
- .verticalScroll(rememberScrollState()),
- expressTimetable = busTimetableUiState.expressTimetable,
- onDirectionChanged = {
- expressDirectionGuideText =
- if (it == CommonDirectionType.TO_CHEONAN) context.getString(
- R.string.guide_koreatech_station
- ) else context.getString(R.string.guide_cheonan_station)
+ CompositionLocalProvider(LocalSelectedTimetableTab provides BusType.EXPRESS) {
+ ExpressTimetableScreenContent(
+ modifier = Modifier
+ .background(KoinTheme.colors.neutral100)
+ .verticalScroll(rememberScrollState()),
+ expressTimetable = busTimetableUiState.expressTimetable,
+ onDirectionChanged = {
+ expressDirectionGuideText =
+ if (it == CommonDirectionType.TO_CHEONAN) context.getString(
+ R.string.guide_koreatech_station
+ ) else context.getString(R.string.guide_cheonan_station)
- onExpressDirectionChange(it)
- }
- )
+ onExpressDirectionChange(it)
+ }
+ )
+ }
}
BusType.CITY.ordinal -> {
- CityTimetableScreenContent(
- modifier = Modifier
- .background(KoinTheme.colors.neutral100)
- .verticalScroll(rememberScrollState()),
- timetable = busTimetableUiState.cityTimetable,
- onBusNumberChanged = { onCityBusNumberChange(it) },
- onDirectionChanged = { onCityDirectionChange(it) },
- )
+ CompositionLocalProvider(LocalSelectedTimetableTab provides BusType.CITY) {
+ CityTimetableScreenContent(
+ modifier = Modifier
+ .background(KoinTheme.colors.neutral100)
+ .verticalScroll(rememberScrollState()),
+ timetable = busTimetableUiState.cityTimetable,
+ onBusNumberChanged = { onCityBusNumberChange(it) },
+ onDirectionChanged = { onCityDirectionChange(it) },
+ )
+ }
}
}
}
@@ -224,6 +246,13 @@ internal fun BusTimetableScreenContent(
LaunchedEffect(pagerState.targetPage) {
selectedTimetableTypeTab = BusType.entriesExceptAll[pagerState.targetPage]
}
+
+ LaunchedEffect(selectedTimetableTypeTab) {
+ EventLogger.logCampusClickEvent(
+ "timetable_bus_type_tab",
+ context.getString(selectedTimetableTypeTab.titleRes)
+ )
+ }
}
@Preview(showBackground = true)
diff --git a/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/CityTimetableScreenContent.kt b/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/CityTimetableScreenContent.kt
index d1957aaf3..8263a9289 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/CityTimetableScreenContent.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/CityTimetableScreenContent.kt
@@ -27,6 +27,7 @@ import `in`.koreatech.bus.state.CityTimetableState
import `in`.koreatech.bus.type.CityBusNumberType
import `in`.koreatech.bus.type.CommonDirectionType
import `in`.koreatech.bus.util.formatUpdatedTime
+import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.designsystem.component.chip.TextChipGroup
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
import `in`.koreatech.koin.feature.bus.R
@@ -64,6 +65,10 @@ internal fun CityTimetableScreenContent(
onChipSelected = { title ->
selectedBusNumberType =
CityBusNumberType.entries.find { context.getString(it.titleRes) == title } ?: CityBusNumberType.N400
+ EventLogger.logCampusClickEvent(
+ "city_bus_route",
+ context.getString(selectedBusNumberType.titleRes)
+ )
},
selectedChipIndexes = intArrayOf(selectedBusNumberType.ordinal),
showClickRipple = false
@@ -87,6 +92,10 @@ internal fun CityTimetableScreenContent(
onChipSelected = { title ->
selectedDirectionType =
CommonDirectionType.entries.find { context.getString(it.titleRes) == title } ?: CommonDirectionType.TO_BYEONGCHEON
+ EventLogger.logCampusClickEvent(
+ "city_bus_direction",
+ context.getString(selectedDirectionType.titleRes)
+ )
},
selectedChipIndexes = intArrayOf(selectedDirectionType.ordinal),
showClickRipple = false
diff --git a/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/CommonTimetableView.kt b/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/CommonTimetableView.kt
index 1dcdaf559..d8e03d40d 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/CommonTimetableView.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/CommonTimetableView.kt
@@ -15,8 +15,8 @@ import androidx.compose.ui.util.fastForEach
import `in`.koreatech.bus.component.WrongInformationText
import `in`.koreatech.bus.mock.commonTimetableMock
import `in`.koreatech.bus.state.CommonTimetableState
+import `in`.koreatech.bus.util.LocalSelectedTimetableTab
import `in`.koreatech.koin.core.designsystem.component.tab.KoinSurface
-import `in`.koreatech.koin.core.designsystem.component.text.LeadingIconText
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
import `in`.koreatech.koin.feature.bus.R
@@ -84,7 +84,8 @@ internal fun CommonTimetableView(
)
WrongInformationText(
- modifier = Modifier.padding(top = 4.dp)
+ modifier = Modifier.padding(top = 4.dp),
+ loggingEventValue = LocalSelectedTimetableTab.current.getEventValue()
)
}
}
diff --git a/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/ExpressTimetableScreenContent.kt b/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/ExpressTimetableScreenContent.kt
index b6a627072..c6cc0f261 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/ExpressTimetableScreenContent.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/ExpressTimetableScreenContent.kt
@@ -26,6 +26,7 @@ import `in`.koreatech.bus.mock.expressTimetableMock
import `in`.koreatech.bus.state.ExpressTimetableState
import `in`.koreatech.bus.type.CommonDirectionType
import `in`.koreatech.bus.util.formatUpdatedTime
+import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.designsystem.component.chip.TextChipGroup
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
import `in`.koreatech.koin.feature.bus.R
@@ -61,6 +62,10 @@ internal fun ExpressTimetableScreenContent(
onChipSelected = { title ->
selectedDirectionType =
CommonDirectionType.entries.find { context.getString(it.titleRes) == title } ?: CommonDirectionType.TO_BYEONGCHEON
+ EventLogger.logCampusClickEvent(
+ "ds_bus_direction",
+ context.getString(selectedDirectionType.titleRes)
+ )
},
selectedChipIndexes = intArrayOf(selectedDirectionType.ordinal),
showClickRipple = false
diff --git a/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/ShuttleCoursesScreenContent.kt b/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/ShuttleCoursesScreenContent.kt
index d1defec4b..770b5889d 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/ShuttleCoursesScreenContent.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/screen/timetable/composable/ShuttleCoursesScreenContent.kt
@@ -32,7 +32,9 @@ import `in`.koreatech.bus.state.ShuttleCourseRegionState
import `in`.koreatech.bus.state.ShuttleCourseRouteState
import `in`.koreatech.bus.state.ShuttleCoursesState
import `in`.koreatech.bus.type.ShuttleBusOperationType
+import `in`.koreatech.bus.util.LocalSelectedTimetableTab
import `in`.koreatech.bus.util.formatPeriod
+import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.designsystem.component.chip.TextChipGroup
import `in`.koreatech.koin.core.designsystem.component.tab.KoinSurface
import `in`.koreatech.koin.core.designsystem.component.text.LeadingIconText
@@ -61,6 +63,10 @@ internal fun ShuttleCoursesScreenContent(
titles = ShuttleBusOperationType.entries.map { stringResource(it.titleRes) },
onChipSelected = { title ->
selectedRouteType = ShuttleBusOperationType.entries.find { context.getString(it.titleRes) == title } ?: ShuttleBusOperationType.ALL
+ EventLogger.logCampusClickEvent(
+ "shuttle_bus_route",
+ context.getString(selectedRouteType.titleRes)
+ )
},
selectedChipIndexes = intArrayOf(selectedRouteType.ordinal),
showClickRipple = false
@@ -79,12 +85,21 @@ internal fun ShuttleCoursesScreenContent(
modifier = Modifier,
region = courseEntry.key,
shuttleCourseRoutes = filteredValue.toImmutableList(),
- onItemClicked = onItemClicked
+ onItemClicked = {
+ EventLogger.logCampusClickEvent(
+ "area_specific_route",
+ "${context.getString(it.type.simpleTitleRes)}_${it.routeName}"
+ )
+ onItemClicked(it)
+ }
)
}
}
- Column(modifier = Modifier.background(Color.White).padding(top = 8.dp).fillMaxWidth()) {
+ Column(modifier = Modifier
+ .background(Color.White)
+ .padding(top = 8.dp)
+ .fillMaxWidth()) {
Text(
modifier = Modifier.padding(horizontal = 24.dp),
text = stringResource(R.string.timetable_semester_information,
@@ -95,9 +110,12 @@ internal fun ShuttleCoursesScreenContent(
color = KoinTheme.colors.neutral500,
)
WrongInformationText(
- modifier = Modifier.padding(top = 4.dp, start = 24.dp)
+ modifier = Modifier.padding(top = 4.dp, start = 24.dp),
+ loggingEventValue = LocalSelectedTimetableTab.current.getEventValue()
)
- Spacer(modifier = Modifier.fillMaxWidth().height(120.dp))
+ Spacer(modifier = Modifier
+ .fillMaxWidth()
+ .height(120.dp))
}
}
}
diff --git a/feature/bus/src/main/java/in/koreatech/bus/type/BusType.kt b/feature/bus/src/main/java/in/koreatech/bus/type/BusType.kt
index ad580b1c6..a8b89c5cf 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/type/BusType.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/type/BusType.kt
@@ -1,6 +1,9 @@
package `in`.koreatech.bus.type
import androidx.annotation.StringRes
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.ui.res.stringResource
import `in`.koreatech.koin.feature.bus.R
// property 이름 바꾸면 안됨!!
@@ -12,6 +15,17 @@ enum class BusType(
EXPRESS(R.string.tab_express),
CITY(R.string.tab_city);
+ @Composable
+ @ReadOnlyComposable
+ fun getEventValue(): String {
+ return when(this) {
+ SHUTTLE -> stringResource(R.string.shuttle_timetable)
+ EXPRESS -> stringResource(R.string.express_timetable)
+ CITY -> stringResource(R.string.city_timetable)
+ else -> ""
+ }
+ }
+
companion object {
val entriesExceptAll = values().filter { it != ALL }
}
diff --git a/feature/bus/src/main/java/in/koreatech/bus/util/CompositionLocal.kt b/feature/bus/src/main/java/in/koreatech/bus/util/CompositionLocal.kt
index a888f229f..17f88e12d 100644
--- a/feature/bus/src/main/java/in/koreatech/bus/util/CompositionLocal.kt
+++ b/feature/bus/src/main/java/in/koreatech/bus/util/CompositionLocal.kt
@@ -1,7 +1,13 @@
package `in`.koreatech.bus.util
+import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.staticCompositionLocalOf
+import `in`.koreatech.bus.type.BusType
internal val LocalOnRefresh = staticCompositionLocalOf {
{}
+}
+
+internal val LocalSelectedTimetableTab = compositionLocalOf {
+ BusType.SHUTTLE
}
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index f4f7222cd..36f74c4c6 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -70,6 +70,7 @@ kotlinxCoroutinesTestVersion = "1.9.0"
turbineVersion = "1.2.0"
kotlinxCollectionsImmutableVersion = "0.3.8"
kspVersion = "1.9.22-1.0.16"
+firebaseCommonKtxVersion = "21.0.0"
[libraries]
@@ -194,6 +195,7 @@ timber = { module = "com.jakewharton.timber:timber", version.ref = "timber"}
coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutinesTestVersion" }
turbine = { module = "app.cash.turbine:turbine", version.ref = "turbineVersion" }
+firebase-common-ktx = { group = "com.google.firebase", name = "firebase-common-ktx", version.ref = "firebaseCommonKtxVersion" }
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradleVersion" }
diff --git a/koin/build.gradle.kts b/koin/build.gradle.kts
index 07b03d2fd..f8b24149d 100644
--- a/koin/build.gradle.kts
+++ b/koin/build.gradle.kts
@@ -94,6 +94,7 @@ dependencies {
implementation(project(":core:notification"))
implementation(project(":core:navigation"))
implementation(project(":core:designsystem"))
+ implementation(project(":core:analytics"))
implementation(project(":data"))
implementation(project(":domain"))
implementation(project(":core:onboarding"))
diff --git a/koin/src/main/java/in/koreatech/koin/ui/article/ArticleActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/article/ArticleActivity.kt
index e61474230..1fb263c4e 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/article/ArticleActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/article/ArticleActivity.kt
@@ -14,7 +14,7 @@ import `in`.koreatech.koin.core.activity.ActivityBase
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.appbar.ToolbarMenu
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.navigation.utils.EXTRA_ID
import `in`.koreatech.koin.core.util.dataBinding
import `in`.koreatech.koin.databinding.ActivityArticleBinding
diff --git a/koin/src/main/java/in/koreatech/koin/ui/article/ArticleDetailFragment.kt b/koin/src/main/java/in/koreatech/koin/ui/article/ArticleDetailFragment.kt
index 0112b3e64..5d71399a7 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/article/ArticleDetailFragment.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/article/ArticleDetailFragment.kt
@@ -18,19 +18,17 @@ import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.RecyclerView
import dagger.hilt.android.AndroidEntryPoint
-import `in`.koreatech.koin.BuildConfig
import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.activity.WebViewActivity
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.dialog.ImageZoomableDialog
import `in`.koreatech.koin.core.download.FileDownloadManager
import `in`.koreatech.koin.core.progressdialog.IProgressDialog
import `in`.koreatech.koin.core.toast.ToastUtil
import `in`.koreatech.koin.core.webview.loadKoreatechHtml
import `in`.koreatech.koin.core.webview.setOnImageClickListener
-import `in`.koreatech.koin.data.constant.URLConstant
import `in`.koreatech.koin.databinding.FragmentArticleDetailBinding
import `in`.koreatech.koin.domain.util.DateFormatUtil
import `in`.koreatech.koin.domain.util.TimeUtil
@@ -43,7 +41,6 @@ import `in`.koreatech.koin.ui.article.viewmodel.ArticleDetailViewModel
import `in`.koreatech.koin.util.ext.withLoading
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-import timber.log.Timber
import javax.inject.Inject
@AndroidEntryPoint
diff --git a/koin/src/main/java/in/koreatech/koin/ui/article/ArticleKeywordFragment.kt b/koin/src/main/java/in/koreatech/koin/ui/article/ArticleKeywordFragment.kt
index bcaaf9b12..8f55b436c 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/article/ArticleKeywordFragment.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/article/ArticleKeywordFragment.kt
@@ -21,7 +21,7 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.dialog.AlertModalDialog
import `in`.koreatech.koin.core.dialog.AlertModalDialogData
import `in`.koreatech.koin.core.permission.checkNotificationPermission
diff --git a/koin/src/main/java/in/koreatech/koin/ui/article/ArticleListFragment.kt b/koin/src/main/java/in/koreatech/koin/ui/article/ArticleListFragment.kt
index b74bbfb96..721e852b2 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/article/ArticleListFragment.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/article/ArticleListFragment.kt
@@ -25,7 +25,7 @@ import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.analytics.EventUtils
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.onboarding.ArrowDirection
import `in`.koreatech.koin.core.onboarding.OnboardingManager
import `in`.koreatech.koin.core.onboarding.OnboardingType
diff --git a/koin/src/main/java/in/koreatech/koin/ui/article/ArticleSearchFragment.kt b/koin/src/main/java/in/koreatech/koin/ui/article/ArticleSearchFragment.kt
index 3f7914244..4becded2e 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/article/ArticleSearchFragment.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/article/ArticleSearchFragment.kt
@@ -20,7 +20,7 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.progressdialog.IProgressDialog
import `in`.koreatech.koin.databinding.FragmentArticleSearchBinding
import `in`.koreatech.koin.ui.article.ArticleDetailFragment.Companion.ARTICLE_ID
diff --git a/koin/src/main/java/in/koreatech/koin/ui/dining/DiningActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/dining/DiningActivity.kt
index ce0d7fa8f..adb9b28de 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/dining/DiningActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/dining/DiningActivity.kt
@@ -4,9 +4,7 @@ import android.content.Intent
import android.os.Bundle
import androidx.activity.OnBackPressedCallback
import androidx.activity.viewModels
-import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.viewpager.widget.ViewPager
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
@@ -16,7 +14,7 @@ import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.appbar.AppBarBase
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.onboarding.OnboardingManager
import `in`.koreatech.koin.core.onboarding.OnboardingType
import `in`.koreatech.koin.core.util.dataBinding
diff --git a/koin/src/main/java/in/koreatech/koin/ui/dining/DiningItemsFragment.kt b/koin/src/main/java/in/koreatech/koin/ui/dining/DiningItemsFragment.kt
index e3b7b4eff..739334cea 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/dining/DiningItemsFragment.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/dining/DiningItemsFragment.kt
@@ -26,7 +26,7 @@ import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.abtest.ExperimentGroup
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.onboarding.OnboardingManager
import `in`.koreatech.koin.core.onboarding.OnboardingType
import `in`.koreatech.koin.core.util.dataBinding
diff --git a/koin/src/main/java/in/koreatech/koin/ui/dining/adapter/DiningAdapter.kt b/koin/src/main/java/in/koreatech/koin/ui/dining/adapter/DiningAdapter.kt
index 418261826..945248de0 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/dining/adapter/DiningAdapter.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/dining/adapter/DiningAdapter.kt
@@ -3,12 +3,9 @@ package `in`.koreatech.koin.ui.dining.adapter
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.TypedValue
-import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.FrameLayout
-import android.widget.ImageView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
@@ -20,7 +17,7 @@ import com.bumptech.glide.request.target.Target
import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.dialog.ImageZoomableDialog
import `in`.koreatech.koin.databinding.ItemDiningBinding
import `in`.koreatech.koin.domain.constant.BREAKFAST
diff --git a/koin/src/main/java/in/koreatech/koin/ui/dining/adapter/DiningOriginalAdapter.kt b/koin/src/main/java/in/koreatech/koin/ui/dining/adapter/DiningOriginalAdapter.kt
index 2a24a8e2b..89092c154 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/dining/adapter/DiningOriginalAdapter.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/dining/adapter/DiningOriginalAdapter.kt
@@ -3,12 +3,9 @@ package `in`.koreatech.koin.ui.dining.adapter
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.TypedValue
-import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.FrameLayout
-import android.widget.ImageView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
@@ -20,9 +17,8 @@ import com.bumptech.glide.request.target.Target
import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.dialog.ImageZoomableDialog
-import `in`.koreatech.koin.databinding.ItemDiningBinding
import `in`.koreatech.koin.databinding.ItemDiningOriginalBinding
import `in`.koreatech.koin.domain.constant.BREAKFAST
import `in`.koreatech.koin.domain.model.dining.Dining
diff --git a/koin/src/main/java/in/koreatech/koin/ui/login/LoginActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/login/LoginActivity.kt
index 300e042b0..19b5c2edb 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/login/LoginActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/login/LoginActivity.kt
@@ -15,7 +15,7 @@ import `in`.koreatech.koin.common.UiStatus
import `in`.koreatech.koin.core.activity.ActivityBase
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.util.dataBinding
import `in`.koreatech.koin.databinding.ActivityLoginBinding
import `in`.koreatech.koin.ui.businesslogin.BusinessLoginActivity
diff --git a/koin/src/main/java/in/koreatech/koin/ui/main/activity/MainActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/main/activity/MainActivity.kt
index 8790d1cdd..9ad3fe724 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/main/activity/MainActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/main/activity/MainActivity.kt
@@ -13,8 +13,6 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
@@ -30,7 +28,7 @@ import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventExtra
import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.analytics.EventUtils
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.navigation.Navigator
import `in`.koreatech.koin.core.navigation.SchemeType
import `in`.koreatech.koin.core.navigation.utils.EXTRA_ID
@@ -202,13 +200,25 @@ class MainActivity : KoinNavigationDrawerTimeActivity() {
setContent {
MainEntryView(
onShuttleTicketClicked = {
+ EventLogger.logCampusClickEvent(
+ "shuttle_ticket",
+ "셔틀 탑승권"
+ )
val intent = Intent(this@MainActivity, WebViewActivity::class.java)
intent.putExtra("url", "https://koreatech.unibus.kr/")
startActivity(intent)
}, onTimetableCardClicked = {
+ EventLogger.logCampusClickEvent(
+ "main_bus_timetable",
+ "버스 시간표 바로가기"
+ )
val intent = Intent(this@MainActivity, BusTimetableActivity::class.java)
startActivity(intent)
}, onSearchCardClicked = {
+ EventLogger.logCampusClickEvent(
+ "main_bus_search",
+ "가장 빠른 버스 조회하기"
+ )
val intent = Intent(this@MainActivity, BusSearchActivity::class.java)
startActivity(intent)
},
diff --git a/koin/src/main/java/in/koreatech/koin/ui/main/fragment/DiningContainerFragment.kt b/koin/src/main/java/in/koreatech/koin/ui/main/fragment/DiningContainerFragment.kt
index c1cdea4e7..823066230 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/main/fragment/DiningContainerFragment.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/main/fragment/DiningContainerFragment.kt
@@ -10,7 +10,7 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.util.dataBinding
import `in`.koreatech.koin.data.util.localized
import `in`.koreatech.koin.databinding.FragmentDiningContainerBinding
diff --git a/koin/src/main/java/in/koreatech/koin/ui/main/viewmodel/MainActivityViewModel.kt b/koin/src/main/java/in/koreatech/koin/ui/main/viewmodel/MainActivityViewModel.kt
index 11be0c6f9..72e9ae31d 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/main/viewmodel/MainActivityViewModel.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/main/viewmodel/MainActivityViewModel.kt
@@ -7,7 +7,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import `in`.koreatech.koin.core.abtest.Experiment
import `in`.koreatech.koin.core.abtest.ExperimentGroup
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.viewmodel.BaseViewModel
import `in`.koreatech.koin.domain.model.article.articleNotiContent
import `in`.koreatech.koin.domain.model.dining.Dining
diff --git a/koin/src/main/java/in/koreatech/koin/ui/navigation/KoinNavigationDrawerActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/navigation/KoinNavigationDrawerActivity.kt
index 9fbe4366c..6d8feadea 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/navigation/KoinNavigationDrawerActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/navigation/KoinNavigationDrawerActivity.kt
@@ -28,7 +28,7 @@ import `in`.koreatech.koin.constant.URL
import `in`.koreatech.koin.core.activity.ActivityBase
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.toast.ToastUtil
import `in`.koreatech.koin.data.constant.URLConstant
import `in`.koreatech.koin.domain.model.user.User
@@ -227,6 +227,20 @@ abstract class KoinNavigationDrawerActivity : ActivityBase(),
)
}
+ MenuState.BusTimetable -> {
+ EventLogger.logCampusClickEvent(
+ AnalyticsConstant.Label.HAMBURGER,
+ "버스 시간표"
+ )
+ }
+
+ MenuState.BusSearch -> {
+ EventLogger.logCampusClickEvent(
+ AnalyticsConstant.Label.HAMBURGER,
+ "교통편 조회하기"
+ )
+ }
+
else -> Unit
}
}
diff --git a/koin/src/main/java/in/koreatech/koin/ui/notification/NotificationActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/notification/NotificationActivity.kt
index f61c3b1fe..105e9b181 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/notification/NotificationActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/notification/NotificationActivity.kt
@@ -1,7 +1,6 @@
package `in`.koreatech.koin.ui.notification
import android.content.Intent
-import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
@@ -14,16 +13,14 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.permission.checkNotificationPermission
import `in`.koreatech.koin.core.activity.ActivityBase
-import `in`.koreatech.koin.core.progressdialog.IProgressDialog
import `in`.koreatech.koin.core.util.dataBinding
import `in`.koreatech.koin.core.util.setAppBarButtonClickedListener
import `in`.koreatech.koin.databinding.ActivityNotificationBinding
import `in`.koreatech.koin.domain.model.notification.SubscribesDetailType
import `in`.koreatech.koin.domain.model.notification.SubscribesType
-import `in`.koreatech.koin.ui.article.ArticleActivity
import `in`.koreatech.koin.ui.notification.viewmodel.NotificationUiState
import `in`.koreatech.koin.ui.notification.viewmodel.NotificationViewModel
import `in`.koreatech.koin.util.ext.withLoading
diff --git a/koin/src/main/java/in/koreatech/koin/ui/scheme/SchemeActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/scheme/SchemeActivity.kt
index 22774c3e2..4d07c3499 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/scheme/SchemeActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/scheme/SchemeActivity.kt
@@ -9,7 +9,7 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.koreatech.koin.core.activity.ActivityBase
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.navigation.Navigator
import `in`.koreatech.koin.core.navigation.NavigatorType
import `in`.koreatech.koin.core.navigation.SchemeType
diff --git a/koin/src/main/java/in/koreatech/koin/ui/signup/SignUpWithDetailInfoActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/signup/SignUpWithDetailInfoActivity.kt
index 85db8bae0..2615705bc 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/signup/SignUpWithDetailInfoActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/signup/SignUpWithDetailInfoActivity.kt
@@ -14,7 +14,7 @@ import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.activity.ActivityBase
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.databinding.ActivitySignUpWithDetailInfoBinding
import `in`.koreatech.koin.domain.error.signup.SignupAlreadySentEmailException
import `in`.koreatech.koin.domain.model.user.Gender
diff --git a/koin/src/main/java/in/koreatech/koin/ui/store/activity/CallBenefitStoreActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/store/activity/CallBenefitStoreActivity.kt
index 5efa509ca..6b4e73be5 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/store/activity/CallBenefitStoreActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/store/activity/CallBenefitStoreActivity.kt
@@ -1,10 +1,8 @@
package `in`.koreatech.koin.ui.store.activity
-import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
-import android.util.Log
import androidx.activity.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
@@ -16,7 +14,7 @@ import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventExtra
import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.appbar.AppBarBase
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.util.dataBinding
import `in`.koreatech.koin.databinding.ActivityCallBenefitStoreMainBinding
import `in`.koreatech.koin.domain.model.store.StoreSorter
diff --git a/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreActivity.kt
index d79e69ab4..52d6d68f2 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreActivity.kt
@@ -6,7 +6,6 @@ import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.Editable
-import android.util.Log
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
@@ -29,14 +28,13 @@ import `in`.koreatech.koin.core.analytics.EventExtra
import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.analytics.EventUtils
import `in`.koreatech.koin.core.appbar.AppBarBase
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.onboarding.OnboardingManager
import `in`.koreatech.koin.core.util.dataBinding
import `in`.koreatech.koin.core.viewpager.HorizontalMarginItemDecoration
import `in`.koreatech.koin.databinding.StoreActivityMainBinding
import `in`.koreatech.koin.domain.model.store.StoreEvent
import `in`.koreatech.koin.domain.model.store.StoreSorter
-import `in`.koreatech.koin.ui.businesssignup.BusinessSignUpCheckActivity
import `in`.koreatech.koin.ui.navigation.KoinNavigationDrawerTimeActivity
import `in`.koreatech.koin.ui.navigation.state.MenuState
import `in`.koreatech.koin.ui.store.adapter.StoreCategoriesRecyclerAdapter
@@ -49,9 +47,7 @@ import `in`.koreatech.koin.ui.store.viewmodel.StoreViewModel
import `in`.koreatech.koin.util.ext.dpToPx
import `in`.koreatech.koin.util.ext.hideSoftKeyboard
import `in`.koreatech.koin.util.ext.observeLiveData
-import `in`.koreatech.koin.util.ext.showSoftKeyboard
import `in`.koreatech.koin.util.ext.statusBarHeight
-import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.properties.Delegates
diff --git a/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreDetailActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreDetailActivity.kt
index f574060e9..87be80fac 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreDetailActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreDetailActivity.kt
@@ -24,7 +24,7 @@ import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventExtra
import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.appbar.AppBarBase
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.dialog.ImageZoomableDialog
import `in`.koreatech.koin.core.toast.ToastUtil
import `in`.koreatech.koin.core.util.dataBinding
diff --git a/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreReviewReportActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreReviewReportActivity.kt
index 131a86ccb..4edba3bbf 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreReviewReportActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/store/activity/StoreReviewReportActivity.kt
@@ -1,13 +1,9 @@
package `in`.koreatech.koin.ui.store.activity
-import android.content.Intent
-import android.net.Uri
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
-import android.util.Log
import android.view.MotionEvent
-import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.activity.viewModels
import androidx.core.content.ContextCompat
@@ -20,17 +16,12 @@ import `in`.koreatech.koin.core.activity.ActivityBase
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.appbar.AppBarBase
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.toast.ToastUtil
-import `in`.koreatech.koin.databinding.ActivitySignupCompleteBinding
import `in`.koreatech.koin.databinding.StoreActivityReportReviewBinding
-import `in`.koreatech.koin.domain.state.signup.SignupContinuationState
import `in`.koreatech.koin.domain.state.store.StoreReviewExceptionState
import `in`.koreatech.koin.domain.state.store.StoreReviewState
-import `in`.koreatech.koin.ui.store.contract.StoreDetailActivityContract
import `in`.koreatech.koin.ui.store.viewmodel.StoreReviewReportViewModel
-import `in`.koreatech.koin.ui.store.viewmodel.StoreViewModel
-import `in`.koreatech.koin.util.SnackbarUtil
import `in`.koreatech.koin.util.ext.observeLiveData
import kotlinx.coroutines.launch
diff --git a/koin/src/main/java/in/koreatech/koin/ui/store/activity/WriteReviewActivity.kt b/koin/src/main/java/in/koreatech/koin/ui/store/activity/WriteReviewActivity.kt
index b716309c8..748eee028 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/store/activity/WriteReviewActivity.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/store/activity/WriteReviewActivity.kt
@@ -22,7 +22,7 @@ import `in`.koreatech.koin.core.activity.ActivityBase
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventExtra
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.databinding.ActivityWriteReviewBinding
import `in`.koreatech.koin.domain.model.store.Review
import `in`.koreatech.koin.domain.model.store.StoreReviewContent
diff --git a/koin/src/main/java/in/koreatech/koin/ui/store/adapter/StoreDetailImageViewpagerAdapter.kt b/koin/src/main/java/in/koreatech/koin/ui/store/adapter/StoreDetailImageViewpagerAdapter.kt
index e2d854c5a..9ced4c33a 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/store/adapter/StoreDetailImageViewpagerAdapter.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/store/adapter/StoreDetailImageViewpagerAdapter.kt
@@ -7,10 +7,6 @@ import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import `in`.koreatech.koin.R
-import `in`.koreatech.koin.core.analytics.EventAction
-import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
-import `in`.koreatech.koin.core.dialog.ImageZoomableDialog
class StoreDetailImageViewpagerAdapter(
private val images: List?,
diff --git a/koin/src/main/java/in/koreatech/koin/ui/store/contract/StoreDetailActivityContract.kt b/koin/src/main/java/in/koreatech/koin/ui/store/contract/StoreDetailActivityContract.kt
index 836c75d67..5f2116815 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/store/contract/StoreDetailActivityContract.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/store/contract/StoreDetailActivityContract.kt
@@ -7,7 +7,7 @@ import androidx.activity.result.contract.ActivityResultContract
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventExtra
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.ui.store.activity.StoreActivity
import `in`.koreatech.koin.ui.store.activity.StoreDetailActivity
diff --git a/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailEventFragment.kt b/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailEventFragment.kt
index cbc70135a..9a59fac39 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailEventFragment.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailEventFragment.kt
@@ -12,7 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
import `in`.koreatech.koin.core.analytics.EventUtils
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.databinding.FragmentStoreDetailEventBinding
import `in`.koreatech.koin.domain.model.store.StoreDetailScrollType
import `in`.koreatech.koin.ui.store.adapter.StoreDetailEventRecyclerAdapter
diff --git a/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailMenuFragment.kt b/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailMenuFragment.kt
index deef23424..4d485a439 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailMenuFragment.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailMenuFragment.kt
@@ -12,7 +12,7 @@ import androidx.fragment.app.activityViewModels
import `in`.koreatech.koin.R
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.databinding.FragmentStoreDetailMenuBinding
import `in`.koreatech.koin.domain.model.store.ShopMenus
import `in`.koreatech.koin.domain.model.store.StoreDetailScrollType
diff --git a/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailReviewFragment.kt b/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailReviewFragment.kt
index 263e2c5f2..451b47ecf 100644
--- a/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailReviewFragment.kt
+++ b/koin/src/main/java/in/koreatech/koin/ui/store/fragment/StoreDetailReviewFragment.kt
@@ -17,7 +17,7 @@ import `in`.koreatech.koin.R
import `in`.koreatech.koin.contract.LoginContract
import `in`.koreatech.koin.core.analytics.EventAction
import `in`.koreatech.koin.core.analytics.EventLogger
-import `in`.koreatech.koin.core.constant.AnalyticsConstant
+import `in`.koreatech.koin.core.analytics.AnalyticsConstant
import `in`.koreatech.koin.core.toast.ToastUtil
import `in`.koreatech.koin.databinding.FragmentStoreDetailReviewBinding
import `in`.koreatech.koin.domain.model.store.ReviewFilterEnum
diff --git a/settings.gradle b/settings.gradle
index 78a3a120c..39b0a10fe 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -28,3 +28,4 @@ include ':core:onboarding'
include ':feature:timetable'
include ':core:designsystem'
include ':feature:bus'
+include ':core:analytics'