diff --git a/.gitignore b/.gitignore
index 023aca12..cf54d1e2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,3 +62,5 @@ secrets.properties
/app/release/*
/app/google-services.json
+
+.kotlin/
diff --git a/README.md b/README.md
index b92b6a40..08f1e60b 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# unifest-android
-[](https://kotlinlang.org)
+[](https://kotlinlang.org)
[](https://gradle.org/)
[](https://developer.android.com/studio)
[](https://developer.android.com/distribute/best-practices/develop/target-sdk)
@@ -23,6 +23,7 @@
## Features
## Article
+- [[Android] Type-Safe Compose Navigation 적용 - 중첩(Nested) 네비게이션 구조](https://velog.io/@mraz3068/Android-Type-Safe-Compose-Navigation-Applying-in-Nested-Navigation)
- [[Android] Github Action 를 이용하여 CD 를 적용 하는 방법](https://velog.io/@mraz3068/Apply-Android-Github-Action-CD)
- [[Android] Jetpack Compose 가로 세로 길이가 같은 반응형 다이얼로그 만들기](https://velog.io/@mraz3068/Creating-Responsive-Dialog-with-Equal-Width-and-Height-in-Jetpack-Compose)
- [[Android] Jetpack Compose 에서 Snackbar Duration 을 Custom 하는 방법](https://velog.io/@mraz3068/Android-Compose-Snackbar-Duration-Custom)
@@ -35,7 +36,7 @@
- IDE : Android Studio Iguana
- JDK : Java 17을 실행할 수 있는 JDK
-- Kotlin Language : 1.9.23
+- Kotlin Language : 2.0.0
### Language
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index d0f832d7..a99a5e84 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -64,17 +64,25 @@ dependencies {
implementations(
projects.core.common,
projects.core.data,
+ projects.core.database,
+ projects.core.datastore,
projects.core.designsystem,
+ projects.core.model,
+ projects.core.navigation,
projects.core.network,
- projects.core.datastore,
projects.core.ui,
+ projects.feature.booth,
+ projects.feature.festival,
projects.feature.home,
projects.feature.intro,
+ projects.feature.likedBooth,
projects.feature.main,
projects.feature.map,
projects.feature.menu,
+ projects.feature.navigator,
projects.feature.splash,
+ projects.feature.stamp,
projects.feature.waiting,
libs.androidx.activity.compose,
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 34f878b4..806f17f3 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -21,3 +21,97 @@
#-renamesourcefileattribute SourceFile
-keep class com.unifest.android.feature.map.model.** { *; }
+
+-dontwarn com.unifest.android.core.common.ErrorHandlerActions
+-dontwarn com.unifest.android.core.common.HandleExceptionKt
+-dontwarn com.unifest.android.core.common.ObserveEventKt
+-dontwarn com.unifest.android.core.common.PermissionDialogButtonType
+-dontwarn com.unifest.android.core.common.UiText$DirectString
+-dontwarn com.unifest.android.core.common.UiText
+-dontwarn com.unifest.android.core.common.extension.ContextKt
+-dontwarn com.unifest.android.core.common.utils.DateUtilsKt
+-dontwarn com.unifest.android.core.common.utils.DpToPxKt
+-dontwarn com.unifest.android.core.data.datasource.RemoteConfigDataSource
+-dontwarn com.unifest.android.core.data.datasource.RemoteConfigDataSourceImpl
+-dontwarn com.unifest.android.core.data.di.FirebaseModule_ProvideMessagingFactory
+-dontwarn com.unifest.android.core.data.di.FirebaseModule_ProvideRemoteConfigFactory
+-dontwarn com.unifest.android.core.data.repository.BoothRepository
+-dontwarn com.unifest.android.core.data.repository.BoothRepositoryImpl
+-dontwarn com.unifest.android.core.data.repository.FestivalRepository
+-dontwarn com.unifest.android.core.data.repository.FestivalRepositoryImpl
+-dontwarn com.unifest.android.core.data.repository.LikedBoothRepository
+-dontwarn com.unifest.android.core.data.repository.LikedBoothRepositoryImpl
+-dontwarn com.unifest.android.core.data.repository.LikedFestivalRepository
+-dontwarn com.unifest.android.core.data.repository.LikedFestivalRepositoryImpl
+-dontwarn com.unifest.android.core.data.repository.MessagingRepository
+-dontwarn com.unifest.android.core.data.repository.MessagingRepositoryImpl
+-dontwarn com.unifest.android.core.data.repository.OnboardingRepository
+-dontwarn com.unifest.android.core.data.repository.OnboardingRepositoryImpl
+-dontwarn com.unifest.android.core.data.repository.RemoteConfigRepository
+-dontwarn com.unifest.android.core.data.repository.RemoteConfigRepositoryImpl
+-dontwarn com.unifest.android.core.data.repository.WaitingRepository
+-dontwarn com.unifest.android.core.data.repository.WaitingRepositoryImpl
+-dontwarn com.unifest.android.core.database.LikedBoothDao
+-dontwarn com.unifest.android.core.database.LikedFestivalDao
+-dontwarn com.unifest.android.core.database.di.DaoModule_ProvideLikedBoothDaoFactory
+-dontwarn com.unifest.android.core.database.di.DaoModule_ProvideLikedFestivalDaoFactory
+-dontwarn com.unifest.android.core.database.di.DatabaseModule_ProvideLikedBoothDatabaseFactory
+-dontwarn com.unifest.android.core.database.di.DatabaseModule_ProvideLikedFestivalDatabaseFactory
+-dontwarn com.unifest.android.core.datastore.OnboardingDataSource
+-dontwarn com.unifest.android.core.datastore.OnboardingDataSourceImpl
+-dontwarn com.unifest.android.core.datastore.RecentLikedFestivalDataSource
+-dontwarn com.unifest.android.core.datastore.RecentLikedFestivalDataSourceImpl
+-dontwarn com.unifest.android.core.datastore.TokenDataSource
+-dontwarn com.unifest.android.core.datastore.TokenDataSourceImpl
+-dontwarn com.unifest.android.core.datastore.di.DataStoreModule_ProvideOnboardingDataStore$datastore_releaseFactory
+-dontwarn com.unifest.android.core.datastore.di.DataStoreModule_ProvideRecentFestivalDataStore$datastore_releaseFactory
+-dontwarn com.unifest.android.core.designsystem.component.ButtonKt
+-dontwarn com.unifest.android.core.designsystem.component.DialogKt
+-dontwarn com.unifest.android.core.designsystem.component.LoadingWheelKt
+-dontwarn com.unifest.android.core.designsystem.component.NetworkImageKt
+-dontwarn com.unifest.android.core.designsystem.component.ScaffoldKt
+-dontwarn com.unifest.android.core.designsystem.component.SearchTextFieldKt
+-dontwarn com.unifest.android.core.designsystem.component.SnackBarKt
+-dontwarn com.unifest.android.core.designsystem.theme.ColorKt
+-dontwarn com.unifest.android.core.designsystem.theme.FontKt
+-dontwarn com.unifest.android.core.designsystem.theme.ThemeKt
+-dontwarn com.unifest.android.core.navigation.MainTabRoute$Home
+-dontwarn com.unifest.android.core.navigation.MainTabRoute$Map
+-dontwarn com.unifest.android.core.navigation.MainTabRoute$Menu
+-dontwarn com.unifest.android.core.navigation.MainTabRoute$Stamp
+-dontwarn com.unifest.android.core.navigation.MainTabRoute$Waiting
+-dontwarn com.unifest.android.core.navigation.MainTabRoute
+-dontwarn com.unifest.android.core.navigation.Route
+-dontwarn com.unifest.android.core.network.di.ApiModule_ProvideUnifestService$network_releaseFactory
+-dontwarn com.unifest.android.core.network.di.NetworkModule_ProvideHttpLoggingInterceptor$network_releaseFactory
+-dontwarn com.unifest.android.core.network.di.NetworkModule_ProvideUnifestApiRetrofit$network_releaseFactory
+-dontwarn com.unifest.android.core.network.di.NetworkModule_ProvideUnifestOkHttpClient$network_releaseFactory
+-dontwarn com.unifest.android.core.network.service.UnifestService
+-dontwarn com.unifest.android.core.ui.component.CameraPermissionTextProvider
+-dontwarn com.unifest.android.core.ui.component.LikedFestivalGridKt
+-dontwarn com.unifest.android.core.ui.component.PermissionDialogKt
+-dontwarn com.unifest.android.core.ui.component.PermissionTextProvider
+-dontwarn com.unifest.android.feature.booth.navigation.BoothNavigationKt
+-dontwarn com.unifest.android.feature.booth.viewmodel.BoothViewModel
+-dontwarn com.unifest.android.feature.booth.viewmodel.BoothViewModel_HiltModules$KeyModule
+-dontwarn com.unifest.android.feature.festival.viewmodel.FestivalViewModel
+-dontwarn com.unifest.android.feature.festival.viewmodel.FestivalViewModel_HiltModules$KeyModule
+-dontwarn com.unifest.android.feature.home.navigation.HomeNavigationKt
+-dontwarn com.unifest.android.feature.home.viewmodel.HomeViewModel
+-dontwarn com.unifest.android.feature.home.viewmodel.HomeViewModel_HiltModules$KeyModule
+-dontwarn com.unifest.android.feature.liked_booth.navigation.LikedBoothNavigationKt
+-dontwarn com.unifest.android.feature.liked_booth.viewmodel.LikedBoothViewModel
+-dontwarn com.unifest.android.feature.liked_booth.viewmodel.LikedBoothViewModel_HiltModules$KeyModule
+-dontwarn com.unifest.android.feature.map.navigation.MapNavigationKt
+-dontwarn com.unifest.android.feature.map.viewmodel.MapViewModel
+-dontwarn com.unifest.android.feature.map.viewmodel.MapViewModel_HiltModules$KeyModule
+-dontwarn com.unifest.android.feature.menu.navigation.MenuNavigationKt
+-dontwarn com.unifest.android.feature.menu.viewmodel.MenuViewModel
+-dontwarn com.unifest.android.feature.menu.viewmodel.MenuViewModel_HiltModules$KeyModule
+-dontwarn com.unifest.android.feature.navigator.IntroNavigator
+-dontwarn com.unifest.android.feature.navigator.MainNavigator
+-dontwarn com.unifest.android.feature.navigator.Navigator$DefaultImpls
+-dontwarn com.unifest.android.feature.navigator.Navigator
+-dontwarn com.unifest.android.feature.waiting.navigation.WaitingNavigationKt
+-dontwarn com.unifest.android.feature.waiting.viewmodel.WaitingViewModel
+-dontwarn com.unifest.android.feature.waiting.viewmodel.WaitingViewModel_HiltModules$KeyModule
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e7f766b6..854767d6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,6 +5,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/kotlin/com/unifest/android/initializer/FirebaseMessagingInitializer.kt b/app/src/main/kotlin/com/unifest/android/initializer/FirebaseMessagingInitializer.kt
new file mode 100644
index 00000000..130dbbc3
--- /dev/null
+++ b/app/src/main/kotlin/com/unifest/android/initializer/FirebaseMessagingInitializer.kt
@@ -0,0 +1,23 @@
+package com.unifest.android.initializer
+
+import android.content.Context
+import androidx.startup.Initializer
+import com.google.firebase.messaging.FirebaseMessaging
+import timber.log.Timber
+
+class FirebaseMessagingInitializer : Initializer {
+ override fun create(context: Context) {
+ FirebaseMessaging.getInstance().subscribeToTopic("2")
+ .addOnCompleteListener { task ->
+ if (task.isSuccessful) {
+ Timber.d("Subscribed to topic successfully")
+ } else {
+ Timber.e("Failed to subscribe to topic")
+ }
+ }
+ }
+
+ override fun dependencies(): List>> {
+ return emptyList()
+ }
+}
diff --git a/app/src/main/kotlin/com/unifest/android/service/UnifestFirebaseMessagingService.kt b/app/src/main/kotlin/com/unifest/android/service/UnifestFirebaseMessagingService.kt
new file mode 100644
index 00000000..07f3f3df
--- /dev/null
+++ b/app/src/main/kotlin/com/unifest/android/service/UnifestFirebaseMessagingService.kt
@@ -0,0 +1,75 @@
+package com.unifest.android.service
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import androidx.core.app.NotificationCompat
+import com.google.firebase.messaging.FirebaseMessagingService
+import com.google.firebase.messaging.RemoteMessage
+import com.unifest.android.core.designsystem.R as designR
+import com.unifest.android.feature.main.MainActivity
+import timber.log.Timber
+
+class UnifestFirebaseMessagingService : FirebaseMessagingService() {
+ override fun onMessageReceived(remoteMessage: RemoteMessage) {
+ super.onMessageReceived(remoteMessage)
+ if (remoteMessage.notification != null) {
+ sendNotification(remoteMessage)
+ }
+ }
+
+ private fun sendNotification(remoteMessage: RemoteMessage) {
+ val requestCode = System.currentTimeMillis().toInt()
+
+ val intent = Intent(this, MainActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).also {
+ if (remoteMessage.data["boothId"] != null) {
+ if (remoteMessage.data["waitingId"] != null) {
+ Timber.tag("UnifestFirebaseMessagingService").d("waitingId: ${remoteMessage.data["waitingId"]}")
+ putExtra("navigate_to_waiting", true)
+ putExtra("waitingId", remoteMessage.data["waitingId"])
+ } else {
+ Timber.tag("UnifestFirebaseMessagingService").d("boothId: ${remoteMessage.data["boothId"]}")
+ putExtra("navigate_to_booth", true)
+ putExtra("boothId", remoteMessage.data["boothId"])
+ }
+ }
+ }
+ }
+
+ val pendingIntentFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ } else {
+ PendingIntent.FLAG_UPDATE_CURRENT
+ }
+ val pendingIntent = PendingIntent.getActivity(this, requestCode, intent, pendingIntentFlags)
+
+ val channelId = CHANNEL_ID
+
+ val notificationBuilder = NotificationCompat.Builder(this, channelId)
+ .setSmallIcon(designR.mipmap.ic_launcher)
+ .setContentTitle(remoteMessage.notification?.title.toString())
+ .setContentText(remoteMessage.notification?.body.toString())
+ .setAutoCancel(true)
+ .setContentIntent(pendingIntent)
+
+ val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+
+ val channel = NotificationChannel(channelId, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH)
+ notificationManager.createNotificationChannel(channel)
+
+ notificationManager.notify(requestCode, notificationBuilder.build())
+ }
+
+ override fun onNewToken(token: String) {
+ Timber.d("Refreshed token: $token")
+ }
+
+ companion object {
+ private const val CHANNEL_ID = "unifest"
+ private const val CHANNEL_NAME = "unifest_notification"
+ }
+}
diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts
index dfe28ba0..edac0e96 100644
--- a/build-logic/build.gradle.kts
+++ b/build-logic/build.gradle.kts
@@ -34,8 +34,9 @@ repositories {
}
java {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
+ toolchain {
+ languageVersion.set(JavaLanguageVersion.of(17))
+ }
}
kotlin {
@@ -46,6 +47,7 @@ dependencies {
compileOnly(libs.gradle.android)
compileOnly(libs.gradle.kotlin)
compileOnly(libs.gradle.androidx.room)
+ compileOnly(libs.compose.compiler.extension)
compileOnly(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
}
diff --git a/build-logic/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt b/build-logic/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt
index f22cd8a6..8937b66e 100644
--- a/build-logic/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt
+++ b/build-logic/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt
@@ -6,7 +6,7 @@ import org.gradle.kotlin.dsl.configure
internal class AndroidApplicationComposeConventionPlugin : BuildLogicConventionPlugin(
{
- applyPlugins(Plugins.AndroidApplication)
+ applyPlugins(Plugins.ANDROID_APPLICATION, Plugins.COMPOSE_COMPILER)
extensions.configure {
configureCompose(this)
diff --git a/build-logic/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/src/main/kotlin/AndroidApplicationConventionPlugin.kt
index 67a8f93e..06bf4ea0 100644
--- a/build-logic/src/main/kotlin/AndroidApplicationConventionPlugin.kt
+++ b/build-logic/src/main/kotlin/AndroidApplicationConventionPlugin.kt
@@ -7,7 +7,7 @@ import org.gradle.kotlin.dsl.configure
internal class AndroidApplicationConventionPlugin : BuildLogicConventionPlugin(
{
- applyPlugins(Plugins.AndroidApplication, Plugins.KotlinAndroid)
+ applyPlugins(Plugins.ANDROID_APPLICATION, Plugins.KOTLIN_ANDROID)
extensions.configure {
configureAndroid(this)
diff --git a/build-logic/src/main/kotlin/AndroidFeatureConventionPlugin.kt b/build-logic/src/main/kotlin/AndroidFeatureConventionPlugin.kt
index a42a0d76..859aa95a 100644
--- a/build-logic/src/main/kotlin/AndroidFeatureConventionPlugin.kt
+++ b/build-logic/src/main/kotlin/AndroidFeatureConventionPlugin.kt
@@ -17,6 +17,7 @@ internal class AndroidFeatureConventionPlugin : BuildLogicConventionPlugin(
implementation(project(path = ":core:designsystem"))
implementation(project(path = ":core:model"))
implementation(project(path = ":core:ui"))
+ implementation(project(path = ":core:navigation"))
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.hilt.navigation.compose)
diff --git a/build-logic/src/main/kotlin/AndroidFirebaseConventionPlugin.kt b/build-logic/src/main/kotlin/AndroidFirebaseConventionPlugin.kt
index 893f1ac8..c7a1cd96 100644
--- a/build-logic/src/main/kotlin/AndroidFirebaseConventionPlugin.kt
+++ b/build-logic/src/main/kotlin/AndroidFirebaseConventionPlugin.kt
@@ -6,13 +6,14 @@ import org.gradle.kotlin.dsl.dependencies
internal class AndroidFirebaseConventionPlugin : BuildLogicConventionPlugin(
{
- applyPlugins(Plugins.GoogleServices, Plugins.FirebaseCrashlytics)
+ applyPlugins(Plugins.GOOGLE_SERVICES, Plugins.FIREBASE_CRASHLYTICS)
dependencies {
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.analytics)
implementation(libs.firebase.crashlytics)
implementation(libs.firebase.config)
+ implementation(libs.firebase.messaging)
}
},
)
diff --git a/build-logic/src/main/kotlin/AndroidHiltConventionPlugin.kt b/build-logic/src/main/kotlin/AndroidHiltConventionPlugin.kt
index a6efc68b..33f750eb 100644
--- a/build-logic/src/main/kotlin/AndroidHiltConventionPlugin.kt
+++ b/build-logic/src/main/kotlin/AndroidHiltConventionPlugin.kt
@@ -7,7 +7,7 @@ import org.gradle.kotlin.dsl.dependencies
internal class AndroidHiltConventionPlugin : BuildLogicConventionPlugin(
{
- applyPlugins(Plugins.hilt, Plugins.Ksp)
+ applyPlugins(Plugins.HILT, Plugins.KSP)
dependencies {
implementation(libs.hilt.android)
diff --git a/build-logic/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt b/build-logic/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt
index 3a661bbd..cf0b5b87 100644
--- a/build-logic/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt
+++ b/build-logic/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt
@@ -6,7 +6,7 @@ import org.gradle.kotlin.dsl.configure
internal class AndroidLibraryComposeConventionPlugin : BuildLogicConventionPlugin(
{
- applyPlugins(Plugins.AndroidLibrary)
+ applyPlugins(Plugins.ANDROID_LIBRARY, Plugins.COMPOSE_COMPILER)
extensions.configure {
configureCompose(this)
diff --git a/build-logic/src/main/kotlin/AndroidLibraryConventionPlugin.kt b/build-logic/src/main/kotlin/AndroidLibraryConventionPlugin.kt
index 4c4f8c30..eaac2499 100644
--- a/build-logic/src/main/kotlin/AndroidLibraryConventionPlugin.kt
+++ b/build-logic/src/main/kotlin/AndroidLibraryConventionPlugin.kt
@@ -6,7 +6,7 @@ import com.unifest.android.libs
import org.gradle.kotlin.dsl.configure
internal class AndroidLibraryConventionPlugin : BuildLogicConventionPlugin({
- applyPlugins(Plugins.AndroidLibrary, Plugins.KotlinAndroid)
+ applyPlugins(Plugins.ANDROID_LIBRARY, Plugins.KOTLIN_ANDROID)
extensions.configure {
configureAndroid(this)
diff --git a/build-logic/src/main/kotlin/AndroidRetrofitConventionPlugin.kt b/build-logic/src/main/kotlin/AndroidRetrofitConventionPlugin.kt
index c78e6c05..a61a022a 100644
--- a/build-logic/src/main/kotlin/AndroidRetrofitConventionPlugin.kt
+++ b/build-logic/src/main/kotlin/AndroidRetrofitConventionPlugin.kt
@@ -6,7 +6,7 @@ import org.gradle.kotlin.dsl.dependencies
internal class AndroidRetrofitConventionPlugin : BuildLogicConventionPlugin(
{
- applyPlugins(Plugins.KotlinxSerialization)
+ applyPlugins(Plugins.KOTLINX_SERIALIZATION)
dependencies {
implementation(libs.retrofit)
diff --git a/build-logic/src/main/kotlin/AndroidRoomConventionPlugin.kt b/build-logic/src/main/kotlin/AndroidRoomConventionPlugin.kt
index 5a2eb0e8..2f3426c5 100644
--- a/build-logic/src/main/kotlin/AndroidRoomConventionPlugin.kt
+++ b/build-logic/src/main/kotlin/AndroidRoomConventionPlugin.kt
@@ -9,7 +9,7 @@ import org.gradle.kotlin.dsl.dependencies
class AndroidRoomConventionPlugin : BuildLogicConventionPlugin(
{
- applyPlugins(Plugins.AndroidxRoom, Plugins.KotlinxSerialization, Plugins.Ksp)
+ applyPlugins(Plugins.ANDROIDX_ROOM, Plugins.KOTLINX_SERIALIZATION, Plugins.KSP)
extensions.configure {
// The schemas directory contains a schema file for each version of the Room database.
diff --git a/build-logic/src/main/kotlin/JvmKotlinConventionPlugin.kt b/build-logic/src/main/kotlin/JvmKotlinConventionPlugin.kt
index 100e4762..28bd68e8 100644
--- a/build-logic/src/main/kotlin/JvmKotlinConventionPlugin.kt
+++ b/build-logic/src/main/kotlin/JvmKotlinConventionPlugin.kt
@@ -9,7 +9,7 @@ import org.gradle.kotlin.dsl.dependencies
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
internal class JvmKotlinConventionPlugin : BuildLogicConventionPlugin({
- applyPlugins(Plugins.JavaLibrary, Plugins.KotlinJvm)
+ applyPlugins(Plugins.JAVA_LIBRARY, Plugins.KOTLIN_JVM)
extensions.configure {
sourceCompatibility = ApplicationConfig.JavaVersion
diff --git a/build-logic/src/main/kotlin/com/unifest/android/Android.kt b/build-logic/src/main/kotlin/com/unifest/android/Android.kt
index ddd66968..6252fcd7 100644
--- a/build-logic/src/main/kotlin/com/unifest/android/Android.kt
+++ b/build-logic/src/main/kotlin/com/unifest/android/Android.kt
@@ -7,7 +7,7 @@ import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
-internal fun Project.configureAndroid(extension: CommonExtension<*, *, *, *, *>) {
+internal fun Project.configureAndroid(extension: CommonExtension<*, *, *, *, *, *>) {
extension.apply {
compileSdk = libs.versions.compileSdk.get().toInt()
diff --git a/build-logic/src/main/kotlin/com/unifest/android/Compose.kt b/build-logic/src/main/kotlin/com/unifest/android/Compose.kt
index 33e26d02..b4587b1d 100644
--- a/build-logic/src/main/kotlin/com/unifest/android/Compose.kt
+++ b/build-logic/src/main/kotlin/com/unifest/android/Compose.kt
@@ -2,41 +2,25 @@ package com.unifest.android
import com.android.build.api.dsl.CommonExtension
import org.gradle.api.Project
+import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
-import org.gradle.kotlin.dsl.withType
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginExtension
-internal fun Project.configureCompose(extension: CommonExtension<*, *, *, *, *>) {
+internal fun Project.configureCompose(extension: CommonExtension<*, *, *, *, *, *>) {
extension.apply {
- buildFeatures {
- compose = true
- }
-
- composeOptions {
- kotlinCompilerExtensionVersion = libs.versions.androidx.compose.compiler.get()
- }
-
dependencies {
- implementation(libs.androidx.compose.bom)
- androidTestImplementation(libs.androidx.compose.bom)
- implementation(libs.androidx.compose.material.iconsExtended)
- implementation(libs.androidx.compose.material3)
- implementation(libs.androidx.compose.ui)
- implementation(libs.androidx.compose.ui.tooling.preview)
+ implementation(libs.bundles.androidx.compose)
debugImplementation(libs.androidx.compose.ui.tooling)
}
- }
- tasks.withType().configureEach {
- kotlinOptions {
- freeCompilerArgs = freeCompilerArgs + listOf(
- "-P",
- "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=$rootDir/report/compose-metrics",
- )
- freeCompilerArgs = freeCompilerArgs + listOf(
- "-P",
- "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=$rootDir/report/compose-reports",
- )
+ configure {
+ enableStrongSkippingMode.set(true)
+ includeSourceInformation.set(true)
+
+ metricsDestination.file("build/composeMetrics")
+ reportsDestination.file("build/composeReports")
+
+ stabilityConfigurationFile.set(project.rootDir.resolve("stability.config.conf"))
}
}
}
diff --git a/build-logic/src/main/kotlin/com/unifest/android/Extensions.kt b/build-logic/src/main/kotlin/com/unifest/android/Extensions.kt
index 47934c0c..9eb35d79 100644
--- a/build-logic/src/main/kotlin/com/unifest/android/Extensions.kt
+++ b/build-logic/src/main/kotlin/com/unifest/android/Extensions.kt
@@ -22,14 +22,14 @@ internal fun Project.applyPlugins(vararg plugins: String) {
}
internal val Project.isAndroidProject: Boolean
- get() = pluginManager.hasPlugin(Plugins.AndroidApplication) ||
- pluginManager.hasPlugin(Plugins.AndroidLibrary)
+ get() = pluginManager.hasPlugin(Plugins.ANDROID_APPLICATION) ||
+ pluginManager.hasPlugin(Plugins.ANDROID_LIBRARY)
-internal val Project.androidExtensions: CommonExtension<*, *, *, *, *>
+internal val Project.androidExtensions: CommonExtension<*, *, *, *, *, *>
get() {
- return if (pluginManager.hasPlugin(Plugins.AndroidApplication)) {
+ return if (pluginManager.hasPlugin(Plugins.ANDROID_APPLICATION)) {
extensions.getByType()
- } else if (pluginManager.hasPlugin(Plugins.AndroidLibrary)) {
+ } else if (pluginManager.hasPlugin(Plugins.ANDROID_LIBRARY)) {
extensions.getByType()
} else {
throw GradleException("The provided project does not have the Android plugin applied. ($name)")
diff --git a/build-logic/src/main/kotlin/com/unifest/android/Plugins.kt b/build-logic/src/main/kotlin/com/unifest/android/Plugins.kt
index 0897d90c..27a9de1d 100644
--- a/build-logic/src/main/kotlin/com/unifest/android/Plugins.kt
+++ b/build-logic/src/main/kotlin/com/unifest/android/Plugins.kt
@@ -1,21 +1,21 @@
package com.unifest.android
internal object Plugins {
- const val JavaLibrary = "java-library"
- const val KotlinJvm = "org.jetbrains.kotlin.jvm"
+ const val JAVA_LIBRARY = "java-library"
- const val KotlinAndroid = "org.jetbrains.kotlin.android"
+ const val KOTLIN_JVM = "org.jetbrains.kotlin.jvm"
+ const val KOTLIN_ANDROID = "org.jetbrains.kotlin.android"
+ const val KOTLINX_SERIALIZATION = "org.jetbrains.kotlin.plugin.serialization"
- const val KotlinxSerialization = "org.jetbrains.kotlin.plugin.serialization"
+ const val ANDROID_APPLICATION = "com.android.application"
+ const val ANDROID_LIBRARY = "com.android.library"
+ const val COMPOSE_COMPILER = "org.jetbrains.kotlin.plugin.compose"
- const val AndroidApplication = "com.android.application"
- const val AndroidLibrary = "com.android.library"
+ const val ANDROIDX_ROOM = "androidx.room"
- const val AndroidxRoom = "androidx.room"
+ const val HILT = "dagger.hilt.android.plugin"
+ const val KSP = "com.google.devtools.ksp"
- const val hilt = "dagger.hilt.android.plugin"
- const val Ksp = "com.google.devtools.ksp"
-
- const val GoogleServices = "com.google.gms.google-services"
- const val FirebaseCrashlytics = "com.google.firebase.crashlytics"
+ const val GOOGLE_SERVICES = "com.google.gms.google-services"
+ const val FIREBASE_CRASHLYTICS = "com.google.firebase.crashlytics"
}
diff --git a/build.gradle.kts b/build.gradle.kts
index 05b5205e..7a371da9 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -7,9 +7,11 @@ plugins {
alias(libs.plugins.kotlin.ktlint)
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.serialization) apply false
+ alias(libs.plugins.kotlin.parcelize) apply false
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.androidx.room) apply false
+ alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.hilt) apply false
alias(libs.plugins.google.service) apply false
alias(libs.plugins.firebase.crashlytics) apply false
diff --git a/core/common/build.gradle.kts b/core/common/build.gradle.kts
index 1ee4995f..b1875060 100644
--- a/core/common/build.gradle.kts
+++ b/core/common/build.gradle.kts
@@ -5,7 +5,7 @@ plugins {
alias(libs.plugins.unifest.android.library.compose)
alias(libs.plugins.unifest.android.hilt)
alias(libs.plugins.unifest.android.retrofit)
- id("kotlin-parcelize")
+ alias(libs.plugins.kotlin.parcelize)
}
android {
diff --git a/core/common/src/main/kotlin/com/unifest/android/core/common/MultipleEventsCutter.kt b/core/common/src/main/kotlin/com/unifest/android/core/common/MultipleEventsCutter.kt
index d524ab49..3d4fe594 100644
--- a/core/common/src/main/kotlin/com/unifest/android/core/common/MultipleEventsCutter.kt
+++ b/core/common/src/main/kotlin/com/unifest/android/core/common/MultipleEventsCutter.kt
@@ -1,12 +1,12 @@
package com.unifest.android.core.common
-internal interface MultipleEventsCutter {
+interface MultipleEventsCutter {
fun processEvent(event: () -> Unit)
companion object
}
-internal fun MultipleEventsCutter.Companion.get(): MultipleEventsCutter =
+fun MultipleEventsCutter.Companion.get(): MultipleEventsCutter =
MultipleEventsCutterImpl()
private class MultipleEventsCutterImpl : MultipleEventsCutter {
diff --git a/core/common/src/main/kotlin/com/unifest/android/core/common/PermissionDialogButtonType.kt b/core/common/src/main/kotlin/com/unifest/android/core/common/PermissionDialogButtonType.kt
new file mode 100644
index 00000000..a6811db1
--- /dev/null
+++ b/core/common/src/main/kotlin/com/unifest/android/core/common/PermissionDialogButtonType.kt
@@ -0,0 +1,7 @@
+package com.unifest.android.core.common
+
+enum class PermissionDialogButtonType {
+ DISMISS,
+ NAVIGATE_TO_APP_SETTING,
+ CONFIRM,
+}
diff --git a/core/common/src/main/kotlin/com/unifest/android/core/common/extension/Activity.kt b/core/common/src/main/kotlin/com/unifest/android/core/common/extension/Activity.kt
index 0839b608..f37bd6b2 100644
--- a/core/common/src/main/kotlin/com/unifest/android/core/common/extension/Activity.kt
+++ b/core/common/src/main/kotlin/com/unifest/android/core/common/extension/Activity.kt
@@ -24,7 +24,7 @@ inline fun Activity.startActivityWithAnimation(
if (withFinish) finish()
}
-fun Activity.goToAppSettings() {
+fun Activity.navigateToAppSetting() {
Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null),
diff --git a/core/common/src/main/kotlin/com/unifest/android/core/common/utils/DpToPx.kt b/core/common/src/main/kotlin/com/unifest/android/core/common/utils/DpToPx.kt
new file mode 100644
index 00000000..d86a458e
--- /dev/null
+++ b/core/common/src/main/kotlin/com/unifest/android/core/common/utils/DpToPx.kt
@@ -0,0 +1,10 @@
+package com.unifest.android.core.common.utils
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Dp
+
+@Composable
+fun dpToPx(dp: Dp): Float {
+ return with(LocalDensity.current) { dp.toPx() }
+}
diff --git a/core/common/src/main/kotlin/com/unifest/android/core/common/utils/ParseAndFormatTime.kt b/core/common/src/main/kotlin/com/unifest/android/core/common/utils/ParseAndFormatTime.kt
new file mode 100644
index 00000000..d983f0f5
--- /dev/null
+++ b/core/common/src/main/kotlin/com/unifest/android/core/common/utils/ParseAndFormatTime.kt
@@ -0,0 +1,23 @@
+package com.unifest.android.core.common.utils
+
+import java.time.LocalTime
+import java.time.format.DateTimeFormatter
+import java.time.format.DateTimeParseException
+
+// 포매터 정의
+val formatter = DateTimeFormatter.ofPattern("HH:mm")
+val parser = DateTimeFormatter.ofPattern("HH:mm:ss")
+
+// 시간 파싱 및 형식화 함수
+fun parseAndFormatTime(time: String?): Pair {
+ return if (time.isNullOrBlank() || time == "등록된 정보가 없습니다") {
+ "등록된 정보가 없습니다" to null
+ } else {
+ try {
+ val localTime = LocalTime.parse(time, parser)
+ localTime.format(formatter) to localTime
+ } catch (e: DateTimeParseException) {
+ "등록된 정보가 없습니다" to null
+ }
+ }
+}
diff --git a/core/common/src/main/kotlin/com/unifest/android/core/common/utils/PhoneNumberVisualTransformation.kt b/core/common/src/main/kotlin/com/unifest/android/core/common/utils/PhoneNumberVisualTransformation.kt
new file mode 100644
index 00000000..cbee638d
--- /dev/null
+++ b/core/common/src/main/kotlin/com/unifest/android/core/common/utils/PhoneNumberVisualTransformation.kt
@@ -0,0 +1,40 @@
+package com.unifest.android.core.common.utils
+
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.input.OffsetMapping
+import androidx.compose.ui.text.input.TransformedText
+import androidx.compose.ui.text.input.VisualTransformation
+
+class PhoneNumberVisualTransformation : VisualTransformation {
+ override fun filter(text: AnnotatedString): TransformedText {
+ val trimmed = if (text.text.length >= 11) text.text.substring(0..10) else text.text
+ val out = StringBuilder()
+
+ for (i in trimmed.indices) {
+ out.append(trimmed[i])
+ if (i == 2 || i == 6) out.append('-')
+ }
+
+ val phoneNumberOffsetTranslator = object : OffsetMapping {
+ override fun originalToTransformed(offset: Int): Int {
+ return when {
+ offset <= 2 -> offset
+ offset <= 6 -> offset + 1
+ offset <= 10 -> offset + 2
+ else -> out.length
+ }
+ }
+
+ override fun transformedToOriginal(offset: Int): Int {
+ return when {
+ offset <= 3 -> offset
+ offset <= 8 -> offset - 1
+ offset <= out.length -> offset - 2
+ else -> trimmed.length
+ }
+ }
+ }
+
+ return TransformedText(AnnotatedString(out.toString()), phoneNumberOffsetTranslator)
+ }
+}
diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts
index bb0eff1b..94e437e4 100644
--- a/core/data/build.gradle.kts
+++ b/core/data/build.gradle.kts
@@ -3,8 +3,7 @@
plugins {
alias(libs.plugins.unifest.android.library)
alias(libs.plugins.unifest.android.hilt)
- alias(libs.plugins.unifest.android.firebase)
- id("kotlinx-serialization")
+ alias(libs.plugins.kotlin.serialization)
}
android {
@@ -28,6 +27,9 @@ dependencies {
projects.core.model,
projects.core.network,
+ platform(libs.firebase.bom),
+ libs.firebase.config,
+ libs.firebase.messaging,
libs.timber,
)
}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/datasource/RemoteConfigDataSource.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/datasource/RemoteConfigDataSource.kt
index 7b881bef..b231597f 100644
--- a/core/data/src/main/kotlin/com/unifest/android/core/data/datasource/RemoteConfigDataSource.kt
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/datasource/RemoteConfigDataSource.kt
@@ -5,13 +5,4 @@ import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue
interface RemoteConfigDataSource {
suspend fun getValue(key: String): FirebaseRemoteConfigValue?
suspend fun getString(key: String): String?
- suspend fun getString(key: String, defaultValue: String): String
- suspend fun getLong(key: String): Long?
- suspend fun getLong(key: String, defaultValue: Long): Long
-
- suspend fun getBoolean(key: String): Boolean?
- suspend fun getBoolean(key: String, defaultValue: Boolean): Boolean
-
- suspend fun getDouble(key: String): Double?
- suspend fun getDouble(key: String, defaultValue: Double): Double
}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/datasource/RemoteConfigDataSourceImpl.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/datasource/RemoteConfigDataSourceImpl.kt
index 9b2eb22f..c7faf761 100644
--- a/core/data/src/main/kotlin/com/unifest/android/core/data/datasource/RemoteConfigDataSourceImpl.kt
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/datasource/RemoteConfigDataSourceImpl.kt
@@ -27,14 +27,4 @@ class RemoteConfigDataSourceImpl @Inject constructor(
}
override suspend fun getString(key: String): String? = getValue(key)?.asString()
- override suspend fun getString(key: String, defaultValue: String): String = getValue(key)?.asString() ?: defaultValue
-
- override suspend fun getLong(key: String): Long? = getValue(key)?.asLong()
- override suspend fun getLong(key: String, defaultValue: Long): Long = getValue(key)?.asLong() ?: defaultValue
-
- override suspend fun getBoolean(key: String): Boolean? = getValue(key)?.asBoolean()
- override suspend fun getBoolean(key: String, defaultValue: Boolean): Boolean = getValue(key)?.asBoolean() ?: defaultValue
-
- override suspend fun getDouble(key: String): Double? = getValue(key)?.asDouble()
- override suspend fun getDouble(key: String, defaultValue: Double): Double = getValue(key)?.asDouble() ?: defaultValue
}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/di/FirebaseModule.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/di/FirebaseModule.kt
index 57c24bea..ab01e019 100644
--- a/core/data/src/main/kotlin/com/unifest/android/core/data/di/FirebaseModule.kt
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/di/FirebaseModule.kt
@@ -1,5 +1,6 @@
package com.unifest.android.core.data.di
+import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.remoteConfigSettings
import com.unifest.android.core.data.BuildConfig
@@ -24,4 +25,10 @@ internal object FirebaseModule {
setConfigSettingsAsync(configSettings)
}
}
+
+ @Singleton
+ @Provides
+ fun provideMessaging(): FirebaseMessaging {
+ return FirebaseMessaging.getInstance()
+ }
}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/di/RepositoryModule.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/di/RepositoryModule.kt
index 771564e0..b77e3eef 100644
--- a/core/data/src/main/kotlin/com/unifest/android/core/data/di/RepositoryModule.kt
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/di/RepositoryModule.kt
@@ -8,10 +8,14 @@ import com.unifest.android.core.data.repository.LikedBoothRepositoryImpl
import com.unifest.android.core.data.repository.LikedBoothRepository
import com.unifest.android.core.data.repository.LikedFestivalRepository
import com.unifest.android.core.data.repository.LikedFestivalRepositoryImpl
+import com.unifest.android.core.data.repository.MessagingRepository
+import com.unifest.android.core.data.repository.MessagingRepositoryImpl
import com.unifest.android.core.data.repository.OnboardingRepository
import com.unifest.android.core.data.repository.OnboardingRepositoryImpl
import com.unifest.android.core.data.repository.RemoteConfigRepository
import com.unifest.android.core.data.repository.RemoteConfigRepositoryImpl
+import com.unifest.android.core.data.repository.WaitingRepository
+import com.unifest.android.core.data.repository.WaitingRepositoryImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
@@ -44,4 +48,12 @@ internal abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindRemoteConfigRepository(remoteConfigRepositoryImpl: RemoteConfigRepositoryImpl): RemoteConfigRepository
+
+ @Binds
+ @Singleton
+ abstract fun bingWaitingRepository(waitingRepositoryImpl: WaitingRepositoryImpl): WaitingRepository
+
+ @Binds
+ @Singleton
+ abstract fun bindMessagingRepository(messagingRepositoryImpl: MessagingRepositoryImpl): MessagingRepository
}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/BoothEntityMapper.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/BoothEntityMapper.kt
index 24fc1a04..f914e368 100644
--- a/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/BoothEntityMapper.kt
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/BoothEntityMapper.kt
@@ -26,6 +26,7 @@ internal fun MenuEntity.toModel(): MenuModel {
name = name,
price = price,
imgUrl = imgUrl,
+ status = status,
)
}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/BoothMapper.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/BoothMapper.kt
index 59b9a764..e009979f 100644
--- a/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/BoothMapper.kt
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/BoothMapper.kt
@@ -4,10 +4,12 @@ import com.unifest.android.core.model.BoothDetailModel
import com.unifest.android.core.model.BoothModel
import com.unifest.android.core.model.LikedBoothModel
import com.unifest.android.core.model.MenuModel
+import com.unifest.android.core.model.WaitingModel
import com.unifest.android.core.network.response.Booth
import com.unifest.android.core.network.response.BoothDetail
import com.unifest.android.core.network.response.LikedBooth
import com.unifest.android.core.network.response.Menu
+import com.unifest.android.core.network.response.Waiting
internal fun BoothDetail.toModel(): BoothDetailModel {
return BoothDetailModel(
@@ -21,6 +23,9 @@ internal fun BoothDetail.toModel(): BoothDetailModel {
latitude = latitude,
longitude = longitude,
menus = menus.map { it.toModel() },
+ waitingEnabled = waitingEnabled,
+ openTime = openTime ?: "",
+ closeTime = closeTime ?: "",
)
}
@@ -30,6 +35,7 @@ internal fun Menu.toModel(): MenuModel {
name = name,
price = price,
imgUrl = imgUrl ?: "",
+ status = status ?: "",
)
}
@@ -59,3 +65,18 @@ internal fun LikedBooth.toModel(): LikedBoothModel {
warning = warning,
)
}
+
+internal fun Waiting.toModel(): WaitingModel {
+ return WaitingModel(
+ boothId = boothId,
+ waitingId = waitingId,
+ partySize = partySize,
+ tel = tel,
+ deviceId = deviceId,
+ createdAt = createdAt,
+ updatedAt = updatedAt,
+ status = status,
+ waitingOrder = waitingOrder ?: 0L,
+ boothName = boothName,
+ )
+}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/MyWaitingMapper.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/MyWaitingMapper.kt
new file mode 100644
index 00000000..2bbc2757
--- /dev/null
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/mapper/MyWaitingMapper.kt
@@ -0,0 +1,19 @@
+package com.unifest.android.core.data.mapper
+
+import com.unifest.android.core.model.MyWaitingModel
+import com.unifest.android.core.network.response.MyWaiting
+
+internal fun MyWaiting.toModel(): MyWaitingModel {
+ return MyWaitingModel(
+ boothId = boothId,
+ waitingId = waitingId,
+ partySize = partySize,
+ tel = tel,
+ deviceId = deviceId,
+ createdAt = createdAt,
+ updatedAt = updatedAt,
+ status = status,
+ waitingOrder = waitingOrder,
+ boothName = boothName,
+ )
+}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/BoothRepository.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/BoothRepository.kt
index 77a2170b..c1ca6391 100644
--- a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/BoothRepository.kt
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/BoothRepository.kt
@@ -2,6 +2,7 @@ package com.unifest.android.core.data.repository
import com.unifest.android.core.model.BoothModel
import com.unifest.android.core.model.BoothDetailModel
+import com.unifest.android.core.model.WaitingModel
interface BoothRepository {
suspend fun getPopularBooths(festivalId: Long): Result>
@@ -9,4 +10,6 @@ interface BoothRepository {
suspend fun getBoothDetail(boothId: Long): Result
suspend fun likeBooth(boothId: Long): Result
suspend fun getBoothLikes(boothId: Long): Result
+ suspend fun checkPinValidation(boothId: Long, pinNumber: String): Result
+ suspend fun requestBoothWaiting(boothId: Long, tel: String, partySize: Long, pinNumber: String): Result
}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/BoothRepositoryImpl.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/BoothRepositoryImpl.kt
index f06b77bf..0d598980 100644
--- a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/BoothRepositoryImpl.kt
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/BoothRepositoryImpl.kt
@@ -4,6 +4,9 @@ import android.content.Context
import com.unifest.android.core.common.getDeviceId
import com.unifest.android.core.data.mapper.toModel
import com.unifest.android.core.data.util.runSuspendCatching
+import com.unifest.android.core.datastore.TokenDataSource
+import com.unifest.android.core.network.request.BoothWaitingRequest
+import com.unifest.android.core.network.request.CheckPinValidationRequest
import com.unifest.android.core.network.request.LikeBoothRequest
import com.unifest.android.core.network.service.UnifestService
import dagger.hilt.android.qualifiers.ApplicationContext
@@ -12,6 +15,7 @@ import javax.inject.Inject
class BoothRepositoryImpl @Inject constructor(
@ApplicationContext private val context: Context,
private val service: UnifestService,
+ private val tokenDataSource: TokenDataSource,
) : BoothRepository {
override suspend fun getPopularBooths(festivalId: Long) = runSuspendCatching {
service.getPopularBooths(festivalId).data.map { it.toModel() }
@@ -37,4 +41,27 @@ class BoothRepositoryImpl @Inject constructor(
override suspend fun getBoothLikes(boothId: Long) = runSuspendCatching {
service.getBoothLikes(boothId).data
}
+
+ override suspend fun checkPinValidation(boothId: Long, pinNumber: String): Result = runSuspendCatching {
+ service.checkPinValidation(
+ CheckPinValidationRequest(
+ boothId = boothId,
+ pinNumber = pinNumber,
+ ),
+ ).data
+ }
+
+ override suspend fun requestBoothWaiting(boothId: Long, tel: String, partySize: Long, pinNumber: String) = runSuspendCatching {
+ val fcmToken = tokenDataSource.getFCMToken()
+ service.requestBoothWaiting(
+ BoothWaitingRequest(
+ boothId = boothId,
+ tel = tel,
+ deviceId = getDeviceId(context),
+ partySize = partySize,
+ pinNumber = pinNumber,
+ fcmToken = fcmToken,
+ ),
+ ).data.toModel()
+ }
}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/LikedFestivalRepository.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/LikedFestivalRepository.kt
index 5e11bbe4..2ef05bfe 100644
--- a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/LikedFestivalRepository.kt
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/LikedFestivalRepository.kt
@@ -10,5 +10,9 @@ interface LikedFestivalRepository {
suspend fun insertLikedFestivalAtSearch(festival: FestivalModel)
suspend fun deleteLikedFestival(festival: FestivalModel)
suspend fun getRecentLikedFestival(): String
- suspend fun setRecentLikedFestival(schoolName: String)
+ suspend fun setRecentLikedFestival(festivalName: String)
+ suspend fun getRecentLikedFestivalId(): Long
+ suspend fun setRecentLikedFestivalId(festivalId: Long)
+ suspend fun registerLikedFestival(): Result
+ suspend fun unregisterLikedFestival(): Result
}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/LikedFestivalRepositoryImpl.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/LikedFestivalRepositoryImpl.kt
index fc30fd61..7d472735 100644
--- a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/LikedFestivalRepositoryImpl.kt
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/LikedFestivalRepositoryImpl.kt
@@ -2,10 +2,14 @@ package com.unifest.android.core.data.repository
import com.unifest.android.core.data.mapper.toEntity
import com.unifest.android.core.data.mapper.toModel
+import com.unifest.android.core.data.util.runSuspendCatching
import com.unifest.android.core.database.LikedFestivalDao
import com.unifest.android.core.datastore.RecentLikedFestivalDataSource
+import com.unifest.android.core.datastore.TokenDataSource
import com.unifest.android.core.model.FestivalModel
import com.unifest.android.core.model.FestivalTodayModel
+import com.unifest.android.core.network.request.LikedFestivalRequest
+import com.unifest.android.core.network.service.UnifestService
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
@@ -13,6 +17,8 @@ import javax.inject.Inject
internal class LikedFestivalRepositoryImpl @Inject constructor(
private val likedFestivalDao: LikedFestivalDao,
private val recentLikedFestivalDataSource: RecentLikedFestivalDataSource,
+ private val tokenDataSource: TokenDataSource,
+ private val service: UnifestService,
) : LikedFestivalRepository {
override fun getLikedFestivals(): Flow> {
return likedFestivalDao.getLikedFestivalList().map { likedFestivals ->
@@ -35,10 +41,30 @@ internal class LikedFestivalRepositoryImpl @Inject constructor(
}
override suspend fun getRecentLikedFestival(): String {
- return recentLikedFestivalDataSource.getRecentLikedFestival()
+ return recentLikedFestivalDataSource.getRecentLikedFestivalName()
}
- override suspend fun setRecentLikedFestival(schoolName: String) {
- recentLikedFestivalDataSource.setRecentLikedFestival(schoolName)
+ override suspend fun setRecentLikedFestival(festivalName: String) {
+ recentLikedFestivalDataSource.setRecentLikedFestivalName(festivalName)
+ }
+
+ override suspend fun getRecentLikedFestivalId(): Long {
+ return recentLikedFestivalDataSource.getRecentLikedFestivalId()
+ }
+
+ override suspend fun setRecentLikedFestivalId(festivalId: Long) {
+ recentLikedFestivalDataSource.setRecentLikedFestivalId(festivalId)
+ }
+
+ override suspend fun registerLikedFestival() = runSuspendCatching {
+ val festivalId = recentLikedFestivalDataSource.getRecentLikedFestivalId()
+ val fcmToken = tokenDataSource.getFCMToken() ?: ""
+ service.registerLikedFestival(LikedFestivalRequest(festivalId, fcmToken))
+ }
+
+ override suspend fun unregisterLikedFestival() = runSuspendCatching {
+ val festivalId = recentLikedFestivalDataSource.getRecentLikedFestivalId()
+ val fcmToken = tokenDataSource.getFCMToken() ?: ""
+ service.unregisterLikedFestival(LikedFestivalRequest(festivalId, fcmToken))
}
}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/MessagingRepository.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/MessagingRepository.kt
new file mode 100644
index 00000000..d01bd985
--- /dev/null
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/MessagingRepository.kt
@@ -0,0 +1,6 @@
+package com.unifest.android.core.data.repository
+
+interface MessagingRepository {
+ suspend fun refreshFCMToken(): String?
+ suspend fun setFCMToken(token: String)
+}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/MessagingRepositoryImpl.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/MessagingRepositoryImpl.kt
new file mode 100644
index 00000000..95864c4a
--- /dev/null
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/MessagingRepositoryImpl.kt
@@ -0,0 +1,32 @@
+package com.unifest.android.core.data.repository
+
+import com.google.firebase.messaging.FirebaseMessaging
+import com.unifest.android.core.datastore.TokenDataSource
+import timber.log.Timber
+import javax.inject.Inject
+import kotlin.coroutines.resume
+import kotlin.coroutines.suspendCoroutine
+
+class MessagingRepositoryImpl @Inject constructor(
+ private val firebaseMessaging: FirebaseMessaging,
+ private val tokenDataSource: TokenDataSource,
+) : MessagingRepository {
+ override suspend fun refreshFCMToken(): String? = suspendCoroutine { continuation ->
+ firebaseMessaging.token.addOnCompleteListener { task ->
+ if (task.isSuccessful) {
+ continuation.resume(
+ task.result.also {
+ Timber.d("FCM registration token: $it")
+ },
+ )
+ } else {
+ Timber.e(task.exception)
+ continuation.resume(null)
+ }
+ }
+ }
+
+ override suspend fun setFCMToken(token: String) {
+ tokenDataSource.setFCMToken(token)
+ }
+}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/WaitingRepository.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/WaitingRepository.kt
new file mode 100644
index 00000000..bdb46bfe
--- /dev/null
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/WaitingRepository.kt
@@ -0,0 +1,9 @@
+package com.unifest.android.core.data.repository
+
+import com.unifest.android.core.model.MyWaitingModel
+
+interface WaitingRepository {
+ suspend fun getMyWaitingList(): Result>
+ suspend fun cancelBoothWaiting(waitingId: Long): Result
+ suspend fun registerFCMTopic(waitingId: String)
+}
diff --git a/core/data/src/main/kotlin/com/unifest/android/core/data/repository/WaitingRepositoryImpl.kt b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/WaitingRepositoryImpl.kt
new file mode 100644
index 00000000..99159352
--- /dev/null
+++ b/core/data/src/main/kotlin/com/unifest/android/core/data/repository/WaitingRepositoryImpl.kt
@@ -0,0 +1,44 @@
+package com.unifest.android.core.data.repository
+
+import android.content.Context
+import com.google.firebase.messaging.FirebaseMessaging
+import com.unifest.android.core.common.getDeviceId
+import com.unifest.android.core.data.mapper.toModel
+import com.unifest.android.core.data.util.runSuspendCatching
+import com.unifest.android.core.network.request.WaitingRequest
+import com.unifest.android.core.network.service.UnifestService
+import dagger.hilt.android.qualifiers.ApplicationContext
+import timber.log.Timber
+import javax.inject.Inject
+
+class WaitingRepositoryImpl @Inject constructor(
+ @ApplicationContext private val context: Context,
+ private val service: UnifestService,
+ private val firebaseMessaging: FirebaseMessaging,
+) : WaitingRepository {
+ override suspend fun getMyWaitingList() = runSuspendCatching {
+ service.getMyWaitingList(
+ deviceId = getDeviceId(context),
+ ).data?.map { it.toModel() } ?: emptyList()
+ }
+
+ override suspend fun cancelBoothWaiting(waitingId: Long): Result = runSuspendCatching {
+ service.cancelBoothWaiting(
+ WaitingRequest(
+ waitingId = waitingId,
+ deviceId = getDeviceId(context),
+ ),
+ ).data.toModel()
+ }
+
+ override suspend fun registerFCMTopic(waitingId: String) {
+ firebaseMessaging.subscribeToTopic("waiting_$waitingId")
+ .addOnCompleteListener { task ->
+ if (task.isSuccessful) {
+ Timber.d("Subscribed to topic successfully")
+ } else {
+ Timber.e("Failed to subscribe to topic")
+ }
+ }
+ }
+}
diff --git a/core/database/build.gradle.kts b/core/database/build.gradle.kts
index f9409856..e6eef729 100644
--- a/core/database/build.gradle.kts
+++ b/core/database/build.gradle.kts
@@ -4,7 +4,7 @@ plugins {
alias(libs.plugins.unifest.android.library)
alias(libs.plugins.unifest.android.hilt)
alias(libs.plugins.unifest.android.room)
- id("kotlinx-serialization")
+ alias(libs.plugins.kotlin.serialization)
}
android {
diff --git a/core/database/src/main/kotlin/com/unifest/android/core/database/entity/LikedBoothEntity.kt b/core/database/src/main/kotlin/com/unifest/android/core/database/entity/LikedBoothEntity.kt
index ecb9a45d..8eeb48b8 100644
--- a/core/database/src/main/kotlin/com/unifest/android/core/database/entity/LikedBoothEntity.kt
+++ b/core/database/src/main/kotlin/com/unifest/android/core/database/entity/LikedBoothEntity.kt
@@ -39,4 +39,5 @@ data class MenuEntity(
val name: String = "",
val price: Int = 0,
val imgUrl: String = "",
+ val status: String = "",
)
diff --git a/core/datastore/build.gradle.kts b/core/datastore/build.gradle.kts
index 9feb5adf..2996526d 100644
--- a/core/datastore/build.gradle.kts
+++ b/core/datastore/build.gradle.kts
@@ -3,7 +3,7 @@
plugins {
alias(libs.plugins.unifest.android.library)
alias(libs.plugins.unifest.android.hilt)
- id("kotlinx-serialization")
+ alias(libs.plugins.kotlin.serialization)
}
android {
diff --git a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/RecentLikedFestivalDataSource.kt b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/RecentLikedFestivalDataSource.kt
index 7f967e18..aa7140cd 100644
--- a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/RecentLikedFestivalDataSource.kt
+++ b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/RecentLikedFestivalDataSource.kt
@@ -1,6 +1,8 @@
package com.unifest.android.core.datastore
interface RecentLikedFestivalDataSource {
- suspend fun getRecentLikedFestival(): String
- suspend fun setRecentLikedFestival(schoolName: String)
+ suspend fun getRecentLikedFestivalName(): String
+ suspend fun setRecentLikedFestivalName(festivalName: String)
+ suspend fun getRecentLikedFestivalId(): Long
+ suspend fun setRecentLikedFestivalId(festivalId: Long)
}
diff --git a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/RecentLikedFestivalDataSourceImpl.kt b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/RecentLikedFestivalDataSourceImpl.kt
index f964058c..c2c4de7f 100644
--- a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/RecentLikedFestivalDataSourceImpl.kt
+++ b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/RecentLikedFestivalDataSourceImpl.kt
@@ -4,6 +4,7 @@ import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
+import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import com.unifest.android.core.datastore.di.RecentLikedFestivalDataStore
import kotlinx.coroutines.flow.catch
@@ -16,15 +17,26 @@ class RecentLikedFestivalDataSourceImpl @Inject constructor(
) : RecentLikedFestivalDataSource {
private companion object {
private val KEY_RECENT_LIKED_FESTIVAL = stringPreferencesKey("recent_liked_festival")
+ private val KEY_RECENT_LIKED_FESTIVAL_ID = longPreferencesKey("recent_liked_festival_id")
}
- override suspend fun getRecentLikedFestival(): String = dataStore.data
+ override suspend fun getRecentLikedFestivalName(): String = dataStore.data
.catch { exception ->
if (exception is IOException) emit(emptyPreferences())
else throw exception
}.first()[KEY_RECENT_LIKED_FESTIVAL] ?: ""
- override suspend fun setRecentLikedFestival(schoolName: String) {
- dataStore.edit { preferences -> preferences[KEY_RECENT_LIKED_FESTIVAL] = schoolName }
+ override suspend fun setRecentLikedFestivalName(festivalName: String) {
+ dataStore.edit { preferences -> preferences[KEY_RECENT_LIKED_FESTIVAL] = festivalName }
+ }
+
+ override suspend fun getRecentLikedFestivalId(): Long = dataStore.data
+ .catch { exception ->
+ if (exception is IOException) emit(emptyPreferences())
+ else throw exception
+ }.first()[KEY_RECENT_LIKED_FESTIVAL_ID] ?: 0L
+
+ override suspend fun setRecentLikedFestivalId(festivalId: Long) {
+ dataStore.edit { preferences -> preferences[KEY_RECENT_LIKED_FESTIVAL_ID] = festivalId }
}
}
diff --git a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/TokenDataSource.kt b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/TokenDataSource.kt
new file mode 100644
index 00000000..bfe6ac65
--- /dev/null
+++ b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/TokenDataSource.kt
@@ -0,0 +1,6 @@
+package com.unifest.android.core.datastore
+
+interface TokenDataSource {
+ suspend fun getFCMToken(): String
+ suspend fun setFCMToken(token: String)
+}
diff --git a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/TokenDataSourceImpl.kt b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/TokenDataSourceImpl.kt
new file mode 100644
index 00000000..21b2b2a7
--- /dev/null
+++ b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/TokenDataSourceImpl.kt
@@ -0,0 +1,30 @@
+package com.unifest.android.core.datastore
+
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.emptyPreferences
+import androidx.datastore.preferences.core.stringPreferencesKey
+import com.unifest.android.core.datastore.di.OnboardingDataStore
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.first
+import java.io.IOException
+import javax.inject.Inject
+
+class TokenDataSourceImpl @Inject constructor(
+ @OnboardingDataStore private val dataStore: DataStore,
+) : TokenDataSource {
+ private companion object {
+ private val KEY_FCM_TOKEN = stringPreferencesKey("fcm_token")
+ }
+
+ override suspend fun getFCMToken(): String = dataStore.data
+ .catch { exception ->
+ if (exception is IOException) emit(emptyPreferences())
+ else throw exception
+ }.first()[KEY_FCM_TOKEN] ?: ""
+
+ override suspend fun setFCMToken(token: String) {
+ dataStore.edit { preferences -> preferences[KEY_FCM_TOKEN] = token }
+ }
+}
diff --git a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataSourceModule.kt b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataSourceModule.kt
index 466d7a4a..bc45ff86 100644
--- a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataSourceModule.kt
+++ b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataSourceModule.kt
@@ -4,6 +4,8 @@ import com.unifest.android.core.datastore.OnboardingDataSource
import com.unifest.android.core.datastore.OnboardingDataSourceImpl
import com.unifest.android.core.datastore.RecentLikedFestivalDataSource
import com.unifest.android.core.datastore.RecentLikedFestivalDataSourceImpl
+import com.unifest.android.core.datastore.TokenDataSource
+import com.unifest.android.core.datastore.TokenDataSourceImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
@@ -20,4 +22,8 @@ abstract class DataSourceModule {
@Binds
@Singleton
abstract fun bindRecentLikedFestivalDataSource(recentLikedFestivalDataSourceImpl: RecentLikedFestivalDataSourceImpl): RecentLikedFestivalDataSource
+
+ @Binds
+ @Singleton
+ abstract fun bindTokenDataSource(tokenDataSourceImpl: TokenDataSourceImpl): TokenDataSource
}
diff --git a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataStoreModule.kt b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataStoreModule.kt
index 8b3059d7..43248534 100644
--- a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataStoreModule.kt
+++ b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataStoreModule.kt
@@ -17,6 +17,9 @@ private val Context.onboardingDataStore: DataStore by preferencesDa
private const val RECENT_LIKED_FESTIVAL_DATASTORE = "recent_liked_festival_datastore"
private val Context.recentLikedFestivalDataStore: DataStore by preferencesDataStore(name = RECENT_LIKED_FESTIVAL_DATASTORE)
+private const val TOKEN_DATASTORE = "onboarding_datastore"
+private val Context.tokenDataStore: DataStore by preferencesDataStore(name = TOKEN_DATASTORE)
+
@Module
@InstallIn(SingletonComponent::class)
internal object DataStoreModule {
@@ -30,4 +33,9 @@ internal object DataStoreModule {
@Singleton
@Provides
internal fun provideRecentFestivalDataStore(@ApplicationContext context: Context) = context.recentLikedFestivalDataStore
+
+ @TokenDataStore
+ @Singleton
+ @Provides
+ internal fun provideTokenDataStore(@ApplicationContext context: Context) = context.tokenDataStore
}
diff --git a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataStoreQualifier.kt b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataStoreQualifier.kt
index e9ac9dd7..56a40594 100644
--- a/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataStoreQualifier.kt
+++ b/core/datastore/src/main/kotlin/com/unifest/android/core/datastore/di/DataStoreQualifier.kt
@@ -9,3 +9,7 @@ annotation class OnboardingDataStore
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class RecentLikedFestivalDataStore
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class TokenDataStore
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/ComponentPreview.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/ComponentPreview.kt
index b1d48b17..4d2a002b 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/ComponentPreview.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/ComponentPreview.kt
@@ -1,6 +1,17 @@
package com.unifest.android.core.designsystem
+import android.content.res.Configuration.UI_MODE_NIGHT_NO
+import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.ui.tooling.preview.Preview
-@Preview(showBackground = true)
+@Preview(
+ name = "Light",
+ showBackground = true,
+ uiMode = UI_MODE_NIGHT_NO,
+)
+@Preview(
+ name = "Dark",
+ showBackground = true,
+ uiMode = UI_MODE_NIGHT_YES,
+)
annotation class ComponentPreview
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/BoothFilterChip.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/BoothFilterChip.kt
index 2f6c833d..ff59d0fa 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/BoothFilterChip.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/BoothFilterChip.kt
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardColors
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@@ -16,7 +17,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.unifest.android.core.designsystem.ComponentPreview
import com.unifest.android.core.designsystem.theme.BoothLocation
-import com.unifest.android.core.designsystem.theme.MainColor
import com.unifest.android.core.designsystem.theme.UnifestTheme
@Composable
@@ -30,12 +30,12 @@ fun BoothFilterChip(
modifier = modifier.padding(4.dp),
shape = RoundedCornerShape(34.dp),
colors = CardColors(
- containerColor = if (isSelected) Color(0xFFFFF0F3) else Color.White,
- contentColor = if (isSelected) MainColor else Color(0xFF4B4B4B),
- disabledContainerColor = Color.White,
- disabledContentColor = Color(0xFF585858),
+ containerColor = if (isSelected) MaterialTheme.colorScheme.tertiary else MaterialTheme.colorScheme.background,
+ contentColor = if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant,
+ disabledContainerColor = MaterialTheme.colorScheme.background,
+ disabledContentColor = MaterialTheme.colorScheme.onSecondaryContainer,
),
- border = BorderStroke(1.dp, if (isSelected) MainColor else Color(0xFFD2D2D2)),
+ border = BorderStroke(1.dp, if (isSelected) MaterialTheme.colorScheme.primary else Color(0xFFD2D2D2)),
) {
Box(
modifier = Modifier.clickable(onClick = { onChipClick(filterName) }),
@@ -55,7 +55,7 @@ fun BoothFilterChip(
@ComponentPreview
@Composable
-fun BoothFilterChipPreview() {
+private fun BoothFilterChipPreview() {
UnifestTheme {
BoothFilterChip(
filterName = "주점",
@@ -64,3 +64,15 @@ fun BoothFilterChipPreview() {
)
}
}
+
+@ComponentPreview
+@Composable
+private fun SelectedBoothFilterChipPreview() {
+ UnifestTheme {
+ BoothFilterChip(
+ filterName = "주점",
+ onChipClick = {},
+ isSelected = true,
+ )
+ }
+}
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Button.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Button.kt
index 470320ee..db194030 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Button.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Button.kt
@@ -5,27 +5,33 @@ import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
+import com.unifest.android.core.common.MultipleEventsCutter
+import com.unifest.android.core.common.get
import com.unifest.android.core.designsystem.ComponentPreview
+import com.unifest.android.core.designsystem.theme.UnifestTheme
@Composable
fun UnifestButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
- containerColor: Color = Color(0xFFf5678E),
+ containerColor: Color = MaterialTheme.colorScheme.primary,
contentColor: Color = Color.White,
- disabledContainerColor: Color = Color(0xFF9C9C9C),
+ disabledContainerColor: Color = MaterialTheme.colorScheme.surfaceVariant,
disabledContentColor: Color = Color.White,
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: @Composable RowScope.() -> Unit,
) {
+ val multipleEventsCutter = remember { MultipleEventsCutter.get() }
Button(
- onClick = onClick,
+ onClick = { multipleEventsCutter.processEvent { onClick() } },
modifier = modifier,
enabled = enabled,
shape = RoundedCornerShape(10.dp),
@@ -42,10 +48,25 @@ fun UnifestButton(
@ComponentPreview
@Composable
-fun UnifestButtonPreview() {
- UnifestButton(
- onClick = {},
- ) {
- Text("Button")
+private fun UnifestButtonPreview() {
+ UnifestTheme {
+ UnifestButton(
+ onClick = {},
+ ) {
+ Text("Button")
+ }
+ }
+}
+
+@ComponentPreview
+@Composable
+private fun UnifestDisabledButtonPreview() {
+ UnifestTheme {
+ UnifestButton(
+ onClick = {},
+ enabled = false,
+ ) {
+ Text("Button")
+ }
}
}
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/CircularOutlineButton.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/CircularOutlineButton.kt
new file mode 100644
index 00000000..a0b7f5b3
--- /dev/null
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/CircularOutlineButton.kt
@@ -0,0 +1,56 @@
+package com.unifest.android.core.designsystem.component
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Remove
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.unit.dp
+import com.unifest.android.core.common.extension.noRippleClickable
+import com.unifest.android.core.designsystem.ComponentPreview
+import com.unifest.android.core.designsystem.theme.UnifestTheme
+
+@Composable
+fun CircularOutlineButton(
+ icon: ImageVector,
+ contentDescription: String?,
+ onClick: () -> Unit,
+ borderColor: Color = Color(0xFFD2D2D2),
+ iconTintColor: Color = MaterialTheme.colorScheme.onBackground,
+) {
+ Box(
+ modifier = Modifier
+ .size(27.dp)
+ .border(BorderStroke(1.dp, borderColor), shape = CircleShape)
+ .noRippleClickable { onClick() },
+ contentAlignment = Alignment.Center,
+ ) {
+ Icon(
+ imageVector = icon,
+ contentDescription = contentDescription,
+ tint = iconTintColor,
+ modifier = Modifier.size(13.dp),
+ )
+ }
+}
+
+@ComponentPreview
+@Composable
+private fun CircularOutlineButtonPreview() {
+ UnifestTheme {
+ CircularOutlineButton(
+ icon = Icons.Default.Remove,
+ contentDescription = "Minus Button",
+ onClick = {},
+ )
+ }
+}
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Dialog.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Dialog.kt
index 10497044..745ec4be 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Dialog.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Dialog.kt
@@ -2,6 +2,7 @@ package com.unifest.android.core.designsystem.component
import androidx.annotation.StringRes
import androidx.compose.foundation.background
+import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -12,6 +13,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.BasicAlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@@ -27,7 +29,8 @@ import androidx.compose.ui.window.DialogProperties
import com.unifest.android.core.designsystem.ComponentPreview
import com.unifest.android.core.designsystem.R
import com.unifest.android.core.designsystem.theme.BoothLocation
-import com.unifest.android.core.designsystem.theme.MainColor
+import com.unifest.android.core.designsystem.theme.DarkGrey400
+import com.unifest.android.core.designsystem.theme.LightGrey200
import com.unifest.android.core.designsystem.theme.Title2
import com.unifest.android.core.designsystem.theme.Title5
import com.unifest.android.core.designsystem.theme.UnifestTheme
@@ -56,7 +59,7 @@ fun UnifestDialog(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(10.dp))
- .background(color = Color.White),
+ .background(color = MaterialTheme.colorScheme.surface),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.height(27.dp))
@@ -71,12 +74,12 @@ fun UnifestDialog(
Text(
text = stringResource(id = titleResId),
style = Title2,
- color = Color.Black,
+ color = MaterialTheme.colorScheme.onBackground,
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(id = descriptionResId),
- color = Color(0xFF545454),
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center,
style = BoothLocation,
)
@@ -98,7 +101,7 @@ fun UnifestDialog(
Modifier
},
),
- containerColor = MainColor,
+ containerColor = MaterialTheme.colorScheme.primary,
contentColor = Color.White,
) {
Text(
@@ -114,11 +117,11 @@ fun UnifestDialog(
.weight(1f)
.height(45.dp)
.padding(start = 4.dp),
- containerColor = Color(0xFFD2D2D2),
- contentColor = Color.Black,
+ containerColor = if (isSystemInDarkTheme()) DarkGrey400 else LightGrey200,
) {
Text(
text = stringResource(id = cancelTextResId),
+ color = MaterialTheme.colorScheme.onBackground,
style = Title5,
)
}
@@ -133,34 +136,38 @@ fun UnifestDialog(
fun ServerErrorDialog(
onRetryClick: () -> Unit,
) {
- UnifestDialog(
- onDismissRequest = {},
- titleResId = R.string.server_error_title,
- iconResId = R.drawable.ic_caution,
- iconDescription = "Caution Icon",
- descriptionResId = R.string.server_error_description,
- confirmTextResId = R.string.retry,
- cancelTextResId = null,
- onCancelClick = {},
- onConfirmClick = onRetryClick,
- )
+ UnifestTheme {
+ UnifestDialog(
+ onDismissRequest = {},
+ titleResId = R.string.server_error_title,
+ iconResId = R.drawable.ic_caution,
+ iconDescription = "Caution Icon",
+ descriptionResId = R.string.server_error_description,
+ confirmTextResId = R.string.retry,
+ cancelTextResId = null,
+ onCancelClick = {},
+ onConfirmClick = onRetryClick,
+ )
+ }
}
@Composable
fun NetworkErrorDialog(
onRetryClick: () -> Unit,
) {
- UnifestDialog(
- onDismissRequest = {},
- titleResId = R.string.network_error_title,
- iconResId = R.drawable.ic_network,
- iconDescription = "Network Error Icon",
- descriptionResId = R.string.network_error_description,
- confirmTextResId = R.string.retry,
- cancelTextResId = null,
- onCancelClick = {},
- onConfirmClick = onRetryClick,
- )
+ UnifestTheme {
+ UnifestDialog(
+ onDismissRequest = {},
+ titleResId = R.string.network_error_title,
+ iconResId = R.drawable.ic_network,
+ iconDescription = "Network Error Icon",
+ descriptionResId = R.string.network_error_description,
+ confirmTextResId = R.string.retry,
+ cancelTextResId = null,
+ onCancelClick = {},
+ onConfirmClick = onRetryClick,
+ )
+ }
}
@Composable
@@ -168,17 +175,19 @@ fun LikedFestivalDeleteDialog(
onCancelClick: () -> Unit,
onConfirmClick: () -> Unit,
) {
- UnifestDialog(
- onDismissRequest = {},
- titleResId = R.string.liked_festival_delete_title,
- iconResId = R.drawable.ic_caution,
- iconDescription = "Caution Icon",
- descriptionResId = R.string.liked_festival_delete_description,
- confirmTextResId = R.string.confirm,
- cancelTextResId = R.string.cancel,
- onCancelClick = onCancelClick,
- onConfirmClick = onConfirmClick,
- )
+ UnifestTheme {
+ UnifestDialog(
+ onDismissRequest = {},
+ titleResId = R.string.liked_festival_delete_title,
+ iconResId = R.drawable.ic_caution,
+ iconDescription = "Caution Icon",
+ descriptionResId = R.string.liked_festival_delete_description,
+ confirmTextResId = R.string.confirm,
+ cancelTextResId = R.string.cancel,
+ onCancelClick = onCancelClick,
+ onConfirmClick = onConfirmClick,
+ )
+ }
}
@Composable
@@ -190,23 +199,25 @@ fun AppUpdateDialog(
dismissOnClickOutside = false,
),
) {
- UnifestDialog(
- onDismissRequest = onDismissRequest,
- titleResId = R.string.app_update_title,
- iconResId = R.drawable.ic_caution,
- iconDescription = "Caution Icon",
- descriptionResId = R.string.app_update_description,
- confirmTextResId = R.string.app_update_confirm,
- cancelTextResId = null,
- onCancelClick = {},
- onConfirmClick = onUpdateClick,
- properties = properties,
- )
+ UnifestTheme {
+ UnifestDialog(
+ onDismissRequest = onDismissRequest,
+ titleResId = R.string.app_update_title,
+ iconResId = R.drawable.ic_caution,
+ iconDescription = "Caution Icon",
+ descriptionResId = R.string.app_update_description,
+ confirmTextResId = R.string.app_update_confirm,
+ cancelTextResId = null,
+ onCancelClick = {},
+ onConfirmClick = onUpdateClick,
+ properties = properties,
+ )
+ }
}
@ComponentPreview
@Composable
-fun ServerErrorDialogPreview() {
+private fun ServerErrorDialogPreview() {
UnifestTheme {
ServerErrorDialog(onRetryClick = {})
}
@@ -214,7 +225,7 @@ fun ServerErrorDialogPreview() {
@ComponentPreview
@Composable
-fun NetworkErrorDialogPreview() {
+private fun NetworkErrorDialogPreview() {
UnifestTheme {
NetworkErrorDialog(onRetryClick = {})
}
@@ -222,7 +233,7 @@ fun NetworkErrorDialogPreview() {
@ComponentPreview
@Composable
-fun LikedFestivalDeleteDialogPreview() {
+private fun LikedFestivalDeleteDialogPreview() {
UnifestTheme {
LikedFestivalDeleteDialog(
onCancelClick = {},
@@ -233,7 +244,7 @@ fun LikedFestivalDeleteDialogPreview() {
@ComponentPreview
@Composable
-fun AppUpdateDialogPreview() {
+private fun AppUpdateDialogPreview() {
UnifestTheme {
AppUpdateDialog(
onDismissRequest = {},
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/HorizontalDivider.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/HorizontalDivider.kt
deleted file mode 100644
index d302af9e..00000000
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/HorizontalDivider.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.unifest.android.core.designsystem.component
-
-import androidx.compose.material3.HorizontalDivider
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.unit.dp
-import com.unifest.android.core.designsystem.ComponentPreview
-import com.unifest.android.core.designsystem.theme.UnifestTheme
-
-@Composable
-fun UnifestHorizontalDivider(
- modifier: Modifier = Modifier,
-) {
- HorizontalDivider(
- thickness = 8.dp,
- color = Color(0xFFF1F3F7),
- modifier = modifier,
- )
-}
-
-@ComponentPreview
-@Composable
-fun UnifestHorizontalDividerPreview() {
- UnifestTheme {
- UnifestHorizontalDivider()
- }
-}
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/LoadingWheel.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/LoadingWheel.kt
index 1bc22305..b161f197 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/LoadingWheel.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/LoadingWheel.kt
@@ -2,12 +2,12 @@ package com.unifest.android.core.designsystem.component
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.unifest.android.core.common.extension.noRippleClickable
import com.unifest.android.core.designsystem.ComponentPreview
-import com.unifest.android.core.designsystem.theme.MainColor
import com.unifest.android.core.designsystem.theme.UnifestTheme
@Composable
@@ -18,13 +18,13 @@ fun LoadingWheel(
modifier = modifier.noRippleClickable { },
contentAlignment = Alignment.Center,
) {
- CircularProgressIndicator(color = MainColor)
+ CircularProgressIndicator(color = MaterialTheme.colorScheme.primary)
}
}
@ComponentPreview
@Composable
-fun LoadingWheelPreview() {
+private fun LoadingWheelPreview() {
UnifestTheme {
LoadingWheel()
}
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/NetworkImage.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/NetworkImage.kt
index f426da76..6f1b0d65 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/NetworkImage.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/NetworkImage.kt
@@ -26,7 +26,7 @@ fun NetworkImage(
) {
if (LocalInspectionMode.current) {
Image(
- painter = painterResource(id = R.drawable.ic_item_placeholder),
+ painter = painterResource(id = R.drawable.item_placeholder),
contentDescription = "Example Image Icon",
modifier = modifier,
)
@@ -49,7 +49,7 @@ fun NetworkImage(
@ComponentPreview
@Composable
-fun NetworkImagePreview() {
+private fun NetworkImagePreview() {
UnifestTheme {
NetworkImage(
imgUrl = "",
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/OutlinedButton.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/OutlinedButton.kt
index ba7b3ad2..4ddb88c8 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/OutlinedButton.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/OutlinedButton.kt
@@ -1,10 +1,12 @@
package com.unifest.android.core.designsystem.component
import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -13,13 +15,15 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.unifest.android.core.designsystem.ComponentPreview
+import com.unifest.android.core.designsystem.theme.UnifestTheme
@Composable
fun UnifestOutlinedButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
- borderColor: Color = Color(0xFFf5678E),
- contentColor: Color = Color(0xFFf5678E),
+ borderColor: Color = MaterialTheme.colorScheme.primary,
+ containerColor: Color = MaterialTheme.colorScheme.background,
+ contentColor: Color = MaterialTheme.colorScheme.primary,
enabled: Boolean = true,
cornerRadius: Dp = 10.dp,
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
@@ -31,6 +35,7 @@ fun UnifestOutlinedButton(
enabled = enabled,
shape = RoundedCornerShape(cornerRadius),
colors = ButtonDefaults.outlinedButtonColors(
+ containerColor = containerColor,
contentColor = contentColor,
),
border = BorderStroke(1.dp, borderColor),
@@ -41,10 +46,12 @@ fun UnifestOutlinedButton(
@ComponentPreview
@Composable
-fun UnifestOutlinedButtonPreview() {
- UnifestOutlinedButton(
- onClick = {},
- ) {
- Text("Outlined Button")
+private fun UnifestOutlinedButtonPreview() {
+ UnifestTheme {
+ UnifestOutlinedButton(
+ onClick = {},
+ ) {
+ Text("Outlined Button")
+ }
}
}
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/SearchTextField.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/SearchTextField.kt
index c5b54c9a..3e0f3b92 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/SearchTextField.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/SearchTextField.kt
@@ -5,6 +5,7 @@ import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
+import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -19,6 +20,7 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.selection.LocalTextSelectionColors
import androidx.compose.foundation.text.selection.TextSelectionColors
import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
@@ -26,6 +28,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
@@ -37,12 +40,13 @@ import androidx.compose.ui.unit.dp
import com.unifest.android.core.designsystem.ComponentPreview
import com.unifest.android.core.designsystem.R
import com.unifest.android.core.designsystem.theme.BoothLocation
-import com.unifest.android.core.designsystem.theme.MainColor
+import com.unifest.android.core.designsystem.theme.LightPrimary100
+import com.unifest.android.core.designsystem.theme.LightPrimary500
import com.unifest.android.core.designsystem.theme.UnifestTheme
val unifestTextSelectionColors = TextSelectionColors(
- handleColor = MainColor,
- backgroundColor = Color(0xFFFAB3BE),
+ handleColor = LightPrimary500,
+ backgroundColor = LightPrimary100,
)
@Composable
@@ -53,16 +57,21 @@ fun SearchTextField(
onSearch: (TextFieldValue) -> Unit,
clearSearchText: () -> Unit,
modifier: Modifier = Modifier,
- backgroundColor: Color = Color.White,
+ backgroundColor: Color = MaterialTheme.colorScheme.background,
+ textColor: Color = MaterialTheme.colorScheme.onBackground,
cornerShape: RoundedCornerShape = RoundedCornerShape(67.dp),
- borderStroke: BorderStroke = BorderStroke(width = 1.dp, color = Color(0xFFBABABA)),
+ borderStroke: BorderStroke = BorderStroke(width = 1.dp, color = MaterialTheme.colorScheme.secondaryContainer),
) {
val keyboardController = LocalSoftwareKeyboardController.current
CompositionLocalProvider(LocalTextSelectionColors provides unifestTextSelectionColors) {
BasicTextField(
value = searchText,
- onValueChange = updateSearchText,
+ onValueChange = {
+ if (it.text.length <= 20) {
+ updateSearchText(it)
+ }
+ },
modifier = Modifier.fillMaxWidth(),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
keyboardActions = KeyboardActions(
@@ -71,7 +80,9 @@ fun SearchTextField(
keyboardController?.hide()
},
),
- textStyle = TextStyle(color = Color.Black),
+ singleLine = true,
+ textStyle = TextStyle(color = textColor),
+ cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground),
decorationBox = { innerTextField ->
Row(
modifier = modifier
@@ -87,7 +98,7 @@ fun SearchTextField(
if (searchText.text.isEmpty()) {
Text(
text = stringResource(id = searchTextHintRes),
- color = Color(0xFF848484),
+ color = MaterialTheme.colorScheme.onSecondaryContainer,
style = BoothLocation,
)
}
@@ -98,14 +109,15 @@ fun SearchTextField(
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_search),
contentDescription = "Search Icon",
- tint = Color.Unspecified,
-// modifier = Modifier.clickable {
-// onSearch(searchText)
-// },
+ tint = MaterialTheme.colorScheme.secondaryContainer,
)
} else {
Icon(
- imageVector = ImageVector.vectorResource(R.drawable.ic_delete_gray),
+ imageVector = if (isSystemInDarkTheme()) {
+ ImageVector.vectorResource(R.drawable.ic_delete_dark)
+ } else {
+ ImageVector.vectorResource(R.drawable.ic_delete_light)
+ },
contentDescription = "Delete Icon",
tint = Color.Unspecified,
modifier = Modifier
@@ -131,9 +143,10 @@ fun FestivalSearchTextField(
setEnableSearchMode: (Boolean) -> Unit,
isSearchMode: Boolean,
modifier: Modifier = Modifier,
- backgroundColor: Color = Color.White,
+ backgroundColor: Color = MaterialTheme.colorScheme.background,
+ textColor: Color = MaterialTheme.colorScheme.onBackground,
cornerShape: RoundedCornerShape = RoundedCornerShape(67.dp),
- borderStroke: BorderStroke = BorderStroke(width = 1.dp, color = Color(0xFFBABABA)),
+ borderStroke: BorderStroke = BorderStroke(width = 1.dp, color = MaterialTheme.colorScheme.secondaryContainer),
) {
LaunchedEffect(key1 = searchText.text) {
setEnableSearchMode(searchText.text.isNotEmpty())
@@ -142,10 +155,16 @@ fun FestivalSearchTextField(
CompositionLocalProvider(LocalTextSelectionColors provides unifestTextSelectionColors) {
BasicTextField(
value = searchText,
- onValueChange = updateSearchText,
+ onValueChange = {
+ if (it.text.length <= 20) {
+ updateSearchText(it)
+ }
+ },
modifier = Modifier.fillMaxWidth(),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
- textStyle = TextStyle(color = Color.Black),
+ singleLine = true,
+ textStyle = TextStyle(color = textColor),
+ cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground),
decorationBox = { innerTextField ->
Row(
modifier = modifier
@@ -161,7 +180,7 @@ fun FestivalSearchTextField(
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_arrow_back_dark_gray),
contentDescription = "Search Icon",
- tint = Color(0xFF767676),
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.clickable {
clearSearchText()
},
@@ -172,7 +191,7 @@ fun FestivalSearchTextField(
if (searchText.text.isEmpty()) {
Text(
text = stringResource(id = searchTextHintRes),
- color = Color(0xFF848484),
+ color = MaterialTheme.colorScheme.onSecondaryContainer,
style = BoothLocation,
)
}
@@ -206,12 +225,12 @@ fun FestivalSearchTextField(
@ComponentPreview
@Composable
-fun SearchTextFieldPreview() {
+private fun SearchTextFieldPreview() {
UnifestTheme {
SearchTextField(
searchText = TextFieldValue(),
updateSearchText = {},
- searchTextHintRes = R.string.intro_search_text_hint,
+ searchTextHintRes = R.string.search_text_hint,
onSearch = {},
clearSearchText = {},
modifier = Modifier
@@ -224,12 +243,12 @@ fun SearchTextFieldPreview() {
@ComponentPreview
@Composable
-fun FestivalSearchTextFieldPreview() {
+private fun FestivalSearchTextFieldPreview() {
UnifestTheme {
FestivalSearchTextField(
searchText = TextFieldValue("건국대학교"),
updateSearchText = {},
- searchTextHintRes = R.string.intro_search_text_hint,
+ searchTextHintRes = R.string.search_text_hint,
onSearch = {},
clearSearchText = {},
setEnableSearchMode = {},
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Tooltip.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Tooltip.kt
index 544efb07..9f52f791 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Tooltip.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/Tooltip.kt
@@ -15,23 +15,24 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.skydoves.balloon.ArrowOrientation
+import com.skydoves.balloon.ArrowOrientationRules
import com.skydoves.balloon.BalloonAnimation
import com.skydoves.balloon.BalloonSizeSpec
import com.skydoves.balloon.compose.Balloon
import com.skydoves.balloon.compose.rememberBalloonBuilder
-import com.skydoves.balloon.compose.setBackgroundColor
import com.unifest.android.core.common.extension.noRippleClickable
import com.unifest.android.core.designsystem.ComponentPreview
import com.unifest.android.core.designsystem.R
import com.unifest.android.core.designsystem.theme.Content5
-import com.unifest.android.core.designsystem.theme.MainColor
import com.unifest.android.core.designsystem.theme.Title1
import com.unifest.android.core.designsystem.theme.UnifestTheme
+import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@Composable
@@ -43,15 +44,18 @@ fun ToolTip(
content: @Composable () -> Unit,
) {
val scope = rememberCoroutineScope()
+ val context = LocalContext.current
+
val builder = rememberBalloonBuilder {
setArrowSize(10)
setArrowPosition(arrowPosition)
setArrowOrientation(arrowOrientation)
+ setArrowOrientationRules(ArrowOrientationRules.ALIGN_FIXED)
setWidth(BalloonSizeSpec.WRAP)
setHeight(BalloonSizeSpec.WRAP)
setPadding(9)
setCornerRadius(8f)
- setBackgroundColor(MainColor)
+ setBackgroundColor(context.getColor(R.color.tooltip_color))
setBalloonAnimation(BalloonAnimation.FADE)
setDismissWhenClicked(true)
setDismissWhenTouchOutside(false)
@@ -77,6 +81,7 @@ fun ToolTip(
content()
LaunchedEffect(key1 = Unit) {
scope.launch {
+ delay(1000)
balloonWindow.awaitAlignEnd()
}
}
@@ -138,7 +143,7 @@ fun SchoolSearchTitleWithToolTip(
@ComponentPreview
@Composable
-fun LikedFestivalToolTipPreview() {
+private fun LikedFestivalToolTipPreview() {
UnifestTheme {
LikedFestivalToolTip(
completeOnboarding = {},
@@ -148,7 +153,7 @@ fun LikedFestivalToolTipPreview() {
@ComponentPreview
@Composable
-fun SchoolSearchTitleWithToolTipPreview() {
+private fun SchoolSearchTitleWithToolTipPreview() {
UnifestTheme {
SchoolSearchTitleWithToolTip(
title = "건국대학교",
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/TopAppBar.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/TopAppBar.kt
index 24a4d15c..6516d145 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/TopAppBar.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/component/TopAppBar.kt
@@ -14,6 +14,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalContentColor
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
@@ -41,8 +42,8 @@ fun UnifestTopAppBar(
titleStyle: TextStyle = Title1,
@DrawableRes navigationIconRes: Int = R.drawable.ic_arrow_back_dark_gray,
navigationIconContentDescription: String? = null,
- containerColor: Color = Color.White,
- contentColor: Color = Color.Black,
+ containerColor: Color = MaterialTheme.colorScheme.background,
+ contentColor: Color = MaterialTheme.colorScheme.onBackground,
onNavigationClick: () -> Unit = {},
onTitleClick: (Boolean) -> Unit = {},
isOnboardingCompleted: Boolean = false,
@@ -59,7 +60,7 @@ fun UnifestTopAppBar(
Icon(
imageVector = imageVector,
contentDescription = navigationIconContentDescription,
- tint = Color.Unspecified,
+ tint = MaterialTheme.colorScheme.onBackground,
)
}
}
@@ -136,7 +137,7 @@ fun SchoolSearchTitle(
@ComponentPreview
@Composable
-fun UnifestTopAppBarPreview() {
+private fun UnifestTopAppBarPreview() {
UnifestTheme {
UnifestTopAppBar(
navigationType = TopAppBarNavigationType.None,
@@ -147,7 +148,7 @@ fun UnifestTopAppBarPreview() {
@ComponentPreview
@Composable
-fun SchoolSearchTitlePreview() {
+private fun SchoolSearchTitlePreview() {
UnifestTheme {
SchoolSearchTitle(
title = "건국대학교",
@@ -158,7 +159,7 @@ fun SchoolSearchTitlePreview() {
@ComponentPreview
@Composable
-fun UnifestTopAppBarWithBackButtonPreview() {
+private fun UnifestTopAppBarWithBackButtonPreview() {
UnifestTheme {
UnifestTopAppBar(
navigationType = TopAppBarNavigationType.Back,
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Color.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Color.kt
index 7e0ba840..45ff0ab7 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Color.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Color.kt
@@ -2,12 +2,50 @@ package com.unifest.android.core.designsystem.theme
import androidx.compose.ui.graphics.Color
-val Purple80 = Color(0xFFD0BCFF)
-val PurpleGrey80 = Color(0xFFCCC2DC)
-val Pink80 = Color(0xFFEFB8C8)
+val LightPrimary900 = Color(0xFF4D101E)
+val LightPrimary800 = Color(0xFFBA3146)
+val LightPrimary700 = Color(0xFFE73D58)
+val LightPrimary500 = Color(0xFFFF748A)
+val LightPrimary300 = Color(0xFFF895A5)
+val LightPrimary100 = Color(0xFFFBC3CB)
+val LightPrimary50 = Color(0xFFFFF0F3)
-val Purple40 = Color(0xFF6650a4)
-val PurpleGrey40 = Color(0xFF625b71)
-val Pink40 = Color(0xFF7D5260)
+val DarkPrimary900 = Color(0xFFF1D9DE)
+val DarkPrimary800 = Color(0xFFEFA7B1)
+val DarkPrimary700 = Color(0xFFEF8192)
+val DarkPrimary500 = Color(0xFFF55770)
+val DarkPrimary300 = Color(0xFFD22F49)
+val DarkPrimary100 = Color(0xFFA93043)
+val DarkPrimary50 = Color(0xFF3F0F1A)
+
+val LightGrey900 = Color(0xFF131316)
+val LightGrey800 = Color(0xFF2B2B30)
+val LightGrey700 = Color(0xFF45464A)
+val LightGrey600 = Color(0xFF727276)
+val LightGrey500 = Color(0xFF8D8D93)
+val LightGrey400 = Color(0xFFBABABF)
+val LightGrey300 = Color(0xFFD4D6DC)
+val LightGrey200 = Color(0xFFE3E4EA)
+val LightGrey100 = Color(0xFFF1F3F7)
+
+val DarkGrey900 = Color(0xFFECEFF5)
+val DarkGrey800 = Color(0xFFD1D3DC)
+val DarkGrey700 = Color(0xFFB6B8C1)
+val DarkGrey600 = Color(0xFF9697A2)
+val DarkGrey500 = Color(0xFF78787F)
+val DarkGrey400 = Color(0xFF5A5A60)
+val DarkGrey300 = Color(0xFF343438)
+val DarkGrey200 = Color(0xFF212126)
+val DarkGrey100 = Color(0xFF131316)
+
+val LightBlueGreen = Color(0xFF1FC0BA)
+val LightRed = Color(0xFFFF5858)
+val LightOrange = Color(0xFFFF8A1F)
+val LightGreen = Color(0xFF15D055)
+
+val DarkBlueGreen = Color(0xFF00A8A1)
+val DarkRed = Color(0xFFF03939)
+val DarkOrange = Color(0xFFE16E05)
+val DarkGreen = Color(0xFF02B540)
val MainColor = Color(0xFFF5687E)
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Font.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Font.kt
index 93a8a627..8c4f66f4 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Font.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Font.kt
@@ -13,12 +13,19 @@ val pretendardFamily = FontFamily(
Font(R.font.pretendard_semi_bold, FontWeight.SemiBold, FontStyle.Normal),
Font(R.font.pretendard_medium, FontWeight.Medium, FontStyle.Normal),
Font(R.font.pretendard_regular, FontWeight.Normal, FontStyle.Normal),
+ Font(R.font.pretendard_light, FontWeight.Light, FontStyle.Normal),
+)
+
+val StampCount = TextStyle(
+ fontFamily = pretendardFamily,
+ fontWeight = FontWeight.Bold,
+ fontSize = 24.sp,
)
val Title0 = TextStyle(
fontFamily = pretendardFamily,
fontWeight = FontWeight.SemiBold,
- fontSize = 24.sp,
+ fontSize = 22.sp,
)
val Title1 = TextStyle(
@@ -50,6 +57,7 @@ val Title5 = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 13.sp,
)
+
val BoothTitle0 = TextStyle(
fontFamily = pretendardFamily,
fontWeight = FontWeight.Bold,
@@ -68,6 +76,12 @@ val BoothTitle2 = TextStyle(
fontSize = 20.sp,
)
+val BoothTitle3 = TextStyle(
+ fontFamily = pretendardFamily,
+ fontWeight = FontWeight.Bold,
+ fontSize = 20.sp,
+)
+
val BoothCaution = TextStyle(
fontFamily = pretendardFamily,
fontWeight = FontWeight.SemiBold,
@@ -157,3 +171,39 @@ val Content9 = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 14.sp,
)
+
+val WaitingNumber = TextStyle(
+ fontFamily = pretendardFamily,
+ fontWeight = FontWeight.SemiBold,
+ fontSize = 45.sp,
+)
+
+val WaitingNumber2 = TextStyle(
+ fontFamily = pretendardFamily,
+ fontWeight = FontWeight.Bold,
+ fontSize = 14.sp,
+)
+
+val WaitingNumber3 = TextStyle(
+ fontFamily = pretendardFamily,
+ fontWeight = FontWeight.Bold,
+ fontSize = 15.sp,
+)
+
+val WaitingNumber4 = TextStyle(
+ fontFamily = pretendardFamily,
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp,
+)
+
+val WaitingNumber5 = TextStyle(
+ fontFamily = pretendardFamily,
+ fontWeight = FontWeight.SemiBold,
+ fontSize = 30.sp,
+)
+
+val QRDescription = TextStyle(
+ fontFamily = pretendardFamily,
+ fontWeight = FontWeight.Light,
+ fontSize = 13.sp,
+)
diff --git a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Theme.kt b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Theme.kt
index e0f49a5d..067d5871 100644
--- a/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Theme.kt
+++ b/core/designsystem/src/main/kotlin/com/unifest/android/core/designsystem/theme/Theme.kt
@@ -5,26 +5,101 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
-
-private val DarkColorScheme = darkColorScheme(
- primary = Purple80,
- secondary = PurpleGrey80,
- tertiary = Pink80,
-)
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Density
private val LightColorScheme = lightColorScheme(
- primary = Purple40,
- secondary = PurpleGrey40,
- tertiary = Pink40,
+ // 앱의 주요 브랜드 색상, 주요 액션 버튼 등에 사용
+ primary = LightPrimary500,
+ // primary 색상 위의 텍스트나 아이콘 색상
+ onPrimary = Color.White,
+ // primary 색상의 더 연한 버전, 백그라운드나 강조 영역에 사용
+ primaryContainer = LightPrimary100,
+ // primaryContainer 위의 텍스트나 아이콘 색상
+ onPrimaryContainer = LightPrimary900,
+ // 보조 액션이나 정보를 위한 색상
+ secondary = LightBlueGreen,
+ // secondary 색상 위의 텍스트나 아이콘 색상
+ onSecondary = LightGrey700,
+ // secondary 색상의 더 연한 버전, 보조 컨테이너에 사용
+ secondaryContainer = LightGrey400,
+ // secondaryContainer 위의 텍스트나 아이콘 색상
+ onSecondaryContainer = LightGrey400,
+ // 대비를 위한 액센트 색상
+ tertiary = LightPrimary50,
+ // tertiary 색상 위의 텍스트나 아이콘 색상
+ onTertiary = Color.White,
+ // tertiary 색상의 더 연한 버전
+ tertiaryContainer = Color.White,
+ // tertiaryContainer 위의 텍스트나 아이콘 색상
+ onTertiaryContainer = Color.White,
+ // 오류 표시를 위한 색상
+ error = LightRed,
+ // error 색상 위의 텍스트나 아이콘 색상
+ onError = Color.White,
+ // error 색상의 더 연한 버전, 오류 메시지 배경 등에 사용
+ errorContainer = LightPrimary100,
+ // errorContainer 위의 텍스트나 아이콘 색상
+ onErrorContainer = LightPrimary900,
+ // 앱의 배경색
+ background = Color.White,
+ // background 위의 텍스트나 아이콘 색상
+ onBackground = LightGrey900,
+ // 카드, 시트 등 표면 요소의 색상
+ surface = Color.White,
+ // surface 위의 텍스트나 아이콘 색상
+ onSurface = LightGrey500,
+ // surface의 변형, 비활성화된 요소나 구분선에 사용
+ surfaceVariant = LightGrey600,
+ surfaceTint = LightRed,
+ // surfaceVariant 위의 텍스트나 아이콘 색상
+ onSurfaceVariant = LightGrey600,
+ // 경계선이나 구분선 등에 사용되는 색상
+ outline = LightGrey200,
+ scrim = LightGrey300,
+ surfaceBright = LightGrey100,
+ surfaceContainer = Color.White,
+ surfaceContainerHigh = LightPrimary50,
+)
-// // Other default colors to override
-// background = Color(0xFFFFFBFE),
-// surface = Color(0xFFFFFBFE),
-// onPrimary = Color.White,
-// onSecondary = Color.White,
-// onTertiary = Color.White,
-// onBackground = Color(0xFF1C1B1F),
-// onSurface = Color(0xFF1C1B1F),
+private val DarkColorScheme = darkColorScheme(
+ // 다크 모드에서의 주요 브랜드 색상
+ primary = DarkPrimary500,
+ onPrimary = Color.White,
+ primaryContainer = DarkPrimary700,
+ onPrimaryContainer = DarkPrimary50,
+ // 다크 모드에서의 보조 색상
+ secondary = DarkBlueGreen,
+ onSecondary = DarkGrey700,
+ secondaryContainer = DarkGrey400,
+ onSecondaryContainer = DarkGrey400,
+ // 다크 모드에서의 강조 색상
+ tertiary = DarkPrimary50,
+ onTertiary = Color.White,
+ tertiaryContainer = DarkGrey300,
+ onTertiaryContainer = DarkGrey300,
+ // 다크 모드에서의 오류 색상
+ error = DarkRed,
+ onError = Color.White,
+ errorContainer = DarkPrimary300,
+ onErrorContainer = DarkPrimary50,
+ // 다크 모드에서의 배경색
+ background = DarkGrey100,
+ onBackground = DarkGrey900,
+ // 다크 모드에서의 표면 색상
+ surface = DarkGrey200,
+ onSurface = DarkGrey500,
+ surfaceVariant = DarkGrey600,
+ onSurfaceVariant = DarkGrey600,
+ surfaceTint = DarkRed,
+ // 다크 모드에서의 경계선이나 구분선 색상
+ outline = DarkGrey200,
+ scrim = DarkGrey300,
+ surfaceBright = DarkGrey200,
+ surfaceContainer = DarkGrey100,
+ surfaceContainerHigh = DarkGrey300,
)
@Composable
@@ -34,9 +109,13 @@ fun UnifestTheme(
) {
val colorScheme = if (darkTheme) DarkColorScheme else LightColorScheme
- MaterialTheme(
- colorScheme = colorScheme,
- typography = Typography,
- content = content,
- )
+ CompositionLocalProvider(
+ LocalDensity provides Density(density = LocalDensity.current.density, fontScale = 1f),
+ ) {
+ MaterialTheme(
+ colorScheme = colorScheme,
+ typography = Typography,
+ content = content,
+ )
+ }
}
diff --git a/core/designsystem/src/main/res/drawable-night/ic_location_green.xml b/core/designsystem/src/main/res/drawable-night/ic_location_green.xml
new file mode 100644
index 00000000..421bbb52
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable-night/ic_location_green.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/core/designsystem/src/main/res/drawable-night/image_placeholder.png b/core/designsystem/src/main/res/drawable-night/image_placeholder.png
new file mode 100644
index 00000000..f1b35384
Binary files /dev/null and b/core/designsystem/src/main/res/drawable-night/image_placeholder.png differ
diff --git a/core/designsystem/src/main/res/drawable-night/item_placeholder.png b/core/designsystem/src/main/res/drawable-night/item_placeholder.png
new file mode 100644
index 00000000..3341cb70
Binary files /dev/null and b/core/designsystem/src/main/res/drawable-night/item_placeholder.png differ
diff --git a/core/designsystem/src/main/res/drawable/ic_arrow_below_waiting.xml b/core/designsystem/src/main/res/drawable/ic_arrow_below_waiting.xml
new file mode 100644
index 00000000..a7801b1d
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_arrow_below_waiting.xml
@@ -0,0 +1,12 @@
+
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_booth_info.xml b/core/designsystem/src/main/res/drawable/ic_booth_info.xml
new file mode 100644
index 00000000..880ed63b
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_booth_info.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_check.xml b/core/designsystem/src/main/res/drawable/ic_check.xml
index fd3e27d2..f4b6466d 100644
--- a/core/designsystem/src/main/res/drawable/ic_check.xml
+++ b/core/designsystem/src/main/res/drawable/ic_check.xml
@@ -1,9 +1,12 @@
+ android:width="17dp"
+ android:height="13dp"
+ android:viewportWidth="17"
+ android:viewportHeight="13">
+ android:pathData="M1,4.75L7,11L16,1"
+ android:strokeWidth="2"
+ android:fillColor="#00000000"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"/>
diff --git a/core/designsystem/src/main/res/drawable/ic_checkbox.xml b/core/designsystem/src/main/res/drawable/ic_checkbox.xml
new file mode 100644
index 00000000..a4b770b9
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_checkbox.xml
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_checkbox_unchecked.xml b/core/designsystem/src/main/res/drawable/ic_checkbox_unchecked.xml
new file mode 100644
index 00000000..4b9a25bc
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_checkbox_unchecked.xml
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_chevron_left.xml b/core/designsystem/src/main/res/drawable/ic_chevron_left.xml
deleted file mode 100644
index e6bb3ca9..00000000
--- a/core/designsystem/src/main/res/drawable/ic_chevron_left.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/core/designsystem/src/main/res/drawable/ic_chevron_right.xml b/core/designsystem/src/main/res/drawable/ic_chevron_right.xml
deleted file mode 100644
index 24835127..00000000
--- a/core/designsystem/src/main/res/drawable/ic_chevron_right.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/core/designsystem/src/main/res/drawable/ic_cluster_icon.xml b/core/designsystem/src/main/res/drawable/ic_cluster_icon.xml
new file mode 100644
index 00000000..4e026e3e
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_cluster_icon.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_delete_dark.xml b/core/designsystem/src/main/res/drawable/ic_delete_dark.xml
new file mode 100644
index 00000000..f99fc3a0
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_delete_dark.xml
@@ -0,0 +1,16 @@
+
+
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_delete_light.xml b/core/designsystem/src/main/res/drawable/ic_delete_light.xml
new file mode 100644
index 00000000..eba2514b
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_delete_light.xml
@@ -0,0 +1,16 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/core/designsystem/src/main/res/drawable/ic_launcher_background.xml
similarity index 100%
rename from app/src/main/res/drawable/ic_launcher_background.xml
rename to core/designsystem/src/main/res/drawable/ic_launcher_background.xml
diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/core/designsystem/src/main/res/drawable/ic_launcher_foreground.xml
similarity index 100%
rename from app/src/main/res/drawable/ic_launcher_foreground.xml
rename to core/designsystem/src/main/res/drawable/ic_launcher_foreground.xml
diff --git a/core/designsystem/src/main/res/drawable/ic_location_gray.xml b/core/designsystem/src/main/res/drawable/ic_location_black.xml
similarity index 94%
rename from core/designsystem/src/main/res/drawable/ic_location_gray.xml
rename to core/designsystem/src/main/res/drawable/ic_location_black.xml
index 102279a3..22777c64 100644
--- a/core/designsystem/src/main/res/drawable/ic_location_gray.xml
+++ b/core/designsystem/src/main/res/drawable/ic_location_black.xml
@@ -5,7 +5,7 @@
android:viewportHeight="14">
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_selected_home.xml b/core/designsystem/src/main/res/drawable/ic_selected_home.xml
deleted file mode 100644
index 66e53789..00000000
--- a/core/designsystem/src/main/res/drawable/ic_selected_home.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
diff --git a/core/designsystem/src/main/res/drawable/ic_warning.xml b/core/designsystem/src/main/res/drawable/ic_warning.xml
new file mode 100644
index 00000000..f3232164
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_warning.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_image_placeholder.png b/core/designsystem/src/main/res/drawable/image_placeholder.png
similarity index 100%
rename from core/designsystem/src/main/res/drawable/ic_image_placeholder.png
rename to core/designsystem/src/main/res/drawable/image_placeholder.png
diff --git a/core/designsystem/src/main/res/drawable/item_divider.xml b/core/designsystem/src/main/res/drawable/item_divider.xml
deleted file mode 100644
index 175523ab..00000000
--- a/core/designsystem/src/main/res/drawable/item_divider.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/core/designsystem/src/main/res/drawable/ic_item_placeholder.png b/core/designsystem/src/main/res/drawable/item_placeholder.png
similarity index 100%
rename from core/designsystem/src/main/res/drawable/ic_item_placeholder.png
rename to core/designsystem/src/main/res/drawable/item_placeholder.png
diff --git a/core/designsystem/src/main/res/font/pretendard_light.otf b/core/designsystem/src/main/res/font/pretendard_light.otf
new file mode 100644
index 00000000..fefa7853
Binary files /dev/null and b/core/designsystem/src/main/res/font/pretendard_light.otf differ
diff --git a/core/designsystem/src/main/res/values-night/colors.xml b/core/designsystem/src/main/res/values-night/colors.xml
new file mode 100644
index 00000000..a2442641
--- /dev/null
+++ b/core/designsystem/src/main/res/values-night/colors.xml
@@ -0,0 +1,13 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
+ #FFF55770
+ #FFF55770
+
diff --git a/core/designsystem/src/main/res/values/colors.xml b/core/designsystem/src/main/res/values/colors.xml
index c341beac..a02adc71 100644
--- a/core/designsystem/src/main/res/values/colors.xml
+++ b/core/designsystem/src/main/res/values/colors.xml
@@ -8,8 +8,6 @@
#FF000000
#FFFFFFFF
- #FFF5687E
- #303F9F
- #FCCA3E
- #BEBEBE
+ #FFFF748A
+ #FFFF748A
diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml
index 9aa1936c..9c490aae 100644
--- a/core/designsystem/src/main/res/values/strings.xml
+++ b/core/designsystem/src/main/res/values/strings.xml
@@ -1,82 +1,17 @@
-
- Uni-Fest
- 추가 완료
- 관심있는 학교 축제를 추가해보세요
- 관심 학교는 언제든지 수정 가능합니다
- 학교를 검색해보세요
- 나의 관심 축제
- 모두 선택 해제
-
- - 전체
- - 서울
- - 경기/인천
- - 강원
- - 대전/충청
- - 광주/전라
- - 부산/대구
- - 경상도
-
- 총 %d개
- 검색 결과가 없어요
-
-
- 의 축제 일정
- 오늘은 축제가 열리는 학교가 없어요
- 다가오는 축제 일정
- 관심 축제 추가하기
- 관심 축제로 추가
- 관심 축제로 저장했습니다
- 축제 일정 없음
- 오늘은 축제가 열리는 학교가 없어요
+ 학교를 검색해보세요
+ 여기를 눌러서 학교를 검색해보세요.
+ 여기를 터치하여 해당 학교로 이동해보세요.
+ 현재는 한경대학교만 서비스중이에요!
+ 나의 관심 축제
-
- 위치 확인하기
- 메뉴
- 웨이팅 하기
- 웨이팅 기능을 지원하지 않는 부스입니다
관심 부스로 저장했습니다.
관심 부스로 저장을 실패했습니다.
관심 부스에서 삭제했습니다.
관심 부스에서 삭제를 실패했습니다.
- 등록된 메뉴가 없어요.
-
-
- 부스 / 주점을 검색해보세요.
- 여기를 눌러서 학교를 검색해보세요.
- 인기 부스
- %d위
- 권한 필요
- 앱 설정으로 이동
- 확인
- 인기 부스 갱신을 실패했습니다.
- 검색 결과가 없습니다
-
-
- 메뉴
- 나의 관심 축제
- 추가하기 >
- 관심 부스
- 더보기 >
- 이용 문의
- 운영자 모드 진입
- 관심 부스 없음
- 지도에서 관심있는 부스를 추가해주세요
- 현재는 건국대학교만 서비스중이에요!
-
-
- 관심 부스
-
-
학교 / 축제 이름을 검색해보세요.
- 나의 관심 축제
- 편집
- 완료
- 추가
- 검색결과
검색 결과가 없어요
- 여기를 터치하여 해당 학교로 이동해보세요.
서버 문제 발생
@@ -92,7 +27,4 @@
원활한 서비스 이용을 위해\n최신 버전으로 업데이트가 필요합니다
업데이트 하기
-
- 이용문의
-
diff --git a/core/model/build.gradle.kts b/core/model/build.gradle.kts
index 5afa5a46..97e746f3 100644
--- a/core/model/build.gradle.kts
+++ b/core/model/build.gradle.kts
@@ -1,6 +1,6 @@
plugins {
alias(libs.plugins.unifest.jvm.kotlin)
- id("kotlinx-serialization")
+ alias(libs.plugins.kotlin.serialization)
}
dependencies {
diff --git a/core/model/src/main/kotlin/com/unifest/android/core/model/BoothDetailModel.kt b/core/model/src/main/kotlin/com/unifest/android/core/model/BoothDetailModel.kt
index 8f906b9f..81239ad0 100644
--- a/core/model/src/main/kotlin/com/unifest/android/core/model/BoothDetailModel.kt
+++ b/core/model/src/main/kotlin/com/unifest/android/core/model/BoothDetailModel.kt
@@ -16,6 +16,9 @@ data class BoothDetailModel(
val menus: List = emptyList(),
val likes: Int = 0,
val isLiked: Boolean = false,
+ val waitingEnabled: Boolean = false,
+ val openTime: String = "",
+ val closeTime: String = "",
)
@Stable
@@ -24,4 +27,19 @@ data class MenuModel(
val name: String,
val price: Int,
val imgUrl: String,
+ val status: String,
+)
+
+@Stable
+data class WaitingModel(
+ val boothId: Long = 0L,
+ val waitingId: Long = 0L,
+ val partySize: Long = 0L,
+ val tel: String = "",
+ val deviceId: String = "",
+ val createdAt: String = "",
+ val updatedAt: String = "",
+ val status: String = "",
+ val waitingOrder: Long = 0L,
+ val boothName: String = "",
)
diff --git a/core/model/src/main/kotlin/com/unifest/android/core/model/MyWaitingModel.kt b/core/model/src/main/kotlin/com/unifest/android/core/model/MyWaitingModel.kt
new file mode 100644
index 00000000..33af4f6b
--- /dev/null
+++ b/core/model/src/main/kotlin/com/unifest/android/core/model/MyWaitingModel.kt
@@ -0,0 +1,17 @@
+package com.unifest.android.core.model
+
+import androidx.compose.runtime.Stable
+
+@Stable
+data class MyWaitingModel(
+ val boothId: Long = 0L,
+ val waitingId: Long = 0L,
+ val partySize: Long = 0L,
+ val tel: String = "",
+ val deviceId: String = "",
+ val createdAt: String = "",
+ val updatedAt: String = "",
+ val status: String = "",
+ val waitingOrder: Long = 0L,
+ val boothName: String = "",
+)
diff --git a/core/model/src/main/kotlin/com/unifest/android/core/model/StampBoothModel.kt b/core/model/src/main/kotlin/com/unifest/android/core/model/StampBoothModel.kt
new file mode 100644
index 00000000..265a2c37
--- /dev/null
+++ b/core/model/src/main/kotlin/com/unifest/android/core/model/StampBoothModel.kt
@@ -0,0 +1,16 @@
+package com.unifest.android.core.model
+
+import androidx.compose.runtime.Stable
+
+@Stable
+data class StampBoothModel(
+ val id: Long,
+ val name: String = "",
+ val category: String = "",
+ val description: String = "",
+ val thumbnail: String = "",
+ val location: String = "",
+ val latitude: Float = 0F,
+ val longitude: Float = 0F,
+ val isChecked: Boolean = false,
+)
diff --git a/core/navigation/.gitignore b/core/navigation/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/core/navigation/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/core/navigation/build.gradle.kts b/core/navigation/build.gradle.kts
new file mode 100644
index 00000000..609f87e6
--- /dev/null
+++ b/core/navigation/build.gradle.kts
@@ -0,0 +1,12 @@
+plugins {
+ alias(libs.plugins.unifest.android.library)
+ alias(libs.plugins.kotlin.serialization)
+}
+
+android {
+ namespace = "com.unifest.android.core.navigation"
+}
+
+dependencies {
+ implementation(libs.kotlinx.serialization.json)
+}
diff --git a/core/navigation/src/main/kotlin/com/unifest/android/core/navigation/RouteModel.kt b/core/navigation/src/main/kotlin/com/unifest/android/core/navigation/RouteModel.kt
new file mode 100644
index 00000000..a845b0a4
--- /dev/null
+++ b/core/navigation/src/main/kotlin/com/unifest/android/core/navigation/RouteModel.kt
@@ -0,0 +1,34 @@
+package com.unifest.android.core.navigation
+
+import kotlinx.serialization.Serializable
+
+sealed interface MainTabRoute : Route {
+ @Serializable
+ data object Home : MainTabRoute
+
+ @Serializable
+ data object Waiting : MainTabRoute
+
+ @Serializable
+ data object Map : MainTabRoute
+
+ @Serializable
+ data object Stamp : MainTabRoute
+
+ @Serializable
+ data object Menu : MainTabRoute
+}
+
+sealed interface Route {
+ @Serializable
+ data object Booth {
+ @Serializable
+ data class BoothDetail(val boothId: Long) : Route
+
+ @Serializable
+ data object BoothLocation : Route
+ }
+
+ @Serializable
+ data object LikeBooth : Route
+}
diff --git a/core/network/build.gradle.kts b/core/network/build.gradle.kts
index b1ddaf92..7a266a00 100644
--- a/core/network/build.gradle.kts
+++ b/core/network/build.gradle.kts
@@ -9,7 +9,7 @@ plugins {
alias(libs.plugins.unifest.android.retrofit)
alias(libs.plugins.unifest.android.hilt)
alias(libs.plugins.google.secrets)
- id("kotlinx-serialization")
+ alias(libs.plugins.kotlin.serialization)
}
val localPropertiesFile = rootProject.file("local.properties")
@@ -47,5 +47,5 @@ secrets {
}
fun getServerBaseUrl(propertyKey: String): String {
- return gradleLocalProperties(rootDir).getProperty(propertyKey)
+ return gradleLocalProperties(rootDir, providers).getProperty(propertyKey)
}
diff --git a/core/network/src/main/kotlin/com/unifest/android/core/network/di/NetworkModule.kt b/core/network/src/main/kotlin/com/unifest/android/core/network/di/NetworkModule.kt
index ce2a61ed..ecd91eb3 100644
--- a/core/network/src/main/kotlin/com/unifest/android/core/network/di/NetworkModule.kt
+++ b/core/network/src/main/kotlin/com/unifest/android/core/network/di/NetworkModule.kt
@@ -2,7 +2,6 @@ package com.unifest.android.core.network.di
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.unifest.android.core.network.BuildConfig
-import com.unifest.android.core.network.FileApi
import com.unifest.android.core.network.UnifestApi
import com.unifest.android.core.network.UnifestClient
import dagger.Module
@@ -28,7 +27,6 @@ private val jsonRule = Json {
}
private val jsonConverterFactory = jsonRule.asConverterFactory("application/json".toMediaType())
-private val fileConverterFactory = jsonRule.asConverterFactory("multipart/form-data".toMediaType())
@Module
@InstallIn(SingletonComponent::class)
@@ -74,17 +72,4 @@ internal object NetworkModule {
.addConverterFactory(jsonConverterFactory)
.build()
}
-
- @FileApi
- @Singleton
- @Provides
- internal fun provideFileApiRetrofit(
- @UnifestClient okHttpClient: OkHttpClient,
- ): Retrofit {
- return Retrofit.Builder()
- .baseUrl(BuildConfig.SERVER_BASE_URL)
- .client(okHttpClient)
- .addConverterFactory(fileConverterFactory)
- .build()
- }
}
diff --git a/core/network/src/main/kotlin/com/unifest/android/core/network/request/BoothCreateRequest.kt b/core/network/src/main/kotlin/com/unifest/android/core/network/request/BoothCreateRequest.kt
deleted file mode 100644
index e9f4f795..00000000
--- a/core/network/src/main/kotlin/com/unifest/android/core/network/request/BoothCreateRequest.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.unifest.android.core.network.request
-
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class BoothCreateRequest(
- @SerialName("name")
- val name: String,
- @SerialName("category")
- val category: String,
- @SerialName("description")
- val description: String,
- @SerialName("detail")
- val detail: String,
- @SerialName("thumbnail")
- val thumbnail: String,
- @SerialName("festivalId")
- val festivalId: Long,
- @SerialName("latitude")
- val latitude: Float,
- @SerialName("longitude")
- val longitude: Float,
- @SerialName("enabled")
- val enabled: Boolean,
-)
diff --git a/core/network/src/main/kotlin/com/unifest/android/core/network/request/BoothWaitingRequest.kt b/core/network/src/main/kotlin/com/unifest/android/core/network/request/BoothWaitingRequest.kt
new file mode 100644
index 00000000..37c8f5cc
--- /dev/null
+++ b/core/network/src/main/kotlin/com/unifest/android/core/network/request/BoothWaitingRequest.kt
@@ -0,0 +1,20 @@
+package com.unifest.android.core.network.request
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class BoothWaitingRequest(
+ @SerialName("boothId")
+ val boothId: Long,
+ @SerialName("tel")
+ val tel: String,
+ @SerialName("deviceId")
+ val deviceId: String,
+ @SerialName("partySize")
+ val partySize: Long,
+ @SerialName("pinNumber")
+ val pinNumber: String,
+ @SerialName("fcmToken")
+ val fcmToken: String,
+)
diff --git a/core/network/src/main/kotlin/com/unifest/android/core/network/request/CheckPinValidationRequest.kt b/core/network/src/main/kotlin/com/unifest/android/core/network/request/CheckPinValidationRequest.kt
new file mode 100644
index 00000000..f5f8b849
--- /dev/null
+++ b/core/network/src/main/kotlin/com/unifest/android/core/network/request/CheckPinValidationRequest.kt
@@ -0,0 +1,12 @@
+package com.unifest.android.core.network.request
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class CheckPinValidationRequest(
+ @SerialName("boothId")
+ val boothId: Long,
+ @SerialName("pinNumber")
+ val pinNumber: String,
+)
diff --git a/core/network/src/main/kotlin/com/unifest/android/core/network/request/LikedFestivalRequest.kt b/core/network/src/main/kotlin/com/unifest/android/core/network/request/LikedFestivalRequest.kt
new file mode 100644
index 00000000..ee82a42b
--- /dev/null
+++ b/core/network/src/main/kotlin/com/unifest/android/core/network/request/LikedFestivalRequest.kt
@@ -0,0 +1,12 @@
+package com.unifest.android.core.network.request
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class LikedFestivalRequest(
+ @SerialName("festivalId")
+ val festivalId: Long,
+ @SerialName("fcmToken")
+ val fcmToken: String,
+)
diff --git a/core/network/src/main/kotlin/com/unifest/android/core/network/request/WaitingRequest.kt b/core/network/src/main/kotlin/com/unifest/android/core/network/request/WaitingRequest.kt
new file mode 100644
index 00000000..2666beae
--- /dev/null
+++ b/core/network/src/main/kotlin/com/unifest/android/core/network/request/WaitingRequest.kt
@@ -0,0 +1,12 @@
+package com.unifest.android.core.network.request
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class WaitingRequest(
+ @SerialName("waitingId")
+ val waitingId: Long,
+ @SerialName("deviceId")
+ val deviceId: String,
+)
diff --git a/core/network/src/main/kotlin/com/unifest/android/core/network/response/BoothResponse.kt b/core/network/src/main/kotlin/com/unifest/android/core/network/response/BoothResponse.kt
index c9343f91..397fac71 100644
--- a/core/network/src/main/kotlin/com/unifest/android/core/network/response/BoothResponse.kt
+++ b/core/network/src/main/kotlin/com/unifest/android/core/network/response/BoothResponse.kt
@@ -65,6 +65,12 @@ data class BoothDetail(
val longitude: Float,
@SerialName("menus")
val menus: List